Blame sgmls-1.1/serv.c

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
*/