📄 md1.c
字号:
#include "sgmlincl.h" /* #INCLUDE statements for SGML parser. *//* MDADL: Process ATTLIST declaration.*/VOID mdadl(tbuf)UNCH *tbuf; /* Work area for tokenization (tbuf). */{ int i; /* Loop counter; temporary variable. */ int adlim; /* Number of unused ad slots in al. */ struct ad *alperm = 0; /* Attribute definition list. */ int stored = 0; mdname = key[KATTLIST]; /* Identify declaration for messages. */ subdcl = 0; /* No subject as yet. */ parmno = 0; /* No parameters as yet. */ mdessv = es; /* Save es level for entity nesting check. */ reqadn = noteadn = 0; /* No required attributes yet. */ idadn = conradn = 0; /* No special atts yet.*/ AN(al) = 0; /* Number of attributes defined. */ ADN(al) = 0; /* Number of ad's in al (atts + name vals).*/ /* PARAMETER 1: Element name or a group of them. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("1: element name or group"); switch (pcbmd.action) { case NAS: nmgrp[0] = etddef(tbuf); nmgrp[1] = 0; break; case GRPS: parsegrp(nmgrp, &pcbgrnm, tbuf); break; case RNS: /* Reserved name started. */ if (ustrcmp(tbuf+1, key[KNOTATION])) { mderr(118, tbuf+1, key[KNOTATION]); return; } mdnadl(tbuf); return; default: mderr(121, (UNCH *)0, (UNCH *)0); return; } /* Save first GI for error msgs. */ if (nmgrp[0]) subdcl = nmgrp[0]->etdgi+1; /* PARAMETER 2: Attribute definition list. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("2: attribute list"); if (pcbmd.action!=NAS) { mderr(120, (UNCH *)0, (UNCH *)0); return; } while (pcbmd.action==NAS) { al[ADN(al)+1].adname = savenm(tbuf); if ((adlim = ATTCNT-((int)++ADN(al)))<0) { mderr(111, (UNCH *)0, (UNCH *)0); adlfree(al, 1); return; } ++AN(al); if (mdattdef(adlim, 0)) { adlfree(al, 1); return; } parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); } if (AN(al)>0) { /* Save list only if 1 or more good atts. */ if (reqadn) SET(ADLF(al), ADLREQ); /* Element must have start-tag. */ if (noteadn) SET(ADLF(al), ADLNOTE); /* Element cannot be EMPTY. */ if (conradn) SET(ADLF(al), ADLCONR); /* Element cannot be EMPTY. */ alperm = (struct ad *)rmalloc((1+ADN(al))*ADSZ); memcpy((UNIV)alperm, (UNIV)al, (1+ADN(al))*ADSZ ); ds.attcnt += AN(al); /* Number of attributes defined. */ ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */ TRACEADL(alperm); } /* Clear attribute list for next declaration. */ MEMZERO((UNIV)al, (1+ADN(al))*ADSZ); /* PARAMETER 3: End of declaration. */ /* Next pcb.action was set during attribute definition loop. */ TRACEMD(emd); if (pcbmd.action!=EMD) {mderr(126, (UNCH *)0, (UNCH *)0); return;} if (es!=mdessv) synerr(37, &pcbmd); /* EXECUTE: Store the definition for each element name specified. */ TRACEGRP(nmgrp); for (i = 0; nmgrp[i]; i++) { if (nmgrp[i]->adl) { /* Error if an ADL exists. */ mderr(112, (UNCH *)0, (UNCH *)0); continue; } nmgrp[i]->adl = alperm; /* If virgin, store the adl ptr. */ stored = 1; if (alperm && nmgrp[i]->etdmod) etdadl(nmgrp[i]); /* Check for conflicts with ETD. */ } if (!stored && alperm) { adlfree(alperm, 1); frem((UNIV)alperm); }}/* ETDADL: Check compatibility between ETD and ADL.*/VOID etdadl(p)struct etd *p; /* Pointer to element type definition. */{ parmno = 0; /* Minimizable element cannot have required attribute. */ if (GET(p->etdmin, SMO) && GET(p->adl[0].adflags, ADLREQ)) { mderr(40, (UNCH *)0, (UNCH *)0); RESET(p->etdmin, SMO); } /* Empty element cannot have NOTATION attribute. Attribute is not removed (too much trouble), but we trap attempts to specify it on the start-tag in adlval(). */ if (GET(p->etdmod->ttype, MNONE)) { if (GET(p->adl[0].adflags, ADLNOTE)) mderr(83, (UNCH *)0, (UNCH *)0); /* Empty element cannot have CONREF attribute. Attribute is not removed because it just acts like IMPLIED anyway. */ if (GET(p->adl[0].adflags, ADLCONR)) mderr(85, (UNCH *)0, (UNCH *)0); }#if 0 /* "-" should not be specified for the end-tag minimization if the element has a content reference attribute. */ if (GET(p->adl[0].adflags, ADLCONR) && BITON(p->etdmin, EMM)) mderr(153, (UNCH *)0, (UNCH *)0);#endif}/* MDNADL: Process ATTLIST declaration for notation. TO DO: Pass deftab and dvtab as parameters so that prohibited types can be handled by leaving them out of the tables.*/VOID mdnadl(tbuf)UNCH *tbuf; /* Work area for tokenization (tbuf). */{ int i; /* Loop counter; temporary variable. */ int adlim; /* Number of unused ad slots in al. */ struct ad *alperm = 0; /* Attribute definition list. */ int stored = 0; /* PARAMETER 1: Notation name or a group of them. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("1: notation name or group"); switch (pcbmd.action) { case NAS: nnmgrp[0] = dcndef(tbuf); nnmgrp[1] = 0; break; case GRPS: parsngrp(nnmgrp, &pcbgrnm, tbuf); break; default: mderr(121, (UNCH *)0, (UNCH *)0); return; } subdcl = nnmgrp[0]->ename+1; /* Save first name for error msgs. */ /* PARAMETER 2: Attribute definition list. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("2: attribute list"); if (pcbmd.action!=NAS) { mderr(120, (UNCH *)0, (UNCH *)0); return; } while (pcbmd.action==NAS) { al[ADN(al)+1].adname = savenm(tbuf); if ((adlim = ATTCNT-((int)ADN(al)++))<0) { mderr(111, (UNCH *)0, (UNCH *)0); adlfree(al, 1); return; } ++AN(al); if (mdattdef(adlim, 1)) { adlfree(al, 1); return; } parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); } if (AN(al)>0) { /* Save list only if 1 or more good atts. */ alperm = (struct ad *)rmalloc((1+ADN(al))*ADSZ); memcpy((UNIV)alperm, (UNIV)al, (1+ADN(al))*ADSZ ); ds.attcnt += AN(al); /* Number of attributes defined. */ ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */ TRACEADL(alperm); } /* Clear attribute list for next declaration. */ MEMZERO((UNIV)al, (1+ADN(al))*ADSZ); /* PARAMETER 3: End of declaration. */ /* Next pcb.action was set during attribute definition loop. */ TRACEMD(emd); if (pcbmd.action!=EMD) {mderr(126, (UNCH *)0, (UNCH *)0); return;} if (es!=mdessv) synerr(37, &pcbmd); /* EXECUTE: Store the definition for each notation name specified. */ TRACENGR(nnmgrp); for (i = 0; nnmgrp[i]; i++) { if (nnmgrp[i]->adl) { /* Error if an ADL exists. */ mderr(112, (UNCH *)0, (UNCH *)0); continue; } nnmgrp[i]->adl = alperm; /* If virgin, store the adl ptr. */ if (nnmgrp[i]->entsw) fixdatt(nnmgrp[i]); stored = 1; TRACEDCN(nnmgrp[i]); } if (!stored && alperm) { adlfree(alperm, 1); frem((UNIV)alperm); }}/* Data attributes have been specified for notation p, but entitieshave already been declared with notation p. Fix up the definitions ofall entities with notation p. Generate an error for any dataattribute that was required. */VOID fixdatt(p)struct dcncb *p;{ int i; for (i = 0; i < ENTHASH; i++) { struct entity *ep; for (ep = etab[i]; ep; ep = ep->enext) if (ep->estore == ESN && ep->etx.n && ep->etx.n->nedcn == p) { int adn; initatt(p->adl); /* Don't use adlval because if there were required attributes the error message wouldn't say what entity was involved. */ for (adn = 1; adn <= ADN(al); adn++) { if (GET(ADFLAGS(al,adn), AREQ)) { sgmlerr(218, &pcbstag, ADNAME(al,adn), ep->ename + 1); SET(ADFLAGS(al,adn), AINVALID); } if (BITON(ADFLAGS(al, adn), AGROUP)) adn += ADNUM(al, adn); } storedatt(ep->etx.n); } }}/* MDATTDEF: Process an individual attribute definition. The attribute name is parsed by the caller. Duplicate attributes are parsed, but removed from list. Returns 0 if successful, otherwise returns 1.*/int mdattdef(adlim, datt)int adlim; /* Remaining capacity of al (in tokens).*/int datt; /* Non-zero if a data attribute. */{ int deftype; /* Default value type: 0=not keyword. */ int errsw = 0; /* 1=semantic error; ignore att. */ int novalsw = 0; /* 1=semantic error; treat as IMPLIED. */ int attadn = (int)ADN(al); /* Save ad number of this attribute. */ struct parse *grppcb = NULL; /* PCB for name/token grp parse. */ int errcode; /* Error type returned by PARSEVAL, ANMTGRP. */ UNCH *advalsv; /* Save area for permanent value ptr. */ /* PARAMETER 1: Attribute name (parsed by caller). */ TRACEMD("1: attribute name"); if (anmget((int)ADN(al)-1, al[attadn].adname)) { errsw = 1; mderr(99, ADNAME(al,attadn), (UNCH *)0); } ADNUM(al,attadn) = ADFLAGS(al,attadn) = ADLEN(al,attadn) = 0; ADVAL(al,attadn) = 0; ADDATA(al,attadn).x = 0; ADTYPE(al,attadn) = ANMTGRP; /* PARAMETER 2: Declared value. */ parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("2: declared value"); switch (pcbmd.action) { case NAS: /* Keyword for value type. */ switch (ADTYPE(al,attadn) = (UNCH)mapsrch(dvtab, lbuf+1)) { case 0: mderr(100, ADNAME(al,attadn), lbuf+1); return 1; case ANOTEGRP: if (datt) { errsw = 1; mderr(156, (UNCH *)0, (UNCH *)0); } else if (!noteadn) noteadn = ADN(al); else { errsw = 1; mderr(101, ADNAME(al,attadn), (UNCH *)0); } grppcb = &pcbgrnm; /* NOTATION requires name grp. */ parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);/* Get GRPO*/ break; case AID: if (datt) { errsw = 1; mderr(144, (UNCH *)0, (UNCH *)0); } else if (!idadn) idadn = attadn; else { errsw = 1; mderr(102, ADNAME(al,attadn), (UNCH *)0); } break; case AIDREF: case AIDREFS: if (datt) { errsw = 1; mderr(155, (UNCH *)0, (UNCH *)0); } break; case AENTITY: case AENTITYS: if (datt) { errsw = 1; mderr(154, (UNCH *)0, (UNCH *)0); } break; } break; case GRPS: grppcb = &pcbgrnt; /* Normal grp is name token grp. */ break; case EMD: mderr(103, ADNAME(al,attadn), (UNCH *)0); return 1; default: mderr(104, ADNAME(al,attadn), (UNCH *)0); return 1; } /* PARAMETER 2A: Name token group. */ if (grppcb != NULL) { TRACEMD("2A: name group"); switch (pcbmd.action) { case GRPS: /* Name token list. */ SET(ADFLAGS(al,attadn), AGROUP); /* Call routine to parse group, create ad entries in adl. */ errcode = anmtgrp(grppcb, al+attadn, (GRPCNT<adlim ? GRPCNT+1 : adlim+1), &al[attadn].adnum, ADN(al)); if (errcode<=0) { if (adlim < GRPCNT) mderr(111, (UNCH *)0, (UNCH *)0); else mderr(105, ADNAME(al,attadn), (UNCH *)0); return 1; } ADN(al) += ADNUM(al,attadn); /* Add grp size to total ad cnt.*/ break; default: mderr(106, ADNAME(al,attadn), (UNCH *)0); return 1; } } /* PARAMETER 3: Default value keyword. */ parsemd(lbuf, AVALCASE, (ADTYPE(al,attadn)==ACHARS) ? &pcblitr : &pcblitt, LITLEN); TRACEMD("3: default keyword"); switch (pcbmd.action) { case RNS: /* Keyword. */ deftype = mapsrch(deftab, lbuf+1); switch (deftype) { case DFIXED: /* FIXED */ SET(ADFLAGS(al,attadn), AFIXED); parsemd(lbuf, AVALCASE, (ADTYPE(al,attadn)==ACHARS) ? &pcblitr : &pcblitt, LITLEN); /* Real default. */ goto parm3x; /* Go process specified value. */ case DCURR: /* CURRENT: If ID, treat as IMPLIED. */ if (ADTYPE(al,attadn)==AID) { mderr(80, ADNAME(al,attadn), (UNCH *)0); break; } if (datt) { mderr(157, (UNCH *)0, (UNCH *)0); break; } SET(ADFLAGS(al,attadn), ACURRENT); break; case DREQ: /* REQUIRED */ SET(ADFLAGS(al,attadn), AREQ); ++reqadn; break; case DCONR: /* CONREF */ if (ADTYPE(al,attadn)==AID) { mderr(107, ADNAME(al,attadn), (UNCH *)0); break; } if (datt) { mderr(158, (UNCH *)0, (UNCH *)0); break; } SET(ADFLAGS(al,attadn), ACONREF); conradn = 1; case DNULL: /* IMPLIED */ break; default: /* Unknown keyword is an error. */ mderr(108, ADNAME(al,attadn), lbuf+1); errsw = 1; } if (errsw) { /* Ignore erroneous att. */ adlfree(al, attadn); --AN(al); ADN(al) = (UNCH)attadn-1; } return(0); default: break; } /* PARAMETER 3x: Default value (non-keyword). */ parm3x: TRACEMD("3x: default (non-keyword)"); if (ADTYPE(al,attadn)==AID) { /* If ID, treat as IMPLIED. */ mderr(81, ADNAME(al,attadn), (UNCH *)0); novalsw = 1; /* Keep parsing to keep things straight. */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -