|
Packit |
9741aa |
#include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
|
|
Packit |
9741aa |
/* ETDDEF: Define an element type definition.
|
|
Packit |
9741aa |
Use an existing one if there is one; otherwise create one, which
|
|
Packit |
9741aa |
rmalloc initializes to zero which shows it is a virgin etd.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
PETD etddef(ename)
|
|
Packit |
9741aa |
UNCH *ename; /* Element name (GI) with length byte. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
PETD p; /* Pointer to an etd. */
|
|
Packit |
9741aa |
int hnum; /* Hash number for ename. */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
|
|
Packit |
9741aa |
p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return p;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* ETDSET: Store data in an element type definition.
|
|
Packit |
9741aa |
The etd must be valid and virgin (except for adl and etdmin).
|
|
Packit |
9741aa |
As an etd cannot be modified, there is no checking for existing
|
|
Packit |
9741aa |
pointers and no freeing of their storage.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
#ifdef USE_PROTOTYPES
|
|
Packit |
9741aa |
PETD etdset(PETD p, UNCH fmin, struct thdr *cmod, PETD *mexgrp, PETD *pexgrp,
|
|
Packit |
9741aa |
struct entity **srm)
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
PETD etdset(p, fmin, cmod, mexgrp, pexgrp, srm)
|
|
Packit |
9741aa |
PETD p; /* Pointer to an etd. */
|
|
Packit |
9741aa |
UNCH fmin; /* Minimization bit flags. */
|
|
Packit |
9741aa |
struct thdr *cmod; /* Pointer to content model. */
|
|
Packit |
9741aa |
PETD *mexgrp; /* Pointers to minus and plus exception lists. */
|
|
Packit |
9741aa |
PETD *pexgrp; /* Pointers to minus and plus exception lists. */
|
|
Packit |
9741aa |
struct entity **srm; /* Short reference map. */
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
p->etdmin |= fmin;
|
|
Packit |
9741aa |
p->etdmod = cmod;
|
|
Packit |
9741aa |
p->etdmex = mexgrp;
|
|
Packit |
9741aa |
p->etdpex = pexgrp;
|
|
Packit |
9741aa |
p->etdsrm = srm;
|
|
Packit |
9741aa |
return p;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* ETDREF: Retrieve the pointer to an element type definition.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
PETD etdref(ename)
|
|
Packit |
9741aa |
UNCH *ename; /* Element name (GI) with length byte.. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* ETDCAN: Cancel an element definition. The etd is freed and is removed
|
|
Packit |
9741aa |
from the hash table, but its model and other pointers are not freed.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
VOID etdcan(ename)
|
|
Packit |
9741aa |
UNCH *ename; /* GI name (with length and EOS). */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
PETD p;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
|
|
Packit |
9741aa |
frem((UNIV)p);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* SYMBOL TABLE FUNCTIONS: These functions manage hash tables that are used
|
|
Packit |
9741aa |
for entities, element type definitions, IDs, and other purposes. The
|
|
Packit |
9741aa |
interface will be expanded in the future to include multiple environments,
|
|
Packit |
9741aa |
probably by creating arrays of the present hash tables with each table
|
|
Packit |
9741aa |
in the array corresponding to an environment level.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
/* HASH: Form hash value for a string.
|
|
Packit |
9741aa |
From the Dragon Book, p436.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
int hash(s, hashsize)
|
|
Packit |
9741aa |
UNCH *s; /* String to be hashed. */
|
|
Packit |
9741aa |
int hashsize; /* Size of hash table array. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
unsigned long h = 0, g;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
while (*s != 0) {
|
|
Packit |
9741aa |
h <<= 4;
|
|
Packit |
9741aa |
h += *s++;
|
|
Packit |
9741aa |
if ((g = h & 0xf0000000) != 0) {
|
|
Packit |
9741aa |
h ^= g >> 24;
|
|
Packit |
9741aa |
h ^= g;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return (int)(h % hashsize);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* HFIND: Look for a name in a hash table.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
struct hash *hfind(htab, s, h)
|
|
Packit |
9741aa |
struct hash *htab[]; /* Hash table. */
|
|
Packit |
9741aa |
UNCH *s; /* Entity name. */
|
|
Packit |
9741aa |
int h; /* Hash value for entity name. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
struct hash *np;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (np = htab[h]; np != 0; np = np->enext)
|
|
Packit |
9741aa |
if (ustrcmp(s, np->ename) == 0) return np; /* Found it. */
|
|
Packit |
9741aa |
return (struct hash *)0; /* Not found. */
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* HIN: Locates an entry in a hash table, or allocates a new one.
|
|
Packit |
9741aa |
Returns a pointer to a structure containing a name
|
|
Packit |
9741aa |
and a pointer to the next entry. Other data in the
|
|
Packit |
9741aa |
structure must be maintained by the caller.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
struct hash *hin(htab, name, h, size)
|
|
Packit |
9741aa |
struct hash *htab[]; /* Hash table. */
|
|
Packit |
9741aa |
UNCH *name; /* Entity name. */
|
|
Packit |
9741aa |
int h; /* Hash value for entity name. */
|
|
Packit |
9741aa |
UNS size; /* Size of structures pointed to by table. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
struct hash *np;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if ((np = hfind(htab, name, h))!=0) return np; /* Return if name found. */
|
|
Packit |
9741aa |
/* Allocate space for structure and name. */
|
|
Packit |
9741aa |
np = (struct hash *)rmalloc(size + name[0]);
|
|
Packit |
9741aa |
np->ename = (UNCH *)np + size;
|
|
Packit |
9741aa |
memcpy(np->ename, name, name[0]); /* Store name in it. */
|
|
Packit |
9741aa |
np->enext = htab[h]; /* 1st entry is now 2nd.*/
|
|
Packit |
9741aa |
htab[h] = np; /* New entry is now 1st.*/
|
|
Packit |
9741aa |
return np; /* Return new entry ptr. */
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* HOUT: Remove an entry from a hash table and return its pointer.
|
|
Packit |
9741aa |
The caller must free any pointers in the entry and then
|
|
Packit |
9741aa |
free the entry itself if that is what is desired; this
|
|
Packit |
9741aa |
routine does not free any storage.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
struct hash *hout(htab, s, h)
|
|
Packit |
9741aa |
struct hash *htab[]; /* Hash table. */
|
|
Packit |
9741aa |
UNCH *s; /* Search argument entry name. */
|
|
Packit |
9741aa |
int h; /* Hash value for search entry name. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
struct hash **pp;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (pp = &htab[h]; *pp != 0; pp = &(*pp)->enext)
|
|
Packit |
9741aa |
if (ustrcmp(s, (*pp)->ename) == 0) { /* Found it. */
|
|
Packit |
9741aa |
struct hash *tem = *pp;
|
|
Packit |
9741aa |
*pp = (*pp)->enext;
|
|
Packit |
9741aa |
return tem;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return 0; /* NULL if not found; else ptr. */
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* SAVESTR: Save a null-terminated string
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
UNCH *savestr(s)
|
|
Packit |
9741aa |
UNCH *s;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
UNCH *rp;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
rp = (UNCH *)rmalloc(ustrlen(s) + 1);
|
|
Packit |
9741aa |
ustrcpy(rp, s);
|
|
Packit |
9741aa |
return rp;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* SAVENM: Save a name (with length and EOS)
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
UNCH *savenm(s)
|
|
Packit |
9741aa |
UNCH *s;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
UNCH *p;
|
|
Packit |
9741aa |
p = (UNCH *)rmalloc(*s);
|
|
Packit |
9741aa |
memcpy(p, s, *s);
|
|
Packit |
9741aa |
return p;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* REPLACE: Free the storage for the old string (p) and store the new (s).
|
|
Packit |
9741aa |
If the specified ptr is NULL, don't free it.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
UNCH *replace(p, s)
|
|
Packit |
9741aa |
UNCH *p;
|
|
Packit |
9741aa |
UNCH *s;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
if (p) frem((UNIV)p); /* Free old storage (if any). */
|
|
Packit |
9741aa |
if (!s) return(s); /* Return NULL if new string is NULL. */
|
|
Packit |
9741aa |
return savestr(s);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* RMALLOC: Interface to memory allocation with error handling.
|
|
Packit |
9741aa |
If storage is not available, fatal error message is issued.
|
|
Packit |
9741aa |
Storage is initialized to zeros.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
UNIV rmalloc(size)
|
|
Packit |
9741aa |
unsigned size; /* Number of bytes of initialized storage. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
UNIV p = (UNIV)calloc(size, 1);
|
|
Packit |
9741aa |
if (!p) exiterr(33, (struct parse *)0);
|
|
Packit |
9741aa |
return p;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
UNIV rrealloc(p, n)
|
|
Packit |
9741aa |
UNIV p;
|
|
Packit |
9741aa |
UNS n;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
UNIV r = realloc(p, n);
|
|
Packit |
9741aa |
if (!r)
|
|
Packit |
9741aa |
exiterr(33, (struct parse *)0);
|
|
Packit |
9741aa |
return r;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
UNCH *pt;
|
|
Packit |
9741aa |
/* FREM: Free specified memory area gotten with rmalloc().
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
VOID frem(ptr)
|
|
Packit |
9741aa |
UNIV ptr; /* Memory area to be freed. */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
free(ptr);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* MAPSRCH: Find a string in a table and return its associated value.
|
|
Packit |
9741aa |
The last entry must be a dummy consisting of a NULL pointer for
|
|
Packit |
9741aa |
the string and whatever return code is desired if the
|
|
Packit |
9741aa |
string is not found in the table.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
int mapsrch(maptab, name)
|
|
Packit |
9741aa |
struct map maptab[];
|
|
Packit |
9741aa |
UNCH *name;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
int i = 0;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
do {
|
|
Packit |
9741aa |
UNCH *mapnm, *nm;
|
|
Packit |
9741aa |
for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
|
|
Packit |
9741aa |
if (!*nm++) return maptab[i].mapdata;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
} while (maptab[++i].mapnm);
|
|
Packit |
9741aa |
return maptab[i].mapdata;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* IDDEF: Define an ID control block; return -1 if it already exists.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
int iddef(iname)
|
|
Packit |
9741aa |
UNCH *iname; /* ID name (with length and EOS). */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
PID p;
|
|
Packit |
9741aa |
struct fwdref *r;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
|
|
Packit |
9741aa |
if (p->iddefed) return(-1);
|
|
Packit |
9741aa |
p->iddefed = 1;
|
|
Packit |
9741aa |
TRACEID("IDDEF", p);
|
|
Packit |
9741aa |
/* Delete any forward references. */
|
|
Packit |
9741aa |
r = p->idrl;
|
|
Packit |
9741aa |
p->idrl = 0;
|
|
Packit |
9741aa |
while (r) {
|
|
Packit |
9741aa |
struct fwdref *tem = r->next;
|
|
Packit |
9741aa |
if (r->msg)
|
|
Packit |
9741aa |
msgsfree(r->msg);
|
|
Packit |
9741aa |
frem((UNIV)r);
|
|
Packit |
9741aa |
r = tem;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return(0);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* IDREF: Store a reference to an ID and define the ID if it doesn't yet exist.
|
|
Packit |
9741aa |
Return 0 if already defined, otherwise pointer to a fwdref.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
struct fwdref *idref(iname)
|
|
Packit |
9741aa |
UNCH *iname; /* ID name (with length and EOS). */
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
PID p;
|
|
Packit |
9741aa |
int hnum;
|
|
Packit |
9741aa |
struct fwdref *rp;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0)
|
|
Packit |
9741aa |
p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
|
|
Packit |
9741aa |
if (p->iddefed)
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
rp = (struct fwdref *)rmalloc(FWDREFSZ);
|
|
Packit |
9741aa |
rp->next = p->idrl;
|
|
Packit |
9741aa |
p->idrl = rp;
|
|
Packit |
9741aa |
rp->msg = 0;
|
|
Packit |
9741aa |
TRACEID("IDREF", p);
|
|
Packit |
9741aa |
return rp;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* IDRCK: Check idrefs.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
VOID idrck()
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
int i;
|
|
Packit |
9741aa |
PID p;
|
|
Packit |
9741aa |
struct fwdref *r;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (i = 0; i < IDHASH; i++)
|
|
Packit |
9741aa |
for (p = itab[i]; p; p = p->idnext)
|
|
Packit |
9741aa |
if (!p->iddefed)
|
|
Packit |
9741aa |
for (r = p->idrl; r; r = r->next)
|
|
Packit |
9741aa |
svderr(r->msg);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* NTOA: Converts a positive integer to an ASCII string (abuf)
|
|
Packit |
9741aa |
No leading zeros are generated.
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
UNCH *ntoa(i)
|
|
Packit |
9741aa |
int i;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
static UNCH buf[1 + 3*sizeof(int) + 1];
|
|
Packit |
9741aa |
sprintf((char *)buf, "%d", i);
|
|
Packit |
9741aa |
return buf;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/*
|
|
Packit |
9741aa |
Local Variables:
|
|
Packit |
9741aa |
c-indent-level: 5
|
|
Packit |
9741aa |
c-continued-statement-offset: 5
|
|
Packit |
9741aa |
c-brace-offset: -5
|
|
Packit |
9741aa |
c-argdecl-indent: 0
|
|
Packit |
9741aa |
c-label-offset: -5
|
|
Packit |
9741aa |
comment-column: 30
|
|
Packit |
9741aa |
End:
|
|
Packit |
9741aa |
*/
|