home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 10 / Fresh_Fish_10_2352.bin / new / dev / lang / sgmls / src / md2.c < prev    next >
C/C++ Source or Header  |  1994-07-10  |  30KB  |  793 lines

  1. #include "sgmlincl.h"         /* #INCLUDE statements for SGML parser. */
  2. /* MDENTITY: Process ENTITY declaration.
  3. */
  4. VOID mdentity(tbuf)
  5. UNCH *tbuf;                   /* Work area for tokenization[LITLEN+2]. */
  6. {
  7.      struct fpi fpicb;        /* Formal public identifier structure. */
  8.      struct fpi *fpis = &fpicb;  /* Ptr to current or #DEFAULT fpi. */
  9.      union etext etx;         /* Ptr to entity text. */
  10.      UNCH estore = ESM;       /* Entity storage class. */
  11.      struct entity *ecb;      /* Ptr to entity control block. */
  12.      int parmsw = 0;          /* 1=parameter entity declaration; 0 = not. */
  13.      int defltsw = 0;         /* 1=#DEFAULT declaration; 0=not. */
  14.      PNE pne = 0;             /* Ptr to N/C/SDATA entity control block. */
  15.  
  16.      mdname = key[KENTITY];  /* Declaration name for messages. */
  17.      subdcl = NULL;           /* No subject as yet. */
  18.      parmno = 0;              /* No parameters as yet. */
  19.      mdessv = es;             /* Save es for checking entity nesting. */
  20.      /* PARAMETER 1: Entity name.
  21.      */
  22.      pcbmd.newstate = 0;
  23.      parsemd(nmbuf, ENTCASE, &pcblitp, NAMELEN);
  24.      TRACEMD("1: entity nm");
  25.      switch (pcbmd.action) {
  26.      case PEN:
  27.           parsemd(nmbuf + 1, ENTCASE, &pcblitp, NAMELEN);
  28.           if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); return;}
  29.       if (nmbuf[1] == NAMELEN + 2) {
  30.            /* It was too long. */
  31.            nmbuf[0] = NAMELEN + 2;
  32.            nmbuf[NAMELEN + 1] = '\0';
  33.            mderr(65, (UNCH *)0, (UNCH *)0);
  34.       }
  35.       else
  36.            nmbuf[0] = nmbuf[1] + 1;    /* Increment length for PERO. */
  37.           nmbuf[1] = lex.d.pero;        /* Prefix PERO to name. */
  38.           parmsw = 1;                   /* Indicate parameter entity. */
  39.      case NAS:
  40.           break;
  41.      case RNS:           /* Reserved name started. */
  42.           if (ustrcmp(nmbuf+1, key[KDEFAULT])) {
  43.                mderr(118, nmbuf+1, key[KDEFAULT]);
  44.                return;
  45.           }
  46.           memcpy(nmbuf, indefent, *indefent);/* Copy #DEFAULT to name buffer. */
  47.           fpis = &fpidf;                /* Use #DEFAULT fpi if external. */
  48.           defltsw = 1;                  /* Indicate #DEFAULT is being defined.*/
  49.           break;
  50.      default:
  51.           mderr(122, (UNCH *)0, (UNCH *)0);
  52.           return;
  53.      }
  54.      subdcl = nmbuf+1;                  /* Subject name for error messages. */
  55.      /* PARAMETER 2: Entity text keyword (optional).
  56.      */
  57.      parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
  58.      TRACEMD("2: keyword");
  59.      switch (pcbmd.action) {
  60.      case NAS:
  61.           if ((estore = (UNCH)mapsrch(enttab, tbuf+1))==0) {
  62.            estore = parmsw ? ESP : ESF;
  63.                pne = (PNE)rmalloc(NESZ);
  64.                if (mdextid(tbuf, fpis, nmbuf+1+parmsw, &estore, pne)==0)
  65.             return;
  66.                if (defltsw) etx.x = NULL;
  67.                else if ((etx.x = entgen(&fpicb))==0) {
  68.             if (parmsw)
  69.                  mderr(148, nmbuf+2, (UNCH *)0);
  70.             else
  71.                  mderr(147, nmbuf+1, (UNCH *)0);
  72.            }
  73.                goto parm4;
  74.           }
  75.           if (parmsw && (estore==ESX || estore==ESC)) {
  76.                mderr(38, tbuf+1, (UNCH *)0);
  77.                estore = ESM;
  78.           }
  79.           parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
  80.           break;
  81.      default:
  82.           estore = ESM;
  83.           break;
  84.      }
  85.      /* PARAMETER 3: Parameter literal.
  86.      */
  87.      TRACEMD("3: literal");
  88.      switch (pcbmd.action) {
  89.      case LITE:
  90.      case LIT:
  91.           switch (estore) {
  92.           case ESM:           /* LITERAL: parameter literal required. */
  93.           case ESC:           /* CDATA: parameter literal required. */
  94.           case ESX:           /* SDATA: parameter literal required. */
  95.           case ESI:           /* PI: parameter literal required. */
  96.                etx.c = savestr(tbuf);
  97.                break;
  98.           case ESMD:          /* MD: parameter literal required. */
  99.                etx.c = sandwich(tbuf, lex.m.mdo, lex.m.mdc); 
  100.            goto bcheck;
  101.           case ESMS:          /* MS: parameter literal required. */
  102.                etx.c = sandwich(tbuf, lex.m.mss, lex.m.mse);
  103.            goto bcheck;
  104.           case ESS:           /* STARTTAG: parameter literal required. */
  105.            etx.c = sandwich(tbuf, lex.m.stag, lex.m.tagc);
  106.            goto bcheck;
  107.           case ESE:           /* ENDTAG: parameter literal required. */
  108.            etx.c = sandwich(tbuf, lex.m.etag, lex.m.tagc);
  109.       bcheck:
  110.            if (etx.c == 0) {
  111.             mderr(225, (UNCH *)0, (UNCH *)0);
  112.             return;
  113.            }
  114.                break;
  115.           }
  116.           break;
  117.      default:
  118.           mderr(123, (UNCH *)0, (UNCH *)0);
  119.           return;
  120.      }
  121.      /* PARAMETER 4: End of declaration.
  122.      */
  123.      parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
  124.      parm4:
  125.      TRACEMD(emd);
  126.      if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
  127.      if (es!=mdessv) synerr(37, &pcbmd);
  128.  
  129.      /* EXECUTE: If the entity already exists, ignore the new definition.
  130.                  If it is a new entity, store the definition.
  131.      */
  132.      if ((ecb = entfind(nmbuf))!=0 && ecb->estore) {
  133.       if (ecb->dflt) {
  134.            mderr(228, nmbuf + 1, (UNCH *)0);
  135.            hout((THASH)etab, nmbuf, hash(nmbuf, ENTHASH));
  136.            if (ecb->estore == ESN) {
  137.             frem((UNIV)NEID(ecb->etx.n));
  138.             frem((UNIV)ecb->etx.n);
  139.            }
  140.            else if (ecb->estore >= ESFM)
  141.             frem((UNIV)ecb->etx.x);
  142.            frem((UNIV)ecb);
  143.       }
  144.       else {
  145.            /* Duplicate definition: not an error. */
  146.            if (sw.swdupent) mderr(68, nmbuf+1, (UNCH *)0);
  147.            if (estore<ESFM) frem((UNIV)etx.c);
  148.            return;
  149.       }
  150.      }
  151.      ++ds.ecbcnt;                       /* Do capacity before NOTATION. */
  152.      ds.ecbtext += estore<ESFM ? ustrlen(etx.c) : entlen;
  153.      ecb = entdef(nmbuf, estore, &etx); /* Define the entity. */
  154.      if (estore==ESN) {                 /* If entity is external: */
  155.           NEENAME(pne) = ecb->ename;    /* Store entity name in ne. */
  156.           NEID(pne) = etx.x;            /* Store system fileid in ne. */
  157.       NESYSID(pne) = fpis->fpisysis ? savestr(fpis->fpisysis) : 0;
  158.       NEPUBID(pne) = fpis->fpipubis ? savestr(fpis->fpipubis) : 0;
  159.           ecb->etx.n = pne;             /* Store ne control block in etx. */
  160.           TRACEESN(pne);
  161.      }
  162.      else if (pne)
  163.       frem((UNIV)pne);
  164.      if (defltsw) {
  165.       ecbdeflt = ecb;     /* If #DEFAULT save ecb. */
  166.       if (fpidf.fpipubis)
  167.            fpidf.fpipubis = savestr(fpidf.fpipubis);
  168.       if (fpidf.fpisysis)
  169.            fpidf.fpisysis = savestr(fpidf.fpisysis);
  170.      }
  171. }
  172. /* SANDWICH: Catenate a prefix and suffix to a string.
  173.    The result has an EOS but no length.
  174.    Return 0 if the result if longer than LITLEN.
  175. */
  176. UNCH *sandwich(s, pref, suff)
  177. UNCH *s;                      /* String, with EOS. */
  178. UNCH *pref;                   /* Prefix, with length and EOS. */
  179. UNCH *suff;                   /* Suffix, with length and EOS. */
  180. {
  181.      UNCH *pt;
  182.      UNS slen, tlen;
  183.  
  184.      slen = ustrlen(s);
  185.      tlen = slen + (*pref - 2) + (*suff - 2);
  186.      if (tlen > LITLEN)
  187.       return 0;
  188.      pt = (UNCH *)rmalloc(tlen + 1);
  189.      memcpy(pt, pref + 1, *pref - 2);
  190.      memcpy(pt + (*pref - 2), s, slen);
  191.      memcpy(pt + (*pref - 2) + slen, suff + 1, *suff - 1);
  192.      return pt;
  193. }
  194. /* MDEXTID: Process external identifier parameter of a markup declaration.
  195.             On entry, tbuf contains SYSTEM or PUBLIC if all is well.
  196.             NULL is returned if an error, otherwise fpis.  If it is a
  197.             valid external data entity, the caller's estore is set to ESN
  198.             and its nxetype is set to the code for the external entity type.
  199.             The event that terminated the parse is preserved in pcb.action,
  200.             so the caller should process it before further parsing.
  201. */
  202. struct fpi *mdextid(tbuf, fpis, ename, estore, pne)
  203. UNCH *tbuf;                   /* Work area for tokenization[2*(LITLEN+2)]. */
  204. struct fpi *fpis;             /* FPI structure. */
  205. UNCH *ename;                  /* Entity or notation name, with EOS, no length.*/
  206.                               /* NOTE: No PERO on parameter entity name. */
  207. UNCH *estore;                 /* DTD, general or parameter entity, DCN. */
  208. PNE pne;                      /* Caller's external entity ptr. */
  209. {
  210.      PDCB dcb;