/* ARGSUSED */ static enum rofferr roff_userdef(ROFF_ARGS) { const char *arg[9]; char *cp, *n1, *n2; int i; /* * Collect pointers to macro argument strings * and null-terminate them. */ cp = *bufp + pos; for (i = 0; i < 9; i++) arg[i] = '\0' == *cp ? "" : mandoc_getarg(r->parse, &cp, ln, &pos); /* * Expand macro arguments. */ *szp = 0; n1 = cp = mandoc_strdup(r->current_string); while (NULL != (cp = strstr(cp, "\\$"))) { i = cp[2] - '1'; if (0 > i || 8 < i) { /* Not an argument invocation. */ cp += 2; continue; } *szp = strlen(n1) - 3 + strlen(arg[i]) + 1; n2 = mandoc_malloc(*szp); strlcpy(n2, n1, (size_t)(cp - n1 + 1)); strlcat(n2, arg[i], *szp); strlcat(n2, cp + 3, *szp); cp = n2 + (cp - n1); free(n1); n1 = n2; } /* * Replace the macro invocation * by the expanded macro. */ free(*bufp); *bufp = n1; if (0 == *szp) *szp = strlen(*bufp) + 1; return(*szp > 1 && '\n' == (*bufp)[(int)*szp - 2] ? ROFF_REPARSE : ROFF_APPEND); }
static int man_args(struct roff_man *man, int line, int *pos, char *buf, char **v) { char *start; assert(*pos); *v = start = buf + *pos; assert(' ' != *start); if ('\0' == *start) return 0; *v = mandoc_getarg(man->parse, v, line, pos); return 1; }
static enum margserr args(struct mdoc *mdoc, int line, int *pos, char *buf, enum argsflag fl, char **v) { char *p, *pp; int pairs; enum margserr rc; if ('\0' == buf[*pos]) { if (MDOC_PPHRASE & mdoc->flags) return(ARGS_EOLN); /* * If we're not in a partial phrase and the flag for * being a phrase literal is still set, the punctuation * is unterminated. */ if (MDOC_PHRASELIT & mdoc->flags) mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); mdoc->flags &= ~MDOC_PHRASELIT; return(ARGS_EOLN); } *v = &buf[*pos]; if (ARGSFL_DELIM == fl) if (args_checkpunct(buf, *pos)) return(ARGS_PUNCT); /* * First handle TABSEP items, restricted to `Bl -column'. This * ignores conventional token parsing and instead uses tabs or * `Ta' macros to separate phrases. Phrases are parsed again * for arguments at a later phase. */ if (ARGSFL_TABSEP == fl) { /* Scan ahead to tab (can't be escaped). */ p = strchr(*v, '\t'); pp = NULL; /* Scan ahead to unescaped `Ta'. */ if ( ! (MDOC_PHRASELIT & mdoc->flags)) for (pp = *v; ; pp++) { if (NULL == (pp = strstr(pp, "Ta"))) break; if (pp > *v && ' ' != *(pp - 1)) continue; if (' ' == *(pp + 2) || '\0' == *(pp + 2)) break; } /* By default, assume a phrase. */ rc = ARGS_PHRASE; /* * Adjust new-buffer position to be beyond delimiter * mark (e.g., Ta -> end + 2). */ if (p && pp) { *pos += pp < p ? 2 : 1; rc = pp < p ? ARGS_PHRASE : ARGS_PPHRASE; p = pp < p ? pp : p; } else if (p && ! pp) { rc = ARGS_PPHRASE; *pos += 1; } else if (pp && ! p) { p = pp; *pos += 2; } else { rc = ARGS_PEND; p = strchr(*v, 0); } /* Whitespace check for eoln case... */ if ('\0' == *p && ' ' == *(p - 1)) mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); *pos += (int)(p - *v); /* Strip delimiter's preceding whitespace. */ pp = p - 1; while (pp > *v && ' ' == *pp) { if (pp > *v && '\\' == *(pp - 1)) break; pp--; } *(pp + 1) = 0; /* Strip delimiter's proceeding whitespace. */ for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++) /* Skip ahead. */ ; return(rc); } /* * Process a quoted literal. A quote begins with a double-quote * and ends with a double-quote NOT preceded by a double-quote. * NUL-terminate the literal in place. * Collapse pairs of quotes inside quoted literals. * Whitespace is NOT involved in literal termination. */ if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) { if ( ! (MDOC_PHRASELIT & mdoc->flags)) *v = &buf[++(*pos)]; if (MDOC_PPHRASE & mdoc->flags) mdoc->flags |= MDOC_PHRASELIT; pairs = 0; for ( ; buf[*pos]; (*pos)++) { /* Move following text left after quoted quotes. */ if (pairs) buf[*pos - pairs] = buf[*pos]; if ('\"' != buf[*pos]) continue; /* Unquoted quotes end quoted args. */ if ('\"' != buf[*pos + 1]) break; /* Quoted quotes collapse. */ pairs++; (*pos)++; } if (pairs) buf[*pos - pairs] = '\0'; if ('\0' == buf[*pos]) { if (MDOC_PPHRASE & mdoc->flags) return(ARGS_QWORD); mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); return(ARGS_QWORD); } mdoc->flags &= ~MDOC_PHRASELIT; buf[(*pos)++] = '\0'; if ('\0' == buf[*pos]) return(ARGS_QWORD); while (' ' == buf[*pos]) (*pos)++; if ('\0' == buf[*pos]) mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); return(ARGS_QWORD); } p = &buf[*pos]; *v = mandoc_getarg(mdoc->parse, &p, line, pos); return(ARGS_WORD); }