📄 pars2.c
字号:
(which is always >= the actual length). */ if (!attval(0, antvptr+1, adn, adl)) pt += ADLEN(al,adn); continue; default: /* All attributes have been parsed. */ REPEATCC; /* Put next char back for tag close parse. */ break; } break; } if (pt>tbuflim) synerr(75, &pcbstag); if (es!=mdessv) synerr(37, &pcbstag); if (adn<0) return((struct ad *)0); /* List was empty. */ TRACEADL(al); return al;}/* ATTVAL: Validate a specified attribute value. Issue a message if it is the wrong type (or otherwise is not up to spec), and use the default. Call PARSEVAL to tokenize the value, unless it is a CDATA string. If the attribute is a group, the value is a string. For other types, the token count is set by PARSEVAL if the value is syntactically correct. If incorrect (or if CDATA) the token count is zero (i.e., the value is a string). The length of a token does not include the length byte, and there is no EOS. A string length (as always) includes both the length byte and the EOS. If it is a CONREF attribute, set a switch for STAG(). If it is a CURRENT attribute, store the value as the new default.*/#define DEFVAL adl[adn].addef /* Default value of current attribute. */#define DEFNUM adl[adn].adnum /* Default group size of current attribute. */#define DEFLEN adl[adn].adlen /* Length of default value of current attribute.*/int attval(mtvsw, adval, adn, adl)int mtvsw; /* Must tokenize value: 1=yes; 0=no. */UNCH *adval; /* Untokenized attribute value. */int adn; /* Attribute's position in list. */struct ad *adl; /* Element's master att def list. */{ int errcode; /* Value/declaration conflict error code. */ if (GET(ADFLAGS(al,adn), ASPEC)) /* Can't respecify same attribute. */ {sgmlerr(73, &pcbstag, ADNAME(al,adn), adval); return(1);} SET(ADFLAGS(al,adn), ASPEC); /* Indicate att was specified. */ if (GET(ADFLAGS(al,adn), ACONREF)) /* If attribute is content reference: */ conrefsw = TAGREF; /* Set switch for STAG(). */ if (mtvsw && ADTYPE(al,adn)!=ACHARS) { /* If no syntax errors, check for proper group membership. */ if ( ((errcode = parseval(adval, ADTYPE(al,adn), lbuf))==0) && GET(ADFLAGS(al,adn), AGROUP) && !amemget(&al[adn], ADNUM(al,adn), lbuf) ) errcode = 18; /* If syntax or group membership error, send message and exit. */ if (errcode) { sgmlerr(errcode, &pcbstag, ADNAME(al,adn), adval); SET(ADFLAGS(al,adn), AERROR); return(1); } /* Replace specified value in adval with tokenized in lbuf. */ ustrcpy(adval, lbuf); if (BITOFF(ADFLAGS(al,adn), AGROUP)) ADNUM(al,adn) = (UNCH)tokencnt; } if (!mtvsw) adval--; /* If attribute is FIXED, specified value must equal default. */ if (BITON(ADFLAGS(al,adn), AFIXED) && ustrcmp(adval, DEFVAL)) { /* Since the value has been tokenized, don't use it in the error message. */ sgmlerr(67, &pcbstag, ADNAME(al,adn), (UNCH *)0); SET(ADFLAGS(al,adn), AERROR); return(1); } ADLEN(al,adn) = vallen(ADTYPE(al,adn), ADNUM(al,adn), adval); if (ADLEN(al,adn) > LITLEN) { sgmlerr(224, &pcbstag, ADNAME(al,adn), (UNCH *)0); SET(ADFLAGS(al,adn), AERROR); return 1; } ADVAL(al,adn) = adval; /* If attribute is CURRENT, value is new default.*/ if (GET(ADFLAGS(al,adn), ACURRENT)) { if (ADLEN(al,adn)>DEFLEN) { ds.attdef += (ADLEN(al,adn) - DEFLEN); DEFLEN = ADLEN(al,adn); } DEFVAL = replace(DEFVAL, ADVAL(al,adn)); DEFNUM = ADNUM(al,adn); } return(0); /* Indicate value was valid. */}/* ADLVAL: Validate the completed attribute definition list (defaults plus specified values). Issue a message if an attribute is required or current and its value is NULL.*/VOID adlval(adsz, newetd)int adsz; /* Size of list. */struct etd *newetd; /* Element type definition for this element. */{ int adn = 1; /* Position in list. */ UNCH *npt, *pt; /* Ptr save areas. */ UNCH nptsv; /* Save area for ptr value (length?). */ struct dcncb *dpt; /* Save area for dcncb ptr. */ aentctr = 0; /* Number of AENTITY tokens in this att list. */ idrctr = 0; /* Number of IDREF tokens in this att list. */ do { if (ADVAL(al,adn)==NULL) { /* NULL value */ if (GET(ADFLAGS(al,adn), AREQ+ACURRENT)) { /*Error if REQ, CURRENT*/ sgmlerr(19, &pcbstag, ADNAME(al,adn), (UNCH *)0); SET(ADFLAGS(al,adn), AINVALID); } } else switch (ADTYPE(al,adn)) { case AENTITY: /* Return data ecb pointer if valid entity. */ aenttst(adn, ADVAL(al,adn)); break; case AENTITYS: /* Return data ecb pointers if valid entities. */ pt = ADVAL(al,adn); tokencnt = (int)ADNUM(al,adn); while (tokencnt--) { nptsv = *(npt = pt + *pt+1); *pt += 2; *npt = EOS; aenttst(adn, pt); *pt -= 2; *(pt = npt) = nptsv; } break; case AID: /* Define ID; msg if it already exists. */ if (iddef(ADVAL(al,adn))) { sgmlerr(71, &pcbstag, ADNAME(al,adn), ADVAL(al,adn)+1); SET(ADFLAGS(al,adn), AINVALID); continue; } ++ds.idcnt; break; case AIDREF: idreftst(adn, ADVAL(al,adn)); break; case AIDREFS: pt = ADVAL(al,adn); tokencnt = (int)ADNUM(al,adn); while (tokencnt--) { nptsv = *(npt = pt + *pt+1); *pt += 2; *npt = EOS; idreftst(adn, pt); *pt -= 2; *(pt = npt) = nptsv; } break; case ANOTEGRP: /* Return notation identifier. */ if (GET(ADFLAGS(al,adn), ASPEC)) notadn = adn;/*NOTATION specified*/ if ((dpt = dcnfind(ADVAL(al,adn)))==0) { sgmlerr(77, &pcbstag, ADNAME(al,adn), ADVAL(al,adn)+1); SET(ADFLAGS(al,adn), AINVALID); } else ADDATA(al,adn).x = dpt; break; } if (!sd.shorttag && !sd.omittag && ADVAL(al,adn)!=NULL && !GET(ADFLAGS(al,adn), ASPEC+AINVALID)) sgmlerr(197, &pcbstag, ADNAME(al,adn), (UNCH *)0); } while ((adn+=BITON(ADFLAGS(al,adn),AGROUP) ? (int)ADNUM(al,adn)+1 : 1)<=adsz); /* Error if NOTATION specified with CONREF attribute or EMPTY element. */ if (notadn && (conrefsw || (newetd && GET(newetd->etdmod->ttype, MNONE)))) { sgmlerr((UNS)(conrefsw ? 84 : 76), &pcbstag, ADNAME(al,notadn), ADVAL(al,notadn)+1); SET(ADFLAGS(al,notadn), AINVALID); }}/* AENTTST: Validate an individual ENTITY token in AENTITY or AENTITYS value.*/VOID aenttst(adn, pt)int adn; /* Position in list. */UNCH *pt; /* Ptr to current ENTITY token in value. */{ struct entity *ept; /* Save area for ecb ptr. */ if (++aentctr>GRPCNT) { sgmlerr(136, &pcbstag, ADNAME(al,adn), pt+1); SET(ADFLAGS(al,adn), AINVALID); return; } if ( (ept = entfind(pt))==0 && (ecbdeflt==0 || (ept = usedef(pt))==0) ) { sgmlerr(ecbdeflt ? 151 : 72, &pcbstag, ADNAME(al,adn), pt+1); SET(ADFLAGS(al,adn), AINVALID); return; } if (ept->estore==ESX || ept->estore==ESC || ept->estore==ESN) { /* Error if DCN has no notation identifier. */ if (ept->estore==ESN && NEXTYPE(ept->etx.n)!=ESNSUB && !NEDCNDEFINED(ept->etx.n)) { sgmlerr(78, &pcbstag, NEDCN(ept->etx.n)+1, pt+1); SET(ADFLAGS(al,adn), AINVALID); } } else { sgmlerr(86, &pcbstag, ADNAME(al,adn), pt+1); SET(ADFLAGS(al,adn), AINVALID); }}/* IDREFTST: Validate an individual IDREF token in an IDREF or IDREFS value.*/VOID idreftst(adn, pt)int adn; /* Position in list. */UNCH *pt; /* Ptr to current IDREF token in value. */{ struct fwdref *rp; if (++idrctr>GRPCNT) { sgmlerr(70, &pcbstag, ADNAME(al,adn), pt+1); SET(ADFLAGS(al,adn), AINVALID); return; } /* Note IDREF; indicate if ID exists. */ if ((rp = idref(pt)) != 0) rp->msg = saverr(69, &pcbstag, ADNAME(al,adn), pt+1); ++ds.idrcnt;}/* ANMGET: Locate an attribute name in an attribute definition list.*/int anmget(adsz, nm)int adsz; /* Size of list. */UNCH *nm; /* Value to be found (with length byte). */{ int adn = 0; /* Position in list. */ while (++adn <= adsz && ustrcmp(nm+1, ADNAME(al,adn))) { if (BITON(ADFLAGS(al,adn), AGROUP)) adn += (int)ADNUM(al,adn); } return (adn > adsz) ? 0 : adn;}/* ANTVGET: Find the position of a name token value in an attribute list. Return the position of the attribute definition, or zero if none was found. Set pp to the value, if non-NULL.*/int antvget(adsz, nm, pp)int adsz; /* Size of list. */UNCH *nm; /* Value to be found (with length byte). */UNCH **pp; /* Store value here */{ int adn = 0; /* Position in list. */ while (++adn<=adsz) { /* Test only name group members. */ if (BITON(ADFLAGS(al,adn), AGROUP)) { int advn; /* Position of value in sub-list. */ if ((advn = amemget(&al[adn], (int)ADNUM(al,adn), nm))!=0) { if (pp) *pp = al[adn+advn].adname; return adn; } adn += (int)ADNUM(al,adn); } } return 0;}/* AMEMGET: Get the position of a member in an attribute name token group. Returns the position, or zero if not found. The length byte is ignored in the comparison so that final form tokens from ATTVAL can be compared to group members.*/int amemget(anmtgrp, adsz, nm)struct ad anmtgrp[]; /* Name token group. */int adsz; /* Size of group. */UNCH *nm; /* Name to be found (with length byte). */{ int adn = 0; /* Position in group. */ while ( ++adn<=adsz && ustrncmp(nm+1, anmtgrp[adn].adname+1, (UNS)*nm-1)) ; return (adn>adsz) ? 0 : adn;}/* VALLEN: Returns the length of an attribute value for capacity calculations. Normally, the length is NORMSEP plus the number of characters. For tokenized lists, it is NORMSEP, plus the number of characters in the tokens, plus NORMSEP for each token. ACHARS and tokenized lists don't have a length byte.*/UNS vallen(type, num, def)int type; /* ADTYPE(al,adn) */int num; /* ADNUM(al,adn) */UNCH *def; /* ADVAL(al,adn) */{ if (type == ACHARS) return ustrlen(def) + NORMSEP; if (type < ATKNLIST) return *def - 2 + NORMSEP; return ustrlen(def) + num * (NORMSEP - 1) + NORMSEP;}/* PARSEGRP: Parse GI names, get their etds, and form an array of pointers to them. The array is terminated by a NULL pointer. The number of pointers (including the NULL) is returned. The grp buffer must have room for GRPCNT+1 etds.*/UNS parsegrp(grp, pcb, tbuf)struct etd *grp[]; /* Buffer for building the group. */struct parse *pcb; /* Current parse control block. */UNCH *tbuf;{ int grpcnt = 0; /* Number of etds in the group. */ int i; int essv = es; /* Entity stack level when grp started. */ while (parse(pcb)!=GRPE && grpcnt<GRPCNT) { switch (pcb->action) { case NAS_: /* GI name: get its etd for the group. */ grp[grpcnt] = etddef(parsenm(tbuf, NAMECASE)); for (i = 0; i < grpcnt; i++) if (grp[i] == grp[grpcnt]) { mderr(98, ntoa(grpcnt + 1), grp[grpcnt]->etdgi + 1); break; } if (i == grpcnt) grpcnt++; continue; case EE_: /* Entity ended (correctly or incorrectly). */ if (es<essv) {synerr(37, pcb); essv = es;} continue; case PIE_: /* PI entity reference (invalid). */ entpisw = 0; /* Reset PI entity indicator. */ synerr(59, pcb); continue; default: break; } break; } grp[grpcnt++] = 0; /* NULL pointer indicates end of group. */ if (es!=essv) synerr(37, pcb); return grpcnt; /* Return number of ptrs in group. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -