/* * dyngets.c (library) Matt Bishop January 15, 1994 * * Entry point: * char *dyngets(char *buf, int n, FILE *fp) * Read the next line from the input and return a pointer to a buffer * containing that line. If buf is non-NULL on entry, this call is * identical to fgets(3S); if buf is NULL, the second argument n is * ignored, and the pointer returned points to an allocated buffer * with all of the next line of the file in it, REGARDLESS of length. * * Modification history: * 1/10/94 Matt Bishop original */ #include #include /* * macros */ #define INCREMENT 10 /* allocate this many chars, and */ /* increase space by this many */ /* chars when necessary */ #define NCHAR(n) ((n) * sizeof(char)) /* space for n chars */ /* * chins: insert a character into an array, increasing the size of * the array if necessary by INCREMENT characters * * arguments: int c character to be inserted * int pos position in the array to insert character * char **space points to pointer to array * int *nspace points to integer representing size of array * already allocated * * return: 0 attempt to increase size of array failed, so * the character could not be inserted * 1 character inserted successfully * * output: none * * exceptions: cannot allocate (reallocate) memory (no message, return 0) */ int chins(int c, int pos, char **space, int *nspace) { char *r; /* temp pointer to allocated space */ /* * see if we need more space */ if (pos >= *nspace){ /* yes -- get size of the new allocation */ *nspace += INCREMENT; /* do we allocate or make it grow? */ if (*space == NULL){ /* first time -- allocate */ if ((r = malloc(NCHAR(*nspace))) == NULL) return(0); } else{ /* not the first time -- reallocate */ if ((r = realloc(*space, NCHAR(*nspace))) == NULL) return(0); } /* now update the reserved space parameter */ *space = r; } /* * we have enough space or * we wouldn't be here -- add the char */ (*space)[pos] = c; return(1); } /* * dyngets: read a line from the given file, and return a pointer to * a character array holding it * * arguments: char *buf buffer to put input characters in; if NULL, * dyngets will use (and allocate if necessary) * its own buffer * int n size of array buf; ignored if buf is NULL * FILE *fp pointer to file to be read * * return: char * points to array holding input line: * if buf is non-NULL, this is the same as buf, * and one line (or n-1 chars from that line, * whichever is less) is stored inbuf * if buf is NULL, one line is stored in * allocated space * NULL on EOF or error * * output: dyngets: ran out of room * could not allocate enough space to hold input line * * exceptions: ran out of room (error message and return) */ char *dyngets(char *buf, int n, FILE *fp) { static char *space = NULL; /* internal buffer */ static int nspace = 0; /* size of internal buffer */ int c; /* input character */ int i; /* index of space to put char in */ /* * if we're told where to put the input * let someone else do the work for us! */ if (buf != NULL) return(fgets(buf, n, fp)); /* * read up to the next newline or EOF, * and append it to the current line */ for(i = 0; (c = getc(fp)) != '\n' && c != EOF; i++) if (chins(c, i, &space, &nspace) == 0){ fprintf(stderr, "dyngets: ran out of room\n"); return(NULL); } /* * if EOF is the first character in the line, * you're done; indicate this */ if (c == EOF && i == 0) return(NULL); /* * tack on the newline, if present */ if (c == '\n' && chins('\n', i++, &space, &nspace) == 0){ fprintf(stderr, "dyngets: ran out of room\n"); return(NULL); } /* * tack on the string terminator */ if (chins('\0', i, &space, &nspace) == 0){ fprintf(stderr, "dyngets: ran out of room\n"); return(NULL); } /* * return pointer to internally allocated buffer */ return(space); }