static int eqn_do_define(struct eqn_node *ep) { const char *start; size_t sz; struct eqn_def *def; int i; if (NULL == (start = eqn_nextrawtok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(0); } /* * Search for a key that already exists. * Create a new key if none is found. */ if (NULL == (def = eqn_def_find(ep, start, sz))) { /* Find holes in string array. */ for (i = 0; i < (int)ep->defsz; i++) if (0 == ep->defs[i].keysz) break; if (i == (int)ep->defsz) { ep->defsz++; ep->defs = mandoc_realloc (ep->defs, ep->defsz * sizeof(struct eqn_def)); ep->defs[i].key = ep->defs[i].val = NULL; } ep->defs[i].keysz = sz; ep->defs[i].key = mandoc_realloc (ep->defs[i].key, sz + 1); memcpy(ep->defs[i].key, start, sz); ep->defs[i].key[(int)sz] = '\0'; def = &ep->defs[i]; } start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0); if (NULL == start) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(0); } def->valsz = sz; def->val = mandoc_realloc(def->val, sz + 1); memcpy(def->val, start, sz); def->val[(int)sz] = '\0'; return(1); }
static void eqn_def(struct eqn_node *ep) { const char *start; size_t sz; struct eqn_def *def; int i; if ((start = eqn_nextrawtok(ep, &sz)) == NULL) { mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, ep->eqn.ln, ep->eqn.pos, "define"); return; } /* * Search for a key that already exists. * Create a new key if none is found. */ if (NULL == (def = eqn_def_find(ep, start, sz))) { /* Find holes in string array. */ for (i = 0; i < (int)ep->defsz; i++) if (0 == ep->defs[i].keysz) break; if (i == (int)ep->defsz) { ep->defsz++; ep->defs = mandoc_reallocarray(ep->defs, ep->defsz, sizeof(struct eqn_def)); ep->defs[i].key = ep->defs[i].val = NULL; } def = ep->defs + i; free(def->key); def->key = mandoc_strndup(start, sz); def->keysz = sz; } start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0); if (start == NULL) { mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse, ep->eqn.ln, ep->eqn.pos, "define %s", def->key); free(def->key); free(def->val); def->key = def->val = NULL; def->keysz = def->valsz = 0; return; } free(def->val); def->val = mandoc_strndup(start, sz); def->valsz = sz; }
static int eqn_do_undef(struct eqn_node *ep) { const char *start; struct eqn_def *def; size_t sz; if (NULL == (start = eqn_nextrawtok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(0); } else if (NULL != (def = eqn_def_find(ep, start, sz))) def->keysz = 0; return(1); }
/* * Undefine a previously-defined string. */ static void eqn_undef(struct eqn_node *ep) { const char *start; struct eqn_def *def; size_t sz; if ((start = eqn_nextrawtok(ep, &sz)) == NULL) { mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, ep->eqn.ln, ep->eqn.pos, "undef"); return; } if ((def = eqn_def_find(ep, start, sz)) == NULL) return; free(def->key); free(def->val); def->key = def->val = NULL; def->keysz = def->valsz = 0; }
/* * Get the next token from the input stream using the given quote * character. * Optionally make any replacements. */ static const char * eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl) { char *start, *next; int q, diff, lim; size_t ssz, dummy; struct eqn_def *def; if (NULL == sz) sz = &dummy; lim = 0; ep->rew = ep->cur; again: /* Prevent self-definitions. */ if (lim >= EQN_NEST_MAX) { mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse, ep->eqn.ln, ep->eqn.pos, NULL); return(NULL); } ep->cur = ep->rew; start = &ep->data[(int)ep->cur]; q = 0; if ('\0' == *start) return(NULL); if (quote == *start) { ep->cur++; q = 1; } start = &ep->data[(int)ep->cur]; if ( ! q) { if ('{' == *start || '}' == *start) ssz = 1; else ssz = strcspn(start + 1, " ^~\"{}\t") + 1; next = start + (int)ssz; if ('\0' == *next) next = NULL; } else next = strchr(start, quote); if (NULL != next) { *sz = (size_t)(next - start); ep->cur += *sz; if (q) ep->cur++; while (' ' == ep->data[(int)ep->cur] || '\t' == ep->data[(int)ep->cur] || '^' == ep->data[(int)ep->cur] || '~' == ep->data[(int)ep->cur]) ep->cur++; } else { if (q) mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse, ep->eqn.ln, ep->eqn.pos, NULL); next = strchr(start, '\0'); *sz = (size_t)(next - start); ep->cur += *sz; } /* Quotes aren't expanded for values. */ if (q || ! repl) return(start); if (NULL != (def = eqn_def_find(ep, start, *sz))) { diff = def->valsz - *sz; if (def->valsz > *sz) { ep->sz += diff; ep->data = mandoc_realloc(ep->data, ep->sz + 1); ep->data[ep->sz] = '\0'; start = &ep->data[(int)ep->rew]; } diff = def->valsz - *sz; memmove(start + *sz + diff, start + *sz, (strlen(start) - *sz) + 1); memcpy(start, def->val, def->valsz); lim++; goto again; } return(start); }