Kay, here's the function with a bunch of changes made that reflect what I learned in this thread and from my book. Now it reclaims it's own memory, tracks the memory to make sure, and checks for more error conditions. I also got rid of calloc even though I'm not sure it makes any difference. Did I get everything, except for using the expensive list that is, I still think it's a good way to do it.
Code:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable: 4706)
char *sfgets(FILE *src);
char *sgets();
#define TRACKMEMORY
#if defined(TRACKMEMORY)
int trackmem;
#define tmalloc(x) (trackmem++, malloc((x)))
#define tfree(x) (trackmem--, free((x)))
#define tprint printf("Leaked memory calls: %d\n", trackmem)
#else
#define tmalloc(x) (malloc((x)))
#define tfree(x) (free((x)))
#define tprint
#endif
main(){
char *s;
printf("What's your name? ");
s = sgets();
printf("Heyas, %s!\n", s);
tfree(s);
tprint;
}
char *sfgets(FILE *src){
typedef struct list{int val; struct list *n;}LIST;
int i, c = 0;
char *dst;
LIST *head = tmalloc(sizeof(LIST)), *save, *walk = head;
if (!head)
return 0;
while ((i = getc(src)) != '\n' && i != EOF){
if (!(walk->n = tmalloc(sizeof(LIST))))
break;
walk = walk->n, walk->val = i, walk->n = 0;
c++;
}
if (!(dst = tmalloc(c * sizeof(char)+1)) && !c)
return 0;
for (i = 0, walk = head->n; walk; walk = save){
save = walk->n;
dst[i++] = (char)walk->val;
tfree(walk);
}
tfree(head);
return(dst[i] = 0, dst);
}
char *sgets(){
return sfgets(stdin);
}