diff options
Diffstat (limited to 'gnu/usr.bin/rcs/lib/rcslex.c')
-rw-r--r-- | gnu/usr.bin/rcs/lib/rcslex.c | 1568 |
1 files changed, 0 insertions, 1568 deletions
diff --git a/gnu/usr.bin/rcs/lib/rcslex.c b/gnu/usr.bin/rcs/lib/rcslex.c deleted file mode 100644 index 7a11f79..0000000 --- a/gnu/usr.bin/rcs/lib/rcslex.c +++ /dev/null @@ -1,1568 +0,0 @@ -/* 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 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. - -RCS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -RCS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -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, -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Report problems and direct all questions to: - - rcs-bugs@cs.purdue.edu - -*/ - - - -/* - * 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 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. - * - * Revision 5.10 1991/10/07 17:32:46 eggert - * Support piece tables even if !has_mmap. - * - * Revision 5.9 1991/09/24 00:28:42 eggert - * Don't export errsay(). - * - * Revision 5.8 1991/08/19 03:13:55 eggert - * Add eoflex(), mmap support. Tune. - * - * Revision 5.7 1991/04/21 11:58:26 eggert - * Add MS-DOS support. - * - * Revision 5.6 1991/02/25 07:12:42 eggert - * Work around fputs bug. strsave -> str_save (DG/UX name clash) - * - * Revision 5.5 1990/12/04 05:18:47 eggert - * Use -I for prompts and -q for diagnostics. - * - * Revision 5.4 1990/11/19 20:05:28 hammer - * no longer gives warning about unknown keywords if -q is specified - * - * Revision 5.3 1990/11/01 05:03:48 eggert - * When ignoring unknown phrases, copy them to the output RCS file. - * - * Revision 5.2 1990/09/04 08:02:27 eggert - * Count RCS lines better. - * - * Revision 5.1 1990/08/29 07:14:03 eggert - * Work around buggy compilers with defective argument promotion. - * - * Revision 5.0 1990/08/22 08:12:55 eggert - * Remove compile-time limits; use malloc instead. - * Report errno-related errors with perror(). - * Ansify and Posixate. Add support for ISO 8859. - * Use better hash function. - * - * Revision 4.6 89/05/01 15:13:07 narten - * changed copyright header to reflect current distribution rules - * - * Revision 4.5 88/08/28 15:01:12 eggert - * Don't loop when writing error messages to a full filesystem. - * Flush stderr/stdout when mixing output. - * Yield exit status compatible with diff(1). - * Shrink stdio code size; allow cc -R; remove lint. - * - * Revision 4.4 87/12/18 11:44:47 narten - * fixed to use "varargs" in "fprintf"; this is required if it is to - * work on a SPARC machine such as a Sun-4 - * - * Revision 4.3 87/10/18 10:37:18 narten - * Updating version numbers. Changes relative to 1.1 actually relative - * to version 4.1 - * - * Revision 1.3 87/09/24 14:00:17 narten - * Sources now pass through lint (if you ignore printf/sprintf/fprintf - * warnings) - * - * Revision 1.2 87/03/27 14:22:33 jenkins - * Port to suns - * - * Revision 4.1 83/03/25 18:12:51 wft - * Only changed $Header to $Id. - * - * Revision 3.3 82/12/10 16:22:37 wft - * Improved error messages, changed exit status on error to 1. - * - * Revision 3.2 82/11/28 21:27:10 wft - * Renamed ctab to map and included EOFILE; ctab is now a macro in rcsbase.h. - * Added fflsbuf(), fputs(), and fprintf(), which abort the RCS operations - * properly in case there is an IO-error (e.g., file system full). - * - * Revision 3.1 82/10/11 19:43:56 wft - * removed unused label out:; - * made sure all calls to getc() return into an integer, not a char. - */ - - -/* -#define LEXDB -*/ -/* version LEXDB is for testing the lexical analyzer. The testprogram - * reads a stream of lexemes, enters the revision numbers into the - * hashtable, and prints the recognized tokens. Keywords are recognized - * as identifiers. - */ - - - -#include "rcsbase.h" - -libId(lexId, "$FreeBSD$") - -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*/ - -enum tokens nexttok; /*next token, set by nextlex */ - -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 */ - -long rcsline; /*current line-number of input */ -int nerror; /*counter for errors */ -int quietflag; /*indicates quiet mode */ -RILE * finptr; /*input file descriptor */ - -FILE * frewrite; /*file descriptor for echoing input */ - -FILE * foutptr; /* copy of frewrite, but 0 to suppress echo */ - -static struct buf tokbuf; /* token buffer */ - -char const * NextString; /* next token */ - -/* - * Our hash algorithm is h[0] = 0, h[i+1] = 4*h[i] + c, - * so hshsize should be odd. - * See B J McKenzie, R Harries & T Bell, Selecting a hashing algorithm, - * Software--practice & experience 20, 2 (Feb 1990), 209-224. - */ -#ifndef hshsize -# define hshsize 511 -#endif - -static struct hshentry *hshtab[hshsize]; /*hashtable */ - -static int ignored_phrases; /* have we ignored phrases in this RCS file? */ - - void -warnignore() -{ - if (!ignored_phrases) { - ignored_phrases = true; - rcswarn("Unknown phrases like `%s ...;' are present.", NextString); - } -} - - - - static void -lookup(str) - char const *str; -/* Function: Looks up the character string pointed to by str in the - * hashtable. If the string is not present, a new entry for it is created. - * In any case, the address of the corresponding hashtable entry is placed - * into nexthsh. - */ -{ - register unsigned ihash; /* index into hashtable */ - register char const *sp; - register struct hshentry *n, **p; - - /* calculate hash code */ - sp = str; - ihash = 0; - while (*sp) - ihash = (ihash<<2) + *sp++; - ihash %= hshsize; - - for (p = &hshtab[ihash]; ; p = &n->nexthsh) - if (!(n = *p)) { - /* empty slot found */ - *p = n = ftalloc(struct hshentry); - n->num = fstr_save(str); - n->nexthsh = 0; -# ifdef LEXDB - VOID printf("\nEntered: %s at %u ", str, ihash); -# endif - break; - } else if (strcmp(str, n->num) == 0) - /* match found */ - break; - nexthsh = n; - NextString = n->num; -} - - - - - - - void -Lexinit() -/* Function: Initialization of lexical analyzer: - * initializes the hashtable, - * initializes nextc, nexttok if finptr != 0 - */ -{ register int c; - - for (c = hshsize; 0 <= --c; ) { - hshtab[c] = 0; - } - - nerror = 0; - if (finptr) { - foutptr = 0; - hshenter = true; - ignored_phrases = false; - rcsline = 1; - bufrealloc(&tokbuf, 2); - Iget_(finptr, nextc) - nextlex(); /*initial token*/ - } -} - - - - - - - - void -nextlex() - -/* Function: Reads the next token and sets nexttok to the next token code. - * Only if hshenter is set, a revision number is entered into the - * hashtable and a pointer to it is placed into nexthsh. - * This is useful for avoiding that dates are placed into the hashtable. - * For ID's and NUM's, NextString is set to the character string. - * Assumption: nextc contains the next character. - */ -{ register c; - declarecache; - register FILE *frew; - register char * sp; - char const *limit; - register enum tokens d; - register RILE *fin; - - fin=finptr; frew=foutptr; - setupcache(fin); cache(fin); - c = nextc; - - for (;;) { switch ((d = ctab[c])) { - - default: - fatserror("unknown character `%c'", c); - /*NOTREACHED*/ - - case NEWLN: - ++rcsline; -# ifdef LEXDB - afputc('\n',stdout); -# endif - /* Note: falls into next case */ - - case SPACE: - GETC_(frew, c) - continue; - - 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) - 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; - } - break; - } - *sp = 0; - if (d == DIGIT || d == PERIOD) { - d = NUM; - if (hshenter) { - lookup(tokbuf.string); - break; - } - } - NextString = fstr_save(tokbuf.string); - break; - - case SBEGIN: /* long string */ - d = STRING; - /* note: only the initial SBEGIN has been read*/ - /* read the string, and reset nextc afterwards*/ - break; - - case COLON: - case SEMI: - GETC_(frew, c) - break; - } break; } - nextc = c; - nexttok = d; - uncache(fin); -} - - int -eoflex() -/* - * Yield true if we look ahead to the end of the input, false otherwise. - * nextc becomes undefined at end of file. - */ -{ - register int c; - declarecache; - register FILE *fout; - register RILE *fin; - - c = nextc; - fin = finptr; - fout = foutptr; - setupcache(fin); cache(fin); - - for (;;) { - switch (ctab[c]) { - default: - nextc = c; - uncache(fin); - return false; - - case NEWLN: - ++rcsline; - /* fall into */ - case SPACE: - cachegeteof_(c, {uncache(fin);return true;}) - break; - } - if (fout) - aputc_(c, fout) - } -} - - -int getlex(token) -enum tokens token; -/* Function: Checks if nexttok is the same as token. If so, - * advances the input by calling nextlex and returns true. - * otherwise returns false. - * Doesn't work for strings and keywords; loses the character string for ids. - */ -{ - if (nexttok==token) { - nextlex(); - return(true); - } else return(false); -} - - int -getkeyopt(key) - char const *key; -/* Function: If the current token is a keyword identical to key, - * advances the input by calling nextlex and returns true; - * otherwise returns false. - */ -{ - if (nexttok==ID && strcmp(key,NextString) == 0) { - /* match found */ - ffree1(NextString); - nextlex(); - return(true); - } - return(false); -} - - void -getkey(key) - char const *key; -/* Check that the current input token is a keyword identical to key, - * and advance the input by calling nextlex. - */ -{ - if (!getkeyopt(key)) - fatserror("missing '%s' keyword", key); -} - - void -getkeystring(key) - char const *key; -/* Check that the current input token is a keyword identical to key, - * and advance the input by calling nextlex; then look ahead for a string. - */ -{ - getkey(key); - if (nexttok != STRING) - fatserror("missing string after '%s' keyword", key); -} - - - char const * -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 0. - * Treats keywords as identifiers. - */ -{ - register char const *name; - if (nexttok==ID) { - name = NextString; - nextlex(); - return name; - } 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 0. - * Doesn't work if hshenter is false. - */ -{ - register struct hshentry * num; - if (nexttok==NUM) { - num=nexthsh; - nextlex(); - return num; - } 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. 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 const *kn; - struct cbuf r; - 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) - clear_buf(&r); - else { - warnignore(); - fin = finptr; - frew = foutptr; - setupcache(fin); cache(fin); -# 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); - c = nextc; - for (;;) { - for (;;) { - savech_(c) - switch (ctab[c]) { - default: - fatserror("unknown character `%c'", c); - /*NOTREACHED*/ - case NEWLN: - ++rcsline; - /* fall into */ - case COLON: case DIGIT: case LETTER: case Letter: - case PERIOD: case SPACE: - GETC_(frew, c) - continue; - case SBEGIN: /* long string */ - for (;;) { - for (;;) { - GETC_(frew, c) - savech_(c) - switch (c) { - case '\n': - ++rcsline; - /* fall into */ - default: - continue; - - case SDELIM: - break; - } - break; - } - GETC_(frew, c) - if (c != SDELIM) - break; - savech_(c) - } - continue; - case SEMI: - cacheget_(c) - if (ctab[c] == NEWLN) { - if (frew) - aputc_(c, frew) - ++rcsline; - 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) - continue; - - default: break; - } - break; - } - if (frew) - aputc_(c, frew) - break; - } - break; - } - if (ctab[c] == Letter) { - for (kn = key; c && *kn==c; kn++) - GETC_(frew, c) - if (!*kn) - switch (ctab[c]) { - case DIGIT: case LETTER: case Letter: - case IDCHAR: case PERIOD: - break; - default: - nextc = c; - NextString = fstr_save(key); - nexttok = ID; - uncache(fin); - goto returnit; - } -# if !large_memory - { - register char const *ki; - for (ki=key; ki<kn; ) - savech_(*ki++) - } -# endif - } else { - nextc = c; - uncache(fin); - nextlex(); - break; - } - } - returnit:; -# if !large_memory - return bufremember(&b, (size_t)(p - b.string)); -# endif - } - return r; -} - - - void -readstring() -/* skip over characters until terminating single SDELIM */ -/* If foutptr is set, copy every character read to foutptr. */ -/* Does not advance nextlex at the end. */ -{ register c; - declarecache; - register FILE *frew; - register RILE *fin; - fin=finptr; frew=foutptr; - setupcache(fin); cache(fin); - for (;;) { - GETC_(frew, c) - switch (c) { - case '\n': - ++rcsline; - break; - - case SDELIM: - GETC_(frew, c) - if (c != SDELIM) { - /* end of string */ - nextc = c; - uncache(fin); - return; - } - break; - } - } -} - - - void -printstring() -/* Function: copy a string to stdout, until terminated with a single SDELIM. - * Does not advance nextlex at the end. - */ -{ - register c; - declarecache; - register FILE *fout; - register RILE *fin; - fin=finptr; - fout = stdout; - setupcache(fin); cache(fin); - for (;;) { - cacheget_(c) - switch (c) { - case '\n': - ++rcsline; - break; - case SDELIM: - cacheget_(c) - if (c != SDELIM) { - nextc=c; - uncache(fin); - return; - } - break; - } - aputc_(c,fout) - } -} - - - - struct cbuf -savestring(target) - struct buf *target; -/* Copies a string terminated with SDELIM from file finptr to buffer target. - * Double SDELIM is replaced with SDELIM. - * If foutptr is set, the string is also copied unchanged to foutptr. - * Does not advance nextlex at the end. - * Yield a copy of *TARGET, except with exact length. - */ -{ - register c; - declarecache; - register FILE *frew; - register char *tp; - register RILE *fin; - char const *limit; - struct cbuf r; - - fin=finptr; frew=foutptr; - setupcache(fin); cache(fin); - tp = target->string; limit = tp + target->size; - for (;;) { - GETC_(frew, c) - switch (c) { - case '\n': - ++rcsline; - break; - case SDELIM: - GETC_(frew, c) - if (c != SDELIM) { - /* end of string */ - nextc=c; - r.string = target->string; - r.size = tp - r.string; - uncache(fin); - return r; - } - break; - } - if (tp == limit) - tp = bufenlarge(target, &limit); - *tp++ = c; - } -} - - - 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 char *temp; - register char c; - register char delim = delimiter; - int isid = false; - - temp = id; - 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 */ - while ((c = *id) && c!=' ' && c!='\t' && c!='\n' && c!=delim) - id++; - *id = '\0'; - 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; -/* Check whether the string ID is an identifier. */ -{ - 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 * -fd2_RILE(fd, name, status) -#else - 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 *name; - register struct stat *status; -{ - struct stat st; - - if (!status) - status = &st; - if (fstat(fd, status) != 0) - efaterror(name); - if (!S_ISREG(status->st_mode)) { - error("`%s' is not a regular file", name); - VOID close(fd); - errno = EINVAL; - return 0; - } else { - -# if !(large_memory && maps_memory) - FILE *stream; - 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: 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; - } -# endif - } - } - 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 !maps_memory && large_memory - int -Igetmore(f) - register RILE *f; -{ - register fread_type r; - register size_t s = f->lim - f->readlim; - - if (BUFSIZ < s) - s = BUFSIZ; - if (!(r = Fread(f->readlim, sizeof(*f->readlim), s, f->stream))) { - testIerror(f->stream); - f->lim = f->readlim; /* The file might have shrunk! */ - return 0; - } - f->readlim += r; - return 1; -} -#endif - -#if has_madvise && has_mmap && large_memory - void -advise_access(f, advice) - register RILE *f; - int advice; -{ - 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 large_memory && maps_memory -I_open(name, status) -#else -Iopen(name, type, status) - char const *type; -#endif - char const *name; - struct stat *status; -/* Open NAME for reading, yield its descriptor, and set *STATUS. */ -{ - int fd = fdSafer(open(name, O_RDONLY -# if OPEN_O_BINARY - | (strchr(type,'b') ? OPEN_O_BINARY : 0) -# endif - )); - - if (fd < 0) - return 0; -# if large_memory && maps_memory - return fd2_RILE(fd, name, status); -# else - return fd2RILE(fd, name, type, status); -# endif -} - - -static int Oerrloop; - - void -Oerror() -{ - if (Oerrloop) - exiterr(); - Oerrloop = true; - efaterror("output 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(); } -void Ofclose(f) FILE *f; { if (f && fclose(f)!=0) Oerror(); } -void Izclose(p) RILE **p; { Ifclose(*p); *p = 0; } -void Ozclose(p) FILE **p; { Ofclose(*p); *p = 0; } - -#if !large_memory - void -testIeof(f) - FILE *f; -{ - testIerror(f); - if (feof(f)) - Ieof(); -} -void Irewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Ierror(); } -#endif - -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(); -} - - void -fatcleanup(already_newline) - int already_newline; -{ - VOID fprintf(stderr, already_newline+"\n%s aborted\n", cmdid); - exiterr(); -} - - 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); } - - void -enerror(e,s) - int e; - char const *s; -{ - errsay((char const*)0); - errno = e; - perror(s); - eflush(); -} - -void efaterror(s) char const *s; { enfaterror(errno,s); } - - void -enfaterror(e,s) - int e; - char const *s; -{ - fatsay((char const*)0); - errno = e; - perror(s); - fatcleanup(true); -} - -#if has_prototypes - void -error(char const *format,...) -#else - /*VARARGS1*/ void error(format, va_alist) char const *format; va_dcl -#endif -/* non-fatal error */ -{ - va_list args; - 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); - afputc('\n',stderr); - eflush(); -} - -#if has_prototypes - void -fatserror(char const *format,...) -#else - /*VARARGS1*/ void - fatserror(format, va_alist) char const *format; va_dcl -#endif -/* fatal RCS file syntax error */ -{ - va_list args; - oflush(); - VOID fprintf(stderr, "%s: %s:%ld: ", cmdid, RCSname, rcsline); - vararg_start(args, format); - fvfprintf(stderr, format, args); - va_end(args); - fatcleanup(false); -} - -#if has_prototypes - void -faterror(char const *format,...) -#else - /*VARARGS1*/ void faterror(format, va_alist) - char const *format; va_dcl -#endif -/* fatal error, terminates program after cleanup */ -{ - va_list args; - fatsay((char const*)0); - vararg_start(args, format); - fvfprintf(stderr, format, args); - va_end(args); - fatcleanup(false); -} - -#if has_prototypes - void -rcsfaterror(char const *format,...) -#else - /*VARARGS1*/ void rcsfaterror(format, va_alist) - char const *format; va_dcl -#endif -/* fatal RCS file error, terminates program after cleanup */ -{ - va_list args; - fatsay(RCSname); - vararg_start(args, format); - fvfprintf(stderr, format, args); - va_end(args); - 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 -redefined(c) - int c; -{ - warn("redefinition of -%c option", c); -} - -#if has_prototypes - void -diagnose(char const *format,...) -#else - /*VARARGS1*/ void diagnose(format, va_alist) char const *format; va_dcl -#endif -/* prints a diagnostic message */ -/* Unlike the other routines, it does not append a newline. */ -/* This lets some callers suppress the newline, and is faster */ -/* in implementations that flush stderr just at the end of each printf. */ -{ - va_list args; - if (!quietflag) { - oflush(); - vararg_start(args, format); - fvfprintf(stderr, format, args); - va_end(args); - eflush(); - } -} - - - - void -afputc(c, f) -/* afputc(c,f); acts like aputc_(c,f) but is smaller and slower. */ - int c; - register FILE *f; -{ - aputc_(c,f) -} - - - void -aputs(s, iop) - char const *s; - FILE *iop; -/* Function: Put string s on file iop, abort on error. - */ -{ -#if has_fputs - if (fputs(s, iop) < 0) - Oerror(); -#else - awrite(s, strlen(s), iop); -#endif -} - - - - void -#if has_prototypes -fvfprintf(FILE *stream, char const *format, va_list args) -#else - fvfprintf(stream,format,args) FILE *stream; char *format; va_list args; -#endif -/* like vfprintf, except abort program on error */ -{ -#if has_vfprintf - if (vfprintf(stream, format, args) < 0) - Oerror(); -#else -# if has__doprintf - _doprintf(stream, format, args); -# else -# if has__doprnt - _doprnt(format, args, stream); -# else - int *a = (int *)args; - VOID fprintf(stream, format, - a[0], a[1], a[2], a[3], a[4], - a[5], a[6], a[7], a[8], a[9] - ); -# endif -# endif - if (ferror(stream)) - Oerror(); -#endif -} - -#if has_prototypes - void -aprintf(FILE *iop, char const *fmt, ...) -#else - /*VARARGS2*/ void -aprintf(iop, fmt, va_alist) -FILE *iop; -char const *fmt; -va_dcl -#endif -/* Function: formatted output. Same as fprintf in stdio, - * but aborts program on error - */ -{ - va_list ap; - vararg_start(ap, fmt); - fvfprintf(iop, fmt, ap); - va_end(ap); -} - - - -#ifdef LEXDB -/* test program reading a stream of lexemes and printing the tokens. - */ - - - - int -main(argc,argv) -int argc; char * argv[]; -{ - cmdid="lextest"; - if (argc<2) { - aputs("No input file\n",stderr); - exitmain(EXIT_FAILURE); - } - if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) { - faterror("can't open input file %s",argv[1]); - } - Lexinit(); - while (!eoflex()) { - switch (nexttok) { - - case ID: - VOID printf("ID: %s",NextString); - break; - - case NUM: - if (hshenter) - VOID printf("NUM: %s, index: %d",nexthsh->num, nexthsh-hshtab); - else - VOID printf("NUM, unentered: %s",NextString); - hshenter = !hshenter; /*alternate between dates and numbers*/ - break; - - case COLON: - VOID printf("COLON"); break; - - case SEMI: - VOID printf("SEMI"); break; - - case STRING: - readstring(); - VOID printf("STRING"); break; - - case UNKN: - VOID printf("UNKN"); break; - - default: - VOID printf("DEFAULT"); break; - } - VOID printf(" | "); - nextlex(); - } - exitmain(EXIT_SUCCESS); -} - -void exiterr() { _exit(EXIT_FAILURE); } - - -#endif |