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

17
modules/src/idf/Makefile Normal file
View 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
View 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.

View 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 = &notch->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;
}
}

View 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)