Initial revision
This commit is contained in:
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)
|
||||
Reference in New Issue
Block a user