diff options
Diffstat (limited to 'gnu/usr.bin/rcs/lib/rcslex.c')
-rw-r--r-- | gnu/usr.bin/rcs/lib/rcslex.c | 829 |
1 files changed, 572 insertions, 257 deletions
diff --git a/gnu/usr.bin/rcs/lib/rcslex.c b/gnu/usr.bin/rcs/lib/rcslex.c index 621d492..09d41cb 100644 --- a/gnu/usr.bin/rcs/lib/rcslex.c +++ b/gnu/usr.bin/rcs/lib/rcslex.c @@ -1,17 +1,16 @@ -/* - * RCS file input - */ -/********************************************************************************* +/* lexical analysis of RCS files */ + +/****************************************************************************** * Lexical Analysis. * hashtable, Lexinit, nextlex, getlex, getkey, * getid, getnum, readstring, printstring, savestring, * checkid, fatserror, error, faterror, warn, diagnose * Testprogram: define LEXDB - ********************************************************************************* + ****************************************************************************** */ -/* Copyright (C) 1982, 1988, 1989 Walter Tichy - Copyright 1990, 1991 by Paul Eggert +/* Copyright 1982, 1988, 1989 Walter Tichy + Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert Distributed under license by the Free Software Foundation, Inc. This file is part of RCS. @@ -27,8 +26,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with RCS; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +along with RCS; see the file COPYING. +If not, write to the Free Software Foundation, +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Report problems and direct all questions to: @@ -38,13 +38,43 @@ Report problems and direct all questions to: -/* $Log: rcslex.c,v $ - * Revision 1.2 1993/06/28 19:13:10 nate - * Added Chris Demetriou's FSYNC_ALL option which causes all writes to be - * flushed immediately. (In case of a crash in the middle of CVS/RCS commits +/* + * $Log: rcslex.c,v $ + * Revision 5.19 1995/06/16 06:19:24 eggert + * Update FSF address. + * + * Revision 5.18 1995/06/01 16:23:43 eggert + * (map_fd_deallocate,mmap_deallocate,read_deallocate,nothing_to_deallocate): + * New functions. + * (Iclose): If large_memory and maps_memory, use them to deallocate mapping. + * (fd2RILE): Use map_fd if available. + * If one mapping method fails, try the next instead of giving up; + * if they all fail, fall back on ordinary read. + * Work around bug: root mmap over NFS succeeds, but accessing dumps core. + * Use MAP_FAILED macro for mmap failure, and `char *' instead of caddr_t. + * (advise_access): Use madvise only if this instance used mmap. + * (Iopen): Use fdSafer to get safer file descriptor. + * (aflush): Moved here from rcsedit.c. + * + * Revision 5.17 1994/03/20 04:52:58 eggert + * Don't worry if madvise fails. Add Orewind. Remove lint. + * + * Revision 5.16 1993/11/09 17:55:29 eggert + * Fix `label: }' typo. * - * Revision 1.1.1.1 1993/06/18 04:22:12 jkh - * Updated GNU utilities + * Revision 5.15 1993/11/03 17:42:27 eggert + * Improve quality of diagnostics by putting file names in them more often. + * Don't discard ignored phrases. + * + * Revision 5.14 1992/07/28 16:12:44 eggert + * Identifiers may now start with a digit and (unless they are symbolic names) + * may contain `.'. Avoid `unsigned'. Statement macro names now end in _. + * + * Revision 5.13 1992/02/17 23:02:27 eggert + * Work around NFS mmap SIGBUS problem. + * + * Revision 5.12 1992/01/06 02:42:34 eggert + * Use OPEN_O_BINARY if mode contains 'b'. * * Revision 5.11 1991/11/03 03:30:44 eggert * Fix porting bug to ancient hosts lacking vfprintf. @@ -139,7 +169,14 @@ Report problems and direct all questions to: #include "rcsbase.h" -libId(lexId, "$Id: rcslex.c,v 1.2 1993/06/28 19:13:10 nate Exp $") +libId(lexId, "$Id: rcslex.c,v 5.19 1995/06/16 06:19:24 eggert Exp $") + +static char *checkidentifier P((char*,int,int)); +static void errsay P((char const*)); +static void fatsay P((char const*)); +static void lookup P((char const*)); +static void startsay P((const char*,const char*)); +static void warnsay P((char const*)); static struct hshentry *nexthsh; /*pointer to next hash entry, set by lookup*/ @@ -149,7 +186,7 @@ int hshenter; /*if true, next suitable lexeme will be entered */ /*into the symbol table. Handle with care. */ int nextc; /*next input character, initialized by Lexinit */ -unsigned long rcsline; /*current line-number of input */ +long rcsline; /*current line-number of input */ int nerror; /*counter for errors */ int quietflag; /*indicates quiet mode */ RILE * finptr; /*input file descriptor */ @@ -179,9 +216,9 @@ static int ignored_phrases; /* have we ignored phrases in this RCS file? */ void warnignore() { - if (! (ignored_phrases|quietflag)) { + if (!ignored_phrases) { ignored_phrases = true; - warn("Unknown phrases like `%s ...;' are in the RCS file.", NextString); + rcswarn("Unknown phrases like `%s ...;' are present.", NextString); } } @@ -212,7 +249,7 @@ lookup(str) /* empty slot found */ *p = n = ftalloc(struct hshentry); n->num = fstr_save(str); - n->nexthsh = nil; + n->nexthsh = 0; # ifdef LEXDB VOID printf("\nEntered: %s at %u ", str, ihash); # endif @@ -238,7 +275,7 @@ Lexinit() { register int c; for (c = hshsize; 0 <= --c; ) { - hshtab[c] = nil; + hshtab[c] = 0; } nerror = 0; @@ -248,7 +285,7 @@ Lexinit() ignored_phrases = false; rcsline = 1; bufrealloc(&tokbuf, 2); - Iget(finptr, nextc); + Iget_(finptr, nextc) nextlex(); /*initial token*/ } } @@ -295,46 +332,48 @@ nextlex() /* Note: falls into next case */ case SPACE: - GETC(frew, c); + GETC_(frew, c) continue; - case DIGIT: - sp = tokbuf.string; - limit = sp + tokbuf.size; - *sp++ = c; - for (;;) { - GETC(frew, c); - if ((d=ctab[c])!=DIGIT && d!=PERIOD) - break; - *sp++ = c; /* 1.2. and 1.2 are different */ - if (limit <= sp) - sp = bufenlarge(&tokbuf, &limit); - } - *sp = 0; - if (hshenter) - lookup(tokbuf.string); - else - NextString = fstr_save(tokbuf.string); - d = NUM; - break; - - - case LETTER: + case IDCHAR: + case LETTER: case Letter: + d = ID; + /* fall into */ + case DIGIT: + case PERIOD: sp = tokbuf.string; limit = sp + tokbuf.size; *sp++ = c; for (;;) { - GETC(frew, c); - if ((d=ctab[c])!=LETTER && d!=Letter && d!=DIGIT && d!=IDCHAR) + GETC_(frew, c) + switch (ctab[c]) { + case IDCHAR: + case LETTER: + case Letter: + d = ID; + /* fall into */ + case DIGIT: + case PERIOD: + *sp++ = c; + if (limit <= sp) + sp = bufenlarge(&tokbuf, &limit); + continue; + + default: break; - *sp++ = c; - if (limit <= sp) - sp = bufenlarge(&tokbuf, &limit); + } + break; } *sp = 0; + if (d == DIGIT || d == PERIOD) { + d = NUM; + if (hshenter) { + lookup(tokbuf.string); + break; + } + } NextString = fstr_save(tokbuf.string); - d = ID; /* may be ID or keyword */ break; case SBEGIN: /* long string */ @@ -345,7 +384,7 @@ nextlex() case COLON: case SEMI: - GETC(frew, c); + GETC_(frew, c) break; } break; } nextc = c; @@ -381,11 +420,11 @@ eoflex() ++rcsline; /* fall into */ case SPACE: - cachegeteof(c, {uncache(fin);return true;}); + cachegeteof_(c, {uncache(fin);return true;}) break; } if (fout) - aputc(c, fout); + aputc_(c, fout) } } @@ -449,7 +488,7 @@ getkeystring(key) getid() /* Function: Checks if nexttok is an identifier. If so, * advances the input by calling nextlex and returns a pointer - * to the identifier; otherwise returns nil. + * to the identifier; otherwise returns 0. * Treats keywords as identifiers. */ { @@ -458,14 +497,15 @@ getid() name = NextString; nextlex(); return name; - } else return nil; + } else + return 0; } struct hshentry * getnum() /* Function: Checks if nexttok is a number. If so, * advances the input by calling nextlex and returns a pointer - * to the hashtable entry. Otherwise returns nil. + * to the hashtable entry. Otherwise returns 0. * Doesn't work if hshenter is false. */ { @@ -474,46 +514,55 @@ struct hshentry * getnum() num=nexthsh; nextlex(); return num; - } else return nil; + } else + return 0; } struct cbuf getphrases(key) char const *key; -/* Get a series of phrases that do not start with KEY, yield resulting buffer. - * Stop when the next phrase starts with a token that is not an identifier, - * or is KEY. - * Assume !foutptr. - */ +/* +* Get a series of phrases that do not start with KEY. Yield resulting buffer. +* Stop when the next phrase starts with a token that is not an identifier, +* or is KEY. Copy input to foutptr if it is set. Unlike ignorephrases(), +* this routine assumes nextlex() has already been invoked before we start. +*/ { declarecache; register int c; - register char *p; - char const *limit; - register char const *ki, *kn; + register char const *kn; struct cbuf r; - struct buf b; register RILE *fin; + register FILE *frew; +# if large_memory +# define savech_(c) ; +# else + register char *p; + char const *limit; + struct buf b; +# define savech_(c) {if (limit<=p)p=bufenlarge(&b,&limit); *p++ =(c);} +# endif - if (nexttok!=ID || strcmp(NextString,key) == 0) { - r.string = 0; - r.size = 0; - return r; - } else { + if (nexttok!=ID || strcmp(NextString,key) == 0) + clear_buf(&r); + else { warnignore(); fin = finptr; + frew = foutptr; setupcache(fin); cache(fin); - bufautobegin(&b); - bufscpy(&b, NextString); +# if large_memory + r.string = (char const*)cacheptr() - strlen(NextString) - 1; +# else + bufautobegin(&b); + bufscpy(&b, NextString); + p = b.string + strlen(b.string); + limit = b.string + b.size; +# endif ffree1(NextString); - p = b.string + strlen(b.string); - limit = b.string + b.size; c = nextc; for (;;) { for (;;) { - if (limit <= p) - p = bufenlarge(&b, &limit); - *p++ = c; + savech_(c) switch (ctab[c]) { default: fatserror("unknown character `%c'", c); @@ -523,15 +572,13 @@ getphrases(key) /* fall into */ case COLON: case DIGIT: case LETTER: case Letter: case PERIOD: case SPACE: - cacheget(c); + GETC_(frew, c) continue; case SBEGIN: /* long string */ for (;;) { for (;;) { - if (limit <= p) - p = bufenlarge(&b, &limit); - cacheget(c); - *p++ = c; + GETC_(frew, c) + savech_(c) switch (c) { case '\n': ++rcsline; @@ -544,48 +591,50 @@ getphrases(key) } break; } - cacheget(c); + GETC_(frew, c) if (c != SDELIM) break; - if (limit <= p) - p = bufenlarge(&b, &limit); - *p++ = c; + savech_(c) } continue; case SEMI: - cacheget(c); + cacheget_(c) if (ctab[c] == NEWLN) { + if (frew) + aputc_(c, frew) ++rcsline; - if (limit <= p) - p = bufenlarge(&b, &limit); - *p++ = c; - cacheget(c); + savech_(c) + cacheget_(c) } +# if large_memory + r.size = (char const*)cacheptr() - 1 - r.string; +# endif for (;;) { switch (ctab[c]) { case NEWLN: ++rcsline; /* fall into */ case SPACE: - cacheget(c); + cacheget_(c) continue; default: break; } break; } + if (frew) + aputc_(c, frew) break; } break; } - switch (ctab[c]) { - case LETTER: - case Letter: + if (ctab[c] == Letter) { for (kn = key; c && *kn==c; kn++) - cacheget(c); + GETC_(frew, c) if (!*kn) switch (ctab[c]) { case DIGIT: case LETTER: case Letter: + case IDCHAR: case PERIOD: break; default: nextc = c; @@ -594,23 +643,26 @@ getphrases(key) uncache(fin); goto returnit; } - for (ki=key; ki<kn; ) { - if (limit <= p) - p = bufenlarge(&b, &limit); - *p++ = *ki++; - } - break; - - default: +# if !large_memory + { + register char const *ki; + for (ki=key; ki<kn; ) + savech_(*ki++) + } +# endif + } else { nextc = c; uncache(fin); nextlex(); - goto returnit; + break; } } - returnit: - return bufremember(&b, (size_t)(p - b.string)); + returnit:; +# if !large_memory + return bufremember(&b, (size_t)(p - b.string)); +# endif } + return r; } @@ -626,14 +678,14 @@ readstring() fin=finptr; frew=foutptr; setupcache(fin); cache(fin); for (;;) { - GETC(frew, c); + GETC_(frew, c) switch (c) { case '\n': ++rcsline; break; case SDELIM: - GETC(frew, c); + GETC_(frew, c) if (c != SDELIM) { /* end of string */ nextc = c; @@ -660,13 +712,13 @@ printstring() fout = stdout; setupcache(fin); cache(fin); for (;;) { - cacheget(c); + cacheget_(c) switch (c) { case '\n': ++rcsline; break; case SDELIM: - cacheget(c); + cacheget_(c) if (c != SDELIM) { nextc=c; uncache(fin); @@ -674,7 +726,7 @@ printstring() } break; } - aputc(c,fout); + aputc_(c,fout) } } @@ -702,13 +754,13 @@ savestring(target) setupcache(fin); cache(fin); tp = target->string; limit = tp + target->size; for (;;) { - GETC(frew, c); + GETC_(frew, c) switch (c) { case '\n': ++rcsline; break; case SDELIM: - GETC(frew, c); + GETC_(frew, c) if (c != SDELIM) { /* end of string */ nextc=c; @@ -726,44 +778,76 @@ savestring(target) } - char * -checkid(id, delimiter) + static char * +checkidentifier(id, delimiter, dotok) register char *id; int delimiter; + register int dotok; /* Function: check whether the string starting at id is an */ /* identifier and return a pointer to the delimiter*/ /* after the identifier. White space, delim and 0 */ /* are legal delimiters. Aborts the program if not*/ /* a legal identifier. Useful for checking commands*/ /* If !delim, the only delimiter is 0. */ +/* Allow '.' in identifier only if DOTOK is set. */ { - register enum tokens d; register char *temp; - register char c,tc; + register char c; register char delim = delimiter; + int isid = false; temp = id; - if ((d = ctab[(unsigned char)(c = *id)])==LETTER || d==Letter) { - while ((d = ctab[(unsigned char)(c = *++id)])==LETTER - || d==Letter || d==DIGIT || d==IDCHAR - ) - ; - if (c && (!delim || c!=delim && c!=' ' && c!='\t' && c!='\n')) { + for (;; id++) { + switch (ctab[(unsigned char)(c = *id)]) { + case IDCHAR: + case LETTER: + case Letter: + isid = true; + continue; + + case DIGIT: + continue; + + case PERIOD: + if (dotok) + continue; + break; + + default: + break; + } + break; + } + if ( ! isid + || (c && (!delim || (c!=delim && c!=' ' && c!='\t' && c!='\n'))) + ) { /* append \0 to end of id before error message */ - tc = c; - while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ; + while ((c = *id) && c!=' ' && c!='\t' && c!='\n' && c!=delim) + id++; *id = '\0'; - faterror("invalid character %c in identifier `%s'",tc,temp); - } - } else { - /* append \0 to end of id before error message */ - while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ; - *id = '\0'; - faterror("identifier `%s' doesn't start with letter", temp); - } + faterror("invalid %s `%s'", + dotok ? "identifier" : "symbol", temp + ); + } return id; } + char * +checkid(id, delimiter) + char *id; + int delimiter; +{ + return checkidentifier(id, delimiter, true); +} + + char * +checksym(sym, delimiter) + char *sym; + int delimiter; +{ + return checkidentifier(sym, delimiter, false); +} + void checksid(id) char *id; @@ -772,16 +856,92 @@ checksid(id) VOID checkid(id, 0); } + void +checkssym(sym) + char *sym; +{ + VOID checksym(sym, 0); +} + + +#if !large_memory +# define Iclose(f) fclose(f) +#else +# if !maps_memory + static int Iclose P((RILE *)); + static int + Iclose(f) + register RILE *f; + { + tfree(f->base); + f->base = 0; + return fclose(f->stream); + } +# else + static int Iclose P((RILE *)); + static int + Iclose(f) + register RILE *f; + { + (* f->deallocate) (f); + f->base = 0; + return close(f->fd); + } + +# if has_map_fd + static void map_fd_deallocate P((RILE *)); + static void + map_fd_deallocate(f) + register RILE *f; + { + if (vm_deallocate( + task_self(), + (vm_address_t) f->base, + (vm_size_t) (f->lim - f->base) + ) != KERN_SUCCESS) + efaterror("vm_deallocate"); + } +# endif +# if has_mmap + static void mmap_deallocate P((RILE *)); + static void + mmap_deallocate(f) + register RILE *f; + { + if (munmap((char *) f->base, (size_t) (f->lim - f->base)) != 0) + efaterror("munmap"); + } +# endif + static void read_deallocate P((RILE *)); + static void + read_deallocate(f) + RILE *f; + { + tfree(f->base); + } + + static void nothing_to_deallocate P((RILE *)); + static void + nothing_to_deallocate(f) + RILE *f; + { + } +# endif +#endif + +#if large_memory && maps_memory + static RILE *fd2_RILE P((int,char const*,struct stat*)); static RILE * -#if has_mmap && large_memory -fd2_RILE(fd, filename, status) +fd2_RILE(fd, name, status) #else -fd2RILE(fd, filename, mode, status) - char const *mode; + static RILE *fd2RILE P((int,char const*,char const*,struct stat*)); + static RILE * +fd2RILE(fd, name, type, status) + char const *type; #endif int fd; - char const *filename; + char const *name; register struct stat *status; { struct stat st; @@ -789,67 +949,127 @@ fd2RILE(fd, filename, mode, status) if (!status) status = &st; if (fstat(fd, status) != 0) - efaterror(filename); + efaterror(name); if (!S_ISREG(status->st_mode)) { - error("`%s' is not a regular file", filename); + error("`%s' is not a regular file", name); VOID close(fd); errno = EINVAL; return 0; } else { -# if ! (has_mmap && large_memory) +# if !(large_memory && maps_memory) FILE *stream; - if (!(stream = fdopen(fd, mode))) - efaterror(filename); + if (!(stream = fdopen(fd, type))) + efaterror(name); # endif # if !large_memory return stream; # else # define RILES 3 - { - static RILE rilebuf[RILES]; - - register RILE *f; - size_t s = status->st_size; - - if (s != status->st_size) - faterror("`%s' is enormous", filename); - for (f = rilebuf; f->base; f++) - if (f == rilebuf+RILES) - faterror("too many RILEs"); - if (!s) { - static unsigned char dummy; - f->base = &dummy; - } else { -# if has_mmap - if ( - (f->base = (unsigned char *)mmap( - (caddr_t)0, s, PROT_READ, MAP_SHARED, - fd, (off_t)0 - )) == (unsigned char *)-1 - ) - efaterror("mmap"); -# else - f->base = tnalloc(unsigned char, s); + { + static RILE rilebuf[RILES]; + + register RILE *f; + size_t s = status->st_size; + + if (s != status->st_size) + faterror("%s: too large", name); + for (f = rilebuf; f->base; f++) + if (f == rilebuf+RILES) + faterror("too many RILEs"); +# if maps_memory + f->deallocate = nothing_to_deallocate; +# endif + if (!s) { + static unsigned char nothing; + f->base = ¬hing; /* Any nonzero address will do. */ + } else { + f->base = 0; +# if has_map_fd + map_fd( + fd, (vm_offset_t)0, (vm_address_t*) &f->base, + TRUE, (vm_size_t)s + ); + f->deallocate = map_fd_deallocate; +# endif +# if has_mmap + if (!f->base) { + catchmmapints(); + f->base = (unsigned char *) mmap( + (char *)0, s, PROT_READ, MAP_SHARED, + fd, (off_t)0 + ); +# ifndef MAP_FAILED +# define MAP_FAILED (-1) # endif + if (f->base == (unsigned char *) MAP_FAILED) + f->base = 0; + else { +# if has_NFS && mmap_signal + /* + * On many hosts, the superuser + * can mmap an NFS file it can't read. + * So access the first page now, and print + * a nice message if a bus error occurs. + */ + readAccessFilenameBuffer(name, f->base); +# endif + } + f->deallocate = mmap_deallocate; + } +# endif + if (!f->base) { + f->base = tnalloc(unsigned char, s); +# if maps_memory + { + /* + * We can't map the file into memory for some reason. + * Read it into main memory all at once; this is + * the simplest substitute for memory mapping. + */ + char *bufptr = (char *) f->base; + size_t bufsiz = s; + do { + ssize_t r = read(fd, bufptr, bufsiz); + switch (r) { + case -1: + efaterror(name); + + case 0: + /* The file must have shrunk! */ + status->st_size = s -= bufsiz; + bufsiz = 0; + break; + + default: + bufptr += r; + bufsiz -= r; + break; + } + } while (bufsiz); + if (lseek(fd, (off_t)0, SEEK_SET) == -1) + efaterror(name); + f->deallocate = read_deallocate; } - f->ptr = f->base; - f->lim = f->base + s; -# if has_mmap - f->fd = fd; -# else - f->readlim = f->base; - f->stream = stream; # endif - if_advise_access(s, f, MADV_SEQUENTIAL); - return f; + } } + f->ptr = f->base; + f->lim = f->base + s; + f->fd = fd; +# if !maps_memory + f->readlim = f->base; + f->stream = stream; +# endif + if_advise_access(s, f, MADV_SEQUENTIAL); + return f; + } # endif } } -#if !has_mmap && large_memory +#if !maps_memory && large_memory int Igetmore(f) register RILE *f; @@ -875,59 +1095,42 @@ advise_access(f, advice) register RILE *f; int advice; { - if (madvise((caddr_t)f->base, (size_t)(f->lim - f->base), advice) != 0) - efaterror("madvise"); + if (f->deallocate == mmap_deallocate) + VOID madvise((char *)f->base, (size_t)(f->lim - f->base), advice); + /* Don't worry if madvise fails; it's only advisory. */ } #endif RILE * -#if has_mmap && large_memory -I_open(filename, status) +#if large_memory && maps_memory +I_open(name, status) #else -Iopen(filename, mode, status) - char const *mode; +Iopen(name, type, status) + char const *type; #endif - char const *filename; + char const *name; struct stat *status; -/* Open FILENAME for reading, yield its descriptor, and set *STATUS. */ +/* Open NAME for reading, yield its descriptor, and set *STATUS. */ { - int fd; + int fd = fdSafer(open(name, O_RDONLY +# if OPEN_O_BINARY + | (strchr(type,'b') ? OPEN_O_BINARY : 0) +# endif + )); - if ((fd = open(filename,O_RDONLY|O_BINARY)) < 0) + if (fd < 0) return 0; -# if has_mmap && large_memory - return fd2_RILE(fd, filename, status); +# if large_memory && maps_memory + return fd2_RILE(fd, name, status); # else - return fd2RILE(fd, filename, mode, status); + return fd2RILE(fd, name, type, status); # endif } -#if !large_memory -# define Iclose(f) fclose(f) -#else - static int - Iclose(f) - register RILE *f; - { -# if has_mmap - size_t s = f->lim - f->base; - if (s && munmap((caddr_t)f->base, s) != 0) - return -1; - f->base = 0; - return close(f->fd); -# else - tfree(f->base); - f->base = 0; - return fclose(f->stream); -# endif - } -#endif - - static int Oerrloop; - exiting void + void Oerror() { if (Oerrloop) @@ -936,19 +1139,13 @@ Oerror() efaterror("output error"); } -exiting void Ieof() { fatserror("unexpected end of file"); } -exiting void Ierror() { efaterror("input error"); } +void Ieof() { fatserror("unexpected end of file"); } +void Ierror() { efaterror("input error"); } void testIerror(f) FILE *f; { if (ferror(f)) Ierror(); } void testOerror(o) FILE *o; { if (ferror(o)) Oerror(); } void Ifclose(f) RILE *f; { if (f && Iclose(f)!=0) Ierror(); } -#ifndef FSYNC_ALL void Ofclose(f) FILE *f; { if (f && fclose(f)!=0) Oerror(); } -#else -void Ofclose(f) FILE *f; { if (f && (fflush(f)!=0 || - fsync(fileno(f))!=0 || - fclose(f)!=0)) Oerror(); } -#endif void Izclose(p) RILE **p; { Ifclose(*p); *p = 0; } void Ozclose(p) FILE **p; { Ofclose(*p); *p = 0; } @@ -964,19 +1161,17 @@ testIeof(f) void Irewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Ierror(); } #endif -void eflush() -{ - if (fflush(stderr) != 0 && !Oerrloop) - Oerror(); -} +void Orewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Oerror(); } +void aflush(f) FILE *f; { if (fflush(f) != 0) Oerror(); } +void eflush() { if (fflush(stderr)!=0 && !Oerrloop) Oerror(); } void oflush() { if (fflush(workstdout ? workstdout : stdout) != 0 && !Oerrloop) Oerror(); } - static exiting void + void fatcleanup(already_newline) int already_newline; { @@ -984,8 +1179,38 @@ fatcleanup(already_newline) exiterr(); } -static void errsay() { oflush(); aprintf(stderr,"%s error: ",cmdid); nerror++; } -static void fatsay() { oflush(); VOID fprintf(stderr,"%s error: ",cmdid); } + static void +startsay(s, t) + const char *s, *t; +{ + oflush(); + if (s) + aprintf(stderr, "%s: %s: %s", cmdid, s, t); + else + aprintf(stderr, "%s: %s", cmdid, t); +} + + static void +fatsay(s) + char const *s; +{ + startsay(s, ""); +} + + static void +errsay(s) + char const *s; +{ + fatsay(s); + nerror++; +} + + static void +warnsay(s) + char const *s; +{ + startsay(s, "warning: "); +} void eerror(s) char const *s; { enerror(errno,s); } @@ -994,20 +1219,20 @@ enerror(e,s) int e; char const *s; { - errsay(); + errsay((char const*)0); errno = e; perror(s); eflush(); } -exiting void efaterror(s) char const *s; { enfaterror(errno,s); } +void efaterror(s) char const *s; { enfaterror(errno,s); } - exiting void + void enfaterror(e,s) int e; char const *s; { - fatsay(); + fatsay((char const*)0); errno = e; perror(s); fatcleanup(true); @@ -1022,7 +1247,41 @@ error(char const *format,...) /* non-fatal error */ { va_list args; - errsay(); + errsay((char const*)0); + vararg_start(args, format); + fvfprintf(stderr, format, args); + va_end(args); + afputc('\n',stderr); + eflush(); +} + +#if has_prototypes + void +rcserror(char const *format,...) +#else + /*VARARGS1*/ void rcserror(format, va_alist) char const *format; va_dcl +#endif +/* non-fatal RCS file error */ +{ + va_list args; + errsay(RCSname); + vararg_start(args, format); + fvfprintf(stderr, format, args); + va_end(args); + afputc('\n',stderr); + eflush(); +} + +#if has_prototypes + void +workerror(char const *format,...) +#else + /*VARARGS1*/ void workerror(format, va_alist) char const *format; va_dcl +#endif +/* non-fatal working file error */ +{ + va_list args; + errsay(workname); vararg_start(args, format); fvfprintf(stderr, format, args); va_end(args); @@ -1031,17 +1290,17 @@ error(char const *format,...) } #if has_prototypes - exiting void + void fatserror(char const *format,...) #else - /*VARARGS1*/ exiting void + /*VARARGS1*/ void fatserror(format, va_alist) char const *format; va_dcl #endif -/* fatal syntax error */ +/* fatal RCS file syntax error */ { va_list args; oflush(); - VOID fprintf(stderr, "%s: %s:%lu: ", cmdid, RCSfilename, rcsline); + VOID fprintf(stderr, "%s: %s:%ld: ", cmdid, RCSname, rcsline); vararg_start(args, format); fvfprintf(stderr, format, args); va_end(args); @@ -1049,16 +1308,16 @@ fatserror(char const *format,...) } #if has_prototypes - exiting void + void faterror(char const *format,...) #else - /*VARARGS1*/ exiting void faterror(format, va_alist) + /*VARARGS1*/ void faterror(format, va_alist) char const *format; va_dcl #endif /* fatal error, terminates program after cleanup */ { va_list args; - fatsay(); + fatsay((char const*)0); vararg_start(args, format); fvfprintf(stderr, format, args); va_end(args); @@ -1067,20 +1326,76 @@ faterror(char const *format,...) #if has_prototypes void -warn(char const *format,...) +rcsfaterror(char const *format,...) #else - /*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl + /*VARARGS1*/ void rcsfaterror(format, va_alist) + char const *format; va_dcl #endif -/* prints a warning message */ +/* fatal RCS file error, terminates program after cleanup */ { va_list args; - oflush(); - aprintf(stderr,"%s warning: ",cmdid); + fatsay(RCSname); vararg_start(args, format); fvfprintf(stderr, format, args); va_end(args); - afputc('\n',stderr); - eflush(); + fatcleanup(false); +} + +#if has_prototypes + void +warn(char const *format,...) +#else + /*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl +#endif +/* warning */ +{ + va_list args; + if (!quietflag) { + warnsay((char *)0); + vararg_start(args, format); + fvfprintf(stderr, format, args); + va_end(args); + afputc('\n', stderr); + eflush(); + } +} + +#if has_prototypes + void +rcswarn(char const *format,...) +#else + /*VARARGS1*/ void rcswarn(format, va_alist) char const *format; va_dcl +#endif +/* RCS file warning */ +{ + va_list args; + if (!quietflag) { + warnsay(RCSname); + vararg_start(args, format); + fvfprintf(stderr, format, args); + va_end(args); + afputc('\n', stderr); + eflush(); + } +} + +#if has_prototypes + void +workwarn(char const *format,...) +#else + /*VARARGS1*/ void workwarn(format, va_alist) char const *format; va_dcl +#endif +/* working file warning */ +{ + va_list args; + if (!quietflag) { + warnsay(workname); + vararg_start(args, format); + fvfprintf(stderr, format, args); + va_end(args); + afputc('\n', stderr); + eflush(); + } } void @@ -1115,12 +1430,11 @@ diagnose(char const *format,...) void afputc(c, f) -/* Function: afputc(c,f) acts like aputc(c,f), but is smaller and slower. - */ +/* afputc(c,f); acts like aputc_(c,f) but is smaller and slower. */ int c; register FILE *f; { - aputc(c,f); + aputc_(c,f) } @@ -1151,6 +1465,7 @@ fvfprintf(FILE *stream, char const *format, va_list args) { #if has_vfprintf if (vfprintf(stream, format, args) < 0) + Oerror(); #else # if has__doprintf _doprintf(stream, format, args); @@ -1166,8 +1481,8 @@ fvfprintf(FILE *stream, char const *format, va_list args) # endif # endif if (ferror(stream)) -#endif Oerror(); +#endif } #if has_prototypes @@ -1248,7 +1563,7 @@ int argc; char * argv[]; exitmain(EXIT_SUCCESS); } -exiting void exiterr() { _exit(EXIT_FAILURE); } +void exiterr() { _exit(EXIT_FAILURE); } #endif |