2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: serv.c /main/3 1996/06/19 17:17:10 drk $ */
24 #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
25 /* ETDDEF: Define an element type definition.
26 Use an existing one if there is one; otherwise create one, which
27 rmalloc initializes to zero which shows it is a virgin etd.
30 UNCH *ename; /* Element name (GI) with length byte. */
32 PETD p; /* Pointer to an etd. */
33 int hnum; /* Hash number for ename. */
35 if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
36 p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
40 /* ETDSET: Store data in an element type definition.
41 The etd must be valid and virgin (except for adl and etdmin).
42 As an etd cannot be modified, there is no checking for existing
43 pointers and no freeing of their storage.
46 PETD etdset(PETD p, UNCH fmin, struct thdr *cmod, PETD *mexgrp, PETD *pexgrp,
49 PETD etdset(p, fmin, cmod, mexgrp, pexgrp, srm)
50 PETD p; /* Pointer to an etd. */
51 UNCH fmin; /* Minimization bit flags. */
52 struct thdr *cmod; /* Pointer to content model. */
53 PETD *mexgrp; /* Pointers to minus and plus exception lists. */
54 PETD *pexgrp; /* Pointers to minus and plus exception lists. */
55 struct entity **srm; /* Short reference map. */
65 /* ETDREF: Retrieve the pointer to an element type definition.
68 UNCH *ename; /* Element name (GI) with length byte.. */
71 return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
73 /* ETDCAN: Cancel an element definition. The etd is freed and is removed
74 from the hash table, but its model and other pointers are not freed.
77 UNCH *ename; /* GI name (with length and EOS). */
81 if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
84 /* SYMBOL TABLE FUNCTIONS: These functions manage hash tables that are used
85 for entities, element type definitions, IDs, and other purposes. The
86 interface will be expanded in the future to include multiple environments,
87 probably by creating arrays of the present hash tables with each table
88 in the array corresponding to an environment level.
90 /* HASH: Form hash value for a string.
91 From the Dragon Book, p436.
94 UNCH *s; /* String to be hashed. */
95 int hashsize; /* Size of hash table array. */
97 unsigned long h = 0, g;
102 if ((g = h & 0xf0000000) != 0) {
107 return (int)(h % hashsize);
109 /* HFIND: Look for a name in a hash table.
111 struct hash *hfind(htab, s, h)
112 struct hash *htab[]; /* Hash table. */
113 UNCH *s; /* Entity name. */
114 int h; /* Hash value for entity name. */
118 for (np = htab[h]; np != 0; np = np->enext)
119 if (ustrcmp(s, np->ename) == 0) return np; /* Found it. */
120 return (struct hash *)0; /* Not found. */
122 /* HIN: Locates an entry in a hash table, or allocates a new one.
123 Returns a pointer to a structure containing a name
124 and a pointer to the next entry. Other data in the
125 structure must be maintained by the caller.
127 struct hash *hin(htab, name, h, size)
128 struct hash *htab[]; /* Hash table. */
129 UNCH *name; /* Entity name. */
130 int h; /* Hash value for entity name. */
131 UNS size; /* Size of structures pointed to by table. */
135 if ((np = hfind(htab, name, h))!=0) return np; /* Return if name found. */
136 /* Allocate space for structure and name. */
137 np = (struct hash *)rmalloc(size + name[0]);
138 np->ename = (UNCH *)np + size;
139 memcpy(np->ename, name, name[0]); /* Store name in it. */
140 np->enext = htab[h]; /* 1st entry is now 2nd.*/
141 htab[h] = np; /* New entry is now 1st.*/
142 return np; /* Return new entry ptr. */
144 /* HOUT: Remove an entry from a hash table and return its pointer.
145 The caller must free any pointers in the entry and then
146 free the entry itself if that is what is desired; this
147 routine does not free any storage.
149 struct hash *hout(htab, s, h)
150 struct hash *htab[]; /* Hash table. */
151 UNCH *s; /* Search argument entry name. */
152 int h; /* Hash value for search entry name. */
156 for (pp = &htab[h]; *pp != 0; pp = &(*pp)->enext)
157 if (ustrcmp(s, (*pp)->ename) == 0) { /* Found it. */
158 struct hash *tem = *pp;
162 return 0; /* NULL if not found; else ptr. */
164 /* SAVESTR: Save a null-terminated string
171 rp = (UNCH *)rmalloc(ustrlen(s) + 1);
175 /* SAVENM: Save a name (with length and EOS)
181 p = (UNCH *)rmalloc(*s);
185 /* REPLACE: Free the storage for the old string (p) and store the new (s).
186 If the specified ptr is NULL, don't free it.
192 if (p) frem((UNIV)p); /* Free old storage (if any). */
193 if (!s) return(s); /* Return NULL if new string is NULL. */
196 /* RMALLOC: Interface to memory allocation with error handling.
197 If storage is not available, fatal error message is issued.
198 Storage is initialized to zeros.
201 unsigned size; /* Number of bytes of initialized storage. */
203 UNIV p = (UNIV)calloc(size, 1);
204 if (!p) exiterr(33, (struct parse *)0);
211 UNIV r = realloc(p, n);
213 exiterr(33, (struct parse *)0);
218 /* FREM: Free specified memory area gotten with rmalloc().
221 UNIV ptr; /* Memory area to be freed. */
225 /* MAPSRCH: Find a string in a table and return its associated value.
226 The last entry must be a dummy consisting of a NULL pointer for
227 the string and whatever return code is desired if the
228 string is not found in the table.
230 int mapsrch(maptab, name)
238 for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
239 if (!*nm++) return maptab[i].mapdata;
241 } while (maptab[++i].mapnm);
242 return maptab[i].mapdata;
244 /* IDDEF: Define an ID control block; return -1 if it already exists.
247 UNCH *iname; /* ID name (with length and EOS). */
252 p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
253 if (p->iddefed) return(-1);
256 /* Delete any forward references. */
260 struct fwdref *tem = r->next;
268 /* IDREF: Store a reference to an ID and define the ID if it doesn't yet exist.
269 Return 0 if already defined, otherwise pointer to a fwdref.
271 struct fwdref *idref(iname)
272 UNCH *iname; /* ID name (with length and EOS). */
278 if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0)
279 p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
282 rp = (struct fwdref *)rmalloc(FWDREFSZ);
289 /* IDRCK: Check idrefs.
297 for (i = 0; i < IDHASH; i++)
298 for (p = itab[i]; p; p = p->idnext)
300 for (r = p->idrl; r; r = r->next)
303 /* NTOA: Converts a positive integer to an ASCII string (abuf)
304 No leading zeros are generated.
309 static UNCH buf[1 + 3*sizeof(int) + 1];
310 sprintf((char *)buf, "%d", i);
316 c-continued-statement-offset: 5