home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************/
- #include "sgmlapi.h" /* SGML application programming interface. */
- /******************************************************************************/
- /* VM (Validate Markup): Analyze and validate SGML markup.
- SGMLAPI is used for normal text processor services.
- Parser control blocks are accessed directly for additional VM information.
- */
- #include "vmincl.h" /* Include files for VM. */
- #include "vmxtrn.h" /* Declarations for VM public variables. */
- extern int TPisVM; /* Set to 1 by TP if it is markup validator. */
- static char vmomsg[] = /* Text for invalid option error message. */
- "/c10 /s";
- static char teattspc[] = "\n "; /* Tag/link att spacing. */
- static char deattspc[] = "\n "; /* Data att spacing. */
- static char *attspc = teattspc; /* Initial spacing is for tag/link atts. */
- static char *typetab [] = { /* Text for printing data entity type. */
- "CDATA", /* 1 Internal character data entity. */
- "SDATA", /* 2 Internal specific character data entity. */
- "CDATA", /* 3 External character data entity. */
- "NDATA", /* 4 Non-SGML data entity. */
- "SDATA", /* 5 External specific character data entity. */
- "SUBDOC" /* 6 SGML subdocument entity (NOT SUPPORTED). */
- };
- static void docproc(void); /* Main loop for processing document. */
- static void getatts(void); /* Get attribute list (tag or data). */
- static void proctkn(unsigned, char *); /* Process attribute token by type. */
- static void getde(void); /* Get data entity control block. */
- /******************************************************************************/
- VOID main(argc, argv)
- int argc;
- UNCH **argv;
- {
- UNCH *fileid = 0; /* Primary file identifier. */
- int i; /* Loop control. */
- unsigned msgcnt; /* Number of messages issued by parser. */
-
- /* PARSE ARGUMENTS
- */
- /* SGMLOPT handles common parser options. We handle the other args. */
- sgmloset(); /* Initialize for SGML option processing. */
- suppsw = 1; /* Assume no parsing information is wanted. */
- for (i = 0; ++i<argc;) {
- if (argv[i][0]!='/') fileid = argv[i];
- else if (sgmlopt(argv[i])!=0) switch (toupper((int)argv[i][1])) {
- case 'C': /* Data or PI chars to print: 0 or more. */
- prntmax = atoi(&argv[i][2]);
- continue;
- case 'S': /* Show parsing information. */
- suppsw = 0;
- continue;
- default:
- printf(
- "\nVM001-> \"%s\" option switch is incorrect; usage is: %s %s",
- argv[i], vmomsg, sgmlomsg);
- exit(001);
- }
- }
- if (fileid==0 || *fileid=='?') {
- printf(
- "\nVM002-> No primary file specified; usage is: %s %s [profile;]file",
- vmomsg, sgmlomsg);
- exit(002);
- }
- /* IDENTIFY THE SGML DOCUMENT ENTITY
- */
- /* Define specified external file(s) as document entity. */
- if (docent(fileid)) {
- printf(
- "\nVM005-> SGML document entity system ID (%s) exceeds 240 characters.",
- fileid);
- exit(005);
- }
- /* INITIALIZE THE RUN
- */
- TPisVM = 1; /* Signal that validator is here. */
- sgmlset(); /* Initialize the SGML parser. */
- while (++te.pass<=te.passes) {
- /* INITIALIZE THE PASS
- */
- if (sgmlpset()) {
- printf(
- "\nVM006-> Could not open SGML document entity in file: %s", fileid);
- exit(006);
- }
- /* RUN THE PASS
- */
- printf(
- "\nVM105-> Pass %d of %d.", te.pass, te.passes);
- docproc();
- }
- /* END OF RUN: Report message count and capacity statistics.
- */
- msgcnt = sgmlend();
- printf(
- "\nVM106-> Processing completed; %u messag%s issued.",
- msgcnt, (msgcnt==1) ? "e" : "es");
- if (!suppsw) prtstat((struct stat *)srcbp);
- exit(0);
- }
- /******************************************************************************/
- /* DOCPROC: Process the returns from SGMLNEXT.
- */
- void docproc()
- {
- int rc; /* Return code from SGMLNEXT. */
-
- while ((rc = sgmlnext())!=TPEOD) switch (rc) {
- case TPNDATA: /* Non-SGML data entity reference. */
- location(10);
- printf("Non-SGML data entity");
- if (CONTERSW) printf(" (out of context)");
- printf("\n %-8s = \"%s", "*ENTITY", de.ename);
- getde();
- continue;
-
- case TPNSGML: /* Non-SGML character reference. */
- location(10);
- printf("Non-SGML character%s %d [%c]: [%c%c]",
- (CONTERSW ? " (out of context)" : ""),
- te.nonsgml, ZAPEOL(te.nonsgml), te.data[0], te.data[1]);
- continue;
-
- case TPPCDATA: /* Parsed character data found. */
- case TPCDATA: /* Character data entity reference. */
- case TPSDATA: /* System data entity reference. */
- location(10);
- printf("%d data characte%s%s%s%s: [",
- te.datalen, ((te.datalen==1) ? "r" : "rs"),
- (rc==TPCDATA ? " in CDATA entity" : ""),
- (rc==TPSDATA ? " in SDATA entity" : ""),
- (CONTERSW ? " (out of context)" : ""));
- if (prntmax<te.datalen) printf("%.*s] ...", prntmax, te.data);
- else printf("%.*s]", te.datalen, te.data);
- continue;
-
- case TPSTAG: /* Start-tag. */
- location(11);
- if (TAGMIN==MINNONE) {
- printf("%s start-tag found%s.",
- te.data, CONTERSW ? " (out of context)" :
- PEXSW ? " (inclusion)" : "" );
- if (ETISW)
- printf("\b; NET delimiter enabled (%d total).", ETICTR);
- }
- else if (TAGMIN==MINSTAG) {
- printf("%s start-tag implied by %s%s", te.data,
- (TAGREAL<MINPTR ? realmsg[(UNS)TAGREAL]
- : TAGRLNM+1),
- (TAGREAL==ETDCDATA ? "." : " start-tag."));
- }
- else printf("Short (no GI) %s start-tag found.", te.data);
- #ifdef V2
- printf(" (Format %s.)", formats[te.format]);
- #endif
- if (SRMNM) printf(" SHORTREF map is \"%s\".", SRMNM+1);
- else if (srmsw) printf(" SHORTREF map is empty.");
- /* if (te.gidata) printf(" [GIDATA = \"%s\" in %04x]", te.gidata);*/
- if (te.alcnt) getatts();
- continue;
-
- case TPETAG: /* End-tag found. */
- location(12);
- if (MTYSW) printf("%s end-tag implied by empty content;", te.data);
- else if (TAGMIN==MINSTAG || TAGMIN==MINETAG) {
- printf("%s end-tag implied by %s%s", te.data,
- (TAGREAL<MINPTR ? realmsg[(UNS)TAGREAL]
- : TAGRLNM+1),
- (TAGREAL==ETDCDATA ? ";" :
- (TAGMIN==MINSTAG ? " start-tag;" : " end-tag;")));
- }
- else printf(eminmsg[TAGMIN], te.data);
- if (PEXSW) printf(" (Inclusion ended.)");
- if (ETISW) printf(" NET delimiter disabled (%u left);", ETICTR);
- printf(" %s element resumed.", OLDGI+1);
- #ifdef V2
- printf(" (Ending format %s.)", formats[te.format]);
- #endif
- if (SRMNM) printf(" SHORTREF map is \"%s\".", SRMNM+1);
- else if (srmsw) printf(" SHORTREF map is empty.");
- /* if (te.gidata) printf(" [gidata = \"%s\" in %04x]", te.gidata);*/
- continue;
-
- case TPPI: /* Processing instruction. */
- case TPPIENT: /* Processing instruction entity. */
- if (suppsw) continue;
- location(13);
- printf("%d character processing instruction%s: [",
- te.datalen, (rc==TPPIENT ? " in PI entity" : ""));
- if (prntmax<te.datalen) printf("%.*s] ...", prntmax, te.data);
- else printf("%.*s]", te.datalen, te.data);
- continue;
-
- case TPRE: /* Significant record end. */
- if (suppsw) continue;
- location(14);
- printf("Record end%s.", (CONTERSW ? " (out of context)" : ""));
- continue;
-
- case TPSDTD: /* Document type definition started. */
- location(15);
- printf("Document type definition started for %s.", te.data);
- continue;
-
- case TPEDTD: /* Document type definition completed. */
- location(16); /* GISET and GIGET can now be done. */
- printf("Document type definition completed for %s; ", te.data);
- printf("%d SHORTREF map%s defined.",
- SRMCNT, (SRMCNT==1) ? "" : "s");
- srmsw = SRMCNT>0; /* Short reference maps are in use. */
- /* Store GIDATA for element start-tags and end-tags here. */
- /* GISET returns non-zero for undefined elements. */
- /* TESTING ONLY: Store GIDATA for document type element. */
- /* giset("DUMMYGI", /* Dummy GI. */
- /* "start-data", /* Phoney GIDATA for start-tag. */
- /* "end-data"); /* Phoney GIDATA for start-tag. */
- /* END OF TEST */
- continue;
-
- case TPMV: /* Markup validator information. */
- if (suppsw) continue;
- location(17);
- printf("USEMAP declaration:");
- if (CDATA) {
- printf(" SHORTREF map is \"%s\".", CDATA+1);
- }
- else printf(" SHORTREF map is empty.");
- continue;
-
- default:
- continue;
- }
- /* TPEOD: End of document. */
- return;
- }
- /******************************************************************************/
- /* GETATTS: Retrieve attribute specifications, one by one, and print them.
- */
- void getatts()
- {
- while (alnext()) {
- /* No value specified for #IMPLIED or #REQUIRED.
- */
- if (CA.astatus==TPAIMPLY || CA.astatus==TPANOREQ) {
- printf("\n %-8s = [NONE]", CA.aname);
- if (CA.astatus==TPANOREQ) printf(" [INVALID]");
- return;
- }
- /* Value specified or defaulted.
- */
- printf(attspc);
- printf("%-8s = \"", CA.aname);
- switch (CA.atype) {
- case TPALIST: /* Value is list of tokens. */
- avnext(); /* First token is on same line. */
- printf("%.*s", CA.tokenlen, CA.token);
- proctkn(CA.tokenlen, CA.token);
- while (avnext()) { /* New lines for any other tokens. */
- printf(attspc);
- printf(" %.*s", CA.tokenlen, CA.token);
- proctkn(CA.tokenlen, CA.token);
- }
- printf("\"");
- break;
- case TPACDATA: /* Value is string.*/
- case TPATOKEN: /* Value is single token.*/
- printf("%.*s", CA.avallen, CA.aval);
- proctkn(CA.avallen, CA.aval);
- printf("\"");
- break;
- }
- if (CA.astatus==TPAERROR) printf(" [ERROR]");
- else if (CA.astatus==TPAINVAL) printf(" [INVALID]");
- else if (!GET(CA.aflags, ASPEC)) printf(" [DEFAULT]");
- else if (GET(CA.aflags, ACURRENT)) printf(" [NEW DEFAULT]");
- if (CA.aconref) printf(" [CONREF]");
- }
- if (attspc==deattspc) attspc = teattspc;
- }
- /******************************************************************************/
- /* PROCTKN: Process a single token or list member according to its type.
- */
- void proctkn(tokenlen, token)
- UNS tokenlen; /* Length of token. */
- UNCH *token; /* The token itself. */
- {
- switch (CA.adata) {
- case TPANOTE: /* dcnid, dcnidlen */
- printf("=>%s", CA.dcnid);
- break;
- case TPAENTIT: /* neid,dcnnm,dcnid+len; alcnt */
- getent(tokenlen, token); /* Set up rcbde for this entity. */
- getde();
- break;
- case TPAIDREF: /* idrstat */
- idrnext();
- if (!CA.idrstat) printf(" [INVALID]");
- break;
- }
- }
- /******************************************************************************/
- /* GETDE: Get control block information for data entity named in
- AENTITY attribute or external data entity reference.
- */
- void getde()
- {
- if (de.detype<=TPISDATA) {
- printf("=>%s [internal %s]", de.detxt, typetab[de.detype-1]);
- return;
- }
- printf("=>%s [%s]; notation is %s=>%s.",
- de.detxt+2, typetab[de.detype-1],
- (de.dcnnm!=0) ? de.dcnnm : "[UNDEFINED]",
- (de.dcnid!=0) ? de.dcnid+2 : "[UNDEFINED]");
- if (de.alcnt) {attspc = deattspc; getatts();}
- }
- /******************************************************************************/
- /* PRTSTAT: Print capacity statistics from the stat structure (verbosely).
- */
- void prtstat(ps)
- struct stat *ps; /* Pointer to SGML stat structure. */
- {
- printf("\n %3u entit%s declared with %u character%s of text.",
- ps->ecbcnt, (ps->ecbcnt==1) ? "y" : "ies",
- ps->ecbtext, (ps->ecbtext==1) ? "" : "s");
- printf("\n %3u element typ%s declared",
- ps->etdcnt, (ps->etdcnt==1) ? "e" : "es");
- if (ps->etdercnt) printf(
- " (plus %u undeclared)", ps->etdercnt);
- printf(",\n with %u model token%s and %u exception group%s",
- ps->modcnt, (ps->modcnt==1) ? "" : "s",
- ps->pmexgcnt, (ps->pmexgcnt==1) ? "" : "s");
- if (ps->pmexcnt) printf(
- " with %u name%s", ps->pmexcnt, (ps->pmexcnt==1) ? "" : "s");
- printf(".\n %3u attribute%s with %u group member%s",
- ps->attcnt, (ps->attcnt==1) ? "" : "s",
- ps->attgcnt, (ps->attgcnt==1) ? "" : "s");
- printf("\n and %u character%s of value text.",
- ps->attdef, (ps->attdef==1) ? "" : "s");
- printf("\n %3u ID%s and %u ID reference%s specified.",
- ps->idcnt, (ps->idcnt==1) ? "" : "s",
- ps->idrcnt, (ps->idrcnt==1) ? "" : "s");
- printf("\n %3u data content notation%s with %u text character%s.",
- ps->dcncnt, (ps->dcncnt==1) ? "" : "s",
- ps->dcntext, (ps->dcntext==1) ? "" : "s");
- printf("\n %3u short reference map%s declared.",
- ps->srcnt, (ps->srcnt==1) ? "" : "s");
- printf("\n %lu capacity points required (%lu%% of %lu permitted).",
- ps->capused, ps->capused*100/ps->capacity, ps->capacity);
- }
- /******************************************************************************/