diff options
-rw-r--r-- | Makefile | 22 | ||||
-rw-r--r-- | argv.c | 256 | ||||
-rw-r--r-- | hash.c | 6 | ||||
-rw-r--r-- | macro.c | 277 | ||||
-rw-r--r-- | mdoc.c | 37 | ||||
-rw-r--r-- | mdoc.h | 10 | ||||
-rw-r--r-- | mdocml.c | 41 | ||||
-rw-r--r-- | private.h | 19 | ||||
-rw-r--r-- | xstd.c | 71 |
9 files changed, 650 insertions, 89 deletions
@@ -2,15 +2,15 @@ VERSION = 1.1.0 CFLAGS += -W -Wall -Wno-unused-parameter -g -LNS = macro.ln mdoc.ln mdocml.ln hash.ln strings.ln +LNS = macro.ln mdoc.ln mdocml.ln hash.ln strings.ln xstd.ln argv.ln LLNS = llib-llibmdoc.ln llib-lmdocml.ln LIBS = libmdoc.a -OBJS = macro.o mdoc.o mdocml.o hash.o strings.o +OBJS = macro.o mdoc.o mdocml.o hash.o strings.o xstd.o argv.o -SRCS = macro.c mdoc.c mdocml.c hash.c strings.c +SRCS = macro.c mdoc.c mdocml.c hash.c strings.c xstd.c argv.c HEADS = mdoc.h @@ -28,8 +28,8 @@ mdocml: mdocml.o libmdoc.a clean: rm -f $(CLEAN) -llib-llibmdoc.ln: macro.ln mdoc.ln hash.ln strings.ln - $(LINT) $(LINTFLAGS) -Clibmdoc mdoc.ln macro.ln hash.ln strings.ln +llib-llibmdoc.ln: macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln + $(LINT) $(LINTFLAGS) -Clibmdoc mdoc.ln macro.ln hash.ln strings.ln xstd.ln argv.ln llib-lmdocml.ln: mdocml.ln llib-llibmdoc.ln $(LINT) $(LINTFLAGS) -Cmdocml mdocml.ln llib-llibmdoc.ln @@ -54,8 +54,16 @@ mdocml.ln: mdocml.c mdoc.h mdocml.o: mdocml.c mdoc.h +xstd.ln: xstd.c private.h + +xstd.o: xstd.c private.h + +argv.ln: argv.c private.h + +argv.o: argv.c private.h + private.h: mdoc.h -libmdoc.a: macro.o mdoc.o hash.o strings.o - $(AR) rs $@ macro.o mdoc.o hash.o strings.o +libmdoc.a: macro.o mdoc.o hash.o strings.o xstd.o argv.o + $(AR) rs $@ macro.o mdoc.o hash.o strings.o xstd.o argv.o @@ -0,0 +1,256 @@ +/* $Id$ */ +/* + * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include <assert.h> +#include <ctype.h> +#include <err.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "private.h" + + +static int parse_next(struct mdoc *, int, + int *, char *, char **); + + +static int +parse_next(struct mdoc *mdoc, int tok, + int *pos, char *buf, char **v) +{ + + if (0 == buf[*pos]) + return(0); + + if ('\"' != buf[*pos]) { + *v = &buf[*pos]; + + while (buf[*pos] && ! isspace(buf[*pos])) + (*pos)++; + + if (0 == buf[*pos]) + return(1); + + buf[(*pos)++] = 0; + if (0 == buf[*pos]) + return(1); + + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + if (buf[*pos]) + return(1); + + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) + return(-1); + return(1); + } + + if ('-' == buf[*pos]) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_ARGLIKE)) + return(-1); + + *v = &buf[++(*pos)]; + + while (buf[*pos] && '\"' != buf[*pos]) + (*pos)++; + + if (0 == buf[*pos]) { + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_UNQUOTE); + return(-1); + } + + buf[(*pos)++] = 0; + if (0 == buf[*pos]) + return(1); + + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + if (buf[*pos]) + return(1); + + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) + return(-1); + return(1); +} + + +int +mdoc_argv_lookup(int tok, const char *argv) +{ + + switch (tok) { + case (MDOC_Bl): + if (xstrcmp(argv, "ragged")) + return(MDOC_Ragged); + else if (xstrcmp(argv, "unfilled")) + return(MDOC_Unfilled); + else if (xstrcmp(argv, "literal")) + return(MDOC_Literal); + else if (xstrcmp(argv, "file")) + return(MDOC_File); + else if (xstrcmp(argv, "offset")) + return(MDOC_Offset); + else if (xstrcmp(argv, "bullet")) + return(MDOC_Bullet); + else if (xstrcmp(argv, "dash")) + return(MDOC_Dash); + else if (xstrcmp(argv, "hyphen")) + return(MDOC_Hyphen); + else if (xstrcmp(argv, "item")) + return(MDOC_Item); + else if (xstrcmp(argv, "enum")) + return(MDOC_Enum); + else if (xstrcmp(argv, "tag")) + return(MDOC_Tag); + else if (xstrcmp(argv, "diag")) + return(MDOC_Diag); + else if (xstrcmp(argv, "hang")) + return(MDOC_Hang); + else if (xstrcmp(argv, "ohang")) + return(MDOC_Ohang); + else if (xstrcmp(argv, "inset")) + return(MDOC_Inset); + else if (xstrcmp(argv, "column")) + return(MDOC_Column); + else if (xstrcmp(argv, "width")) + return(MDOC_Width); + else if (xstrcmp(argv, "compact")) + return(MDOC_Compact); + + break; + default: + abort(); + /* NOTREACHED */ + } + + return(MDOC_ARG_MAX); +} + + +int +mdoc_argv_parse(struct mdoc *mdoc, int tok, int arg, + struct mdoc_arg *v, int *pos, char *buf) +{ + char *p; + int c, ppos, i; + + v->arg = arg; + ppos = *pos; + + switch (arg) { + case(MDOC_Compact): + /* FALLTHROUGH */ + case(MDOC_Ragged): + /* FALLTHROUGH */ + case(MDOC_Unfilled): + /* FALLTHROUGH */ + case(MDOC_Literal): + /* FALLTHROUGH */ + case(MDOC_File): + /* FALLTHROUGH */ + case(MDOC_Bullet): + /* FALLTHROUGH */ + case(MDOC_Dash): + /* FALLTHROUGH */ + case(MDOC_Hyphen): + /* FALLTHROUGH */ + case(MDOC_Item): + /* FALLTHROUGH */ + case(MDOC_Enum): + /* FALLTHROUGH */ + case(MDOC_Tag): + /* FALLTHROUGH */ + case(MDOC_Diag): + /* FALLTHROUGH */ + case(MDOC_Hang): + /* FALLTHROUGH */ + case(MDOC_Ohang): + /* FALLTHROUGH */ + case(MDOC_Inset): + v->sz = 0; + v->value = NULL; + break; + + case(MDOC_Width): + /* FALLTHROUGH */ + case(MDOC_Offset): + /* + * This has a single value for an argument. + */ + c = parse_next(mdoc, tok, pos, buf, &p); + if (-1 == c) + return(0); + else if (0 == c) + return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGVAL)); + + v->sz = 1; + v->value = xcalloc(1, sizeof(char *)); + v->value[0] = p; + break; + + case(MDOC_Column): + /* + * This has several value for a single argument. We + * pre-allocate a pointer array and don't let it exceed + * this size. + */ + v->sz = 0; + v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *)); + for (i = 0; i < MDOC_LINEARG_MAX; i++) { + c = parse_next(mdoc, tok, pos, buf, &p); + if (-1 == c) { + free(v->value); + return(0); + } else if (0 == c) + break; + v->value[i] = p; + } + if (0 == i) { + free(v->value); + return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGVAL)); + } else if (MDOC_LINEARG_MAX == i) + return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGMANY)); + + v->sz = i; + break; + default: + abort(); + /* NOTREACHED */ + } + + return(1); +} + + +void +mdoc_argv_free(int sz, struct mdoc_arg *arg) +{ + int i; + + for (i = 0; i < sz; i++) { + if (0 == arg[i].sz) { + assert(NULL == arg[i].value); + continue; + } + assert(arg[i].value); + free(arg[i].value); + } +} @@ -27,7 +27,7 @@ void -mdoc_hash_free(void *htab) +mdoc_tokhash_free(void *htab) { free(htab); @@ -35,7 +35,7 @@ mdoc_hash_free(void *htab) void * -mdoc_hash_alloc(void) +mdoc_tokhash_alloc(void) { int i, major, minor, ind; const void **htab; @@ -80,7 +80,7 @@ mdoc_hash_alloc(void) int -mdoc_hash_find(const void *arg, const char *tmp) +mdoc_tokhash_find(const void *arg, const char *tmp) { int major, minor, ind, slot; const void **htab; @@ -26,15 +26,128 @@ #define _CC(p) ((const char **)p) -static int xstrlcat(char *, const char *, size_t); -static int xstrlcpy(char *, const char *, size_t); -static int xstrcmp(const char *, const char *); +static int scope_rewind_exp(struct mdoc *, int, int, int); static int append_text(struct mdoc *, int, int, int, char *[]); -static int append_scoped(struct mdoc *, int, - int, int, char *[]); +static int append_scoped(struct mdoc *, int, int, int, + const char *[], int, const struct mdoc_arg *); static int args_next(struct mdoc *, int, int *, char *, char **); +static int argv_next(struct mdoc *, int, + int *, char *, struct mdoc_arg *); +static int args_next_quoted(struct mdoc *, int, + int *, char *, char **); + + +static int +args_next_quoted(struct mdoc *mdoc, int tok, + int *pos, char *buf, char **v) +{ + + if (0 == buf[*pos]) + return(0); + + assert( ! isspace(buf[*pos])); + + if ('\"' != buf[*pos]) + return(args_next(mdoc, tok, pos, buf, v)); + + *v = &buf[++(*pos)]; + + while (buf[*pos] && '\"' != buf[*pos]) + (*pos)++; + + if (0 == buf[*pos]) { + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_UNQUOTE); + return(-1); + } + + buf[(*pos)++] = 0; + if (0 == buf[*pos]) + return(1); + + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + if (0 == buf[*pos]) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) + return(-1); + + return(1); +} + + +static int +scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int dst) +{ + struct mdoc_node *n; + + /* LINTED */ + for (n = mdoc->last; n; n = n->parent) { + if (MDOC_BLOCK != n->type) + continue; + if (dst == n->data.block.tok) + break; + return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK)); + } + + if (NULL == (mdoc->last = n)) + return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX)); + + mdoc_msg(mdoc, ppos, "scope: rewound `%s' to `%s'", + mdoc_macronames[tok], mdoc_macronames[dst]); + + return(1); +} + + +static int +argv_next(struct mdoc *mdoc, int tok, + int *pos, char *buf, struct mdoc_arg *v) +{ + char *argv; + int i, val; + + if (0 == buf[*pos]) + return(0); + + assert( ! isspace(buf[*pos])); + + if ('-' != buf[*pos]) { + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_ARGS); + return(-1); + } + + i = *pos; + argv = &buf[++(*pos)]; + + while (buf[*pos] && ! isspace(buf[*pos])) + (*pos)++; + + if (buf[*pos]) + buf[(*pos)++] = 0; + + /* + * XXX This is a little bit ugly. The mdoc_argv structure + * points to a pointer array, which we allocate on-the-fly in + * this function. If there's any failure, we need to release + * this memory, which is done by the caller of this function + * with mdoc_argv_free. Ew. This should be simpler. + */ + + if (MDOC_ARG_MAX == (val = mdoc_argv_lookup(tok, argv))) { + (void)mdoc_err(mdoc, tok, i, ERR_SYNTAX_BADARG); + return(-1); + } + + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + if ( ! mdoc_argv_parse(mdoc, tok, val, v, pos, buf)) + return(-1); + + return(1); +} static int @@ -82,17 +195,18 @@ args_next(struct mdoc *mdoc, int tok, static int -append_scoped(struct mdoc *mdoc, int tok, - int pos, int sz, char *args[]) +append_scoped(struct mdoc *mdoc, int tok, int pos, + int sz, const char *args[], + int argc, const struct mdoc_arg *argv) { enum mdoc_sec sec; - if (0 == sz) - return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1)); - switch (tok) { /* ======= ADD MORE MACRO CHECKS BELOW. ======= */ case (MDOC_Sh): + if (0 == sz) + return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1)); + sec = mdoc_atosec((size_t)sz, _CC(args)); if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn) if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO)) @@ -105,17 +219,22 @@ append_scoped(struct mdoc *mdoc, int tok, mdoc->sec_lastn = sec; mdoc->sec_last = sec; break; + case (MDOC_Ss): + if (0 == sz) + return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1)); + break; + + case (MDOC_Bl): break; + /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */ default: abort(); /* NOTREACHED */ } - assert(sz >= 0); - args[sz] = NULL; - mdoc_block_alloc(mdoc, pos, tok, 0, NULL); + mdoc_block_alloc(mdoc, pos, tok, (size_t)argc, argv); mdoc_head_alloc(mdoc, pos, tok, (size_t)sz, _CC(args)); mdoc_body_alloc(mdoc, pos, tok); return(1); @@ -198,8 +317,10 @@ macro_text(MACRO_PROT_ARGS) return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE)); again: - lastarg = *pos; + + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); c = args_next(mdoc, tok, pos, buf, &args[j]); if (-1 == c) @@ -262,10 +383,12 @@ macro_prologue_dtitle(MACRO_PROT_ARGS) again: lastarg = *pos; + + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); c = args_next(mdoc, tok, pos, buf, &args[++j]); if (0 == c) { - mdoc->sec_lastn = mdoc->sec_last = SEC_BODY; /* FIXME */ if (mdoc->meta.title) return(1); if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1)) @@ -306,6 +429,44 @@ again: int +macro_prologue_os(MACRO_PROT_ARGS) +{ + int c, lastarg, j; + char *args[MDOC_LINEARG_MAX]; + + if (SEC_PROLOGUE != mdoc->sec_lastn) + return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE)); + if (0 == mdoc->meta.title[0]) + return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO)); + if (mdoc->meta.os[0]) + return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP)); + + j = -1; + +again: + lastarg = *pos; + + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); + c = args_next_quoted(mdoc, tok, pos, buf, &args[++j]); + + if (0 == c) { + mdoc->sec_lastn = mdoc->sec_last = SEC_BODY; + return(1); + } else if (-1 == c) + return(0); + + if ( ! xstrlcat(mdoc->meta.os, args[j], sizeof(mdoc->meta.os))) + return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS)); + if ( ! xstrlcat(mdoc->meta.os, " ", sizeof(mdoc->meta.os))) + return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS)); + + goto again; + /* NOTREACHED */ +} + + +int macro_prologue_ddate(MACRO_PROT_ARGS) { int c, lastarg, j; @@ -322,9 +483,12 @@ macro_prologue_ddate(MACRO_PROT_ARGS) date[0] = 0; again: - lastarg = *pos; + + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); c = args_next(mdoc, tok, pos, buf, &args[++j]); + if (0 == c) { if (mdoc->meta.date) return(1); @@ -360,6 +524,55 @@ again: int +macro_scoped_explicit(MACRO_PROT_ARGS) +{ + int c, lastarg, j; + struct mdoc_arg argv[MDOC_LINEARG_MAX]; + + if (SEC_PROLOGUE == mdoc->sec_lastn) + return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE)); + + /* + * First close out the explicit scope. The `end' tags (such as + * `.El' to `.Bl' don't cause anything to happen: we merely + * readjust our last parse point. + */ + + switch (tok) { + case (MDOC_El): + return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bl)); + default: + break; + } + + assert(MDOC_EXPLICIT & mdoc_macros[tok].flags); + + lastarg = *pos; + + for (j = 0; j < MDOC_LINEARG_MAX; j++) { + lastarg = *pos; + c = argv_next(mdoc, tok, pos, buf, &argv[j]); + if (0 == c) + break; + else if (1 == c) + continue; + + mdoc_argv_free(j, argv); + return(0); + } + + if (MDOC_LINEARG_MAX == j) { + mdoc_argv_free(j, argv); + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); + } + + c = append_scoped(mdoc, tok, ppos, 0, NULL, j, argv); + mdoc_argv_free(j, argv); + return(c); +} + + +int macro_scoped_implicit(MACRO_PROT_ARGS) { int t, c, lastarg, j; @@ -371,6 +584,8 @@ macro_scoped_implicit(MACRO_PROT_ARGS) if (SEC_PROLOGUE == mdoc->sec_lastn) return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE)); + /* FIXME: put into scope_rewind_imp(). */ + /* LINTED */ for (n = mdoc->last; n; n = n->parent) { if (MDOC_BLOCK != n->type) @@ -393,14 +608,17 @@ macro_scoped_implicit(MACRO_PROT_ARGS) j = 0; again: - lastarg = *pos; + + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); c = args_next(mdoc, tok, pos, buf, &args[j]); if (-1 == c) return(0); if (0 == c) - return(append_scoped(mdoc, tok, ppos, j, args)); + return(append_scoped(mdoc, tok, ppos, + j, _CC(args), 0, NULL)); /* Command found. */ @@ -416,26 +634,3 @@ again: /* NOTREACHED */ } - -static int -xstrcmp(const char *p1, const char *p2) -{ - - return(0 == strcmp(p1, p2)); -} - - -static int -xstrlcat(char *dst, const char *src, size_t sz) -{ - - return(strlcat(dst, src, sz) < sz); -} - - -static int -xstrlcpy(char *dst, const char *src, size_t sz) -{ - - return(strlcpy(dst, src, sz) < sz); -} @@ -86,7 +86,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { NULL, 0 }, /* \" */ { macro_prologue_ddate, 0 }, /* Dd */ { macro_prologue_dtitle, 0 }, /* Dt */ - { NULL, 0 }, /* Os */ + { macro_prologue_os, 0 }, /* Os */ { macro_scoped_implicit, 0 }, /* Sh */ { macro_scoped_implicit, 0 }, /* Ss */ { NULL, 0 }, /* Pp */ @@ -94,8 +94,8 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { NULL, 0 }, /* Dl */ { NULL, 0 }, /* Bd */ { NULL, 0 }, /* Ed */ - { NULL, 0 }, /* Bl */ - { NULL, 0 }, /* El */ + { macro_scoped_explicit, MDOC_EXPLICIT }, /* Bl */ + { macro_scoped_explicit, 0 }, /* El */ { NULL, 0 }, /* It */ { macro_text, MDOC_CALLABLE }, /* Ad */ { NULL, 0 }, /* An */ @@ -196,9 +196,6 @@ const char * const *mdoc_argnames = __mdoc_argnames; const struct mdoc_macro * const mdoc_macros = __mdoc_macros; -static void *xcalloc(size_t, size_t); -static char *xstrdup(const char *); - static struct mdoc_arg *argdup(size_t, const struct mdoc_arg *); static void argfree(size_t, struct mdoc_arg *); static void argcpy(struct mdoc_arg *, @@ -228,7 +225,7 @@ mdoc_free(struct mdoc *mdoc) if (mdoc->first) mdoc_node_freelist(mdoc->first); if (mdoc->htab) - mdoc_hash_free(mdoc->htab); + mdoc_tokhash_free(mdoc->htab); free(mdoc); } @@ -244,33 +241,11 @@ mdoc_alloc(void *data, const struct mdoc_cb *cb) p->data = data; (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb)); - p->htab = mdoc_hash_alloc(); - return(p); -} - - -static void * -xcalloc(size_t num, size_t sz) -{ - void *p; - - if (NULL == (p = calloc(num, sz))) - err(EXIT_FAILURE, "calloc"); + p->htab = mdoc_tokhash_alloc(); return(p); } -static char * -xstrdup(const char *p) -{ - char *pp; - - if (NULL == (pp = strdup(p))) - err(EXIT_FAILURE, "strdup"); - return(pp); -} - - int mdoc_parseln(struct mdoc *mdoc, char *buf) { @@ -668,7 +643,7 @@ int mdoc_find(const struct mdoc *mdoc, const char *key) { - return(mdoc_hash_find(mdoc->htab, key)); + return(mdoc_tokhash_find(mdoc->htab, key)); } @@ -193,11 +193,16 @@ enum mdoc_err { ERR_SYNTAX_QUOTE, + ERR_SYNTAX_UNQUOTE, ERR_SYNTAX_WS, ERR_SYNTAX_ARGS, + ERR_SYNTAX_BADARG, + ERR_SYNTAX_ARGVAL, + ERR_SYNTAX_ARGMANY, ERR_MACRO_NOTSUP, ERR_MACRO_NOTCALL, ERR_SCOPE_BREAK, + ERR_SCOPE_NOCTX, ERR_SEC_PROLOGUE, ERR_SEC_NPROLOGUE, ERR_SEC_PROLOGUE_OO, @@ -211,7 +216,8 @@ enum mdoc_warn { WARN_SYNTAX_WS_EOLN, WARN_SYNTAX_MACLIKE, WARN_SEC_OO, - WARN_ARGS_GE1 + WARN_ARGS_GE1, + WARN_SYNTAX_ARGLIKE }; struct mdoc_arg { @@ -320,6 +326,8 @@ struct mdoc_meta { time_t date; #define META_TITLE_SZ (64) char title[META_TITLE_SZ]; +#define META_OS_SZ (64) + char os[META_OS_SZ]; }; struct mdoc_text { @@ -182,7 +182,12 @@ static void print_node(const struct mdoc_node *n, int indent) { const char *p, *t; - int i; + int i, j; + size_t argc; + struct mdoc_arg *argv; + + argv = NULL; + argc = 0; switch (n->type) { case (MDOC_TEXT): @@ -202,10 +207,14 @@ print_node(const struct mdoc_node *n, int indent) assert(NULL == n->child); p = mdoc_macronames[n->data.elem.tok]; t = "element"; + argv = n->data.elem.argv; + argc = n->data.elem.argc; break; case (MDOC_BLOCK): p = mdoc_macronames[n->data.block.tok]; t = "block"; + argv = n->data.block.argv; + argc = n->data.block.argc; break; default: abort(); @@ -214,7 +223,15 @@ print_node(const struct mdoc_node *n, int indent) for (i = 0; i < indent; i++) (void)printf(" "); - (void)printf("%s (%s)\n", p, t); + (void)printf("%s (%s)", p, t); + + for (i = 0; i < (int)argc; i++) { + (void)printf(" -%s", mdoc_argnames[argv[i].arg]); + for (j = 0; j < (int)argv[i].sz; j++) + (void)printf(" \"%s\"", argv[i].value[j]); + } + + (void)printf("\n"); if (n->child) print_node(n->child, indent + 1); @@ -301,6 +318,9 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type) switch (type) { case (ERR_SYNTAX_QUOTE): + lit = "syntax: disallowed argument quotation"; + break; + case (ERR_SYNTAX_UNQUOTE): lit = "syntax: unterminated quotation"; break; case (ERR_SYNTAX_WS): @@ -309,9 +329,15 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type) case (ERR_SYNTAX_ARGS): fmt = "syntax: macro `%s' arguments malformed"; break; + case (ERR_SYNTAX_BADARG): + fmt = "syntax: unknown argument for macro `%s'"; + break; case (ERR_SCOPE_BREAK): /* Which scope is broken? */ - fmt = "macro `%s' breaks prior explicit scope"; + fmt = "scope: macro `%s' breaks prior explicit scope"; + break; + case (ERR_SCOPE_NOCTX): + fmt = "scope: closure macro `%s' has no context"; break; case (ERR_MACRO_NOTSUP): fmt = "macro `%s' not supported"; @@ -340,6 +366,12 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type) case (ERR_SEC_NAME): lit = "`NAME' section must be first"; break; + case (ERR_SYNTAX_ARGVAL): + lit = "syntax: expected value for macro argument"; + break; + case (ERR_SYNTAX_ARGMANY): + lit = "syntax: too many values for macro argument"; + break; default: abort(); /* NOTREACHED */ @@ -422,6 +454,9 @@ msg_warn(void *arg, int tok, int col, enum mdoc_warn type) case (WARN_SYNTAX_MACLIKE): lit = "syntax: macro-like argument"; break; + case (WARN_SYNTAX_ARGLIKE): + lit = "syntax: argument-like value"; + break; case (WARN_SEC_OO): lit = "section is out of conventional order"; break; @@ -63,9 +63,9 @@ void mdoc_body_alloc(struct mdoc *, int, int); void mdoc_node_free(struct mdoc_node *); void mdoc_sibling(struct mdoc *, int, struct mdoc_node **, struct mdoc_node **, struct mdoc_node *); -void *mdoc_hash_alloc(void); -int mdoc_hash_find(const void *, const char *); -void mdoc_hash_free(void *); +void *mdoc_tokhash_alloc(void); +int mdoc_tokhash_find(const void *, const char *); +void mdoc_tokhash_free(void *); int mdoc_isdelim(const char *); enum mdoc_sec mdoc_atosec(size_t, const char **); enum mdoc_msec mdoc_atomsec(const char *); @@ -73,10 +73,23 @@ enum mdoc_vol mdoc_atovol(const char *); enum mdoc_arch mdoc_atoarch(const char *); time_t mdoc_atotime(const char *); +int mdoc_argv_lookup(int, const char *); +int mdoc_argv_parse(struct mdoc *, int, + int, struct mdoc_arg *, int *, char *); +void mdoc_argv_free(int, struct mdoc_arg *); + +int xstrlcat(char *, const char *, size_t); +int xstrlcpy(char *, const char *, size_t); +int xstrcmp(const char *, const char *); +void *xcalloc(size_t, size_t); +char *xstrdup(const char *); + int macro_text(MACRO_PROT_ARGS); int macro_scoped_implicit(MACRO_PROT_ARGS); +int macro_scoped_explicit(MACRO_PROT_ARGS); int macro_prologue_ddate(MACRO_PROT_ARGS); int macro_prologue_dtitle(MACRO_PROT_ARGS); +int macro_prologue_os(MACRO_PROT_ARGS); __END_DECLS @@ -0,0 +1,71 @@ +/* $Id$ */ +/* + * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include <err.h> +#include <stdlib.h> +#include <string.h> + +#include "private.h" + + +int +xstrcmp(const char *p1, const char *p2) +{ + + return(0 == strcmp(p1, p2)); +} + + +int +xstrlcat(char *dst, const char *src, size_t sz) +{ + + return(strlcat(dst, src, sz) < sz); +} + + +int +xstrlcpy(char *dst, const char *src, size_t sz) +{ + + return(strlcpy(dst, src, sz) < sz); +} + + + +void * +xcalloc(size_t num, size_t sz) +{ + void *p; + + if (NULL == (p = calloc(num, sz))) + err(EXIT_FAILURE, "calloc"); + return(p); +} + + +char * +xstrdup(const char *p) +{ + char *pp; + + if (NULL == (pp = strdup(p))) + err(EXIT_FAILURE, "strdup"); + return(pp); +} + |