home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff319.lzh
/
CNewsSrc
/
cnews.src.lzh
/
libc
/
fgetmfs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-07-15
|
3KB
|
138 lines
/*
* fgetmfs - read an arbitrarily long, possibly continued line;
* return a pointer to it, in malloced memory.
*/
#include <stdio.h>
#include <ctype.h>
#ifndef AMIGA
# include <sys/types.h>
#endif /* AMIGA */
#include "fgetmfs.h"
#include "libc.h"
#ifndef max
# define max(a,b) ((a) > (b)? (a): (b))
# define min(a,b) ((a) < (b)? (a): (b))
#endif /* max */
/* One could make these arguments, with defaults. */
#define INITLN 90 /* initial allocation per line */
#define GROWLN 200 /* additional allocation size */
/* getseg returns */
#define FAILED 0
#define HITLIMIT 1
#define OKAY 2
static unsigned sz; /* bytes currently allocated (in line) */
static int incr; /* for sz */
static char *line; /* current allocation */
static char *segment; /* start of line segment in "line" */
static char *morep; /* last byte possibly containing input */
/*
* `fget malloced, flagged string' with continuations and limit on bytes.
* The limit is like fgets's; limit-1 bytes can be read.
* -1 means "no limit".
*/
char *fgetmfs(fp, limit, cont)
FILE *fp;
register int limit, cont; /* honour \ continuations? */
{
/* allocate room for an initial segment of a line */
sz = INITLN;
incr = GROWLN;
if (limit >= 0 && sz > limit)
sz = limit;
line = malloc(sz);
if (line == NULL)
return NULL; /* no memory, can't go on */
segment = line;
morep = line + sz - 2;
/* read all lines, including continuations */
do {
/* read the first segment of a line */
*morep = '\0'; /* mark end of segment */
if (fgets(segment, (int)sz-(segment-line), fp) == NULL) {
fprintf(stderr, "bytes read: '%.*s'\n",
(int)sz - (segment - line), segment);
free(line); /* EOF: give up */
return NULL;
}
/* read more of this line, if it didn't fit */
while (*morep != '\0' && *morep != '\n') {
register int code = getseg(fp, limit);
if (code == FAILED)
return NULL;
else if (code == HITLIMIT)
break;
}
} while (cont && ismore(fp, cont));
return realloc(line, (unsigned)(strlen(line)+1)); /* save space */
}
static int getseg(fp, limit)
FILE *fp;
register int limit;
{
register int oldsz = sz;
/* extend the allocation, within limit */
incr = GROWLN;
sz += incr;
if (limit >= 0 && sz > limit) {
sz = limit;
incr = sz - oldsz;
}
if (incr <= 0) /* hit the limit? */
return HITLIMIT;
line = realloc(line, sz);
if (line == NULL)
return FAILED; /* no memory, can't go on */
/* -1 starts on the terminating NUL of the prev. segment */
segment = line + oldsz - 1;
morep = line + sz - 2; /* recompute for new line, sz */
/* read the next segment */
*morep = '\0';
/* +1 because segment includes terminating NUL of the prev. segment */
if (fgets(segment, incr+1, fp) == NULL) {
free(line); /* EOF: give up */
return FAILED;
}
return OKAY;
}
static int
ismore(fp, cont)
register FILE *fp;
int cont;
{
register char *nlp;
/* got a whole line: is it to be continued? */
if (incr > 0 && cont && (nlp = rindex(line, '\n')) != NULL &&
nlp > line && *--nlp == '\\') {
*nlp = '\0'; /* delete "\\\n" */
segment = nlp;
if (cont == CONT_NOSPC) {
register int c;
/* discard leading whitespace */
while ((c = getc(fp)) != EOF && c != '\n' &&
isascii(c) && isspace(c))
;
if (c != EOF)
(void) ungetc(c, fp);
}
return 1; /* read next line */
} else
return 0;
}