home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / misc / compsci / arcsgm.cpt / ARC SGML 1.0 / sgmlc / sgmlapi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-17  |  16.6 KB  |  379 lines

  1. #ifdef applec
  2. #pragma segment SegC
  3. #endif
  4. /*****************************************************************************/
  5. /* SGMLAPI: SGML API for C                                                   */
  6. /* Author: Charles F. Goldfarb                                               */
  7. /******************************************************************************/
  8. #include "vmincl.h"           /* Include files for VM. */
  9. #include "vmxtrn.h"           /* Declarations for VM public variables. */
  10. #include "sgmlapi.h"          /* Text processor header for SGML interfacing. */
  11. /******************************************************************************/
  12. struct rcbde de = {0};        /* RCB for current data entity information. */
  13. struct rcbte te = {0};        /* RCB for calls to SGMLAPI (TP+ENV). */
  14. UNCH sgmlomsg[] =             /* Text for invalid option error message. */
  15.      "-d -e -f -g -mSGML.MSG -p1 -r -t3";
  16. /******************************************************************************/
  17. /* Secret public variable for use by markup validator (not in SGMLAPI.H). */
  18. int TPisVM = 0;               /* Set to 1 by TP if it is markup validator. */
  19. /******************************************************************************/
  20. void alset(struct ad *);      /* Set up to start processing att list. */
  21. void setndata(PNE);           /* Build ext data entity rcbde with entity text.*/
  22. /******************************************************************************/
  23. /* SGMLNEXT: Get the next RCB from SGML and transfer data to local variables.
  24. */
  25. int sgmlnext(void)
  26. {
  27.      loop:
  28.      sgml((struct ipbt *)0);
  29.      if (!suppsw)
  30.           getscbs(SGMLSCBS, SGMLES);
  31.      switch (RCBTYPE) {
  32.      case SGMLDAF:            /* Data found. */
  33.           if (suppsw) goto loop;
  34.           te.datalen = CDATALEN;
  35.           te.data = CDATA;
  36.           if (CDESW) return (TPCDATA);
  37.           /* else */ if (SDESW) return (TPSDATA);
  38.           /* else */ if (NDESW) {setndata(NEPTR); return(TPNDATA);}
  39.           /* else */ if (*te.data==tpsw.delnonch) {
  40.                te.nonsgml = te.data[1]-tpsw.addnonch;
  41.                return(TPNSGML);
  42.           }
  43.           /* else */ return(TPPCDATA);
  44.  
  45.      case SGMLSTG:            /* Start-tag found. */
  46.           memcpy( &tptags[++tpts][0] , GI, (size_t)*(GI-1) ); /* Stack the GI. */
  47.           if (suppsw) goto loop;
  48.           te.data = GI;
  49.           te.datalen = *(GI-1)-2;
  50.           te.gidata = GIDATA;
  51. #ifdef V2
  52.           te.format = FORMAT;
  53. #endif
  54.           if (ALPTR) {             /* Tag attributes will be processed. */
  55.                alptr = ALPTR;      /* Tag attributes are active att list. */
  56.                te.alcnt = AN;      /* Indicate number of attributes in list. */
  57.                te.pca = &te.ca;    /* Current attribute structure in rcbte. */
  58.                alset((struct ad *)0); /* Initialize for alnext processing. */
  59.           }
  60.           else te.alcnt = 0;
  61.           return(TPSTAG);
  62.  
  63.      case SGMLETG:            /* End-tag found. */
  64.           --tpts;             /* Destack the GI. */
  65.           if (suppsw) goto loop;
  66.           te.data = GI;
  67.           te.datalen = *(GI-1)-2;
  68.           te.gidata = GIDATA;
  69. #ifdef V2
  70.           te.format = FORMAT;
  71. #endif
  72.           return(TPETAG);
  73.  
  74.      case SGMLPIS:            /* Processing instruction: string. */
  75.           if (suppsw) goto loop;
  76.           te.datalen = PDATALEN;
  77.           te.data = PDATA;
  78.           return(PIESW ? TPPIENT : TPPI);
  79.  
  80.      case SGMLREF:            /* Record end found. */
  81.           if (suppsw) goto loop;
  82.           return(TPRE);
  83.  
  84.      case SGMLSDTD:           /* Document type definition started. */
  85.           eltrsw = 0;         /* Suppress GI stack trace in messages. */
  86.           if (!TPisVM || suppsw) goto loop;
  87.           te.datalen = DTYPELEN-2;
  88.           te.data = DOCTYPE+1;
  89.           return(TPSDTD);
  90.  
  91.      case SGMLEDTD:           /* Document type definition completed. */
  92.           eltrsw = eltrsv;    /* Restore GI stack trace in messages. */
  93.           if (suppsw) goto loop;
  94.           te.datalen = DTYPELEN-2;
  95.           te.data = DOCTYPE+1;
  96.           return(TPEDTD);
  97.  
  98.      case SGMLMV:             /* Markup validator information. */
  99.           if (!TPisVM) goto loop;
  100.           /* else */ return(TPMV);
  101.  
  102.      case SGMLEOD:            /* End of document. */
  103.           return(TPEOD);
  104.      }
  105.      return(TPEOD);           /* Avoid lint and TurboC warnings. */
  106. }
  107. /******************************************************************************/
  108. /* #include "sgmlsubs.c"         /* Subroutines for SGML API. */
  109. /* These were physically copied into here to accomodate symbolic debugging.  WMW */
  110. /******************************************************************************/
  111. /******************************************************************************/
  112. /* SGMLSUBS: Subroutines for SGML APIs.  Must be "included" in SGMLAPI?.C.    */
  113. /******************************************************************************/
  114. void alset(struct ad *);      /* Set up to start processing att list. */
  115. void setndata(PNE);           /* Build ext data entity rcbde with entity text.*/
  116. /******************************************************************************/
  117. static struct ad *alptrsv;    /* Save pending (tag or link) att list.        */
  118. static UNCH *docentid;        /* System identifier of SGML document entity.  */
  119. /******************************************************************************/
  120. /* ALSET: Prepares for ALNEXT processing of tag or data attribute list.
  121. */
  122. VOID alset(al)
  123. struct ad *al;                /* Attribute list (NULL=tag or link atts). */
  124. {
  125.      if (al) {                /* Non-null means data attributes. */
  126.           alptrsv = alptr;    /* Save pending (tag or link) att list. */
  127.           alptr = al;         /* Data attribute list is now current. */
  128.           te.pca = &de.ca;    /* Current attribute structure in rcbde. */
  129.      }
  130.      CA.aln = 0;              /* Index of attribute to process. */
  131.      CA.idrn = 0;             /* No IDREF(S) tokens as yet. */
  132.      CA.entityn = 0;          /* No AENTITY(S) tokens as yet. */
  133. }
  134. /******************************************************************************/
  135. /* ALNEXT: Transfers next attribute list entry to global variables.
  136.            Returns 1 if there is yet another entry; 0 if all done.
  137. */
  138. int alnext(void)
  139. {
  140.      if ((CA.aln += BITON(ADFLAGS(CA.aln), AGROUP) ? ADNUM(CA.aln)+1 : 1)>ADN) {
  141.           if (te.pca==&de.ca) {
  142.                alptr = alptrsv;    /* Restore pending (tag or link) att list. */
  143.                te.pca = &te.ca;    /* Current attribute structure in rcbte. */
  144.           }
  145.           return(0);
  146.      }
  147.      CA.aname = ADNAME(CA.aln);
  148.      CA.anamelen = *(CA.aname-1)-2;
  149.      CA.aflags = ADFLAGS(CA.aln);       /* For validator only. */
  150.      if (ADVAL(CA.aln)==NULL)           /* No value specified. */
  151.           CA.astatus = GET(CA.aflags, AINVALID) ? TPANOREQ : TPAIMPLY;
  152.      else {
  153.           CA.aval = (ADVAL(CA.aln)+1);
  154.           CA.avallen = *(CA.aval-1)-2;
  155.           CA.aconref = (UNS)(GET(CA.aflags, ACONREF));
  156.           CA.adata = TPANONE;           /* Assume no special data. */
  157.           if (ADTYPE(CA.aln)<ATKNLIST) {/* Value is a string or token. */
  158.                CA.atype = (ADTYPE(CA.aln)==ACHARS) ? TPACDATA : TPATOKEN;
  159.                if (ADTYPE(CA.aln)==ANOTEGRP) {
  160.                     CA.adata = TPANOTE;
  161.                     CA.dcnid = ((UNCH *)ADDATA(CA.aln).x)+1;
  162.                     CA.dcnidlen = *(CA.dcnid)-2;
  163.                }
  164.                else if (ADTYPE(CA.aln)==AENTITY) CA.adata = TPAENTIT;
  165.                else if (ADTYPE(CA.aln)==AIDREF)  CA.adata = TPAIDREF;
  166.           }
  167.           else {              /* Value is a list of one or more tokens. */
  168.                CA.atype = TPALIST;
  169.                CA.avn = 0;
  170.                CA.tn = 0;
  171.                if (ADTYPE(CA.aln)==AENTITYS) CA.adata = TPAENTIT;
  172.                else if (ADTYPE(CA.aln)==AIDREFS) CA.adata = TPAIDREF;
  173.           }
  174.           if (GET(CA.aflags, AERROR)) CA.astatus = TPAERROR;
  175.           else if (GET(CA.aflags, AINVALID)) CA.astatus = TPAINVAL;
  176.           else CA.astatus = TPAOK;      /* Specified attribute value is o.k. */
  177.      }
  178.      if (!TPisVM) CA.aflags = 0;        /* Flags are for validator only. */
  179.      return(1);
  180. }
  181. /******************************************************************************/
  182. /* AVNEXT: Transfers next attribute value token to global variables.
  183.            The number of tokens is in ADNUM(CA.aln).
  184.            Returns 1 if there is yet another entry; 0 if all done.
  185. */
  186. int avnext(void)
  187. {
  188.      if (++CA.tn>ADNUM(CA.aln)) return(0);
  189.      CA.tokenlen = *(CA.aval+CA.avn);
  190.      CA.token = CA.aval+CA.avn+1;
  191.      CA.avn += CA.tokenlen+1;
  192.      return(1);
  193. }
  194. /******************************************************************************/
  195. /* IDRNEXT: Sets idrstat global variable for current IDREF token.
  196. */
  197. VOID idrnext(void)
  198. {
  199.      CA.idrstat = (int)IDRHIT(++CA.idrn);
  200. }
  201. /******************************************************************************/
  202. /* GETENT: Sets up global variables for a data entity.
  203.            Returns:
  204.                3 if entity is internal SDATA;
  205.                2 if entity is internal CDATA;
  206.                1 if entity is NDATA;
  207.               -1 if entity is not defined;
  208.               -2 if not CDATA, SDATA, or NDATA;
  209.               -3 if entity name is too long.
  210. */
  211. int getent(
  212. UNS enmlen,                   /* Length of GI of element (without EOS). */
  213. UNCH *ename)                  /* GI of element (EOS optional). */
  214. {
  215.      if ((*pd = (unsigned char)enmlen+2)>NAMELEN+2) return(-3);
  216.      memcpy(pd+1, ename, (size_t)enmlen);
  217.      *(pd+*pd-1) = EOS;
  218.      it.itnm = pd;             /* Entity name (len+EOS). */
  219.      it.ipbtype = ENTGET; sgml(itlpu);  /* Retrieve entity information. */
  220.      switch (src) {
  221.      case 1:                       /* External NDATA entity. */
  222.           setndata((PNE)it.itp1);
  223.           break;
  224.      case 2:                       /* Internal CDATA entity. */
  225.      case 3:                       /* Internal SDATA entity. */
  226.           de.detype = src-1;       /* Data entity type. */
  227.           de.ename = pd+1;         /* Current entity name. */
  228.           de.enamelen = *pd-2;
  229.           de.detxt = ((UNCH *)it.itp1)+1;    /* Entity text. */
  230.           de.detxtlen = *(de.detxt-1)-2;
  231.           break;
  232.      }
  233.      return(src);                  /* Return with error code or entity type. */
  234. }
  235. /******************************************************************************/
  236. /* SETNDATA: Set system ID and notation for NDATA entity reference in
  237.              global variables for text processor use.
  238. */
  239. VOID setndata(
  240. PNE p)                        /* Pointer to data entity control block. */
  241. {
  242.      de.detype = NEXTYPE(p) + TPISDATA;   /* Data entity type. */
  243.      de.ename = NEENAME(p)+1;             /* Current entity name. */
  244.      de.enamelen = *(de.ename-1)-2;
  245.      de.detxt = ((UNCH *)NEID(p))+1;      /* Entity system ID. */
  246.      de.detxtlen = *(de.detxt-1)-2;
  247.      de.dcnnm = NEDCN(p)+1;               /* Data content notation name. */
  248.      de.dcnnmlen = *(de.dcnnm-1)-2;
  249.      de.dcnid = ((UNCH *)NEDCNID(p))+1;   /* Notation system ID. */
  250.      de.dcnidlen = *(de.dcnid-1)-2;
  251.      if (NEAL(p)) {           /* Data attributes will be processed. */
  252.           de.alcnt = AN;      /* Indicate number of attributes in list. */
  253.           alset(NEAL(p));     /* Initialize for alnext processing. */
  254.      }
  255.      else de.alcnt = 0;       /* No data attributes for this entity. */
  256. }
  257. /******************************************************************************/
  258. /* DOCENT: Initialize the SGML document entity.
  259.            Returns: 1 if entity system ID is too long; 0 if o.k.
  260. */
  261. int docent(
  262. unsigned char *sysid)                  /* System identifier of document entity. */
  263. /* was UNCH * WMW 7/24/91 */
  264. {
  265.      if ((*pd = (unsigned char)(strlen((char *)sysid)+1))>LITLEN+1) return(1);
  266.      memcpy( pd+1 , sysid, (size_t)*pd );
  267.      ++*pd;
  268.      docentid = savestr(pd);  /* File identifier (len+EOS). */
  269.      return(0);
  270. }
  271. /******************************************************************************/
  272. /* GISET: Stores data for start- and end-tags of an element.
  273.           Returns 0 if o.k.; 1 if element is not defined.
  274. */
  275. int giset(
  276. UNCH *gi,                     /* GI of element. */
  277. UNIV start,                   /* Data for start-tag. */
  278. UNIV end)                     /* Data for end-tag. */
  279. {
  280.      it.itnm = gi;            /* Document type GI. */
  281.      it.itp1 = start;         /* GIDATA for start-tag. */
  282.      it.itp2 = end;           /* GIDATA for end-tag. */
  283.      it.ipbtype = GISET; sgml(itlpu);  /* Store GIDATA. */
  284.      return(src);             /* Report results. */
  285. }
  286. /******************************************************************************/
  287. /* SGMLOSET: Performs SGML initialization for option processing.
  288. */
  289. void sgmloset(void)
  290. {
  291.      te.passes = 1;           /* Number of passes requested. */
  292.      tpsw.swenttr = 1;        /* 1=trace entity stack in error messages; 0=no.*/
  293.      tpsw.swbufsz = readcnt+2;/* SGML file read buffer size. */
  294. }
  295. /******************************************************************************/
  296. /* SGMLOPT: Processes a TP option argument if it is one of the standard ones
  297.             supported by the interface.  They are:
  298.                   /d /e /f /g /mSGML.MSG /p1 /r /t3
  299.             Other arguments are returned intact to the TP, as they may
  300.             be valid arguments for the application.
  301. */
  302. UNCH *sgmlopt(
  303. UNCH *arg)                    /* Current argument in argv. */
  304. {
  305.           switch (toupper((int)arg[1])) {
  306.           case 'D':           /* Report duplicate entity declarations. */
  307.                tpsw.swdupent = 1;
  308.                return(0);
  309.           case 'E':           /* Suppress entity stack trace in error msg. */
  310.                tpsw.swenttr = 0;
  311.                return(0);
  312.           case 'F':           /* Files located in current directory only. */
  313.                cdirsw = 1;
  314.                return(0);
  315.           case 'G':           /* Suppress GI stack trace in error messages. */
  316.                eltrsv = 0;
  317.                return(0);
  318.           case 'M':           /* Message file identifier. */
  319.                msgfptr = &arg[2];
  320.                return(0);
  321.           case 'P':           /* Number of passes desired: 1 or more. */
  322.                if ((te.passes = atoi((char *)&arg[2]))==0) break;
  323.                return(0);
  324.           case 'R':           /* Give warning for defaulted references. */
  325.                tpsw.swrefmsg = 1;
  326.                return(0);
  327.           case 'T':           /* Don't trim final RE of file or prefix RS. */
  328.                if ((boundsw = (int)arg[2])>'3' || boundsw<'0') break;
  329.                return(0);
  330.           }
  331.           return(arg);        /* Erroneous option argument. */
  332. }
  333. /******************************************************************************/
  334. /* SGMLSET: Performs SGML initialization and other housekeeping for the run.
  335. */
  336. void sgmlset(void)
  337. {
  338.      tpsw.swetdtag = 0;       /* Return on all tags, even if no user data. */
  339.      tpsw.delcdata = '\35';   /* 29 Delimiters: CDATA entity in att value. */
  340.      tpsw.delsdata = '\36';   /* 30 Delimiters: SDATA entity in att value. */
  341.      tpsw.delnonch = '\37';   /* 31 Prefix: non-SGML character. */
  342.      tpsw.addnonch = 64;      /* Addend: added to non-SGML char (mod 256). */
  343.      msginit();                    /* Load error messages. */
  344.      tpsw.src = &src;              /* TP addr for SGMLSERV to put return code.*/
  345.      tpsw.srcbp = &srcbp;          /* TP addr for SGML to put rcb ptr. */
  346.      itlpu = ⁢                  /* Create it ipb LPU to pass to SGML. */
  347.      it.itp1 = (UNIV)&tpsw;        /* Parser control switches. */
  348.      it.ipbtype = SGMLSET; sgml(itlpu);   /* Initialize the run. */
  349.      /* Pointer to markup string array was returned in srcbp. */
  350. }
  351. /******************************************************************************/
  352. /* SGMLPSET: Initialize the pass and open the SGML document entity.
  353.              Returns: <0 if entity could not be opened; 0 if o.k.
  354. */
  355. int sgmlpset(void)
  356. {
  357.      it.itl1 = te.pass;       /* Identify current pass: 1 to passes. */
  358.      it.ipbtype = SGMLRSET; sgml(itlpu);   /* Initialize the pass. */
  359.  
  360.      tpts = 0;                /* Initialize element structure stack. */
  361.      tpes = 1;                /* Initialize entity structure stack. */
  362.  
  363.      it.itl1 = (UNS)*docentid;
  364.      it.itp1 = docentid;      /* File identifier (len+EOS). */
  365.      it.ipbtype = ENTPRIME; sgml(itlpu);  /* Open document entity. */
  366.      return (src);
  367. }
  368. /******************************************************************************/
  369. /* SGMLEND: Performs SGML final cleanup and transfers capacity statistics
  370.             to a local structure.
  371. */
  372. UNS sgmlend(void)
  373. {
  374.      it.ipbtype = SGMLEND; sgml(itlpu);    /* Final cleanup. */
  375.      /* Pointer to statistics is now in srcbp: save it. */
  376.      return (cnterr);
  377. }
  378. /******************************************************************************/
  379.