|
@@ -1,427 +1,18 @@
|
|
|
/* $Header$ */
|
|
|
-/* INPUT AND BUFFER HANDLING MODULE */
|
|
|
|
|
|
-/*
|
|
|
- [input.c input.h]
|
|
|
- Input buffering module: this module contains the routines that
|
|
|
- offers an input buffering mechanism to the user.
|
|
|
-
|
|
|
- This module exports the following objects:
|
|
|
- InsertFile() : suspend input from current buffer and obtain the
|
|
|
- next input characters from the specified file
|
|
|
- InsertText() : suspend input from current buffer and take the
|
|
|
- specified text as stream of input characters
|
|
|
- LoadChar() : (defined in input.h) read next character from
|
|
|
- the input ; LoadChar() invokes loadbuf() on
|
|
|
- encounting a ASCII NUL character
|
|
|
- NoUnstack : if set to non-zero:
|
|
|
- loadbuf() reports "unexpected EOF" on encounting
|
|
|
- the end-of-file or end-of-stacked-text.
|
|
|
-
|
|
|
- Imported objects are:
|
|
|
- IDEPTH, DEBUG, READ_IN_ONE, PATHLENGTH: compile-time parameters
|
|
|
- Malloc(), Salloc(): memory allocation routines
|
|
|
- fatal(), lexerror(): exception handling
|
|
|
- FileName, LineNumber, WorkingDir: input trace for lexical analyser
|
|
|
-
|
|
|
- READ_IN_ONE DEFINED: every input file is read into memory completely
|
|
|
- and made an input buffer
|
|
|
- READ_IN_ONE NOT DEFINED: the input from files is buffered in
|
|
|
- a fixed length input buffer
|
|
|
-*/
|
|
|
-
|
|
|
-#include <system.h>
|
|
|
-#include "nopp.h"
|
|
|
-#include "inputtype.h"
|
|
|
-#include "interface.h"
|
|
|
-#include "arith.h"
|
|
|
-#include "LLlex.h"
|
|
|
-#include "input.h"
|
|
|
-#include "alloc.h"
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-#include "idepth.h"
|
|
|
-#include "debug.h"
|
|
|
-#include "pathlength.h"
|
|
|
-#include "assert.h"
|
|
|
-#include "static.h"
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-EXPORT char *ipp = 0; /* input pointer */
|
|
|
-EXPORT int NoUnstack = 0; /* if 1: report EOF */
|
|
|
-
|
|
|
-#ifndef READ_IN_ONE
|
|
|
-PRIVATE File *FilDes = 0; /* current input medium */
|
|
|
-#endif READ_IN_ONE
|
|
|
+#include "inputtype.h"
|
|
|
+#include "file_info.h"
|
|
|
+#include "input.h"
|
|
|
+#define INP_TYPE struct file_info
|
|
|
+#define INP_VAR finfo
|
|
|
+struct file_info finfo;
|
|
|
+#include <inp_pkg.body>
|
|
|
+#include "nopp.h"
|
|
|
|
|
|
#ifndef NOPP
|
|
|
-struct buffer_header {
|
|
|
- char *bh_name; /* file name where the text comes from */
|
|
|
- unsigned int bh_lineno;
|
|
|
- /* current lineno in file */
|
|
|
- long bh_size; /* = strlen (text), should be unsigned */
|
|
|
- char *bh_text; /* pointer to buffer containing text */
|
|
|
- char *bh_ipp; /* current read pointer (= stacked ipp) */
|
|
|
- char *bh_wdir; /* directory of current file */
|
|
|
- File *bh_fp; /* needed for files if !READ_IN_ONE */
|
|
|
-};
|
|
|
-
|
|
|
-PRIVATE struct buffer_header instack[IDEPTH]; /* stack of input media */
|
|
|
-PRIVATE struct buffer_header *head = 0; /* current input buffer */
|
|
|
-
|
|
|
-IMPORT char **WorkingDir; /* name of current working directory */
|
|
|
-#else NOPP
|
|
|
-long isize;
|
|
|
-char ibuf[BUFSIZ + 1];
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifdef READ_IN_ONE
|
|
|
-/* readfile() creates a buffer in which the text of the file
|
|
|
- is situated. A pointer to the start of this text is
|
|
|
- returned. *size is initialized with the buffer length.
|
|
|
- Note that the file input buffer is prepared for the
|
|
|
- preprocessor by inserting a '\n' in the beginning of the
|
|
|
- text and appending a '\n' at the end of the text. The
|
|
|
- file text start at position 1 of the input buffer. This is
|
|
|
- done to allow pushback.
|
|
|
-*/
|
|
|
-
|
|
|
-PRIVATE char *
|
|
|
-readfile(filename, size)
|
|
|
- char *filename;
|
|
|
- long *size;
|
|
|
-{
|
|
|
- File *fp; /* filedescriptor for `filename' */
|
|
|
- char *cbuf; /* pointer to buffer to be returned */
|
|
|
- int tmp;
|
|
|
- long sys_filesize();
|
|
|
-
|
|
|
- if (sys_open(filename, OP_READ, &fp) == 0) /* can't open this file */
|
|
|
- return (char *) 0;
|
|
|
- if ((*size = sys_filesize(filename)) == -1L)
|
|
|
- fatal("(readfile) cannot get size of file");
|
|
|
- /* allocate enough space to store contents of the file */
|
|
|
- cbuf = Malloc(*size + 2);
|
|
|
- if (sys_read(fp, cbuf + 1, (int) *size, &tmp) == 0 || tmp != *size)
|
|
|
- fatal("(readfile) bad read");
|
|
|
- (*size)++; /* keep book of the size! */
|
|
|
- sys_close(fp); /* filedes no longer needed */
|
|
|
- cbuf[0] = '\0'; /* allow pushback of first char */
|
|
|
- cbuf[*size] = '\0'; /* invoke loadbuf() at end */
|
|
|
- return cbuf;
|
|
|
-}
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-#ifndef READ_IN_ONE
|
|
|
-/* Input buffer supplying routines: pushbuf() and popbuf()
|
|
|
-*/
|
|
|
-PRIVATE char *bufstack[IDEPTH] = 0;
|
|
|
-PRIVATE bufstptr = 0;
|
|
|
-
|
|
|
-PRIVATE char *
|
|
|
-pushbuf()
|
|
|
-{
|
|
|
- if (bufstptr >= IDEPTH)
|
|
|
- fatal("ran out of input buffers");
|
|
|
- if (bufstack[bufstptr] == 0) {
|
|
|
- bufstack[bufstptr] = Malloc(BUFSIZ + 4);
|
|
|
- }
|
|
|
- return bufstack[bufstptr++];
|
|
|
-}
|
|
|
-
|
|
|
-PRIVATE
|
|
|
-popbuf()
|
|
|
-{
|
|
|
- bufstptr--;
|
|
|
- ASSERT(bufstptr >= 0);
|
|
|
-}
|
|
|
-#endif READ_IN_ONE
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-/* Input buffer administration: push_bh() and pop_bh()
|
|
|
-*/
|
|
|
-PRIVATE struct buffer_header *
|
|
|
-push_bh()
|
|
|
-{
|
|
|
- if (head) {
|
|
|
- if (head >= &instack[IDEPTH - 1])
|
|
|
- fatal("too many nested input texts");
|
|
|
- head->bh_ipp = ipp;
|
|
|
- head->bh_lineno = LineNumber;
|
|
|
- head++;
|
|
|
- }
|
|
|
- else
|
|
|
- head = &instack[0];
|
|
|
-
|
|
|
- return head;
|
|
|
-}
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-/* pop_bh() uncovers the previous inputbuffer on the stack
|
|
|
- of headers. 0 is returned if there are no more
|
|
|
- inputbuffers on the stack, 1 is returned in the other case.
|
|
|
-*/
|
|
|
-PRIVATE int
|
|
|
-pop_bh()
|
|
|
-{
|
|
|
- File *pfp = head->bh_fp;
|
|
|
-
|
|
|
- if (NoUnstack) {
|
|
|
- lexerror("unexpected EOF");
|
|
|
- }
|
|
|
-
|
|
|
- if (head <= &instack[0]) { /* no more entries */
|
|
|
- head = (struct buffer_header *) 0;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- ipp = (--head)->bh_ipp; /* restore the previous input pointer */
|
|
|
-
|
|
|
- if (pfp != 0) { /* unstack a file */
|
|
|
-#ifndef READ_IN_ONE
|
|
|
- closefile(pfp);
|
|
|
- popbuf(); /* free last buffer */
|
|
|
-#endif READ_IN_ONE
|
|
|
- LineNumber = head->bh_lineno;
|
|
|
- FileName = head->bh_name;
|
|
|
- *WorkingDir = head->bh_wdir;
|
|
|
- }
|
|
|
-
|
|
|
-#ifndef READ_IN_ONE
|
|
|
- FilDes = head->bh_fp;
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifndef READ_IN_ONE
|
|
|
-/* low level IO routines: openfile(), readblock() and closefile()
|
|
|
-*/
|
|
|
-
|
|
|
-PRIVATE File *
|
|
|
-openfile(filename)
|
|
|
- char *filename;
|
|
|
-{
|
|
|
- File *fp;
|
|
|
-
|
|
|
- if (filename == 0)
|
|
|
- return STDIN;
|
|
|
- if (sys_open(filename, OP_READ, &fp) == 0)
|
|
|
- return (File *)0;
|
|
|
- return fp;
|
|
|
-}
|
|
|
-
|
|
|
-PRIVATE
|
|
|
-closefile(fp)
|
|
|
- File *fp;
|
|
|
-{
|
|
|
- if (fp != STDIN)
|
|
|
- sys_close(fp);
|
|
|
-}
|
|
|
-
|
|
|
-PRIVATE int
|
|
|
-readblock(fp, buf)
|
|
|
- File *fp;
|
|
|
- char buf[];
|
|
|
-{
|
|
|
- int n;
|
|
|
-
|
|
|
- if (sys_read(fp, &buf[1], BUFSIZ, &n) == 0)
|
|
|
- fatal("(readblock) bad read");
|
|
|
- buf[0] = buf[n + 1] = '\0';
|
|
|
- return n;
|
|
|
-}
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
-/* Interface routines : InsertFile(), InsertText() and loadbuf()
|
|
|
-*/
|
|
|
-
|
|
|
-EXPORT int
|
|
|
-InsertFile(filnam, table)
|
|
|
- char *filnam;
|
|
|
- char *table[];
|
|
|
-{
|
|
|
- char *mk_filename(), *newfn;
|
|
|
- char *strcpy();
|
|
|
- File *openfile();
|
|
|
-
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- char *readfile(), *text;
|
|
|
- long size;
|
|
|
-#else READ_IN_ONE
|
|
|
- File *fp = 0;
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- if (!filnam)
|
|
|
- return 0;
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
- if (table == 0 || filnam[0] == '/') { /* don't look in the table! */
|
|
|
-#endif NOPP
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- text = readfile(filnam, &size);
|
|
|
-#else READ_IN_ONE
|
|
|
- fp = openfile(filnam);
|
|
|
- if (filnam == 0)
|
|
|
- filnam = "standard input";
|
|
|
-#endif READ_IN_ONE
|
|
|
-#ifndef NOPP
|
|
|
- }
|
|
|
- else {
|
|
|
- ASSERT(filnam != 0);
|
|
|
- while (*table) { /* look in the directory table */
|
|
|
- newfn = mk_filename(*table++, filnam);
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- if (text = readfile(newfn, &size))
|
|
|
-#else READ_IN_ONE
|
|
|
- if ((fp = openfile(newfn)) != 0)
|
|
|
-#endif READ_IN_ONE
|
|
|
- {
|
|
|
- /* free filnam ??? */
|
|
|
- filnam = Salloc(newfn, strlen(newfn) + 1);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- if (text)
|
|
|
-#else READ_IN_ONE
|
|
|
- if (fp != 0)
|
|
|
-#endif READ_IN_ONE
|
|
|
-#ifndef NOPP
|
|
|
- {
|
|
|
- struct buffer_header *push_bh();
|
|
|
- register struct buffer_header *bh = push_bh();
|
|
|
-
|
|
|
- setwdir(WorkingDir, filnam);
|
|
|
- bh->bh_lineno = LineNumber = 0;
|
|
|
- bh->bh_name = FileName = filnam;
|
|
|
- bh->bh_wdir = *WorkingDir;
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- bh->bh_size = size;
|
|
|
- bh->bh_fp = STDIN; /* this is a file */
|
|
|
- ipp = bh->bh_text = text;
|
|
|
-#else READ_IN_ONE
|
|
|
- bh->bh_size = readblock(fp, ipp = bh->bh_text = pushbuf()) + 1;
|
|
|
- FilDes = bh->bh_fp = fp;
|
|
|
-#endif READ_IN_ONE
|
|
|
- bh->bh_text[0] = '\n'; /* wake up pp if '#' comes first */
|
|
|
- return 1;
|
|
|
- }
|
|
|
-#else NOPP
|
|
|
- {
|
|
|
- LineNumber = 0;
|
|
|
- FileName = filnam;
|
|
|
-#ifdef READ_IN_ONE
|
|
|
- isize = size;
|
|
|
- ipp = text;
|
|
|
-#else READ_IN_ONE
|
|
|
- isize = readblock(FilDes = fp, ipp = &ibuf[0]) + 1;
|
|
|
-#endif READ_IN_ONE
|
|
|
- ibuf[0] = '\n';
|
|
|
- return 1;
|
|
|
- }
|
|
|
-#endif NOPP
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-EXPORT
|
|
|
-InsertText(text, length)
|
|
|
- char *text;
|
|
|
-{
|
|
|
- struct buffer_header *push_bh();
|
|
|
- register struct buffer_header *bh = push_bh();
|
|
|
-
|
|
|
- bh->bh_name = FileName;
|
|
|
- bh->bh_lineno = LineNumber;
|
|
|
- bh->bh_size = (long) length;
|
|
|
- bh->bh_text = text;
|
|
|
- bh->bh_wdir = *WorkingDir;
|
|
|
- bh->bh_fp = 0; /* this is not a file ! */
|
|
|
- ipp = text + 1;
|
|
|
-#ifndef READ_IN_ONE
|
|
|
- FilDes = 0;
|
|
|
-#endif READ_IN_ONE
|
|
|
-}
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-/* loadbuf() is called if LoadChar meets a '\0' character
|
|
|
- which may be the end-of-buffer mark of the current input
|
|
|
- buffer. The '\0' could be genuine although not likely.
|
|
|
- Note: this routine is exported due to its occurence in the definition
|
|
|
- of LoadChar [input.h], that is defined as a macro.
|
|
|
-*/
|
|
|
-EXPORT int
|
|
|
-loadbuf()
|
|
|
-{
|
|
|
-#ifndef NOPP
|
|
|
- if (!head) /* stack exhausted, EOF on sourcefile */
|
|
|
- return EOI;
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
- if (ipp < &(head->bh_text[head->bh_size]))
|
|
|
-#else NOPP
|
|
|
- if (ipp < &ibuf[isize])
|
|
|
-#endif NOPP
|
|
|
- return '\0'; /* a genuine '\0' character has been seen */
|
|
|
-
|
|
|
-#ifndef READ_IN_ONE
|
|
|
-#ifndef NOPP
|
|
|
- if ( FilDes != 0
|
|
|
- && (head->bh_size = readblock(FilDes, head->bh_text)) > 0
|
|
|
- )
|
|
|
- return ipp = &(head->bh_text[1]), *ipp++;
|
|
|
-#else NOPP
|
|
|
- if (FilDes != 0 && (isize = readblock(FilDes, &ibuf[0])) > 0)
|
|
|
- return ipp = &ibuf[1], *ipp++;
|
|
|
-#endif NOPP
|
|
|
-#endif READ_IN_ONE
|
|
|
-
|
|
|
-#ifdef NOPP
|
|
|
- if (NoUnstack)
|
|
|
- lexerror("unexpected EOF");
|
|
|
-#ifndef READ_IN_ONE
|
|
|
- closefile(FilDes);
|
|
|
-#endif READ_IN_ONE
|
|
|
-#endif NOPP
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
- if (pop_bh())
|
|
|
- return *ipp ? *ipp++ : loadbuf();
|
|
|
-#endif NOPP
|
|
|
- ipp = &"\0\0"[1];
|
|
|
- return EOI;
|
|
|
-}
|
|
|
-
|
|
|
-/* Some miscellaneous routines : setwdir() and mk_filename()
|
|
|
-*/
|
|
|
-
|
|
|
-#ifndef NOPP
|
|
|
-/* setwdir() updates *wdir according to the old working
|
|
|
- directory (*wdir) and the filename fn, which may contain
|
|
|
- some path name. The algorithm used here is:
|
|
|
- setwdir(DIR, FILE):
|
|
|
- if (FILE == "/***")
|
|
|
- *DIR = "/"
|
|
|
- else
|
|
|
- if (contains(FILE, '/'))
|
|
|
- *DIR = directory(FILE)
|
|
|
- else
|
|
|
- *DIR remains unchanged
|
|
|
-*/
|
|
|
-PRIVATE
|
|
|
-setwdir(wdir, fn)
|
|
|
- char *fn, **wdir;
|
|
|
+char *
|
|
|
+getwdir(fn)
|
|
|
+ char *fn;
|
|
|
{
|
|
|
register char *p;
|
|
|
char *strrindex();
|
|
@@ -433,32 +24,31 @@ setwdir(wdir, fn)
|
|
|
}
|
|
|
|
|
|
if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
|
|
|
- *wdir = "/";
|
|
|
+ return "";
|
|
|
else
|
|
|
if (p) {
|
|
|
*p = '\0';
|
|
|
- *wdir = Salloc(fn, p - &fn[0] + 1);
|
|
|
+ fn = Salloc(fn, p - &fn[0] + 1);
|
|
|
*p = '/';
|
|
|
+ return fn;
|
|
|
}
|
|
|
+ else return ".";
|
|
|
}
|
|
|
#endif NOPP
|
|
|
|
|
|
-#ifndef NOPP
|
|
|
-/* mk_filename() concatenates a dir and filename.
|
|
|
-*/
|
|
|
-GSTATIC char path[PATHLENGTH];
|
|
|
+int NoUnstack;
|
|
|
|
|
|
-PRIVATE char *
|
|
|
-mk_filename(dir, file)
|
|
|
- register char *dir, *file;
|
|
|
+AtEoIT()
|
|
|
{
|
|
|
- register char *dst = &path[0];
|
|
|
+#ifndef NOPP
|
|
|
+ if (NoUnstack) lexerror("unexpected EOF");
|
|
|
+ DoUnstack();
|
|
|
+#endif NOPP
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
- if (!(dir[0] == '.' && dir[1] == '\0')) {
|
|
|
- while (*dst++ = *dir++);
|
|
|
- *(dst - 1) = '/';
|
|
|
- }
|
|
|
- while (*dst++ = *file++);
|
|
|
- return &path[0];
|
|
|
+AtEoIF()
|
|
|
+{
|
|
|
+ if (NoUnstack) lexerror("unexpected EOF");
|
|
|
+ return 0;
|
|
|
}
|
|
|
-#endif NOPP
|