From 857b9aac8422fa0bebd1d83b87c8fbf4d7a1f044 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Fri, 28 Nov 2014 23:21:32 +0000 Subject: Fold the loop around mdoc_argv() into the function itself, it was the same in all four cases. As a bonus, get rid of one enum type that was used for internal communication. No functional change, minus 40 lines of code. --- libmdoc.h | 9 +--- mdoc_argv.c | 147 +++++++++++++++++++++++++++++++---------------------------- mdoc_macro.c | 50 ++------------------ 3 files changed, 82 insertions(+), 124 deletions(-) diff --git a/libmdoc.h b/libmdoc.h index d4aded37..c65ee055 100644 --- a/libmdoc.h +++ b/libmdoc.h @@ -77,13 +77,6 @@ enum margserr { ARGS_PEND /* last phrase (-column) */ }; -enum margverr { - ARGV_ERROR, - ARGV_EOLN, /* end of line */ - ARGV_ARG, /* valid argument */ - ARGV_WORD /* normal word (or bad argument---same thing) */ -}; - /* * A punctuation delimiter is opening, closing, or "middle mark" * punctuation. These govern spacing. @@ -127,7 +120,7 @@ const char *mdoc_a2st(const char *); const char *mdoc_a2arch(const char *); void mdoc_valid_pre(struct mdoc *, struct mdoc_node *); void mdoc_valid_post(struct mdoc *); -enum margverr mdoc_argv(struct mdoc *, int, enum mdoct, +void mdoc_argv(struct mdoc *, int, enum mdoct, struct mdoc_arg **, int *, char *); void mdoc_argv_free(struct mdoc_arg *); enum margserr mdoc_args(struct mdoc *, int, diff --git a/mdoc_argv.c b/mdoc_argv.c index 20dac8af..aebbac3a 100644 --- a/mdoc_argv.c +++ b/mdoc_argv.c @@ -1,7 +1,7 @@ /* $OpenBSD$ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2012 Ingo Schwarze + * Copyright (c) 2012, 2014 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -270,98 +270,105 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { /* - * Parse an argument from line text. This comes in the form of -key - * [value0...], which may either have a single mandatory value, at least - * one mandatory value, an optional single value, or no value. + * Parse flags and their arguments from the input line. + * These come in the form -flag [argument ...]. + * Some flags take no argument, some one, some multiple. */ -enum margverr +void mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok, - struct mdoc_arg **v, int *pos, char *buf) + struct mdoc_arg **reta, int *pos, char *buf) { - char *p, sv; - struct mdoc_argv tmp; - struct mdoc_arg *arg; - const enum mdocargt *ap; + struct mdoc_argv tmpv; + struct mdoc_argv **retv; + const enum mdocargt *argtable; + char *argname; + int ipos, retc; + char savechar; - if ('\0' == buf[*pos]) - return(ARGV_EOLN); - else if (NULL == (ap = mdocargs[tok].argvs)) - return(ARGV_WORD); - else if ('-' != buf[*pos]) - return(ARGV_WORD); + *reta = NULL; - /* Seek to the first unescaped space. */ + /* Which flags does this macro support? */ - p = &buf[++(*pos)]; + argtable = mdocargs[tok].argvs; + if (argtable == NULL) + return; - assert(*pos > 0); + /* Loop over the flags on the input line. */ - for ( ; buf[*pos] ; (*pos)++) - if (' ' == buf[*pos] && '\\' != buf[*pos - 1]) - break; + ipos = *pos; + while (buf[ipos] == '-') { - /* - * We want to nil-terminate the word to look it up (it's easier - * that way). But we may not have a flag, in which case we need - * to restore the line as-is. So keep around the stray byte, - * which we'll reset upon exiting (if necessary). - */ + /* Seek to the first unescaped space. */ - if ('\0' != (sv = buf[*pos])) - buf[(*pos)++] = '\0'; + for (argname = buf + ++ipos; buf[ipos] != '\0'; ipos++) + if (buf[ipos] == ' ' && buf[ipos - 1] != '\\') + break; - /* - * Now look up the word as a flag. Use temporary storage that - * we'll copy into the node's flags, if necessary. - */ + /* + * We want to nil-terminate the word to look it up. + * But we may not have a flag, in which case we need + * to restore the line as-is. So keep around the + * stray byte, which we'll reset upon exiting. + */ + + if ((savechar = buf[ipos]) != '\0') + buf[ipos++] = '\0'; + + /* + * Now look up the word as a flag. Use temporary + * storage that we'll copy into the node's flags. + */ - memset(&tmp, 0, sizeof(struct mdoc_argv)); + while ((tmpv.arg = *argtable++) != MDOC_ARG_MAX) + if ( ! strcmp(argname, mdoc_argnames[tmpv.arg])) + break; - tmp.line = line; - tmp.pos = *pos; - tmp.arg = MDOC_ARG_MAX; + /* If it isn't a flag, restore the saved byte. */ - while (MDOC_ARG_MAX != (tmp.arg = *ap++)) - if (0 == strcmp(p, mdoc_argnames[tmp.arg])) + if (tmpv.arg == MDOC_ARG_MAX) { + if (savechar != '\0') + buf[ipos - 1] = savechar; break; + } - if (MDOC_ARG_MAX == tmp.arg) { - /* - * The flag was not found. - * Restore saved zeroed byte and return as a word. - */ - if (sv) - buf[*pos - 1] = sv; - return(ARGV_WORD); - } + /* Read to the next word (the first argument). */ - /* Read to the next word (the argument). */ + while (buf[ipos] == ' ') + ipos++; - while (buf[*pos] && ' ' == buf[*pos]) - (*pos)++; + /* Parse the arguments of the flag. */ - switch (argvflags[tmp.arg]) { - case ARGV_SINGLE: - argv_single(mdoc, line, &tmp, pos, buf); - break; - case ARGV_MULTI: - argv_multi(mdoc, line, &tmp, pos, buf); - break; - case ARGV_NONE: - break; - } + tmpv.line = line; + tmpv.pos = ipos; + tmpv.sz = 0; + tmpv.value = NULL; - if (NULL == (arg = *v)) - arg = *v = mandoc_calloc(1, sizeof(struct mdoc_arg)); + switch (argvflags[tmpv.arg]) { + case ARGV_SINGLE: + argv_single(mdoc, line, &tmpv, &ipos, buf); + break; + case ARGV_MULTI: + argv_multi(mdoc, line, &tmpv, &ipos, buf); + break; + case ARGV_NONE: + break; + } - arg->argc++; - arg->argv = mandoc_reallocarray(arg->argv, - arg->argc, sizeof(struct mdoc_argv)); + /* Append to the return values. */ - memcpy(&arg->argv[(int)arg->argc - 1], &tmp, - sizeof(struct mdoc_argv)); + if (*reta == NULL) + *reta = mandoc_calloc(1, sizeof(**reta)); - return(ARGV_ARG); + retc = ++(*reta)->argc; + retv = &(*reta)->argv; + *retv = mandoc_reallocarray(*retv, retc, sizeof(**retv)); + memcpy(*retv + retc - 1, &tmpv, sizeof(**retv)); + + /* Prepare for parsing the next flag. */ + + *pos = ipos; + argtable = mdocargs[tok].argvs; + } } void diff --git a/mdoc_macro.c b/mdoc_macro.c index 0654aa36..789aa4dc 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -843,7 +843,6 @@ static void in_line(MACRO_PROT_ARGS) { int la, scope, cnt, firstarg, mayopen, nc, nl; - enum margverr av; enum mdoct ntok; enum margserr ac; enum mdelim d; @@ -876,15 +875,7 @@ in_line(MACRO_PROT_ARGS) break; } - for (arg = NULL;; ) { - la = *pos; - av = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (av == ARGV_ARG) - continue; - if (av == ARGV_WORD) - *pos = la; - break; - } + mdoc_argv(mdoc, line, tok, &arg, pos, buf); d = DELIM_NONE; firstarg = 1; @@ -1041,7 +1032,6 @@ blk_full(MACRO_PROT_ARGS) struct mdoc_node *n; enum mdoct ntok; enum margserr ac, lac; - enum margverr av; char *p; nl = MDOC_NEWLINE & mdoc->flags; @@ -1078,16 +1068,7 @@ blk_full(MACRO_PROT_ARGS) * regular child nodes. */ - for (arg = NULL;; ) { - la = *pos; - av = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (av == ARGV_ARG) - continue; - if (av == ARGV_WORD) - *pos = la; - break; - } - + mdoc_argv(mdoc, line, tok, &arg, pos, buf); mdoc_block_alloc(mdoc, line, ppos, tok, arg); head = body = NULL; @@ -1402,7 +1383,6 @@ in_line_argn(MACRO_PROT_ARGS) { int la, flushed, j, maxargs, nl; enum margserr ac; - enum margverr av; struct mdoc_arg *arg; char *p; enum mdoct ntok; @@ -1437,15 +1417,7 @@ in_line_argn(MACRO_PROT_ARGS) break; } - for (arg = NULL; ; ) { - la = *pos; - av = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (av == ARGV_ARG) - continue; - if (av == ARGV_WORD) - *pos = la; - break; - } + mdoc_argv(mdoc, line, tok, &arg, pos, buf); for (flushed = j = 0; ; ) { la = *pos; @@ -1502,7 +1474,6 @@ in_line_eoln(MACRO_PROT_ARGS) { int la; enum margserr ac; - enum margverr av; struct mdoc_arg *arg; char *p; enum mdoct ntok; @@ -1512,20 +1483,7 @@ in_line_eoln(MACRO_PROT_ARGS) if (tok == MDOC_Pp) rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos); - /* Parse macro arguments. */ - - for (arg = NULL; ; ) { - la = *pos; - av = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (av == ARGV_ARG) - continue; - if (av == ARGV_WORD) - *pos = la; - break; - } - - /* Open element scope. */ - + mdoc_argv(mdoc, line, tok, &arg, pos, buf); mdoc_elem_alloc(mdoc, line, ppos, tok, arg); /* Parse argument terms. */ -- cgit