1 #include "sgmlincl.h"         /* #INCLUDE statements for SGML parser. */
2 /* ETDDEF: Define an element type definition.
3            Use an existing one if there is one; otherwise create one, which
4            rmalloc initializes to zero which shows it is a virgin etd.
5 */
etddef(ename)6 PETD etddef(ename)
7 UNCH *ename;                  /* Element name (GI) with length byte. */
8 {
9      PETD p;                  /* Pointer to an etd. */
10      int hnum;                /* Hash number for ename. */
11 
12      if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
13           p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
14      }
15      return p;
16 }
17 /* ETDSET: Store data in an element type definition.
18            The etd must be valid and virgin (except for adl and etdmin).
19            As an etd cannot be modified, there is no checking for existing
20            pointers and no freeing of their storage.
21 */
22 #ifdef USE_PROTOTYPES
etdset(PETD p,UNCH fmin,struct thdr * cmod,PETD * mexgrp,PETD * pexgrp,struct entity ** srm)23 PETD etdset(PETD p, UNCH fmin, struct thdr *cmod, PETD *mexgrp, PETD *pexgrp,
24 	    struct entity **srm)
25 #else
26 PETD etdset(p, fmin, cmod, mexgrp, pexgrp, srm)
27 PETD p;                       /* Pointer to an etd. */
28 UNCH fmin;                    /* Minimization bit flags. */
29 struct thdr *cmod;            /* Pointer to content model. */
30 PETD *mexgrp;                 /* Pointers to minus and plus exception lists. */
31 PETD *pexgrp;                 /* Pointers to minus and plus exception lists. */
32 struct entity **srm;          /* Short reference map. */
33 #endif
34 {
35      p->etdmin |= fmin;
36      p->etdmod = cmod;
37      p->etdmex = mexgrp;
38      p->etdpex = pexgrp;
39      p->etdsrm = srm;
40      return p;
41 }
42 /* ETDREF: Retrieve the pointer to an element type definition.
43 */
etdref(ename)44 PETD etdref(ename)
45 UNCH *ename;                  /* Element name (GI) with length byte.. */
46 {
47 
48      return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
49 }
50 /* ETDCAN: Cancel an element definition.  The etd is freed and is removed
51            from the hash table, but its model and other pointers are not freed.
52 */
etdcan(ename)53 VOID etdcan(ename)
54 UNCH *ename;                  /* GI name (with length and EOS). */
55 {
56      PETD p;
57 
58      if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
59           frem((UNIV)p);
60 }
61 /* SYMBOL TABLE FUNCTIONS: These functions manage hash tables that are used
62    for entities, element type definitions, IDs, and other purposes.  The
63    interface will be expanded in the future to include multiple environments,
64    probably by creating arrays of the present hash tables with each table
65    in the array corresponding to an environment level.
66 */
67 /* HASH: Form hash value for a string.
68          From the Dragon Book, p436.
69 */
hash(s,hashsize)70 int hash(s, hashsize)
71 UNCH *s;                      /* String to be hashed. */
72 int hashsize;                 /* Size of hash table array. */
73 {
74      unsigned long h = 0, g;
75 
76      while (*s != 0) {
77 	  h <<= 4;
78 	  h += *s++;
79 	  if ((g = h & 0xf0000000) != 0) {
80 	       h ^= g >> 24;
81 	       h ^= g;
82 	  }
83      }
84      return (int)(h % hashsize);
85 }
86 /* HFIND: Look for a name in a hash table.
87 */
hfind(htab,s,h)88 struct hash *hfind(htab, s, h)
89 struct hash *htab[];          /* Hash table. */
90 UNCH *s;                      /* Entity name. */
91 int h;                        /* Hash value for entity name. */
92 {
93      struct hash *np;
94 
95      for (np = htab[h]; np != 0; np = np->enext)
96           if (ustrcmp(s, np->ename) == 0) return np;    /* Found it. */
97      return (struct hash *)0;                          /* Not found. */
98 }
99 /* HIN: Locates an entry in a hash table, or allocates a new one.
100         Returns a pointer to a structure containing a name
101         and a pointer to the next entry.  Other data in the
102         structure must be maintained by the caller.
103 */
hin(htab,name,h,size)104 struct hash *hin(htab, name, h, size)
105 struct hash *htab[];          /* Hash table. */
106 UNCH *name;                   /* Entity name. */
107 int h;                        /* Hash value for entity name. */
108 UNS size;                     /* Size of structures pointed to by table. */
109 {
110      struct hash *np;
111 
112      if ((np = hfind(htab, name, h))!=0) return np;  /* Return if name found. */
113      /* Allocate space for structure and name. */
114      np = (struct hash *)rmalloc(size + name[0]);
115      np->ename = (UNCH *)np + size;
116      memcpy(np->ename, name, name[0]);            /* Store name in it. */
117      np->enext = htab[h];                         /* 1st entry is now 2nd.*/
118      htab[h] = np;                                /* New entry is now 1st.*/
119      return np;                                   /* Return new entry ptr. */
120 }
121 /* HOUT: Remove an entry from a hash table and return its pointer.
122          The caller must free any pointers in the entry and then
123          free the entry itself if that is what is desired; this
124          routine does not free any storage.
125 */
hout(htab,s,h)126 struct hash *hout(htab, s, h)
127 struct hash *htab[];          /* Hash table. */
128 UNCH *s;                      /* Search argument entry name. */
129 int h;                        /* Hash value for search entry name. */
130 {
131      struct hash **pp;
132 
133      for (pp = &htab[h]; *pp != 0; pp = &(*pp)->enext)
134           if (ustrcmp(s, (*pp)->ename) == 0) {   /* Found it. */
135 	       struct hash *tem = *pp;
136 	       *pp = (*pp)->enext;
137                return tem;
138           }
139      return 0;                /* NULL if not found; else ptr. */
140 }
141 /* SAVESTR: Save a null-terminated string
142 */
savestr(s)143 UNCH *savestr(s)
144 UNCH *s;
145 {
146      UNCH *rp;
147 
148      rp = (UNCH *)rmalloc(ustrlen(s) + 1);
149      ustrcpy(rp, s);
150      return rp;
151 }
152 /* SAVENM: Save a name (with length and EOS)
153 */
savenm(s)154 UNCH *savenm(s)
155 UNCH *s;
156 {
157      UNCH *p;
158      p = (UNCH *)rmalloc(*s);
159      memcpy(p, s, *s);
160      return p;
161 }
162 /* REPLACE: Free the storage for the old string (p) and store the new (s).
163             If the specified ptr is NULL, don't free it.
164 */
replace(p,s)165 UNCH *replace(p, s)
166 UNCH *p;
167 UNCH *s;
168 {
169      if (p) frem((UNIV)p);               /* Free old storage (if any). */
170      if (!s) return(s);            /* Return NULL if new string is NULL. */
171      return savestr(s);
172 }
173 /* RMALLOC: Interface to memory allocation with error handling.
174             If storage is not available, fatal error message is issued.
175             Storage is initialized to zeros.
176 */
rmalloc(size)177 UNIV rmalloc(size)
178 unsigned size;                /* Number of bytes of initialized storage. */
179 {
180      UNIV p = (UNIV)calloc(size, 1);
181      if (!p) exiterr(33, (struct parse *)0);
182      return p;
183 }
rrealloc(p,n)184 UNIV rrealloc(p, n)
185 UNIV p;
186 UNS n;
187 {
188      UNIV r = realloc(p, n);
189      if (!r)
190 	  exiterr(33, (struct parse *)0);
191      return r;
192 }
193 
194 UNCH *pt;
195 /* FREM: Free specified memory area gotten with rmalloc().
196 */
frem(ptr)197 VOID frem(ptr)
198 UNIV ptr;                     /* Memory area to be freed. */
199 {
200      free(ptr);
201 }
202 /* MAPSRCH: Find a string in a table and return its associated value.
203             The last entry must be a dummy consisting of a NULL pointer for
204             the string and whatever return code is desired if the
205             string is not found in the table.
206 */
mapsrch(maptab,name)207 int mapsrch(maptab, name)
208 struct map maptab[];
209 UNCH *name;
210 {
211      int i = 0;
212 
213      do {
214 	  UNCH *mapnm, *nm;
215           for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
216                if (!*nm++) return maptab[i].mapdata;
217           }
218      } while (maptab[++i].mapnm);
219      return maptab[i].mapdata;
220 }
221 /* IDDEF: Define an ID control block; return -1 if it already exists.
222 */
iddef(iname)223 int iddef(iname)
224 UNCH *iname;                  /* ID name (with length and EOS). */
225 {
226      PID p;
227      struct fwdref *r;
228 
229      p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
230      if (p->iddefed) return(-1);
231      p->iddefed = 1;
232      TRACEID("IDDEF", p);
233      /* Delete any forward references. */
234      r = p->idrl;
235      p->idrl = 0;
236      while (r) {
237 	  struct fwdref *tem = r->next;
238 	  if (r->msg)
239 	       msgsfree(r->msg);
240 	  frem((UNIV)r);
241 	  r = tem;
242      }
243      return(0);
244 }
245 /* IDREF: Store a reference to an ID and define the ID if it doesn't yet exist.
246           Return 0 if already defined, otherwise pointer to a fwdref.
247 */
idref(iname)248 struct fwdref *idref(iname)
249 UNCH *iname;                  /* ID name (with length and EOS). */
250 {
251      PID p;
252      int hnum;
253      struct fwdref *rp;
254 
255      if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0)
256           p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
257      if (p->iddefed)
258 	  return 0;
259      rp = (struct fwdref *)rmalloc(FWDREFSZ);
260      rp->next = p->idrl;
261      p->idrl = rp;
262      rp->msg = 0;
263      TRACEID("IDREF", p);
264      return rp;
265 }
266 /* IDRCK: Check idrefs.
267 */
idrck()268 VOID idrck()
269 {
270      int i;
271      PID p;
272      struct fwdref *r;
273 
274      for (i = 0; i < IDHASH; i++)
275 	  for (p = itab[i]; p; p = p->idnext)
276 	       if (!p->iddefed)
277 		    for (r = p->idrl; r; r = r->next)
278 			 svderr(r->msg);
279 }
280 /* NTOA: Converts a positive integer to an ASCII string (abuf)
281          No leading zeros are generated.
282 */
ntoa(i)283 UNCH *ntoa(i)
284 int i;
285 {
286      static UNCH buf[1 + 3*sizeof(int) + 1];
287      sprintf((char *)buf, "%d", i);
288      return buf;
289 }
290 /*
291 Local Variables:
292 c-indent-level: 5
293 c-continued-statement-offset: 5
294 c-brace-offset: -5
295 c-argdecl-indent: 0
296 c-label-offset: -5
297 comment-column: 30
298 End:
299 */
300