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