Initial revision

This commit is contained in:
ceriel
1987-01-05 17:20:13 +00:00
parent 0de3e4a0af
commit eb28fd80f9
20 changed files with 1180 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
/* $Header$ */
/* AtEoIF : a routine doing nothing. It is called at the end of an
inserted file.
*/
int
AtEoIF()
{
return 0;
}

View File

@@ -0,0 +1,10 @@
/* $Header$ */
/* AtEoIT : a routine doing nothing. It is called at the end of an
inserted text.
*/
int
AtEoIT()
{
return 0;
}

View File

@@ -0,0 +1,413 @@
/* INPUT AND BUFFER HANDLING MODULE */
/*
[input.X inp_pkg.spec 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:
input.h : an include-file, which must be included when using
this module
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
PushBack() : (defined in input.h) push last character back onto
the input stream; NPUSHBACK characters of pushback
are guaranteed, provided that they have all been read
from the current input stream
AtEoIT() : this routine is called at the end of an inserted text.
A default one is provided, which does nothing.
AtEoIF() : this routine is called at the end of an inserted file.
A default one is provided, which does nothing.
Imported objects are:
INP_NPUSHBACK, INP_READ_IN_ONE, INP_TYPE, INP_VAR,
routines from the "alloc" package, routines from the "storage"
package, and routines from the "system" package.
INP_READ_IN_ONE defined: every input file is read into memory completely
and made an input buffer. Only use it if the size of a file
fits always fits in an integer and you have lots of memory.
INP_READ_IN_ONE not defined: the input from files is buffered in
a fixed length input buffer
INP_NPUSHBACK: the number of characters pushback
*/
#include <alloc.h>
#include <system.h>
#ifndef INP_NPUSHBACK
#define INP_NPUSHBACK 1
#endif
#if INP_NPUSHBACK < 1
#define INP_NPUSHBACK 1
#endif
#ifndef INP_BUFSIZE
#define INP_BUFSIZE BUFSIZ
#endif
#if INP_NPUSHBACK > INP_BUFSIZE/2
Now this is really ridiculous! You deserve what you get!!
#endif
#ifdef INP_TYPE
extern INP_TYPE INP_VAR;
#endif INP_TYPE
#ifdef DEBUG
#define PRIVATE
#else
#define PRIVATE static
#endif
struct buffer_header {
struct buffer_header *next;
int bh_size; /* = strlen (text), should be unsigned */
char *bh_text; /* pointer to buffer containing text */
char *bh_ipp; /* current read pointer (= stacked ipp) */
#ifdef INP_TYPE
INP_TYPE bh_i; /* user defined */
#endif INP_TYPE
File *bh_fd; /* A file descriptor in case of a file */
char bh_eofreturned; /* set if we returned eof for this buffer */
};
#ifndef INP_READ_IN_ONE
struct i_buf {
struct i_buf *next;
char ib_text[INP_BUFSIZE+INP_NPUSHBACK-1];
};
# endif not INP_READ_IN_ONE
char *_ipp;
PRIVATE struct buffer_header *head;
#ifdef INP_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.
*/
PRIVATE int
readfile(fd, fn, size, pbuf)
register File *fd;
char *fn; /* file name */
register long *size;
extern long sys_filesize();
char **pbuf; /* output parameter */
{
int rsize;
if (
(*size = sys_filesize(fn)) < 0
||
((unsigned) (*size + 1) != (*size + 1))
||
!(*pbuf = malloc((unsigned) (*size + 1)))) {
sys_close(fd);
return 0;
}
if (
!sys_read(fd, *pbuf, (int) *size, &rsize)
||
*size != rsize
) {
sys_close(fd);
free(*pbuf);
return 0;
}
sys_close(fd);
(*pbuf)[*size] = '\0'; /* invoke loadbuf() at end */
return 1;
}
#endif INP_READ_IN_ONE
#ifndef INP_READ_IN_ONE
/* Input buffer supplying routines: pushbuf()
*/
PRIVATE struct i_buf *i_ptr;
PRIVATE char *
pushbuf()
{
register struct i_buf *ib =
(struct i_buf *) malloc(sizeof(struct i_buf));
if (!ib) return 0;
ib->next = i_ptr;
i_ptr = ib;
/* Don't give him all of it, we need some to implement a good
PushBack
*/
return &(ib->ib_text[INP_NPUSHBACK-1]);
}
#endif not INP_READ_IN_ONE
/* Input buffer administration: push_bh() and pop_bh()
*/
PRIVATE struct buffer_header *
push_bh()
{
register struct buffer_header *bh;
if (bh = head) {
bh->bh_ipp = _ipp;
#ifdef INP_TYPE
bh->bh_i = INP_VAR;
#endif INP_TYPE
}
if (!(bh = (struct buffer_header *)malloc(sizeof(struct buffer_header)))) return 0;
bh->next = head;
bh->bh_eofreturned = 0;
head = bh;
return bh;
}
/* 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()
{
register struct buffer_header *bh = head;
if (bh->bh_fd) { /* unstack a file */
#ifndef INP_READ_IN_ONE
struct i_buf *ib;
ib = i_ptr->next;
free((char *) i_ptr);
i_ptr = ib;
#else INP_READ_IN_ONE
free(bh->bh_text);
#endif INP_READ_IN_ONE
}
bh = bh->next;
free((char *) head);
head = bh;
if (!bh) { /* no more entries */
head = (struct buffer_header *) 0;
return 0;
}
_ipp = bh->bh_ipp; /* restore previous input pointer */
#ifdef INP_TYPE
INP_VAR = bh->bh_i;
#endif INP_TYPE
return 1;
}
#ifndef INP_READ_IN_ONE
/* low level I/O routine : read one block from current input
stream : readblock
*/
PRIVATE int
readblock(fd, buf, n)
File *fd;
char buf[];
int *n;
{
if (!sys_read(fd, buf, INP_BUFSIZE, n)) {
return 0;
}
buf[*n] = '\0';
return 1;
}
#endif not INP_READ_IN_ONE
/* Miscellaneous routines :
mk_filename()
*/
/* mk_filename() concatenates a dir and filename.
*/
PRIVATE int
mk_filename(dir, file, newname)
register char *dir, *file;
char **newname;
{
register char *dst;
dst = malloc((unsigned) (strlen(dir) + strlen(file) + 2));
if (!dst) return 0;
*newname = dst;
while (*dst++ = *dir++);
*--dst = '/';
while (*++dst = *file++);
return 1;
}
/* Interface routines : InsertFile, InsertText, and loadbuf
*/
int
InsertFile(filnam, table, result)
char *filnam;
char *table[];
char **result;
{
char *newfn = 0;
#ifdef INP_READ_IN_ONE
char *text;
long size;
#endif INP_READ_IN_ONE
File *fd = 0;
if (!filnam) fd = STDIN;
else {
if (table == 0 || filnam[0] == '/') {
/* don't look in the table! */
if (!sys_open(filnam, OP_READ, &fd)) return 0;
}
else {
while (*table) {
/* look in the directory table */
if (!mk_filename(*table++, filnam, &newfn)) {
return 0;
}
if (sys_open(newfn, OP_READ, &fd)) {
/* free filnam ??? NO we don't know
where it comes from!
*/
filnam = newfn;
break;
}
free(newfn);
newfn = 0;
}
}
}
if (fd) {
struct buffer_header *push_bh();
register struct buffer_header *bh = push_bh();
if (!bh) {
if (fd != STDIN) sys_close(fd);
return 0;
}
#ifdef INP_READ_IN_ONE
if (fd == STDIN) return 0; /* illegal */
if (!readfile(fd, filnam, &size, &text)) {
sys_close(fd);
return 0;
}
bh->bh_size = size;
_ipp = bh->bh_text = text;
#else not INP_READ_IN_ONE
if (
!(_ipp = bh->bh_text = pushbuf())
||
!readblock(fd,_ipp,&(bh->bh_size))) {
if (fd != STDIN) sys_close(fd);
return 0;
}
#endif INP_READ_IN_ONE
bh->bh_fd = fd; /* this is a file */
*result = filnam;
return 1;
}
return 0;
}
int
InsertText(text, length)
char *text;
{
struct buffer_header *push_bh();
register struct buffer_header *bh = push_bh();
if (!bh) return 0;
bh->bh_size = (long) length;
_ipp = bh->bh_text = text;
bh->bh_fd = 0; /* No file! */
return 1;
}
/* 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.
*/
int
loadbuf()
{
register struct buffer_header *bh = head;
static char buf[INP_NPUSHBACK + 1];
int FromFile;
if (!bh) { /* stack exhausted, EOF on sourcefile */
return EOI;
}
if (_ipp < &(bh->bh_text[bh->bh_size])) {
/* a genuine '\0' character has been seen */
return '\0';
}
FromFile = (bh->bh_fd != 0);
#ifndef INP_READ_IN_ONE
if (FromFile) {
#if INP_PUSHBACK > 1
register char *so = &(bh->bh_text[bh->bh_size]);
register char *de = bh->bh_text;
register int i = INP_NPUSHBACK - 1;
while (i-- > 0) {
/* make sure PushBack will work */
*--de = *--so;
}
#endif
if (
readblock(bh->bh_fd, bh->bh_text, &(bh->bh_size))
&&
bh->bh_size > 0
) {
_ipp = bh->bh_text;
return *_ipp++;
}
}
#endif not INP_READ_IN_ONE
if (!bh->bh_eofreturned) {
bh->bh_eofreturned = 1;
_ipp--;
if (FromFile) {
if (AtEoIF()) return EOI;
}
else {
if (AtEoIT()) return EOI;
}
}
#ifndef INP_READ_IN_ONE
if (FromFile && bh->bh_fd != STDIN) sys_close(bh->bh_fd);
#endif not INP_READ_IN_ONE
if (pop_bh()) {
if (*_ipp) return *_ipp++;
return loadbuf();
}
_ipp = &buf[INP_NPUSHBACK];
return EOI;
}

View File

@@ -0,0 +1,53 @@
/* This is the specification of the generic part of the input package.
It can be instantiated by #defining or not #defining
INP_TYPE, INP_VAR, INP_READ_IN_ONE, and INP_NPUSHBACK.
INP_TYPE is the type of the variable INP_VAR, which contains
all values the user wants to save when an InsertFile is done,
and restored when an input stream is continued after a suspend.
For instance, line numbers and position within a line might
be interesting.
Not defining INP_TYPE has the effect that the instantiation is
done without saving and restoring INP_VAR.
Defining INP_READ_IN_ONE has the effect that files will be read
completely with one "read". Only use this if you have lots of
memory. Not defining it causes files to be read in blocks, with
a suitable blocksize.
INP_NPUSHBACK is the number of PushBacks that are guaranteed
to work. Its default value is 1.
*/
/* INPUT PRIMITIVES */
#define LoadChar(dest) ((dest = *_ipp++) || (dest = loadbuf()))
#define PushBack() (--_ipp)
/* EOF may be defined as -1 in most programs but the character -1 may
be expanded to the int -1 which causes troubles at the indexing in
the class or boolean arrays.
*/
#define EOI (0200)
extern char *_ipp;
/* int InsertFile(filename, table, result)
char *filename;
char **table;
char **result;
This function suspends input from the current input stream. The next
characters are obtained from the file indicated by "filename". This file
will be looked for in the directories, mentioned in the null-terminated
list indicated by "table". It returns 1 if it succeeds, 0 if it fails.
"result" will contain the full path if InsertFile returns 1.
*/
extern int InsertFile();
/* int InsertText(text, length)
char *text;
int length;
This funtion suspends input from the current input stream. The next
input characters are obtained from the string indicated by "text",
whose length is indicated by "length".
It returns 1 if it succeeds, 0 if it fails.
*/
extern int InsertText();

140
modules/src/input/input.3 Normal file
View File

@@ -0,0 +1,140 @@
.TH INPUT 3 "March 25, 1986"
.SH NAME
LoadChar, PushBack, InsertFile, InsertText, AtEoIF, AtEoIT\ \-\ input
module for compilers
.SH SYNOPSIS
.B LoadChar(ch)
.br
.B int ch;
.PP
.B PushBack()
.PP
.B int InsertFile(filename, table, result)
.br
.B char *filename;
.br
.B char *table[];
.br
.B char **result;
.PP
.B int InsertText(text, length)
.br
.B char *text;
.br
.B int length;
.PP
.B int AtEoIF()
.PP
.B int AtEoIT()
.SH DESCRIPTION
This set of variables, macros and routines provides a fast input mechanism
for use by compilers.
They also provide a means of inserting new input streams,
thereby temporarily suspending an input
stream to read another one.
The \fBcurrent input stream\fR is the last inserted input stream that
has not reached its end.
.PP
The module is generic: it must be instantiated by #defining INP_TYPE,
INP_VAR, INP_READ_IN_ONE, INP_BUFSIZE, and INP_NPUSHBACK.
An instantiation can be obtained by creating two files: \fIinput.c\fR and
\fIinput.h\fR.
\fIinput.h\fR could contain the following:
.PP
.RS
.nf
#define INP_NPUSHBACK 2
#define INP_TYPE struct f_info
#define INP_VAR file_info
#define INP_BUFSIZE 4096
#include <inp_pkg.spec>
.fi
.RE
.PP
and \fIinput.c\fR could contain:
.PP
.RS
.nf
#include "f_info.h" /* contains definition for struct f_info */
#include "input.h"
#include <inp_pkg.body>
.fi
.RE
.PP
The user may associate certain data with each input stream. The input module
has a facility to save these data when inserting a new input stream, and
restoring them when restoring the suspended input stream. Examples of these
data are for instance a linenumber, a filename, etc.
These data must be collected in a variable INP_VAR of type INP_TYPE.
INP_VAR and INP_TYPE must be preprocessor-#defined.
Not #defining INP_TYPE has the effect that an instantiation will be created
that does not save and restore these data.
.PP
INP_NPUSHBACK is the number of PushBacks that are guaranteed to work.
Its default value is 1. It is expected to be small.
.PP
INP_READ_IN_ONE can either be defined or not defined. Defining it has the
effect that files will be read completely with one read-system call. This
should only be used on machines with lots of memory.
.PP
INP_BUFSIZE defines the input buffer size that is used when INP_READ_IN_ONE
is not defined. Its default value is BUFSIZ, from the \fIsystem\fP(3) module.
.PP
The macro \fILoadChar\fR stores the next character from the current input stream
in the variable \fIch\fR,
which is passed as a parameter.
Note that this simulates an output parameter!
When the end of the current input stream is reached, the next character from
the last suspended input stream will be stored, etc.
If there are no suspended input streams left, the constant EOI,
which is defined in \fIinp_pkg.spec\fR, is returned.
.PP
The macro \fIPushBack\fR pushes the last character read back onto the
input stream.
.PP
The routine \fIInsertFile\fR suspends input from the current input stream.
The next input characters will be obtained from the specified file
\fIfilename\fR.
This file will be looked for in the directories, mentioned in the
null-terminated list \fItable\fR.
If \fIfilename\fR is a null pointer, standard input is used. In this case,
the package may not have been instantiated with INP_READ_IN_ONE defined.
\fIInsertFile\fR returns 1 if it succeeds, 0 if it fails.
When it succeeds, it stores the file name in the \fIresult\fR parameter.
.PP
The routine \fIInsertText\fR also suspends input from the current input stream.
The next input characters will be obtained from the string \fItext\fR,
which is \fIlength\fR characters long.
\fIInsertText\fR returns 1 if it succeeds, 0 if it fails.
.PP
The routine \fIAtEoIF\fR is called at the end of the input stream
inserted by \fIInsertFile\fR.
If it returns 1, the LoadChar causing the call returns EOI, otherwize
the LoadChar returns the next character of the suspended and now restored
input stream.
A default \fIAtEoIF\fR is provided. It does nothing, and returns 0,
making the "unstacking" completely transparent.
The user of the module can write his own if this is not what he wants.
.PP
The routine \fIAtEoIT\fR is called at the end of the string
inserted by \fIInsertText\fR.
If it returns 1, the LoadChar causing the call returns EOI, otherwise
the LoadChar returns the next character of the suspended and now restored
input stream.
A default \fIAtEoIT\fR is provided. It does nothing, and returns 0,
making the "unstacking" completely transparent.
The user of the module can write his own if this is not what he wants.
.SH FILES
~em/modules/pkg/inp_pkg.spec
.br
~em/modules/pkg/inp_pkg.body
.br
~em/modules/lib/libinput.a
.SH MODULES
system(3), alloc(3)
.SH "SEE ALSO"
\fIGeneric Packages in C\fR by Dick Grune.
.SH BUGS
A \fILoadChar\fR-call does look like a function call,
but behaves differently. All for the sake of speed of course ...