Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtdocbook / sgmls / serv.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
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.
28 */
29 PETD etddef(ename)
30 UNCH *ename;                  /* Element name (GI) with length byte. */
31 {
32      PETD p;                  /* Pointer to an etd. */
33      int hnum;                /* Hash number for ename. */
34
35      if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
36           p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
37      }
38      return p;
39 }
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.
44 */
45 #ifdef USE_PROTOTYPES
46 PETD etdset(PETD p, UNCH fmin, struct thdr *cmod, PETD *mexgrp, PETD *pexgrp,
47             struct entity **srm)
48 #else
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. */
56 #endif
57 {
58      p->etdmin |= fmin;
59      p->etdmod = cmod;
60      p->etdmex = mexgrp;
61      p->etdpex = pexgrp;
62      p->etdsrm = srm;
63      return p;
64 }
65 /* ETDREF: Retrieve the pointer to an element type definition.
66 */
67 PETD etdref(ename)
68 UNCH *ename;                  /* Element name (GI) with length byte.. */
69 {
70
71      return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
72 }
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.
75 */
76 VOID etdcan(ename)
77 UNCH *ename;                  /* GI name (with length and EOS). */
78 {
79      PETD p;
80
81      if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
82           frem((UNIV)p);
83 }
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.
89 */
90 /* HASH: Form hash value for a string.
91          From the Dragon Book, p436.
92 */
93 int hash(s, hashsize)
94 UNCH *s;                      /* String to be hashed. */
95 int hashsize;                 /* Size of hash table array. */
96 {
97      unsigned long h = 0, g;
98      
99      while (*s != 0) {
100           h <<= 4;
101           h += *s++;
102           if ((g = h & 0xf0000000) != 0) {
103                h ^= g >> 24;
104                h ^= g;
105           }
106      }
107      return (int)(h % hashsize);
108 }
109 /* HFIND: Look for a name in a hash table.
110 */
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. */
115 {
116      struct hash *np;
117
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. */
121 }
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.
126 */
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. */
132 {
133      struct hash *np;
134
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. */
143 }
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.
148 */
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. */
153 {
154      struct hash **pp;
155
156      for (pp = &htab[h]; *pp != 0; pp = &(*pp)->enext)
157           if (ustrcmp(s, (*pp)->ename) == 0) {   /* Found it. */
158                struct hash *tem = *pp;
159                *pp = (*pp)->enext;
160                return tem;
161           }
162      return 0;                /* NULL if not found; else ptr. */
163 }
164 /* SAVESTR: Save a null-terminated string
165 */
166 UNCH *savestr(s)
167 UNCH *s;
168 {
169      UNCH *rp;
170
171      rp = (UNCH *)rmalloc(ustrlen(s) + 1);
172      ustrcpy(rp, s);
173      return rp;
174 }
175 /* SAVENM: Save a name (with length and EOS)
176 */
177 UNCH *savenm(s)
178 UNCH *s;
179 {
180      UNCH *p;
181      p = (UNCH *)rmalloc(*s);
182      memcpy(p, s, *s);
183      return p;
184 }
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.
187 */
188 UNCH *replace(p, s)
189 UNCH *p;
190 UNCH *s;
191 {
192      if (p) frem((UNIV)p);               /* Free old storage (if any). */
193      if (!s) return(s);            /* Return NULL if new string is NULL. */
194      return savestr(s);
195 }
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.
199 */
200 UNIV rmalloc(size)
201 unsigned size;                /* Number of bytes of initialized storage. */
202 {
203      UNIV p = (UNIV)calloc(size, 1);
204      if (!p) exiterr(33, (struct parse *)0);
205      return p;
206 }
207 UNIV rrealloc(p, n)
208 UNIV p;
209 UNS n;
210 {
211      UNIV r = realloc(p, n);
212      if (!r)
213           exiterr(33, (struct parse *)0);
214      return r;
215 }
216
217 UNCH *pt;
218 /* FREM: Free specified memory area gotten with rmalloc().
219 */
220 VOID frem(ptr)
221 UNIV ptr;                     /* Memory area to be freed. */
222 {
223      free(ptr);
224 }
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.
229 */
230 int mapsrch(maptab, name)
231 struct map maptab[];
232 UNCH *name;
233 {
234      int i = 0;
235
236      do {
237           UNCH *mapnm, *nm;
238           for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
239                if (!*nm++) return maptab[i].mapdata;
240           }
241      } while (maptab[++i].mapnm);
242      return maptab[i].mapdata;
243 }
244 /* IDDEF: Define an ID control block; return -1 if it already exists.
245 */
246 int iddef(iname)
247 UNCH *iname;                  /* ID name (with length and EOS). */
248 {
249      PID p;
250      struct fwdref *r;
251
252      p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
253      if (p->iddefed) return(-1);
254      p->iddefed = 1;
255      TRACEID("IDDEF", p);
256      /* Delete any forward references. */
257      r = p->idrl;
258      p->idrl = 0;
259      while (r) {
260           struct fwdref *tem = r->next;
261           if (r->msg)
262                msgsfree(r->msg);
263           frem((UNIV)r);
264           r = tem;
265      }
266      return(0);
267 }
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.
270 */
271 struct fwdref *idref(iname)
272 UNCH *iname;                  /* ID name (with length and EOS). */
273 {
274      PID p;
275      int hnum;
276      struct fwdref *rp;
277
278      if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0)
279           p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
280      if (p->iddefed)
281           return 0;
282      rp = (struct fwdref *)rmalloc(FWDREFSZ);
283      rp->next = p->idrl;
284      p->idrl = rp;
285      rp->msg = 0;
286      TRACEID("IDREF", p);
287      return rp;
288 }
289 /* IDRCK: Check idrefs.
290 */
291 VOID idrck()
292 {
293      int i;
294      PID p;
295      struct fwdref *r;
296
297      for (i = 0; i < IDHASH; i++)
298           for (p = itab[i]; p; p = p->idnext)
299                if (!p->iddefed)
300                     for (r = p->idrl; r; r = r->next)
301                          svderr(r->msg);
302 }
303 /* NTOA: Converts a positive integer to an ASCII string (abuf)
304          No leading zeros are generated.
305 */
306 UNCH *ntoa(i)
307 int i;
308 {
309      static UNCH buf[1 + 3*sizeof(int) + 1];
310      sprintf((char *)buf, "%d", i);
311      return buf;
312 }
313 /*
314 Local Variables:
315 c-indent-level: 5
316 c-continued-statement-offset: 5
317 c-brace-offset: -5
318 c-argdecl-indent: 0
319 c-label-offset: -5
320 comment-column: 30
321 End:
322 */