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

  1. #ifdef applec
  2. #pragma segment SegC
  3. #endif
  4. /******************************************************************************/
  5. #ifdef THINK_C
  6. #include <console.h>
  7. #endif
  8. /* VM (Validate Markup): Analyze and validate SGML markup.
  9.    SGMLAPI is used for normal text processor services.
  10.    Parser control blocks are accessed directly for additional VM information.
  11. */
  12. #include "vmincl.h"           /* Include files for VM. */
  13. #include "vmxtrn.h"           /* Declarations for VM public variables. */
  14. /******************************************************************************/
  15. #include "sgmlapi.h"          /* SGML application programming interface. */
  16. /******************************************************************************/
  17. extern int TPisVM;            /* Set to 1 by TP if it is markup validator. */
  18. static char vmomsg[] =        /* Text for invalid option error message. */
  19.      "-c10 -s";
  20. static char teattspc[] = "\n     ";             /* Tag/link att spacing. */
  21. static char deattspc[] = "\n                     "; /* Data att spacing. */
  22. static char *attspc = teattspc;  /* Initial spacing is for tag/link atts. */
  23. static char *typetab [] = {   /* Text for printing data entity type. */
  24.      "CDATA",                 /* 1  Internal character data entity. */
  25.      "SDATA",                 /* 2  Internal specific character data entity. */
  26.      "CDATA",                 /* 3  External character data entity. */
  27.      "NDATA",                 /* 4  Non-SGML data entity. */
  28.      "SDATA",                 /* 5  External specific character data entity. */
  29.      "SUBDOC"                 /* 6  SGML subdocument entity (NOT SUPPORTED). */
  30. };
  31. static void docproc(void);    /* Main loop for processing document. */
  32. static void getatts(void);    /* Get attribute list (tag or data). */
  33. static void proctkn(unsigned, UNCH *); /* Process attribute token by type. */
  34. static void getde(void);      /* Get data entity control block. */
  35. /******************************************************************************/
  36. VOID main(argc, argv)
  37. int argc;
  38. char **argv;
  39. {
  40.      UNCH *fileid = 0;        /* Primary file identifier. */
  41.      int i;                   /* Loop control. */
  42.      unsigned msgcnt;         /* Number of messages issued by parser. */
  43.  
  44. #ifdef THINK_C
  45.     argc = ccommand((char ***)&argv);
  46. #endif
  47.      /* PARSE ARGUMENTS
  48.      */
  49.      /* SGMLOPT handles common parser options.  We handle the other args. */
  50.      sgmloset();              /* Initialize for SGML option processing. */
  51.      suppsw = 1;              /* Assume no parsing information is wanted. */
  52.      for (i = 0; ++i<argc; ) {
  53.           if (argv[i][0]!='-') fileid = (UNCH *)argv[i];
  54.           else if (sgmlopt((UNCH *)argv[i])!=0) switch (toupper((int)argv[i][1])) {
  55.           case 'C':           /* Data or PI chars to print: 0 or more. */
  56.                prntmax = atoi(&argv[i][2]);
  57.                continue;
  58.           case 'S':           /* Show parsing information. */
  59.                suppsw = 0;
  60.                continue;
  61.           default:
  62.                printf(
  63. "\nVM001-> \"%s\" option switch is incorrect; usage is: %s %s",
  64.                argv[i], vmomsg, sgmlomsg);
  65.                exit(001);
  66.           }
  67.      }
  68.      if (fileid==0 || *fileid=='?') {
  69.           printf(
  70. "\nVM002-> No primary file specified; usage is: %s %s [profile;]file",
  71.           vmomsg, sgmlomsg);
  72.           exit(002);
  73.      }
  74.      /* IDENTIFY THE SGML DOCUMENT ENTITY
  75.      */
  76.      /* Define specified external file(s) as document entity. */
  77.      if (docent((unsigned char *)fileid)) {
  78.           printf(
  79. "\nVM005-> SGML document entity system ID (%s) exceeds 240 characters.",
  80.           fileid);
  81.           exit(005);
  82.      }
  83.      /* INITIALIZE THE RUN
  84.      */
  85.      TPisVM = 1;                   /* Signal that validator is here. */
  86.      sgmlset();                    /* Initialize the SGML parser. */
  87.      while (++te.pass<=te.passes) {
  88.           /* INITIALIZE THE PASS
  89.           */
  90.           if (sgmlpset()) {
  91.                printf(
  92. "\nVM006-> Could not open SGML document entity in file: %s", fileid);
  93.                exit(006);
  94.           }
  95.           /* RUN THE PASS
  96.           */
  97.           printf(
  98. "\nVM105-> Pass %d of %d.", te.pass, te.passes);
  99.           docproc();
  100.      }
  101.      /* END OF RUN: Report message count and capacity statistics.
  102.      */
  103.      msgcnt = sgmlend();
  104.      printf(
  105. "\nVM106-> Processing completed; %u messag%s issued.",
  106.      msgcnt, (msgcnt==1) ? "e" : "es");
  107.      if (!suppsw) prtstat((struct stat *)srcbp);
  108.      exit(0);
  109. }
  110. /******************************************************************************/
  111. /* DOCPROC: Process the returns from SGMLNEXT.
  112. */
  113. void docproc()
  114. {
  115.      int rc;                  /* Return code from SGMLNEXT. */
  116.  
  117.      while ((rc = sgmlnext())!=TPEOD) switch (rc) {
  118.      case TPNDATA:            /* Non-SGML data entity reference. */
  119.           location(10);
  120.           printf("Non-SGML data entity");
  121.           if (CONTERSW) printf(" (out of context)");
  122.           printf("\n     %-8s = \"%s", "*ENTITY", de.ename);
  123.           getde();
  124.           continue;
  125.  
  126.      case TPNSGML:            /* Non-SGML character reference. */
  127.           location(10);
  128.           printf("Non-SGML character%s %d [%c]: [%c%c]",
  129.                  (CONTERSW ? " (out of context)" : ""),
  130.                  te.nonsgml, ZAPEOL(te.nonsgml), te.data[0], te.data[1]);
  131.           continue;
  132.  
  133.      case TPPCDATA:           /* Parsed character data found. */
  134.      case TPCDATA:            /* Character data entity reference. */
  135.      case TPSDATA:            /* System data entity reference. */
  136.           location(10);
  137.           printf("%d data characte%s%s%s%s: [",
  138.                  te.datalen, ((te.datalen==1) ? "r" : "rs"),
  139.                  (rc==TPCDATA ? " in CDATA entity" : ""),
  140.                  (rc==TPSDATA ? " in SDATA entity" : ""),
  141.                  (CONTERSW ? " (out of context)" : ""));
  142.           if (prntmax<te.datalen) printf("%.*s] ...", prntmax, te.data);
  143.           else printf("%.*s]", te.datalen, te.data);
  144.           continue;
  145.  
  146.      case TPSTAG:             /* Start-tag. */
  147.           location(11);
  148.           if (TAGMIN==MINNONE) {
  149.                printf("%s start-tag found%s.",
  150.                      te.data,  CONTERSW ? " (out of context)" :
  151.                             PEXSW    ? " (inclusion)" : "" );
  152.                if (ETISW)
  153.                      printf("\b; NET delimiter enabled (%d total).", ETICTR);
  154.           }
  155.           else if (TAGMIN==MINSTAG) {
  156.                printf("%s start-tag implied by %s%s", te.data,
  157.                      (TAGREAL<MINPTR ? realmsg[(UNS)TAGREAL]
  158.                                      : TAGRLNM+1),
  159.                      (TAGREAL==ETDCDATA ? "." : " start-tag."));
  160.           }
  161.           else printf("Short (no GI) %s start-tag found.", te.data);
  162. #ifdef V2
  163.           printf(" (Format %s.)", formats[te.format]);
  164. #endif
  165.           if (SRMNM) printf(" SHORTREF map is \"%s\".", SRMNM+1);
  166.           else if (srmsw) printf(" SHORTREF map is empty.");
  167. /*        if (te.gidata) printf(" [GIDATA = \"%s\" in %04x]", te.gidata);*/
  168.           if (te.alcnt) getatts();
  169.           continue;
  170.  
  171.      case TPETAG:             /* End-tag found. */
  172.           location(12);
  173.           if (MTYSW) printf("%s end-tag implied by empty content;", te.data);
  174.           else if (TAGMIN==MINSTAG || TAGMIN==MINETAG) {
  175.                printf("%s end-tag implied by %s%s", te.data,
  176.                      (TAGREAL<MINPTR ? realmsg[(UNS)TAGREAL]
  177.                                      : TAGRLNM+1),
  178.                      (TAGREAL==ETDCDATA ? ";" :
  179.                           (TAGMIN==MINSTAG ? " start-tag;" : " end-tag;")));
  180.           }
  181.           else printf((char *)eminmsg[TAGMIN], te.data);
  182.           if (PEXSW) printf(" (Inclusion ended.)");
  183.           if (ETISW) printf(" NET delimiter disabled (%u left);", ETICTR);
  184.           printf(" %s element resumed.", OLDGI+1);
  185. #ifdef V2
  186.           printf(" (Ending format %s.)", formats[te.format]);
  187. #endif
  188.           if (SRMNM) printf(" SHORTREF map is \"%s\".", SRMNM+1);
  189.           else if (srmsw) printf(" SHORTREF map is empty.");
  190. /*        if (te.gidata) printf(" [gidata = \"%s\" in %04x]", te.gidata);*/
  191.           continue;
  192.  
  193.      case TPPI:               /* Processing instruction. */
  194.      case TPPIENT:            /* Processing instruction entity. */
  195.           if (suppsw) continue;
  196.           location(13);
  197.           printf("%d character processing instruction%s: [",
  198.                te.datalen, (rc==TPPIENT ? " in PI entity" : ""));
  199.           if (prntmax<te.datalen) printf("%.*s] ...", prntmax, te.data);
  200.           else printf("%.*s]", te.datalen, te.data);
  201.           continue;
  202.  
  203.      case TPRE:               /* Significant record end. */
  204.           if (suppsw) continue;
  205.           location(14);
  206.           printf("Record end%s.", (CONTERSW ? " (out of context)" : ""));
  207.           continue;
  208.  
  209.      case TPSDTD:             /* Document type definition started. */
  210.           location(15);
  211.           printf("Document type definition started for %s.", te.data);
  212.           continue;
  213.  
  214.      case TPEDTD:             /* Document type definition completed. */
  215.           location(16);       /* GISET and GIGET can now be done. */
  216.           printf("Document type definition completed for %s; ", te.data);
  217.           printf("%d SHORTREF map%s defined.",
  218.                  SRMCNT, (SRMCNT==1) ? "" : "s");
  219.           srmsw = SRMCNT>0;   /* Short reference maps are in use. */
  220.           /* Store GIDATA for element start-tags and end-tags here. */
  221.           /* GISET returns non-zero for undefined elements. */
  222.           /* TESTING ONLY: Store GIDATA for document type element. */
  223. /*        giset("DUMMYGI",         /* Dummy GI. */
  224. /*              "start-data",      /* Phoney GIDATA for start-tag. */
  225. /*              "end-data");       /* Phoney GIDATA for start-tag. */
  226.           /* END OF TEST */
  227.           continue;
  228.  
  229.      case TPMV:                    /* Markup validator information. */
  230.           if (suppsw) continue;
  231.           location(17);
  232.           printf("USEMAP declaration:");
  233.           if (CDATA) {
  234.                printf(" SHORTREF map is \"%s\".", CDATA+1);
  235.           }
  236.           else printf(" SHORTREF map is empty.");
  237.           continue;
  238.  
  239.      default:
  240.           continue;
  241.      }
  242.      /*   TPEOD:                 End of document. */
  243.      return;
  244. }
  245. /******************************************************************************/
  246. /* GETATTS: Retrieve attribute specifications, one by one, and print them.
  247. */
  248. void getatts()
  249. {
  250.      while (alnext()) {
  251.           /* No value specified for #IMPLIED or #REQUIRED.
  252.           */
  253.           if (CA.astatus==TPAIMPLY || CA.astatus==TPANOREQ) {
  254.                printf("\n     %-8s = [NONE]", CA.aname);
  255.                if (CA.astatus==TPANOREQ) printf(" [INVALID]");
  256.                return;
  257.           }
  258.           /* Value specified or defaulted.
  259.           */
  260.           printf(attspc);
  261.           printf("%-8s = \"", CA.aname);
  262.           switch (CA.atype) {
  263.           case TPALIST:            /* Value is list of tokens. */
  264.                avnext();           /* First token is on same line. */
  265.                printf("%.*s", CA.tokenlen, CA.token);
  266.                proctkn(CA.tokenlen, CA.token);
  267.                while (avnext()) {  /* New lines for any other tokens. */
  268.                     printf(attspc);
  269.                     printf("            %.*s", CA.tokenlen, CA.token);
  270.                     proctkn(CA.tokenlen, CA.token);
  271.                }
  272.                printf("\"");
  273.                break;
  274.           case TPACDATA:           /* Value is string.*/
  275.           case TPATOKEN:           /* Value is single token.*/
  276.                printf("%.*s", (int)CA.avallen, (char *)CA.aval);
  277.                proctkn(CA.avallen, CA.aval);
  278.                printf("\"");
  279.                break;
  280.           }
  281.           if (CA.astatus==TPAERROR) printf(" [ERROR]");
  282.           else if (CA.astatus==TPAINVAL) printf(" [INVALID]");
  283.           else if (!GET(CA.aflags, ASPEC)) printf(" [DEFAULT]");
  284.           else if (GET(CA.aflags, ACURRENT)) printf(" [NEW DEFAULT]");
  285.           if (CA.aconref) printf(" [CONREF]");
  286.      }
  287.      if (attspc==deattspc) attspc = teattspc;
  288. }
  289. /******************************************************************************/
  290. /* PROCTKN: Process a single token or list member according to its type.
  291. */
  292. void proctkn(tokenlen, token)
  293. UNS tokenlen;                 /* Length of token. */
  294. UNCH *token;                  /* The token itself. */
  295. {
  296.      switch (CA.adata) {
  297.      case TPANOTE:                 /* dcnid, dcnidlen */
  298.           printf("=>%s", CA.dcnid);
  299.           break;
  300.      case TPAENTIT:                /* neid,dcnnm,dcnid+len; alcnt */
  301.           getent(tokenlen, token); /* Set up rcbde for this entity. */
  302.           getde();
  303.           break;
  304.      case TPAIDREF:                /* idrstat */
  305.           idrnext();
  306.           if (!CA.idrstat) printf(" [INVALID]");
  307.           break;
  308.      }
  309. }
  310. /******************************************************************************/
  311. /* GETDE: Get control block information for data entity named in
  312.           AENTITY attribute or external data entity reference.
  313. */
  314. void getde()
  315. {
  316.      if (de.detype<=TPISDATA) {
  317.           printf("=>%s [internal %s]", de.detxt, typetab[de.detype-1]);
  318.           return;
  319.      }
  320.      printf("=>%s [%s]; notation is %s=>%s.",
  321.           de.detxt+2, typetab[de.detype-1],
  322.           (de.dcnnm!=0) ? (char *)de.dcnnm   : "[UNDEFINED]",
  323.           (de.dcnid!=0) ? (char *)(de.dcnid+2) : "[UNDEFINED]");
  324.      if (de.alcnt) {attspc = deattspc; getatts();}
  325. }
  326. /******************************************************************************/
  327. /* PRTSTAT: Print capacity statistics from the stat structure (verbosely).
  328. */
  329. void prtstat(ps)
  330. struct stat *ps;              /* Pointer to SGML stat structure. */
  331. {
  332.      printf("\n         %3u entit%s declared with %u character%s of text.",
  333.             ps->ecbcnt, (ps->ecbcnt==1) ? "y" : "ies",
  334.             ps->ecbtext, (ps->ecbtext==1) ? "" : "s");
  335.      printf("\n         %3u element typ%s declared",
  336.             ps->etdcnt, (ps->etdcnt==1) ? "e" : "es");
  337.      if (ps->etdercnt) printf(
  338.            " (plus %u undeclared)", ps->etdercnt);
  339.     printf(",\n             with %u model token%s and %u exception group%s",
  340.             ps->modcnt, (ps->modcnt==1) ? "" : "s",
  341.             ps->pmexgcnt, (ps->pmexgcnt==1) ? "" : "s");
  342.      if (ps->pmexcnt) printf(
  343.            " with %u name%s", ps->pmexcnt, (ps->pmexcnt==1) ? "" : "s");
  344.     printf(".\n         %3u attribute%s with %u group member%s",
  345.             ps->attcnt, (ps->attcnt==1) ? "" : "s",
  346.             ps->attgcnt, (ps->attgcnt==1) ? "" : "s");
  347.      printf("\n             and %u character%s of value text.",
  348.             ps->attdef, (ps->attdef==1) ? "" : "s");
  349.      printf("\n         %3u ID%s and %u ID reference%s specified.",
  350.             ps->idcnt, (ps->idcnt==1) ? "" : "s",
  351.             ps->idrcnt, (ps->idrcnt==1) ? "" : "s");
  352.      printf("\n         %3u data content notation%s with %u text character%s.",
  353.             ps->dcncnt, (ps->dcncnt==1) ? "" : "s",
  354.             ps->dcntext, (ps->dcntext==1) ? "" : "s");
  355.      printf("\n         %3u short reference map%s declared.",
  356.             ps->srcnt, (ps->srcnt==1) ? "" : "s");
  357.      printf("\n         %lu capacity points required (%lu%% of %lu permitted).\n",
  358.             ps->capused, ps->capused*100/ps->capacity, ps->capacity);
  359. }
  360. /******************************************************************************/
  361.