static Bool parsekey(const char *s, const char *e, Key *k) { const char *p, *q; XPRINTF("Parsing key from: '%s'\n", s); for (p = s; p < e && (isalnum(*p) || isblank(*p) || *p == '_'); p++) ; if (p < e && *p == '+') { k->mod = parsemod(s, p); p++; } else p = s; for (q = p; q < e && (isalnum(*q) || isblank(*q) || *q == '_'); q++) ; if (q < e && *q != '=') q = e; if ((k->keysym = parsesym(p, q)) == NoSymbol) { EPRINTF("Failed to parse symbol from '%s' to '%s'\n", p, q); return False; } if (q < e) k->arg = parsearg(q + 1, e); else if (k->arg) k->arg = strdup(k->arg); return True; }
/* MDELEM: Process ELEMENT declaration. */ VOID mdelem(UNCH *tbuf) /* Work area for tokenization (tbuf). */ { UNCH *ranksuff = lbuf; /* Rank suffix. */ UNS dctype = 0; /* Declared content type (from dctab). */ UNCH fmin = 0; /* Minimization bit flags. */ int i; /* Loop counter. */ UNS u; /* Temporary variable. */ struct etd **mexgrp, **pexgrp; /* Ptr to model exceptions array. */ struct thdr *cmod, *cmodsv; /* Ptr to content model. */ UNCH *etdgi; /* GI of current etd (when going through group).*/ int minomitted = 0; /* Tag minimization parameters omitted. */ mdname = key[KELEMENT]; /* Identify declaration for messages. */ subdcl = NULL; /* No subject as yet. */ parmno = 0; /* No parameters as yet. */ mdessv = es; /* Save es level for entity nesting check. */ ranksuff[0] = 0; mexgrp = pexgrp = 0; /* PARAMETER 1: Element name or a group of them. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("1: element name or grp"); switch (pcbmd.action) { case NAS: nmgrp[0] = etddef(tbuf); nmgrp[1] = 0; break; case GRPS: parsegrp(nmgrp, &pcbgrnm, tbuf); break; default: mderr(121, (UNCH *)0, (UNCH *)0); return; } /* Save first GI for trace and error messages. */ if (nmgrp[0]) subdcl = nmgrp[0]->etdgi+1; /* PARAMETER 1A: Rank suffix (optional). */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("1A: rank suffix"); switch (pcbmd.action) { case NUM: ustrcpy(ranksuff, tbuf); parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); default: break; } /* PARAMETER 2A: Start-tag minimization. */ TRACEMD("2A: start min"); switch (pcbmd.action) { case CDR: break; case NAS: if (!ustrcmp(tbuf+1, key[KO])) { if (OMITTAG==YES) SET(fmin, SMO); break; } /* fall through */ default: if (OMITTAG==NO) {minomitted=1; break;} mderr(129, tbuf+1, (UNCH *)0); return; } /* Must omit omitted end-tag minimization, if omitted start-tag minimization was omitted (because OMITTAG == NO). */ if (!minomitted) { /* PARAMETER 2B: End-tag minimization. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); TRACEMD("2B: end min"); switch (pcbmd.action) { case NAS: if (ustrcmp(tbuf+1, key[KO])) {mderr(129, tbuf+1, (UNCH *)0); return;} if (OMITTAG==YES) SET(fmin, EMO); break; case CDR: SET(fmin, EMM); break; default: mderr(129, tbuf+1, (UNCH *)0); return; } /* PARAMETER 3: Declared content. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); } TRACEMD("3: declared content"); switch (pcbmd.action) { case NAS: dctype = mapsrch(dctab, tbuf+1); if (!dctype) {mderr(24, tbuf+1, (UNCH *)0); return;} /* Eliminate incompatibilities among parameters. */ if (GET(fmin, SMO) && GET(dctype, MNONE+MCDATA+MRCDATA)) { mderr(58, (UNCH *)0, (UNCH *)0); RESET(fmin, SMO); } if (GET(dctype, MNONE) && BITON(fmin, EMM)) { mderr(87, (UNCH *)0, (UNCH *)0); SET(fmin, EMO); } /* If valid, process like a content model. */ case GRPS: cmodsv = parsemod((int)(pcbmd.action==GRPS ? 0 : dctype)); if (cmodsv==0) return; u = (dctype ? 1 : cmodsv->tu.tnum+2) * THSZ; cmod = (struct thdr *)rmalloc(u); memcpy((UNIV)cmod , (UNIV)cmodsv, u ); ds.modcnt += cmod->tu.tnum; TRACEMOD(cmod); break; default: mderr(130, (UNCH *)0, (UNCH *)0); return; } /* PARAMETERS 3A, 3B: Exceptions or end. */ parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); if (BITOFF(cmod->ttype, MCDATA+MRCDATA+MNONE)) { /* PARAMETER 3A: Minus exceptions. */ TRACEMD("3A: -grp"); switch (pcbmd.action) { case MGRP: /* We cheat and use nnmgrp for this. */ mexgrp = copygrp((PETD *)nnmgrp, u = parsegrp((PETD *)nnmgrp, &pcbgrnm, tbuf)); ++ds.pmexgcnt; ds.pmexcnt += u-1; TRACEGRP(mexgrp); parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); default: break; } /* PARAMETER 3B: Plus exceptions. */ TRACEMD("3B: +grp"); switch (pcbmd.action) { case PGRP: pexgrp = copygrp((PETD *)nnmgrp, u = parsegrp((PETD *)nnmgrp, &pcbgrnm, tbuf)); ++ds.pmexgcnt; ds.pmexcnt += u-1; TRACEGRP(pexgrp); parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN); default: break; } } /* PARAMETER 4: End of declaration. */ TRACEMD(emd); if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0); if (es!=mdessv) synerr(37, &pcbmd); /* EXECUTE: Store the definition for each element name specified. */ TRACEGRP(nmgrp); for (i = -1; nmgrp[++i];) { etdgi = nmgrp[i]->etdgi; if (*ranksuff) { if ((tbuf[0] = *etdgi + ustrlen(ranksuff)) - 2 > NAMELEN) { mderr(131, etdgi+1, ranksuff); continue; } memcpy(tbuf+1, etdgi+1, *etdgi-1); ustrcpy(tbuf+*etdgi-1, ranksuff); etdcan(etdgi); nmgrp[i] = etddef(tbuf); } if (nmgrp[i]->etdmod) {mderr(56, etdgi+1, (UNCH *)0); continue;} etdset(nmgrp[i], fmin+ETDDCL, cmod, mexgrp, pexgrp, nmgrp[i]->etdsrm); ++ds.etdcnt; if (nmgrp[i]->adl) etdadl(nmgrp[i]); /* Check ETD conflicts. */ TRACEETD(nmgrp[i]); } }