v03i018: getline -- get a long line
David Collier-Brown
daveb at geac.UUCP
Tue May 17 01:23:12 AEST 1988
comp.sources.misc: Volume 3, Issue 18
Submitted-By: "David Collier-Brown" <daveb at geac.UUCP>
Archive-Name: getline
The following is a function to get a long (possibly arbitrarily
long) line from a stream. I've written it twice, so I guess it may
be useful to others.
Tested ONLY on a Vax-Ultrix machine, so beware of machine
dependencies that got by my jaundiced eye.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: getline.c Makefile getline.1
# Wrapped by daveb at geac on Mon May 16 11:00:49 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f getline.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"getline.c\"
else
echo shar: Extracting \"getline.c\" \(1777 characters\)
sed "s/^X//" >getline.c <<'END_OF_getline.c'
X/*
X * getline.c -- get a line into a variable-size cache. Otherwise the
X * behavior is identical to fgets.
X */
X#include <stdio.h>
X
X#define BADEXIT 3 /* Nonzero is sufficent. 3 implies badness. */
X#define INITIAL_CHUNK 60 /* Purely a heuristic value. */
X#define CHUNKSIZE 10
X
X/*
X * getline -- actually get the line. Behaves as expected on an eof
X * at the beginning of a line or at end of file. Dependant on
X * the behavior of fgets as to what happens when an EOF is entered
X * from a terminal in the middle of a line. Under Ultrix/Berkley
X * TTY handling, the ^D seems to disappear...
X */
X char *
Xgetline(fp) FILE *fp; {
X extern char *realloc(), *malloc();
X extern char *lastCharacter();
X extern void exit();
X static char *cache = NULL;
X static int cacheSize = 0;
X
X if (cache == NULL) {
X /* Its the first time... */
X if ((cache= malloc(INITIAL_CHUNK)) == NULL) {
X (void) fprintf(stderr,"getline ran out of space (can't happen)\n");
X exit(BADEXIT);
X }
X cacheSize = INITIAL_CHUNK;
X }
X
X /* For all cases... */
X if (fgets(cache,cacheSize,fp) == NULL) {
X /* We hit an eof in the last line. */
X return NULL;
X }
X while (*lastCharacter(cache) != '\n') {
X /* We have to read some more... */
X if ((cache= realloc(cache,(unsigned)cacheSize+CHUNKSIZE)) == NULL) {
X (void) fprintf(stderr,"getline ran out of space: line longer than available memory\n");
X exit(BADEXIT);
X }
X if (fgets(&cache[cacheSize-1],CHUNKSIZE+1,fp) == NULL) {
X cacheSize += CHUNKSIZE;
X return cache;
X }
X else {
X cacheSize += CHUNKSIZE;
X }
X }
X /* We've got a line ending in \n... */
X return cache;
X}
X
X
X static char *
XlastCharacter(p) char *p; {
X while (p[1] != '\0')
X p++;
X return p;
X }
X
X#ifdef TEST
Xmain() {
X char *p;
X
X while ((p=getline(stdin)) != NULL)
X fputs(p,stdout);
X}
X#endif
X
END_OF_getline.c
if test 1777 -ne `wc -c <getline.c`; then
echo shar: \"getline.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(864 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# getline -- a getline to go with fgets
X#
X# BINDIR is where to put the executable.
X# MANDIR is where the manual pages go, and MANEXT is the extension.
X# for the man pages, e.g., getline.1 or getline.l or getline.m.
X
XBINDIR = /usr/local -- watch out!
XMANDIR = /usr/man/manl
XMANEXT = l
X
X# These should all just be right if the above ones are.
XDIRNAME = $(BINDIR)/getline
XDIRNAME_M = $(MANDIR)/getline.$(MANEXT)
XLDFLAGS =
XCFLAGS = -g -DTEST
X
Xgetline: getline.c
X $(CC) $(CFLAGS) $(LDFLAGS) -o getline getline.c
X @-size getline
X
Xinstall: $(DIRNAME_M)
X
X$(DIRNAME): getline.c
X $(CC) $(LDFLAGS) -o getline getline.c
X install -c -m 755 getline $(DIRNAME)
X
X$(DIRNAME_M): getline.1
X cp getline.1 $(DIRNAME_M)
X chmod 644 $(DIRNAME_M)
X
X
X
Xlint:
X lint getline.c
Xtags:
X ctags -w getline.c
Xgetline.shar:
X shar getline.c Makefile getline.1 > getline.shar
Xclean:
X rm -f a.out core *.o getline
END_OF_Makefile
if test 864 -ne `wc -c <Makefile`; then
echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f getline.1 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"getline.1\"
else
echo shar: Extracting \"getline.1\" \(873 characters\)
sed "s/^X//" >getline.1 <<'END_OF_getline.1'
X.TH getline 1,local
X.SH NAME
Xgetline \- get a line of near-arbitrary length from a stream.
X.SH SYNTAX
X.nf
X#include <stdio.h>
X
Xchar *getline(stream)
XFILE *stream;
X.fi
X
X.SH DESCRIPTION
XThe
X.B getline
Xroutine reads up to a newline character from the stream
Xinto an internal cache of arbitrary size. The last character read
Xis followed by a null character. The getline routine returns
Xits first argument or NULL on end of file or error.
X
X.SH DIAGNOSTICS
XIf a line longer than available memory is read, the program exits
Xwith a message. This is expected to be a rare event.
X
X.SH "SEE ALSO"
Xferror(3s), fread(3s), getc(3s), puts(3s), scanf(3s), fgets(3).
X
X.SH BUGS
XStrictly dependant on the behavior of fgets: treats a ^D (eof) in
Xmid-stream from a terminal as does fgets (ie, it disappears silently
Xunder Ultrix/Berzerkley)
X.PP
XWritten by Dave (instakludge) Collier-Brown.
END_OF_getline.1
if test 873 -ne `wc -c <getline.1`; then
echo shar: \"getline.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
--
David Collier-Brown. {mnetor yunexus utgpu}!geac!daveb
Geac Computers Ltd., | "His Majesty made you a major
350 Steelcase Road, | because he believed you would
Markham, Ontario. | know when not to obey his orders"
More information about the Comp.sources.misc
mailing list