Initial revision
This commit is contained in:
parent
0de3e4a0af
commit
eb28fd80f9
9
modules/src/em_mes/C_ms_com.c
Normal file
9
modules/src/em_mes/C_ms_com.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_com(str)
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_com);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
14
modules/src/em_mes/C_ms_ego.c
Normal file
14
modules/src/em_mes/C_ms_ego.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_ego(hint, offs, siz, regno)
|
||||||
|
int hint, regno;
|
||||||
|
arith offs, siz;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_ego);
|
||||||
|
C_cst((arith)hint);
|
||||||
|
C_cst(offs);
|
||||||
|
C_cst(siz);
|
||||||
|
C_cst((arith)regno);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
11
modules/src/em_mes/C_ms_emx.c
Normal file
11
modules/src/em_mes/C_ms_emx.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_emx(wsiz, psiz)
|
||||||
|
arith wsiz, psiz;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_emx);
|
||||||
|
C_cst(wsiz);
|
||||||
|
C_cst(psiz);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
8
modules/src/em_mes/C_ms_err.c
Normal file
8
modules/src/em_mes/C_ms_err.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_err()
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_err);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
8
modules/src/em_mes/C_ms_flt.c
Normal file
8
modules/src/em_mes/C_ms_flt.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_flt()
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_flt);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
8
modules/src/em_mes/C_ms_gto.c
Normal file
8
modules/src/em_mes/C_ms_gto.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_gto()
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_gto);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
8
modules/src/em_mes/C_ms_opt.c
Normal file
8
modules/src/em_mes/C_ms_opt.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_opt()
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_opt);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
10
modules/src/em_mes/C_ms_par.c
Normal file
10
modules/src/em_mes/C_ms_par.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_par(nparams)
|
||||||
|
arith nparams;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_par);
|
||||||
|
C_cst(nparams);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
14
modules/src/em_mes/C_ms_reg.c
Normal file
14
modules/src/em_mes/C_ms_reg.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_reg(offs, siz, class, prior)
|
||||||
|
arith offs, siz;
|
||||||
|
int class, prior;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_reg);
|
||||||
|
C_cst(offs);
|
||||||
|
C_cst(siz);
|
||||||
|
C_cst((arith)class);
|
||||||
|
C_cst((arith)prior);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
12
modules/src/em_mes/C_ms_src.c
Normal file
12
modules/src/em_mes/C_ms_src.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <em.h>
|
||||||
|
#include <em_mes.h>
|
||||||
|
|
||||||
|
C_ms_src(nlines, filnam)
|
||||||
|
int nlines;
|
||||||
|
char *filnam;
|
||||||
|
{
|
||||||
|
C_mes_begin(ms_src);
|
||||||
|
C_cst((arith)nlines);
|
||||||
|
C_scon(filnam, strlen(filnam) + 1);
|
||||||
|
C_mes_end();
|
||||||
|
}
|
146
modules/src/em_mes/em_mes.3
Normal file
146
modules/src/em_mes/em_mes.3
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
.TH EM_MES 3ACK "86/03/18"
|
||||||
|
.SH NAME
|
||||||
|
em_mes \- EM-message generating routines
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <em.h>
|
||||||
|
.PP
|
||||||
|
.B C_ms_err()
|
||||||
|
.PP
|
||||||
|
.B C_ms_opt()
|
||||||
|
.PP
|
||||||
|
.B C_ms_emx(wsiz, psiz)
|
||||||
|
.B arith wsiz, psiz;
|
||||||
|
.PP
|
||||||
|
.B #include <em_reg.h>
|
||||||
|
.B C_ms_reg(offs, siz, class, prior)
|
||||||
|
.B arith offs, siz;
|
||||||
|
.B int class, prior;
|
||||||
|
.PP
|
||||||
|
.B C_ms_src(nlines, filnam)
|
||||||
|
.B int nlines;
|
||||||
|
.B char *filnam;
|
||||||
|
.PP
|
||||||
|
.B C_ms_flt()
|
||||||
|
.PP
|
||||||
|
.B C_ms_com(str)
|
||||||
|
.B char *str;
|
||||||
|
.PP
|
||||||
|
.B C_ms_par(nparams)
|
||||||
|
.B arith nparams;
|
||||||
|
.PP
|
||||||
|
.B #include <em_ego.h>
|
||||||
|
.B C_ms_ego(hint, offs, siz, regno)
|
||||||
|
.B int hint, regno;
|
||||||
|
.B arith offs, siz;
|
||||||
|
.PP
|
||||||
|
.B C_ms_gto()
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This set of routines forms a front end for the
|
||||||
|
.IR em_code (3L)
|
||||||
|
module.
|
||||||
|
The philosophy behind this package is to provide a single routine for
|
||||||
|
each type of EM message that is generated by a front-end compiler.
|
||||||
|
Each routine internally builds a message instruction by using the
|
||||||
|
.BR C_mes_begin ,
|
||||||
|
.B C_mes_end
|
||||||
|
and the
|
||||||
|
.BI C_ cstp
|
||||||
|
routines from the
|
||||||
|
.I em_code
|
||||||
|
module.
|
||||||
|
The actions taken by these functions depend on the type of
|
||||||
|
.I em_code
|
||||||
|
module that is loaded together with this module.
|
||||||
|
The routines described here do not prevent the user from directly
|
||||||
|
composing EM messages himself.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_err ()
|
||||||
|
generates a message that indicates some error during the compilation.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_opt ()
|
||||||
|
causes any optimization to be suppressed.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_emx ()
|
||||||
|
indicates the wordsize
|
||||||
|
.I wsiz
|
||||||
|
and pointersize
|
||||||
|
.IR psiz .
|
||||||
|
This must be the first code generated, or the generated code is illegal.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_reg ()
|
||||||
|
can be used to indicate that a local variable, having offset
|
||||||
|
.I offs
|
||||||
|
and size (in bytes)
|
||||||
|
.IR siz ,
|
||||||
|
may be stored in a register.
|
||||||
|
.I Class
|
||||||
|
indicates the use of the variable.
|
||||||
|
The following classes are allowed (the names are defined in em_reg.h):
|
||||||
|
.RS
|
||||||
|
.IP reg_any 12
|
||||||
|
no specific type
|
||||||
|
.IP reg_loop 12
|
||||||
|
loop control variable
|
||||||
|
.IP reg_pointer 12
|
||||||
|
pointer variable
|
||||||
|
.IP reg_float 12
|
||||||
|
floating point variable
|
||||||
|
.LP
|
||||||
|
.RE
|
||||||
|
.I Prior
|
||||||
|
is taken to be the priority of the variable; higher numbers indicate
|
||||||
|
better candidates.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_src ()
|
||||||
|
produces an indication of the number of source lines,
|
||||||
|
.IR nlines ,
|
||||||
|
in file
|
||||||
|
.IR filnam .
|
||||||
|
This information can be used by a profiler.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_flt ()
|
||||||
|
produces an indication that floating-point operations are used.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_com ()
|
||||||
|
causes the string
|
||||||
|
.I str
|
||||||
|
to be inserted as comment in the resulting output.
|
||||||
|
Note that this routine does not provide the full semantics of EM in this
|
||||||
|
area, but the user himself can build a comment message with other types
|
||||||
|
of comment if he likes.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_par ()
|
||||||
|
produces an indication that no more than
|
||||||
|
.I nbytes
|
||||||
|
of parameters are accessed, either directly or indirectly.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_ego ()
|
||||||
|
produces a hint from the EM global optimizer.
|
||||||
|
The parameters needed are conform to the format of the message.
|
||||||
|
.PP
|
||||||
|
.BR C_ms_gto ()
|
||||||
|
can be invoked to indicate that a procedure uses a non-local goto.
|
||||||
|
.SH FILES
|
||||||
|
.nf
|
||||||
|
~em/modules/h/em.h
|
||||||
|
~em/h/em_reg.h
|
||||||
|
~em/h/em_ego.h
|
||||||
|
~em/modules/lib/libem_mes.a
|
||||||
|
.fi
|
||||||
|
.SH MODULES
|
||||||
|
em_code(3)
|
||||||
|
.SH SEE ALSO
|
||||||
|
em_code(3), read_em(3)
|
||||||
|
.SH DIAGNOSTICS
|
||||||
|
None of the functions return a value.
|
||||||
|
.SH BUGS
|
||||||
|
The
|
||||||
|
.BR C_ms_ext ()
|
||||||
|
routine has not yet been implemented, since this message uses
|
||||||
|
a variable number of arguments.
|
||||||
|
.PP
|
||||||
|
Please report other bugs to the author.
|
||||||
|
.SH AUTHOR
|
||||||
|
Erik Baalbergen <erikb@vu44.UUCP>
|
17
modules/src/idf/Makefile
Normal file
17
modules/src/idf/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
EMHOME = ../../..
|
||||||
|
INSTALL = $(EMHOME)/modules/install
|
||||||
|
COMPARE = $(EMHOME)/modules/compare
|
||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
install: all
|
||||||
|
$(INSTALL) pkg/idf_pkg.body
|
||||||
|
$(INSTALL) pkg/idf_pkg.spec
|
||||||
|
$(INSTALL) man/idf.3
|
||||||
|
|
||||||
|
cmp: all
|
||||||
|
$(COMPARE) pkg/idf_pkg.body
|
||||||
|
$(COMPARE) pkg/idf_pkg.spec
|
||||||
|
$(COMPARE) man/idf.3
|
||||||
|
|
||||||
|
clean:
|
88
modules/src/idf/idf.3
Normal file
88
modules/src/idf/idf.3
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
.TH IDF 3ACK "March 17, 1986"
|
||||||
|
.UC
|
||||||
|
.SH NAME
|
||||||
|
init_idf, str2idf\ \-\ a namelist module
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.PP
|
||||||
|
.B init_idf()
|
||||||
|
.PP
|
||||||
|
.B struct idf *str2idf(tag, cpy)
|
||||||
|
.br
|
||||||
|
.B char *tag;
|
||||||
|
.PP
|
||||||
|
.B struct idf *findidf(tag)
|
||||||
|
.br
|
||||||
|
.B char *tag;
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This is a generic namelist module. It provides a fast mechanism for
|
||||||
|
associating information with identifiers. To get an instantiation, the
|
||||||
|
user must provide two files \fIidf.h\fR and \fIidf.c\fR.
|
||||||
|
\fIidf.h\fR could contain the following:
|
||||||
|
.br
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
.nf
|
||||||
|
#define IDF_TYPE struct id_info
|
||||||
|
#define IDF_HSIZE 8
|
||||||
|
|
||||||
|
#include <idf_pkg.spec>
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
and \fIidf.c\fR could contain:
|
||||||
|
.br
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
.nf
|
||||||
|
#include "id_info.h" /* contains definition for struct id_info */
|
||||||
|
#include "idf.h"
|
||||||
|
#include <idf_pkg.body>
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
IDF_TYPE denotes a type containing all information associated with
|
||||||
|
an identifier. If it is not defined, the instantiation will not contain
|
||||||
|
any user-defined information.
|
||||||
|
.PP
|
||||||
|
IDF_HSIZE denotes the number of significant characters for the hashing
|
||||||
|
function. It's default value is 64. Notice that this value does \fBnot\fP
|
||||||
|
denote the number of significant characters, but only the number of characters
|
||||||
|
that are used for hashing.
|
||||||
|
.PP
|
||||||
|
The user can also define IDF_NAME, to give a name to the selector in the
|
||||||
|
idf-structure. It's default value is \fIid_user\fP.
|
||||||
|
.PP
|
||||||
|
The routine \fIinit_idf\fR initializes the namelist.
|
||||||
|
.PP
|
||||||
|
The function
|
||||||
|
\fIstr2idf\fR searches for the string \fItag\fR in the namelist, and
|
||||||
|
creates an entry for it if necessary. A pointer to this entry is
|
||||||
|
returned. If \fIcpy\fR is non-zero, a copy of the \fItag\fR is made,
|
||||||
|
otherwise the \fItag\fR itself is used.
|
||||||
|
The entry has the following structure, defined in \fIinp_pkg.spec\fR:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
struct idf {
|
||||||
|
struct idf *next; \kx/* links idf-structures together */
|
||||||
|
char *id_text;\h'|\nxu'/* string representing the name */
|
||||||
|
#ifdef IDF_TYPE
|
||||||
|
IDF_TYPE IDF_NAME;\h'|\nxu'/* user defined type */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
The field \fIid_text\fR will point to a copy of \fItag\fR, or
|
||||||
|
to the \fItag\fR itself, depending on \fIcpy\fR.
|
||||||
|
The field \fInext\fR is used for internal information and must not
|
||||||
|
be changed by the user of this module.
|
||||||
|
.PP
|
||||||
|
The function \fIfindidf\fP searches for the string \fItag\fP in the
|
||||||
|
namelist, but returns 0 when it is'nt present.
|
||||||
|
.SH "MODULES USED"
|
||||||
|
alloc(3)
|
||||||
|
.SH FILES
|
||||||
|
~em/modules/pkg/idf_pkg.spec
|
||||||
|
.br
|
||||||
|
~em/modules/pkg/idf_pkg.body
|
||||||
|
.SH DIAGNOSTICS
|
||||||
|
\fIstr2idf\fP returns a null pointer if there is no memory available.
|
159
modules/src/idf/idf_pkg.body
Normal file
159
modules/src/idf/idf_pkg.body
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/* SYMBOL TABLE HANDLING */
|
||||||
|
|
||||||
|
#include <alloc.h>
|
||||||
|
|
||||||
|
/* Each character of the identifier is xored with an 8-bit mask which
|
||||||
|
depends on the position of the character; the sum of these results
|
||||||
|
is the hash value. The random masks are obtained from a
|
||||||
|
congruence generator.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HASHSIZE 256 /* size of hashtable, must be a power of 2 */
|
||||||
|
#ifndef IDF_HSIZE
|
||||||
|
#define IDF_HSIZE 64 /* # of significant characters for hashing.
|
||||||
|
This is NOT the number of significant
|
||||||
|
characters!
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
#define HASH_X 0253 /* Knuth's X */
|
||||||
|
#define HASH_A 77 /* Knuth's a */
|
||||||
|
#define HASH_C 153 /* Knuth's c */
|
||||||
|
|
||||||
|
#define HASHMASK (HASHSIZE-1) /* since it is a power of 2 */
|
||||||
|
#define STARTHASH() (0)
|
||||||
|
#define ENHASH(hs,ch,hm) (hs + (ch ^ hm))
|
||||||
|
#define STOPHASH(hs) (hs & HASHMASK)
|
||||||
|
|
||||||
|
static char hmask[IDF_HSIZE];
|
||||||
|
|
||||||
|
static struct idf *id_hashtable[HASHSIZE];
|
||||||
|
/* All identifiers can in principle be reached through
|
||||||
|
id_hashtable; id_hashtable[hc] is the start of a chain of
|
||||||
|
idf's whose tags all hash to hc.
|
||||||
|
Any identifier is entered into this
|
||||||
|
list, regardless of the nature of its declaration
|
||||||
|
(variable, selector, structure tag, etc.).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct idf *
|
||||||
|
new_idf(tg, size, cpy)
|
||||||
|
register char *tg;
|
||||||
|
register int size;
|
||||||
|
{
|
||||||
|
static int nidf;
|
||||||
|
static struct idf *pidf;
|
||||||
|
#define NIDS 50
|
||||||
|
#define IBUFSIZ 2048
|
||||||
|
static unsigned int icnt;
|
||||||
|
static char *ip;
|
||||||
|
register char *p;
|
||||||
|
|
||||||
|
|
||||||
|
if (! nidf--) {
|
||||||
|
nidf += NIDS;
|
||||||
|
pidf = (struct idf *) Malloc(NIDS * sizeof (struct idf));
|
||||||
|
clear((char *) pidf, NIDS * sizeof(struct idf));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpy) {
|
||||||
|
if (size > icnt) {
|
||||||
|
icnt = size > IBUFSIZ ? size : IBUFSIZ;
|
||||||
|
p = Malloc(icnt);
|
||||||
|
}
|
||||||
|
else p = ip;
|
||||||
|
icnt -= size;
|
||||||
|
pidf->id_text = p;
|
||||||
|
while (size--) {
|
||||||
|
*p++ = *tg++;
|
||||||
|
}
|
||||||
|
ip = p;
|
||||||
|
}
|
||||||
|
else pidf->id_text = tg;
|
||||||
|
return pidf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
hash_stat()
|
||||||
|
{
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
print("Hash table tally:\n");
|
||||||
|
for (i = 0; i < HASHSIZE; i++) {
|
||||||
|
register struct idf *notch = id_hashtable[i];
|
||||||
|
register int cnt = 0;
|
||||||
|
|
||||||
|
while (notch) {
|
||||||
|
cnt++;
|
||||||
|
notch = notch->next;
|
||||||
|
}
|
||||||
|
print("%d %d\n", i, cnt);
|
||||||
|
}
|
||||||
|
print("End hash table tally\n");
|
||||||
|
}
|
||||||
|
#endif DEBUG
|
||||||
|
|
||||||
|
struct idf *
|
||||||
|
str2idf(tg, cpy)
|
||||||
|
char tg[];
|
||||||
|
{
|
||||||
|
/* str2idf() returns an entry in the symbol table for the
|
||||||
|
identifier tg. If necessary, an entry is created.
|
||||||
|
*/
|
||||||
|
register char *cp = tg;
|
||||||
|
register char *phm = &hmask[0];
|
||||||
|
struct idf **hook;
|
||||||
|
register struct idf *notch;
|
||||||
|
register int hash;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
hash = STARTHASH();
|
||||||
|
while (*cp && phm < &hmask[IDF_HSIZE]) {
|
||||||
|
hash = ENHASH(hash, *cp++, *phm++);
|
||||||
|
}
|
||||||
|
hash = STOPHASH(hash);
|
||||||
|
while (*cp++) /* nothing. Find end of string */ ;
|
||||||
|
size = cp - tg;
|
||||||
|
|
||||||
|
/* The tag tg with length size and known hash value hash is
|
||||||
|
looked up in the identifier table; if not found, it is
|
||||||
|
entered if cpy >= 0. A pointer to it is returned.
|
||||||
|
Notice that the chains of idf's are sorted alphabetically.
|
||||||
|
*/
|
||||||
|
hook = &id_hashtable[hash];
|
||||||
|
|
||||||
|
while ((notch = *hook)) {
|
||||||
|
register char *s1 = tg;
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
cp = notch->id_text;
|
||||||
|
|
||||||
|
while (!(cmp = (*s1 - *cp++))) {
|
||||||
|
if (*s1++ == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp == 0) return notch;
|
||||||
|
if (cmp < 0) break;
|
||||||
|
hook = ¬ch->next;
|
||||||
|
}
|
||||||
|
/* a new struct idf must be inserted at the hook */
|
||||||
|
if (cpy < 0) return 0;
|
||||||
|
notch = new_idf(tg, size, cpy);
|
||||||
|
notch->next = *hook;
|
||||||
|
*hook = notch; /* hooked in */
|
||||||
|
return notch;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_idf() {
|
||||||
|
/* A simple congruence random number generator, as
|
||||||
|
described in Knuth, vol 2.
|
||||||
|
*/
|
||||||
|
int rnd = HASH_X;
|
||||||
|
register char *phm;
|
||||||
|
|
||||||
|
for (phm = &hmask[0]; phm < &hmask[IDF_HSIZE];) {
|
||||||
|
*phm++ = rnd;
|
||||||
|
rnd = (HASH_A * rnd + HASH_C) & HASHMASK;
|
||||||
|
}
|
||||||
|
}
|
42
modules/src/idf/idf_pkg.spec
Normal file
42
modules/src/idf/idf_pkg.spec
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* $Header$ */
|
||||||
|
/* IDENTIFIER DESCRIPTOR */
|
||||||
|
|
||||||
|
/* This a generic package for maintaining a name list */
|
||||||
|
|
||||||
|
/* Instantiation parameters, supplied by #define, are :
|
||||||
|
IDF_TYPE: the type of the user-defined part of the idf-structure,
|
||||||
|
IDF_NAME: the selector name for this field in the idf_structure, and
|
||||||
|
IDF_HSIZE: the number of significant characters for hashing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IDF_NAME
|
||||||
|
#define IDF_NAME id_user
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct idf {
|
||||||
|
struct idf *next; /* links idf-structures together */
|
||||||
|
char *id_text; /* string representing the name */
|
||||||
|
#ifdef IDF_TYPE
|
||||||
|
IDF_TYPE IDF_NAME; /* user defined type and selector */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* init_idf()
|
||||||
|
|
||||||
|
Initializes the namelist
|
||||||
|
*/
|
||||||
|
extern init_idf();
|
||||||
|
|
||||||
|
/* struct idf * str2idf(tg, cp)
|
||||||
|
char *tg;
|
||||||
|
int cp;
|
||||||
|
|
||||||
|
Adds the string indicated by "tg" to the namelist, and returns a
|
||||||
|
pointer to the entry.
|
||||||
|
If cp > 0, a copy of tg is made for id_text, otherwise tg itself
|
||||||
|
is used.
|
||||||
|
If cp < 0, the string is not entered, but only looked for.
|
||||||
|
*/
|
||||||
|
extern struct idf * str2idf();
|
||||||
|
|
||||||
|
#define findidf(tg) str2idf(tg, -1)
|
10
modules/src/input/AtEoIF.c
Normal file
10
modules/src/input/AtEoIF.c
Normal 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;
|
||||||
|
}
|
10
modules/src/input/AtEoIT.c
Normal file
10
modules/src/input/AtEoIT.c
Normal 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;
|
||||||
|
}
|
413
modules/src/input/inp_pkg.body
Normal file
413
modules/src/input/inp_pkg.body
Normal 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;
|
||||||
|
}
|
53
modules/src/input/inp_pkg.spec
Normal file
53
modules/src/input/inp_pkg.spec
Normal 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
140
modules/src/input/input.3
Normal 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 ...
|
Loading…
Reference in a new issue