home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / sgml / unix / sgmlc / modserv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  14.2 KB  |  334 lines

  1. /******************************************************************************/
  2. /* Implements frem() and rmalloc() to call memory management in SGMLMEM.C.    */
  3. /* IDCAN eliminated (conflicts with ISO 8879 ban on re-parsing.)              */
  4. /******************************************************************************/
  5. #include "sgmlincl.h"         /* #INCLUDE statements for SGML parser. */
  6. /******************************************************************************/
  7. /* ETDDEF: Define an element type definition.
  8.            Use an existing one if there is one; otherwise create one, which
  9.            rmalloc initializes to zero which shows it is a virgin etd.
  10. */
  11. PETD etddef(
  12. UNCH *ename)                  /* Element name (GI) with length byte. */
  13. {
  14.      PETD p;                  /* Pointer to an etd. */
  15.      int hnum;                /* Hash number for ename. */
  16.  
  17.      if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
  18.           p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
  19.      }
  20.      return p;
  21. }
  22. /******************************************************************************/
  23. /* ETDSET: Store data in an element type definition.
  24.            The etd must be valid and virgin (except for adl and etdmin).
  25.            As an etd cannot be modified, there is no checking for existing
  26.            pointers and no freeing of their storage.
  27. */
  28. /*lint +fvr                      Returned value may be ignored. */
  29. PETD etdset(
  30. /*lint -fvr                      Restore normal LINT processing. */
  31. PETD p,                       /* Pointer to an etd. */
  32. UNCH fmin,                    /* Minimization bit flags. */
  33. struct thdr *cmod,            /* Pointer to content model. */
  34. PETD *mexgrp,                 /* Pointers to minus and plus exception lists. */
  35. PETD *pexgrp,                 /* Pointers to minus and plus exception lists. */
  36. struct entity **srm)          /* Short reference map. */
  37. {
  38.      p->etdmin |= fmin;
  39.      p->etdmod = cmod;
  40.      p->etdmex = mexgrp;
  41.      p->etdpex = pexgrp;
  42.      p->etdsrm = srm;
  43.      return p;
  44. }
  45. /******************************************************************************/
  46. /* ETDREF: Retrieve the pointer to an element type definition.
  47. */
  48. PETD etdref(
  49. UNCH *ename)                  /* Element name (GI) with length byte.. */
  50. {
  51.  
  52.      return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
  53. }
  54. /******************************************************************************/
  55. /* ETDCAN: Cancel an element definition.  The etd is freed and is removed
  56.            from the hash table, but its model and other pointers are not freed.
  57. */
  58. VOID etdcan(
  59. UNCH *ename)                  /* GI name (with length and EOS). */
  60. {
  61.      PETD p;
  62.  
  63.      if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
  64.           frem((UNIV)p);
  65. }
  66. /******************************************************************************/
  67. /* SYMBOL TABLE FUNCTIONS: These functions manage hash tables that are used
  68.    for entities, element type definitions, IDs, and other purposes.  The
  69.    interface will be expanded in the future to include multiple environments,
  70.    probably by creating arrays of the present hash tables with each table
  71.    in the array corresponding to an environment level.
  72. */
  73. /******************************************************************************/
  74. /* HASH: Form hash value for a string.
  75.          A simple (and probably not practical) algorithm.
  76. */
  77. int hash(
  78. UNCH *s,                      /* String to be hashed (entity name). */
  79. int hashsize)                 /* Size of hash table array. */
  80. {
  81.      int hashval;
  82.  
  83.      for (hashval = 0; *s != EOS;) hashval += (int)*s++;
  84.      return (hashval % hashsize);
  85. }
  86. /******************************************************************************/
  87. /* HFIND: Look for a name in a hash table.
  88. */
  89. struct hash *hfind(
  90. struct hash *htab[],          /* Hash table. */
  91. UNCH *s,                      /* Entity name. */
  92. int h)                        /* Hash value for entity name. */
  93. {
  94.      struct hash *np;
  95.  
  96.      for (np = htab[h]; np != 0; np = np->enext)
  97.           if (strcmp(s, np->ename) == 0) return np;    /* Found it. */
  98.      return (struct hash *)0;                          /* Not found. */
  99. }
  100. /******************************************************************************/
  101. /* HIN: Locates an entry in a hash table, or allocates a new one.
  102.         Returns a pointer to a structure containing a name
  103.         and a pointer to the next entry.  Other data in the
  104.         structure must be maintained by the caller.
  105. */
  106. struct hash *hin(
  107. struct hash *htab[],          /* Hash table. */
  108. UNCH *name,                   /* Entity name. */
  109. int h,                        /* Hash value for entity name. */
  110. UNS size)                     /* Size of structures pointed to by table. */
  111. {
  112.      struct hash *np;
  113.  
  114.      if ((np = hfind(htab, name, h))!=0) return np;  /* Return if name found. */
  115.      np = (struct hash *)rmalloc(size);           /* Else allocate new entry. */
  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. /******************************************************************************/
  122. /* HOUT: Remove an entry from a hash table and return its pointer.
  123.          The caller must free any pointers in the entry and then
  124.          free the entry itself if that is what is desired; this
  125.          routine does not free any storage.
  126. */
  127. /*lint +fvr                      Returned value may be ignored. */
  128. struct hash *hout(
  129. /*lint -fvr                      Restore normal LINT processing. */
  130. struct hash *htab[],          /* Hash table. */
  131. UNCH *s,                      /* Search argument entry name. */
  132. int h)                        /* Hash value for search entry name. */
  133. {
  134.      struct hash *pp, *np;
  135.  
  136.      for (pp = np = htab[h]; np != 0; pp = np, np = np->enext) {
  137.           if (strcmp(s, np->ename) == 0) {   /* Found it. */
  138.                pp->enext = np->enext;        /* Past entry points to next. */
  139.                return np;
  140.           }
  141.      }
  142.      return (struct hash *)0;                /* NULL if not found; else ptr. */
  143. }
  144. /******************************************************************************/
  145. /* STRLSAVE: Save a string whose length is in its first byte.
  146.              The string is saved with the length byte.
  147. */
  148. UNCH *strlsave(
  149. UNCH *s)
  150. {
  151.      UNCH *rp;
  152.  
  153.      rp = rmalloc((UNS)*s);        /* Allocate storage for string. */
  154.      memcpy( rp , s, *s );             /* Copy string into new storage. */
  155.      return rp;                    /* Return pointer to stored string. */
  156. }
  157. /******************************************************************************/
  158. /* REPLACE: Free the storage for the old string (p) and store the new (s).
  159.             If the specified ptr is NULL, don't free it.
  160.             The string is saved with the length byte and EOS.
  161. */
  162. UNCH *replace(
  163. UNCH *p,
  164. UNCH *s)
  165. {
  166.      if (p) frem(p);               /* Free old storage (if any). */
  167.      if (!s) return(s);            /* Return NULL if new string is NULL. */
  168.      if ((p = rmalloc((UNS)*s))==0) { /* Allocate new uninitialized storage. */
  169.           sgmlerr(33, (struct parse *)0, NULL, NULL);
  170.           return NULL;
  171.      }
  172.      memcpy( p , s, *s );              /* Copy string into new storage. */
  173.      return p;                     /* Return pointer to stored string. */
  174. }
  175. /******************************************************************************/
  176. /* SANDWICH: Catenate a prefix and suffix to a string.
  177.              The prefix is placed ahead of it, the suffix after it, and
  178.              the correct length (including length byte and EOS) of the
  179.              catenated string into the length byte of the prefix.
  180.              All three strings start out with length and EOS bytes.
  181.              The pointer to the catenated string is returned.
  182. */
  183. UNCH *sandwich(
  184. UNCH *s,                      /* String, with length and EOS. */
  185. UNCH *pref,                   /* Prefix, with length and EOS. */
  186. UNCH *suff)                   /* Suffix, with length and EOS. */
  187. {
  188.      UNCH *pt;                /* Ptr to permanent storage for sandwich. */
  189.      UNS sz;                  /* Size of sandwich, with length and EOS. */
  190.  
  191.      pt = rmalloc(sz = *s+*pref+*suff-4);  /* Get storage for sandwich. */
  192.      memcpy( pt+1 , pref+1, *pref-2 );      /* Move prefix 1 byte after start. */
  193.      memcpy( pt+*pref-1 , s+1, *s-2 );      /* Move string after prefix. */
  194.      memcpy( pt+*pref+*s-3 , suff+1, *suff-1 ); /* Move suffix after string. */
  195.      *pt = (char)sz;                    /* Store size in length byte. */
  196.      return(pt);                        /* Return ptr to catenated string. */
  197. }
  198. /******************************************************************************/
  199. /* RMALLOC: Interface to memory allocation with error handling.
  200.             If storage is not available, fatal error message is issued.
  201.             Storage is initialized to zeros.
  202. */
  203. UNCH *rmalloc(
  204. unsigned size)                /* Number of bytes of initialized storage. */
  205. {
  206.      im.memarea = NULL;                      /* Clear return data. */
  207.      im.memsize = size;                      /* Size of area desired. */
  208.      im.memtype = MEMGET; sgmlmem(&im);      /* Call GET function. */
  209.      if (im.memarea!=NULL) return im.memarea;/* If ok, return pointer. */
  210.      /* else */ exiterr(33, (struct parse *)0);
  211.      /*lint -unreachable         There is no implied return at this point. */
  212.      return 0;                /* Avoid Borland C++ warning. */
  213. }
  214. /******************************************************************************/
  215. /* FREM: Free specified memory area gotten with rmalloc().
  216. */
  217. VOID frem(
  218. UNIV ptr)                     /* Memory area to be freed. */
  219. {
  220.      im.memarea = ptr;                       /* Area to free. */
  221.      im.memtype = MEMFREE; sgmlmem(&im);     /* Call FREE function. */
  222. }
  223. /******************************************************************************/
  224. /* MAPSRCH: Find a string in a table and return its associated value.
  225.             The last entry must be a dummy consisting of a NULL pointer for
  226.             the string and whatever return code is desired if the
  227.             string is not found in the table.
  228. */
  229. int mapsrch(
  230. struct map maptab[],
  231. UNCH *name)
  232. {
  233.      int i = 0;
  234.      UNCH *mapnm, *nm;
  235.  
  236.      do {
  237. #ifndef FINAL
  238.           if (dtrace) tracemap(
  239.                ((maptab==lex.s.dtb && maptab[i].mapdata<lex.s.prtmin)
  240.                    ? lex.s.pdtb[i] : maptab[i].mapnm), name, maptab[i].mapdata);
  241. #endif
  242.           for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
  243.                if (!*nm++) return maptab[i].mapdata;
  244.           }
  245.      } while (maptab[++i].mapnm);
  246.      return maptab[i].mapdata;
  247. }
  248. /******************************************************************************/
  249. /* IDDEF: Define an ID control block; return -1 if it already exists.
  250. */
  251. int iddef(
  252. UNCH *iname,                  /* ID name (with length and EOS). */
  253. UNCH *igi)                    /* GI of element in which ID or REF occurred. */
  254. {
  255.      PID p;
  256.  
  257.      p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
  258.      if (p->idl) return(-1);
  259.      p->idl = locdef((struct loc *)0, igi);
  260. #ifndef FINAL
  261.      if (itrace) traceid("IDDEF", p);
  262. #endif
  263.      return(0);
  264. }
  265. /******************************************************************************/
  266. /* IDREF: Store a reference to an ID and define the ID if it doesn't yet exist.
  267.           Return 1 if it existed, or 0 if newly defined.
  268. */
  269. int idref(
  270. UNCH *iname,                  /* ID name (with length and EOS). */
  271. UNCH *igi)                    /* GI of element in which ID or REF occurred. */
  272. {
  273.      PID p;
  274.      int hnum, rc;
  275.  
  276.      if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0){
  277.           p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
  278.           rc = 1;
  279.      }
  280.      p->idrl = locdef(p->idrl, igi);
  281. #ifndef FINAL
  282.      if (itrace) traceid("IDREF", p);
  283. #endif
  284.      return(!rc);
  285. }
  286. /******************************************************************************/
  287. /* IDGET: Return 1 if an ID exists; 0 if not.
  288. */
  289. int idget(
  290. UNCH *iname)                  /* ID name (with length and EOS). */
  291. {
  292.      return(hfind((THASH)itab, iname, hash(iname, IDHASH))!=0);
  293. }
  294. /******************************************************************************/
  295. /* LOCDEF: Create a location control block and store the current location
  296.            in it.  Return the pointer to the control block.
  297. */
  298. struct loc *locdef(
  299. struct loc *p,                /* Ptr to location chain. */
  300. UNCH *igi)                    /* GI of element in which ID or REF occurred. */
  301. {
  302.      struct loc *np;
  303.  
  304.      np = (struct loc *)rmalloc(LOCSZ);
  305.      np->lnext = p;           /* Next location in chain. */
  306.      np->letdgi = igi;        /* Element GI (with length and EOS). */
  307.      np->lename = ECBPTR->ename; /* Entity name with length and EOS. */
  308.      np->lrcnt = RCNT;        /* Source record number. */
  309.      np->lccnt = CCNT;        /* Source record chars since last RS. */
  310.      np->lfile = (ECB.estore>=ESFM) ? ECB.etx.x : 0;
  311.      return(np);
  312. }
  313. /******************************************************************************/
  314. /* NTOA: Converts a positive integer (i<1000) to an ASCII string (abuf)
  315.          in a permanent internal buffer (4 chars) whose ptr is returned.
  316.          No leading zeros are generated.
  317. */
  318. char *ntoa(
  319. int i)
  320. {
  321.      char *a = ntoabuf;       /* Ptr to current numeral in string. */
  322.  
  323.      if (i>=100) {                                     /* 3 digits only. */
  324.           *a++ = (char)('0' + i/100); i = i%100;
  325.           if (i>=10) {*a++ = (char)('0' + i/10); i = i%10;}    /* 2nd of 3. */
  326.           else *a++ = '0';
  327.      }
  328.      else if (i>=10) {*a++ = (char)('0'+i/10); i = i%10;}  /* 2 digits only. */
  329.      *a++ = (char)('0'+i);                             /* Last or sole digit. */
  330.      *a = 0;                                           /* End of string. */
  331.      return ntoabuf;
  332. }
  333. /******************************************************************************/
  334.