diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-03-16 22:19:19 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-03-16 22:19:19 +0000 |
commit | 0f78a072b396e52a775bdbe9f6687c67bf1439bb (patch) | |
tree | b27a8c382f8dea4d64b1e228090f7c5197a03726 | |
parent | 0f40156e5aa1d8acdf0a8c560bdeabb48fdd4271 (diff) | |
download | mandoc-0f78a072b396e52a775bdbe9f6687c67bf1439bb.tar.gz |
Fixed mdoc_phrase escape handling.
Added MDOC_IGNDELIM (Pf, soon Li, etc.).
macro_constant_delimited ignargs -> argv.c parsing.
Renamed macro functions to correspond to ontologies.
`Fo' and `St' made callable (compat documented).
strings.sh deprecated (directly using CPP).
Abstracted ASCII translation into ascii.{c,in}.
ASCII table uses a self-reordering chained hashtable.
Removed old regressions.
-rw-r--r-- | Makefile | 141 | ||||
-rw-r--r-- | action.c | 7 | ||||
-rw-r--r-- | arch.c | 34 | ||||
-rw-r--r-- | arch.in | 86 | ||||
-rw-r--r-- | argv.c | 62 | ||||
-rw-r--r-- | ascii.c | 169 | ||||
-rw-r--r-- | ascii.in | 134 | ||||
-rw-r--r-- | att.c | 34 | ||||
-rw-r--r-- | att.in | 58 | ||||
-rw-r--r-- | lib.c | 34 | ||||
-rw-r--r-- | lib.in | 97 | ||||
-rw-r--r-- | macro.c | 842 | ||||
-rw-r--r-- | mdoc.3 | 5 | ||||
-rw-r--r-- | mdoc.7 | 281 | ||||
-rw-r--r-- | mdoc.c | 11 | ||||
-rw-r--r-- | mdoc.h | 6 | ||||
-rw-r--r-- | mdocterm.1 | 135 | ||||
-rw-r--r-- | mdocterm.c | 170 | ||||
-rw-r--r-- | mmain.c | 9 | ||||
-rw-r--r-- | mmain.h | 14 | ||||
-rw-r--r-- | msec.c | 34 | ||||
-rw-r--r-- | msec.in | 64 | ||||
-rw-r--r-- | private.h | 2 | ||||
-rw-r--r-- | st.c | 34 | ||||
-rw-r--r-- | st.in | 91 | ||||
-rw-r--r-- | strings.sh | 89 | ||||
-rw-r--r-- | term.c | 2 | ||||
-rw-r--r-- | term.h | 88 | ||||
-rw-r--r-- | validate.c | 59 | ||||
-rw-r--r-- | vol.c | 34 | ||||
-rw-r--r-- | vol.in | 55 | ||||
-rw-r--r-- | xstd.c | 84 |
32 files changed, 1484 insertions, 1481 deletions
@@ -25,7 +25,7 @@ LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \ TREELNS = mdoctree.ln mmain.ln -TERMLNS = mdoctree.ln mmain.ln term.ln +TERMLNS = mdoctree.ln mmain.ln term.ln ascii.ln LINTLNS = mdoclint.ln mmain.ln @@ -39,7 +39,7 @@ LIBOBJS = macro.o mdoc.o hash.o strings.o xstd.o argv.o \ validate.o action.o lib.o att.o arch.o vol.o msec.o \ st.o -TERMOBJS= mdocterm.o mmain.o term.o +TERMOBJS= mdocterm.o mmain.o term.o ascii.o TREEOBJS= mdoctree.o mmain.o @@ -50,11 +50,7 @@ OBJS = $(LIBOBJS) $(TERMOBJS) $(TREEOBJS) $(LINTOBJS) SRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \ action.c term.c mdoctree.c mdocterm.c mmain.c mdoclint.c -SCRIPTS = strings.sh - -DATAS = arch.in att.in lib.in msec.in st.in vol.in - -GEN = lib.c att.c arch.c vol.c msec.c st.c +DATAS = arch.in att.in lib.in msec.in st.in vol.in ascii.in HEADS = mdoc.h private.h term.h mmain.h @@ -72,84 +68,10 @@ MANS = mdoctree.1 mdocterm.1 mdoclint.1 mdoc.3 mdoc.7 BINS = mdocterm mdoctree mdoclint CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS) \ - $(TARGZS) $(GEN) + $(TARGZS) INSTALL = $(SRCS) $(HEADS) Makefile DESCR $(MANS) $(SGMLS) \ - $(STATICS) $(SCRIPTS) Makefile.netbsd Makefile.openbsd \ - $(DATAS) - -FAIL = regress/test.empty \ - regress/test.prologue.00 \ - regress/test.prologue.01 \ - regress/test.prologue.02 \ - regress/test.prologue.03 \ - regress/test.prologue.04 \ - regress/test.prologue.06 \ - regress/test.prologue.19 \ - regress/test.prologue.23 \ - regress/test.prologue.24 \ - regress/test.prologue.27 \ - regress/test.prologue.28 \ - regress/test.prologue.30 \ - regress/test.prologue.31 \ - regress/test.prologue.32 \ - regress/test.sh.03 \ - regress/test.escape.01 \ - regress/test.escape.02 \ - regress/test.escape.03 \ - regress/test.escape.04 \ - regress/test.escape.06 \ - regress/test.escape.07 \ - regress/test.escape.08 \ - regress/test.escape.09 \ - regress/test.escape.11 \ - regress/test.escape.12 \ - regress/test.escape.14 \ - regress/test.argv.01 \ - regress/test.argv.02 - -SUCCEED = regress/test.prologue.05 \ - regress/test.prologue.07 \ - regress/test.prologue.08 \ - regress/test.prologue.09 \ - regress/test.prologue.10 \ - regress/test.prologue.11 \ - regress/test.prologue.12 \ - regress/test.prologue.13 \ - regress/test.prologue.14 \ - regress/test.prologue.15 \ - regress/test.prologue.16 \ - regress/test.prologue.17 \ - regress/test.prologue.18 \ - regress/test.prologue.20 \ - regress/test.prologue.21 \ - regress/test.prologue.22 \ - regress/test.prologue.25 \ - regress/test.prologue.26 \ - regress/test.prologue.29 \ - regress/test.prologue.33 \ - regress/test.sh.00 \ - regress/test.name.00 \ - regress/test.name.01 \ - regress/test.name.02 \ - regress/test.name.03 \ - regress/test.list.00 \ - regress/test.list.01 \ - regress/test.list.02 \ - regress/test.list.03 \ - regress/test.list.04 \ - regress/test.list.05 \ - regress/test.list.06 \ - regress/test.list.07 \ - regress/test.sh.01 \ - regress/test.sh.02 \ - regress/test.escape.00 \ - regress/test.escape.05 \ - regress/test.escape.10 \ - regress/test.escape.13 \ - regress/test.argv.00 - -REGRESS = $(FAIL) $(SUCCEED) + $(STATICS) Makefile.netbsd Makefile.openbsd $(DATAS) all: $(BINS) @@ -176,14 +98,6 @@ installwww: www install -m 0444 mdocml-nport-$(VERSION).tar.gz $(PREFIX)/ports-netbsd/ install -m 0444 mdocml-nport-$(VERSION).tar.gz $(PREFIX)/ports-netbsd/mdocml.tar.gz -#regress: mdoclint $(FAIL) $(SUCCEED) -# @for f in $(FAIL); do \ -# echo "./mdoclint $$f" ; \ -# ./mdoclint $$f 2>/dev/null || continue ; exit 1 ; done -# @for f in $(SUCCEED); do \ -# echo "./mdoclint $$f" ; \ - ./mdoclint $$f 2>/dev/null || exit 1 ; done - install: mkdir -p $(BINDIR) mkdir -p $(INCLUDEDIR) @@ -211,41 +125,26 @@ uninstall: rm -f $(LIBDIR)/libmdoc.a rm -f $(INCLUDEDIR)/mdoc.h -lib.ln: lib.c private.h -lib.o: lib.c private.h - -att.ln: att.c private.h -att.o: att.c private.h - -arch.ln: arch.c private.h -arch.o: arch.c private.h - -vol.ln: vol.c private.h -vol.o: vol.c private.h - -msec.ln: msec.c private.h -msec.o: msec.c private.h - -st.ln: st.c private.h -st.o: st.c private.h +lib.ln: lib.c lib.in private.h +lib.o: lib.c lib.in private.h -lib.c: lib.in strings.sh - sh strings.sh -o $@ lib lib.in +att.ln: att.c att.in private.h +att.o: att.c att.in private.h -st.c: st.in strings.sh - sh strings.sh -o $@ st st.in +arch.ln: arch.c arch.in private.h +arch.o: arch.c arch.in private.h -msec.c: msec.in strings.sh - sh strings.sh -o $@ msec msec.in +vol.ln: vol.c vol.in private.h +vol.o: vol.c vol.in private.h -att.c: att.in strings.sh - sh strings.sh -o $@ att att.in +ascii.ln: ascii.c ascii.in term.h +ascii.o: ascii.c ascii.in term.h -arch.c: arch.in strings.sh - sh strings.sh -o $@ arch arch.in +msec.ln: msec.c msec.in private.h +msec.o: msec.c msec.in private.h -vol.c: vol.in strings.sh - sh strings.sh -o $@ vol vol.in +st.ln: st.c st.in private.h +st.o: st.c st.in private.h macro.ln: macro.c private.h macro.o: macro.c private.h @@ -336,9 +235,7 @@ mdocml-oport-$(VERSION).tar.gz: mdocml-$(VERSION).tar.gz Makefile.openbsd DESCR mdocml-$(VERSION).tar.gz: $(INSTALL) mkdir -p .dist/mdocml/mdocml-$(VERSION)/ - mkdir -p .dist/mdocml/mdocml-$(VERSION)/regress/ install -m 0644 $(INSTALL) .dist/mdocml/mdocml-$(VERSION)/ - install -m 0644 $(REGRESS) .dist/mdocml/mdocml-$(VERSION)/regress/ ( cd .dist/mdocml/ && tar zcf ../../$@ mdocml-$(VERSION)/ ) rm -rf .dist/ @@ -62,6 +62,9 @@ static int post_sh(struct mdoc *); static int post_std(struct mdoc *); static int post_prologue(struct mdoc *); +#define merr(m, t) nerr((m), (m)->last, (t)) +#define mwarn(m, t) nwarn((m), (m)->last, (t)) + const struct actions mdoc_actions[MDOC_MAX] = { { NULL }, /* \" */ { post_dd }, /* Dd */ @@ -178,10 +181,11 @@ const struct actions mdoc_actions[MDOC_MAX] = { { NULL }, /* Bro */ { NULL }, /* Brc */ { NULL }, /* %C */ + { NULL }, /* Es */ + { NULL }, /* En */ }; -#define merr(m, t) nerr((m), (m)->last, (t)) static int nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type) { @@ -200,7 +204,6 @@ nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type) } -#define mwarn(m, t) nwarn((m), (m)->last, (t)) static int nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type) { @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2arch(const char *p) +{ + +#include "arch.in" + + return(NULL); +} @@ -1,34 +1,54 @@ -# $Id$ -# -# This file defines the `.Dt' macro 'arch' argument. Lines are composed -# of tab-delimited fields -- multiple tabs may delimit fields. Comment -# lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from OpenBSD-4.4's mdoc.samples(7). +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ -alpha Alpha -amd64 AMD64 -amiga Amiga -arc ARC -arm ARM -armish ARMISH -aviion AViiON -hp300 HP300 -hppa HPPA -hppa64 HPPA64 -i386 i386 -landisk LANDISK -luna88k Luna88k -mac68k Mac68k -macppc MacPPC -mvme68k MVME68k -mvme88k MVME88k -mvmeppc MVMEPPC -pmax PMAX -sgi SGI -socppc SOCPPC -sparc SPARC -sparc64 SPARC64 -sun3 Sun3 -vax VAX -zaurus Zaurus +/* + * This file defines the architecture token of the .Dt prologue macro. + * All architectures that your system supports (or the manuals of your + * system) should be included here. The right-hand-side is the + * formatted output. + * + * Be sure to escape strings. + */ + +LINE("alpha", "Alpha") +LINE("amd64", "AMD64") +LINE("amiga", "Amiga") +LINE("arc", "ARC") +LINE("arm", "ARM") +LINE("armish", "ARMISH") +LINE("aviion", "AViiON") +LINE("hp300", "HP300") +LINE("hppa", "HPPA") +LINE("hppa64", "HPPA64") +LINE("i386", "i386") +LINE("landisk", "LANDISK") +LINE("luna88k", "Luna88k") +LINE("mac68k", "Mac68k") +LINE("macppc", "MacPPC") +LINE("mvme68k", "MVME68k") +LINE("mvme88k", "MVME88k") +LINE("mvmeppc", "MVMEPPC") +LINE("pmax", "PMAX") +LINE("sgi", "SGI") +LINE("socppc", "SOCPPC") +LINE("sparc", "SPARC") +LINE("sparc64", "SPARC64") +LINE("sun3", "Sun3") +LINE("vax", "VAX") +LINE("zaurus", "Zaurus") @@ -45,6 +45,8 @@ #define ARGV_MULTI (1 << 2) #define ARGV_OPT_SINGLE (1 << 3) +#define MULTI_STEP 5 + enum mwarn { WQUOTPARM, WARGVPARM, @@ -218,6 +220,8 @@ static int mdoc_argflags[MDOC_MAX] = { 0, /* Bro */ ARGS_DELIM, /* Brc */ ARGS_QUOTED, /* %C */ + 0, /* Es */ + 0, /* En */ }; @@ -238,11 +242,13 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok, if (0 == buf[*pos]) return(ARGV_EOLN); - assert( ! isspace((u_char)buf[*pos])); + assert(' ' != buf[*pos]); - if ('-' != buf[*pos]) + if ('-' != buf[*pos] || ARGS_ARGVLIKE & mdoc_argflags[tok]) return(ARGV_WORD); + /* Parse through to the first unescaped space. */ + i = *pos; p = &buf[++(*pos)]; @@ -250,17 +256,13 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok, /* LINTED */ while (buf[*pos]) { - if (isspace((u_char)buf[*pos])) + if (' ' == buf[*pos]) if ('\\' != buf[*pos - 1]) break; (*pos)++; } - /* - * XXX: save the nullified byte as we'll restore it if this - * doesn't end up being a command after all. This is a little - * bit hacky. I don't like it, but it works for now. - */ + /* XXX - save zeroed byte, if not an argument. */ sv = 0; if (buf[*pos]) { @@ -272,14 +274,10 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok, tmp.line = line; tmp.pos = *pos; - /* - * We now parse out the per-macro arguments. XXX - this can be - * made much cleaner using per-argument tables. See argv_a2arg - * for details. - */ + /* See if our token accepts the argument. */ if (MDOC_ARG_MAX == (tmp.arg = argv_a2arg(tok, p))) { - /* XXX - restore saved byte. */ + /* XXX - restore saved zeroed byte. */ if (sv) buf[*pos - 1] = sv; if ( ! pwarn(mdoc, line, i, WARGVPARM)) @@ -287,11 +285,9 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok, return(ARGV_WORD); } - while (buf[*pos] && isspace((u_char)buf[*pos])) + while (buf[*pos] && ' ' == buf[*pos]) (*pos)++; - /* FIXME: whitespace if no value. */ - if ( ! argv(mdoc, line, &tmp, pos, buf)) return(ARGV_ERROR); @@ -448,8 +444,6 @@ mdoc_args(struct mdoc *mdoc, int line, break; } - /* Continue parsing the arguments themselves... */ - return(args(mdoc, line, pos, buf, fl, v)); } @@ -486,10 +480,10 @@ args(struct mdoc *mdoc, int line, break; i++; /* There must be at least one space... */ - if (0 == buf[i] || ! isspace((u_char)buf[i])) + if (0 == buf[i] || ' ' != buf[i]) break; i++; - while (buf[i] && isspace((u_char)buf[i])) + while (buf[i] && ' ' == buf[i]) i++; } if (0 == buf[i]) { @@ -505,24 +499,16 @@ args(struct mdoc *mdoc, int line, /* * Thar be dragons here! If we're tab-separated, search - * ahead for either a tab or the `Ta' macro. If a tab - * is detected, it mustn't be escaped; if a `Ta' is - * detected, it must be space-buffered before and after. - * If either of these hold true, then prune out the + * ahead for either a tab or the `Ta' macro. + * If a `Ta' is detected, it must be space-buffered before and + * after. If either of these hold true, then prune out the * extra spaces and call it an argument. */ if (ARGS_TABSEP & fl) { /* Scan ahead to unescaped tab. */ - for (p = *v; ; p++) { - if (NULL == (p = strchr(p, '\t'))) - break; - if (p == *v) - break; - if ('\\' != *(p - 1)) - break; - } + p = strchr(*v, '\t'); /* Scan ahead to unescaped `Ta'. */ @@ -597,7 +583,7 @@ args(struct mdoc *mdoc, int line, if ( ! (ARGS_TABSEP & fl)) while (buf[*pos]) { - if (isspace((u_char)buf[*pos])) + if (' ' == buf[*pos]) if ('\\' != buf[*pos - 1]) break; (*pos)++; @@ -612,7 +598,7 @@ args(struct mdoc *mdoc, int line, return(ARGS_WORD); if ( ! (ARGS_TABSEP & fl)) - while (buf[*pos] && isspace((u_char)buf[*pos])) + while (buf[*pos] && ' ' == buf[*pos]) (*pos)++; if (buf[*pos]) @@ -644,7 +630,7 @@ args(struct mdoc *mdoc, int line, if (0 == buf[*pos]) return(ARGS_QWORD); - while (buf[*pos] && isspace((u_char)buf[*pos])) + while (buf[*pos] && ' ' == buf[*pos]) (*pos)++; if (buf[*pos]) @@ -773,9 +759,9 @@ argv_multi(struct mdoc *mdoc, int line, else if (ARGS_EOLN == c) break; - if (0 == v->sz % 5) + if (0 == v->sz % MULTI_STEP) v->value = xrealloc(v->value, - (v->sz + 5) * sizeof(char *)); + (v->sz + MULTI_STEP) * sizeof(char *)); v->value[(int)v->sz] = xstrdup(p); } diff --git a/ascii.c b/ascii.c new file mode 100644 index 00000000..1873f3d6 --- /dev/null +++ b/ascii.c @@ -0,0 +1,169 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <err.h> +#include <stdlib.h> +#include <string.h> + +#include "term.h" + +#define ASCII_PRINT_HI 126 +#define ASCII_PRINT_LO 32 + +/* + * Lookup and hashing routines for constructing the ASCII symbol table, + * which should contain a significant portion of mdoc(7)'s special + * symbols. + */ + +struct line { + const char *code; + const char *out; + /* 32- and 64-bit alignment safe. */ + size_t codesz; + size_t outsz; +}; + +struct linep { + const struct line *line; + struct linep *next; +}; + +#define LINE(w, x, y, z) \ + { (w), (y), (x), (z) }, +static const struct line lines[] = { +#include "ascii.in" +}; + + +static inline int match(const struct line *, + const char *, size_t); + + +void * +ascii2htab(void) +{ + void **htab; + struct linep *pp, *p; + int i, len, hash; + + /* + * Constructs a very basic chaining hashtable. The hash routine + * is simply the integral value of the first character. + * Subsequent entries are chained in the order they're processed + * (they're in-line re-ordered during lookup). + */ + + assert(0 == sizeof(lines) % sizeof(struct line)); + len = sizeof(lines) / sizeof(struct line); + + if (NULL == (p = calloc((size_t)len, sizeof(struct linep)))) + err(1, "malloc"); + + htab = calloc(ASCII_PRINT_HI - ASCII_PRINT_LO + 1, + sizeof(struct linep **)); + + if (NULL == htab) + err(1, "malloc"); + + for (i = 0; i < len; i++) { + assert(lines[i].codesz > 0); + assert(lines[i].code); + assert(lines[i].out); + + p[i].line = &lines[i]; + + hash = (int)lines[i].code[0] - ASCII_PRINT_LO; + + if (NULL == (pp = ((struct linep **)htab)[hash])) { + htab[hash] = &p[i]; + continue; + } + + for ( ; pp->next; pp = pp->next) + /* Scan ahead. */ ; + + pp->next = &p[i]; + } + + return((void *)htab); +} + + +const char * +a2ascii(void *htabp, const char *p, size_t sz, size_t *rsz) +{ + struct linep *pp, *prev; + void **htab; + int hash; + + htab = (void **)htabp; + + assert(p); + assert(sz > 0); + assert(p[0] >= ASCII_PRINT_LO && p[0] <= ASCII_PRINT_HI); + + /* + * Lookup the symbol in the symbol hash. See ascii2htab for the + * hashtable specs. This dynamically re-orders the hash chain + * to optimise for repeat hits. + */ + + hash = (int)p[0] - ASCII_PRINT_LO; + + if (NULL == (pp = ((struct linep **)htab)[hash])) + return(NULL); + + if (NULL == pp->next) { + if ( ! match(pp->line, p, sz)) + return(NULL); + *rsz = pp->line->outsz; + return(pp->line->out); + } + + for (prev = NULL; pp; pp = pp->next) { + if ( ! match(pp->line, p, sz)) { + prev = pp; + continue; + } + + /* Re-order the hash chain. */ + + if (prev) { + prev->next = pp->next; + pp->next = ((struct linep **)htab)[hash]; + htab[hash] = pp; + } + + *rsz = pp->line->outsz; + return(pp->line->out); + } + + return(NULL); +} + + +static inline int +match(const struct line *line, const char *p, size_t sz) +{ + + if (line->codesz != sz) + return(0); + return(0 == strncmp(line->code, p, sz)); +} diff --git a/ascii.in b/ascii.in new file mode 100644 index 00000000..7e6046c5 --- /dev/null +++ b/ascii.in @@ -0,0 +1,134 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ + +/* + * The ASCII translation table. The left-hand side corresponds to the + * escape sequence (\x, \(xx and so on) whose length is listed second + * element. The right-hand side is what's produced by the front-end, + * with the fourth element being its length. + * + * Be sure to escape strings. + */ + +LINE("\\", 1, "\\", 1) +LINE("\'", 1, "\'", 1) +LINE("`", 1, "`", 1) +LINE("-", 1, "-", 1) +LINE(" ", 1, " ", 1) +LINE(".", 1, ".", 1) +LINE("&", 1, "", 0) +LINE("e", 1, "\\", 1) +LINE("q", 1, "\"", 1) +LINE("|", 1, "", 0) +LINE("rC", 2, "}", 1) +LINE("lC", 2, "{", 1) +LINE("rB", 2, "]", 1) +LINE("lB", 2, "[", 1) +LINE("ra", 2, ">", 1) +LINE("la", 2, "<", 1) +LINE("Lq", 2, "``", 2) +LINE("lq", 2, "``", 2) +LINE("Rq", 2, "\'\'", 2) +LINE("rq", 2, "\'\'", 2) +LINE("oq", 2, "`", 1) +LINE("aq", 2, "\'", 1) +LINE("<-", 2, "<-", 2) +LINE("->", 2, "->", 2) +LINE("<>", 2, "<>", 2) +LINE("ua", 2, "^", 1) +LINE("da", 2, "v", 1) +LINE("bu", 2, "o", 1) +LINE("Ba", 2, "|", 1) +LINE("ba", 2, "|", 1) +LINE("co", 2, "(C)", 3) +LINE("rg", 2, "(R)", 3) +LINE("tm", 2, "tm", 2) +LINE("Am", 2, "&", 1) +LINE("Le", 2, "<=", 2) +LINE("<=", 2, "<=", 2) +LINE("Ge", 2, ">=", 2) +LINE(">=", 2, ">=", 2) +LINE("==", 2, "==", 2) +LINE("Ne", 2, "!=", 2) +LINE("!=", 2, "!=", 2) +LINE("Pm", 2, "+-", 2) +LINE("+-", 2, "+-", 2) +LINE("If", 2, "infinity", 8) +LINE("if", 2, "oo", 2) +LINE("Na", 2, "NaN", 3) +LINE("na", 2, "NaN", 3) +LINE("**", 2, "*", 1) +LINE("Gt", 2, ">", 1) +LINE("Lt", 2, "<", 1) +LINE("aa", 2, "\'", 1) +LINE("a~", 2, "~", 1) +LINE("ga", 2, "`", 1) +LINE("en", 2, "-", 1) +LINE("em", 2, "--", 2) +LINE("Pi", 2, "pi", 2) +LINE("<<", 2, "<<", 2) +LINE(">>", 2, ">>", 2) +LINE("lh", 2, "<=", 2) +LINE("rh", 2, "=>", 2) +LINE("ae", 2, "ae", 2) +LINE("AE", 2, "AE", 2) +LINE("oe", 2, "oe", 2) +LINE("OE", 2, "OE", 2) +LINE("\'A", 2, "A", 1) +LINE("\'E", 2, "E", 1) +LINE("\'I", 2, "I", 1) +LINE("\'O", 2, "O", 1) +LINE("\'U", 2, "U", 1) +LINE("\'a", 2, "a", 1) +LINE("\'e", 2, "e", 1) +LINE("\'i", 2, "i", 1) +LINE("\'o", 2, "o", 1) +LINE("\'u", 2, "u", 1) +LINE("`A", 2, "A", 1) +LINE("`E", 2, "E", 1) +LINE("`I", 2, "I", 1) +LINE("`O", 2, "O", 1) +LINE("`U", 2, "U", 1) +LINE("`a", 2, "a", 1) +LINE("`e", 2, "e", 1) +LINE("`i", 2, "i", 1) +LINE("`o", 2, "o", 1) +LINE("`u", 2, "u", 1) +LINE("~A", 2, "A", 1) +LINE("~N", 2, "N", 1) +LINE("~O", 2, "O", 1) +LINE("~a", 2, "a", 1) +LINE("~n", 2, "n", 1) +LINE("~o", 2, "o", 1) +LINE("lA", 2, "<=", 2) +LINE("rA", 2, "=>", 2) +LINE("uA", 2, "^", 1) +LINE("dA", 2, "v", 1) +LINE("hA", 2, "<=>", 3) +LINE(":A", 2, "A", 1) +LINE(":E", 2, "E", 1) +LINE(":I", 2, "I", 1) +LINE(":O", 2, "O", 1) +LINE(":U", 2, "U", 1) +LINE(":a", 2, "a", 1) +LINE(":e", 2, "e", 1) +LINE(":i", 2, "i", 1) +LINE(":o", 2, "o", 1) +LINE(":u", 2, "u", 1) +LINE(":y", 2, "y", 1) @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2att(const char *p) +{ + +#include "att.in" + + return(NULL); +} @@ -1,21 +1,39 @@ -# $Id$ -# -# This file defines the `.At' macro argument. Lines are composed of -# tab-delimited fields -- multiple tabs may delimit fields. Comment -# lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from OpenBSD-4.4's mdoc.samples(7). +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ -v1 Version 1 AT&T UNIX -v2 Version 2 AT&T UNIX -v3 Version 3 AT&T UNIX -v4 Version 4 AT&T UNIX -v5 Version 5 AT&T UNIX -v6 Version 6 AT&T UNIX -v7 Version 7 AT&T UNIX -32v Version 32V AT&T UNIX -V AT&T System V UNIX -V.1 AT&T System V.1 UNIX -V.2 AT&T System V.2 UNIX -V.3 AT&T System V.3 UNIX -V.4 AT&T System V.4 UNIX +/* + * This file defines the AT&T versions of the .At macro. This probably + * isn't going to change. The right-hand side is the formatted string. + * + * Be sure to escape strings. + */ + +LINE("v1", "Version 1 AT&T UNIX") +LINE("v2", "Version 2 AT&T UNIX") +LINE("v3", "Version 3 AT&T UNIX") +LINE("v4", "Version 4 AT&T UNIX") +LINE("v5", "Version 5 AT&T UNIX") +LINE("v6", "Version 6 AT&T UNIX") +LINE("v7", "Version 7 AT&T UNIX") +LINE("32v", "Version 32V AT&T UNIX") +LINE("V", "AT&T System V UNIX") +LINE("V.1", "AT&T System V.1 UNIX") +LINE("V.2", "AT&T System V.2 UNIX") +LINE("V.3", "AT&T System V.3 UNIX") +LINE("V.4", "AT&T System V.4 UNIX") @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2lib(const char *p) +{ + +#include "lib.in" + + return(NULL); +} @@ -1,40 +1,59 @@ -# $Id$ -# -# This file defines the `.Lb' macro argument. Lines are composed of -# tab-delimited fields -- multiple tabs may delimit fields. Comment -# lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from NetBSD-4.0.1's mdoc.samples(7). +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ -libarm ARM Architecture Library (libarm, -larm) -libarm32 ARM32 Architecture Library (libarm32, -larm32) -libc Standard C Library (libc, -lc) -libcdk Curses Development Kit Library (libcdk, -lcdk) -libcompat Compatibility Library (libcompat, -lcompat) -libcrypt Crypt Library (libcrypt, -lcrypt) -libcurses Curses Library (libcurses, -lcurses) -libedit Command Line Editor Library (libedit, -ledit) -libevent Event Notification Library (libevent, -levent) -libform Curses Form Library (libform, -lform) -libi386 i386 Architecture Library (libi386, -li386) -libintl Internationalized Message Handling Library (libintl, -lintl) -libipsec IPsec Policy Control Library (libipsec, -lipsec) -libkvm Kernel Data Access Library (libkvm, -lkvm) -libm Math Library (libm, -lm) -libm68k m68k Architecture Library (libm68k, -lm68k) -libmagic Magic Number Recognition Library (libmagic, -lmagic) -libmenu Curses Menu Library (libmenu, -lmenu) -libossaudio OSS Audio Emulation Library (libossaudio, -lossaudio) -libpam Pluggable Authentication Module Library (libpam, -lpam) -libpcap Capture Library (libpcap, -lpcap) -libpci PCI Bus Access Library (libpci, -lpci) -libpmc Performance Counters Library (libpmc, -lpmc) -libposix POSIX Compatibility Library (libposix, -lposix) -libpthread POSIX Threads Library (libpthread, -lpthread) -libresolv DNS Resolver Library (libresolv, -lresolv) -librt POSIX Real-time Library (librt, -lrt) -libtermcap Termcap Access Library (libtermcap, -ltermcap) -libusbhid USB Human Interface Devices Library (libusbhid, -lusbhid) -libutil System Utilities Library (libutil, -lutil) -libx86_64 x86_64 Architecture Library (libx86_64, -lx86_64) -libz Compression Library (libz, -lz) +/* + * These are all possible .Lb strings. When a new library is added, add + * its short-string to the left-hand side and formatted string to the + * right-hand side. + * + * Be sure to escape strings. + */ + +LINE("libarm", "ARM Architecture Library (libarm, \\-larm)") +LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)") +LINE("libc", "Standard C Library (libc, \\-lc)") +LINE("libcdk", "Curses Development Kit Library (libcdk, \\-lcdk)") +LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)") +LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)") +LINE("libcurses", "Curses Library (libcurses, \\-lcurses)") +LINE("libedit", "Command Line Editor Library (libedit, \\-ledit)") +LINE("libevent", "Event Notification Library (libevent, \\-levent)") +LINE("libform", "Curses Form Library (libform, \\-lform)") +LINE("libi386", "i386 Architecture Library (libi386, \\-li386)") +LINE("libintl", "Internationalized Message Handling Library (libintl, \\-lintl)") +LINE("libipsec", "IPsec Policy Control Library (libipsec, \\-lipsec)") +LINE("libkvm", "Kernel Data Access Library (libkvm, \\-lkvm)") +LINE("libm", "Math Library (libm, \\-lm)") +LINE("libm68k", "m68k Architecture Library (libm68k, \\-lm68k)") +LINE("libmagic", "Magic Number Recognition Library (libmagic, \\-lmagic)") +LINE("libmenu", "Curses Menu Library (libmenu, \\-lmenu)") +LINE("libossaudio", "OSS Audio Emulation Library (libossaudio, \\-lossaudio)") +LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)") +LINE("libpcap", "Capture Library (libpcap, \\-lpcap)") +LINE("libpci", "PCI Bus Access Library (libpci, \\-lpci)") +LINE("libpmc", "Performance Counters Library (libpmc, \\-lpmc)") +LINE("libposix", "POSIX Compatibility Library (libposix, \\-lposix)") +LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)") +LINE("libresolv", "DNS Resolver Library (libresolv, \\-lresolv)") +LINE("librt", "POSIX Real\\-time Library (librt, -lrt)") +LINE("libtermcap", "Termcap Access Library (libtermcap, \\-ltermcap)") +LINE("libusbhid", "USB Human Interface Devices Library (libusbhid, \\-lusbhid)") +LINE("libutil", "System Utilities Library (libutil, \\-lutil)") +LINE("libx86_64", "x86_64 Architecture Library (libx86_64, \\-lx86_64)") +LINE("libz", "Compression Library (libz, \\-lz)") @@ -32,244 +32,222 @@ /* FIXME: .Fl, .Ar, .Cd handling of `|'. */ -static int macro_obsolete(MACRO_PROT_ARGS); -static int macro_constant(MACRO_PROT_ARGS); -static int macro_constant_scoped(MACRO_PROT_ARGS); -static int macro_constant_delimited(MACRO_PROT_ARGS); -static int macro_text(MACRO_PROT_ARGS); -static int macro_scoped(MACRO_PROT_ARGS); -static int macro_scoped_close(MACRO_PROT_ARGS); -static int macro_scoped_line(MACRO_PROT_ARGS); -static int macro_phrase(struct mdoc *, int, int, char *); +enum mwarn { + WMACPARM, + WOBS +}; + +enum merr { + EOPEN, + EQUOT, + ENOCTX, + ENOPARMS +}; #define REWIND_REWIND (1 << 0) #define REWIND_NOHALT (1 << 1) #define REWIND_HALT (1 << 2) -static int rewind_dohalt(int, enum mdoc_type, +static int obsolete(MACRO_PROT_ARGS); +static int blk_part_exp(MACRO_PROT_ARGS); +static int in_line_eoln(MACRO_PROT_ARGS); +static int in_line_argn(MACRO_PROT_ARGS); +static int in_line(MACRO_PROT_ARGS); +static int blk_full(MACRO_PROT_ARGS); +static int blk_exp_close(MACRO_PROT_ARGS); +static int blk_part_imp(MACRO_PROT_ARGS); + +static int phrase(struct mdoc *, int, int, char *); +static int rew_dohalt(int, enum mdoc_type, const struct mdoc_node *); -static int rewind_alt(int); -static int rewind_dobreak(int, const struct mdoc_node *); -static int rewind_elem(struct mdoc *, int); -static int rewind_impblock(struct mdoc *, int, int, int); -static int rewind_expblock(struct mdoc *, int, int, int); -static int rewind_subblock(enum mdoc_type, +static int rew_alt(int); +static int rew_dobreak(int, const struct mdoc_node *); +static int rew_elem(struct mdoc *, int); +static int rew_impblock(struct mdoc *, int, int, int); +static int rew_expblock(struct mdoc *, int, int, int); +static int rew_subblock(enum mdoc_type, struct mdoc *, int, int, int); -static int rewind_last(struct mdoc *, struct mdoc_node *); +static int rew_last(struct mdoc *, struct mdoc_node *); static int append_delims(struct mdoc *, int, int *, char *); static int lookup(struct mdoc *, int, int, int, const char *); -static int pwarn(struct mdoc *, int, int, int); -static int perr(struct mdoc *, int, int, int); -static int scopewarn(struct mdoc *, enum mdoc_type, int, int, +static int pwarn(struct mdoc *, int, int, enum mwarn); +static int perr(struct mdoc *, int, int, enum merr); +static int swarn(struct mdoc *, enum mdoc_type, int, int, const struct mdoc_node *); -#define WMACPARM (1) -#define WOBS (2) - -#define ENOCTX (1) -#define ENOPARMS (2) +#define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t)) /* Central table of library: who gets parsed how. */ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { NULL, 0 }, /* \" */ - { macro_constant, MDOC_PROLOGUE }, /* Dd */ - { macro_constant, MDOC_PROLOGUE }, /* Dt */ - { macro_constant, MDOC_PROLOGUE }, /* Os */ - { macro_scoped, 0 }, /* Sh */ - { macro_scoped, 0 }, /* Ss */ - { macro_text, 0 }, /* Pp */ - { macro_scoped_line, MDOC_PARSED }, /* D1 */ - { macro_scoped_line, MDOC_PARSED }, /* Dl */ - { macro_scoped, MDOC_EXPLICIT }, /* Bd */ - { macro_scoped_close, MDOC_EXPLICIT }, /* Ed */ - { macro_scoped, MDOC_EXPLICIT }, /* Bl */ - { macro_scoped_close, MDOC_EXPLICIT }, /* El */ - { macro_scoped, MDOC_PARSED }, /* It */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ - { macro_text, MDOC_PARSED }, /* An */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ - { macro_constant, MDOC_CALLABLE }, /* Cd */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ - { macro_constant, 0 }, /* Ex */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ - { macro_constant, 0 }, /* Fd */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ - { macro_text, MDOC_PARSED }, /* Ft */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ - { macro_constant, 0 }, /* In */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Li */ - { macro_constant, 0 }, /* Nd */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ - { macro_obsolete, 0 }, /* Ot */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ - { macro_constant, 0 }, /* Rv */ - /* XXX - .St supposed to be (but isn't) callable. */ - { macro_constant_delimited, MDOC_PARSED }, /* St */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ - { macro_constant, 0 }, /* %A */ - { macro_constant, 0 }, /* %B */ - { macro_constant, 0 }, /* %D */ - { macro_constant, 0 }, /* %I */ - { macro_constant, 0 }, /* %J */ - { macro_constant, 0 }, /* %N */ - { macro_constant, 0 }, /* %O */ - { macro_constant, 0 }, /* %P */ - { macro_constant, 0 }, /* %R */ - { macro_constant, 0 }, /* %T */ - { macro_constant, 0 }, /* %V */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* At */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */ - { macro_scoped, MDOC_EXPLICIT }, /* Bf */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ - { macro_constant, 0 }, /* Db */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */ - { macro_scoped_close, MDOC_EXPLICIT }, /* Ef */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ - { macro_text, MDOC_PARSED }, /* Ms */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* No */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */ - { macro_constant_delimited, MDOC_PARSED }, /* Pf */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */ - { macro_scoped_close, MDOC_EXPLICIT }, /* Re */ - { macro_scoped, MDOC_EXPLICIT }, /* Rs */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */ - { macro_constant, 0 }, /* Sm */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */ - { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ - /* XXX - .Fo supposed to be (but isn't) callable. */ - { macro_scoped, MDOC_EXPLICIT }, /* Fo */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */ - { macro_scoped, MDOC_EXPLICIT }, /* Bk */ - { macro_scoped_close, MDOC_EXPLICIT }, /* Ek */ - { macro_constant, 0 }, /* Bt */ - { macro_constant, 0 }, /* Hf */ - { macro_obsolete, 0 }, /* Fr */ - { macro_constant, 0 }, /* Ud */ - { macro_constant, 0 }, /* Lb */ - { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */ - { macro_text, 0 }, /* Lp */ - { macro_text, MDOC_PARSED }, /* Lk */ - { macro_text, MDOC_PARSED }, /* Mt */ - { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */ - { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */ - { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */ - { macro_constant, 0 }, /* %C */ + { in_line_eoln, MDOC_PROLOGUE }, /* Dd */ + { in_line_eoln, MDOC_PROLOGUE }, /* Dt */ + { in_line_eoln, MDOC_PROLOGUE }, /* Os */ + { blk_full, 0 }, /* Sh */ + { blk_full, 0 }, /* Ss */ + { in_line, 0 }, /* Pp */ + { blk_part_imp, MDOC_PARSED }, /* D1 */ + { blk_part_imp, MDOC_PARSED }, /* Dl */ + { blk_full, MDOC_EXPLICIT }, /* Bd */ + { blk_exp_close, MDOC_EXPLICIT }, /* Ed */ + { blk_full, MDOC_EXPLICIT }, /* Bl */ + { blk_exp_close, MDOC_EXPLICIT }, /* El */ + { blk_full, MDOC_PARSED }, /* It */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ + { in_line, MDOC_PARSED }, /* An */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ + { in_line_eoln, MDOC_CALLABLE }, /* Cd */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ + { in_line_eoln, 0 }, /* Ex */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ + { in_line_eoln, 0 }, /* Fd */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ + { in_line, MDOC_PARSED }, /* Ft */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ + { in_line_eoln, 0 }, /* In */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */ + { in_line_eoln, 0 }, /* Nd */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ + { obsolete, 0 }, /* Ot */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ + { in_line_eoln, 0 }, /* Rv */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ + { in_line_eoln, 0 }, /* %A */ + { in_line_eoln, 0 }, /* %B */ + { in_line_eoln, 0 }, /* %D */ + { in_line_eoln, 0 }, /* %I */ + { in_line_eoln, 0 }, /* %J */ + { in_line_eoln, 0 }, /* %N */ + { in_line_eoln, 0 }, /* %O */ + { in_line_eoln, 0 }, /* %P */ + { in_line_eoln, 0 }, /* %R */ + { in_line_eoln, 0 }, /* %T */ + { in_line_eoln, 0 }, /* %V */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */ + { blk_full, MDOC_EXPLICIT }, /* Bf */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ + { in_line_eoln, 0 }, /* Db */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */ + { blk_exp_close, MDOC_EXPLICIT }, /* Ef */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ + { in_line, MDOC_PARSED }, /* Ms */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */ + { in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */ + { blk_exp_close, MDOC_EXPLICIT }, /* Re */ + { blk_full, MDOC_EXPLICIT }, /* Rs */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */ + { in_line_eoln, 0 }, /* Sm */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */ + { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ + { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */ + { blk_full, MDOC_EXPLICIT }, /* Bk */ + { blk_exp_close, MDOC_EXPLICIT }, /* Ek */ + { in_line_eoln, 0 }, /* Bt */ + { in_line_eoln, 0 }, /* Hf */ + { obsolete, 0 }, /* Fr */ + { in_line_eoln, 0 }, /* Ud */ + { in_line_eoln, 0 }, /* Lb */ + { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */ + { in_line, 0 }, /* Lp */ + { in_line, MDOC_PARSED }, /* Lk */ + { in_line, MDOC_PARSED }, /* Mt */ + { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */ + { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */ + { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */ + { in_line_eoln, 0 }, /* %C */ + { obsolete, 0 }, /* Es */ + { obsolete, 0 }, /* En */ }; const struct mdoc_macro * const mdoc_macros = __mdoc_macros; -/* - * This is called at the end of parsing. It must traverse up the tree, - * closing out open [implicit] scopes. Obviously, open explicit scopes - * are errors. - */ -int -macro_end(struct mdoc *mdoc) -{ - struct mdoc_node *n; - - assert(mdoc->first); - assert(mdoc->last); - - /* Scan for open explicit scopes. */ - - n = MDOC_VALID & mdoc->last->flags ? - mdoc->last->parent : mdoc->last; - - for ( ; n; n = n->parent) { - if (MDOC_BLOCK != n->type) - continue; - if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags)) - continue; - return(mdoc_nerr(mdoc, n, - "macro scope still open on exit")); - } - - return(rewind_last(mdoc, mdoc->first)); -} - - static int -perr(struct mdoc *mdoc, int line, int pos, int type) +perr(struct mdoc *mdoc, int line, int pos, enum merr type) { - int c; + char *p; + p = NULL; switch (type) { + case (EOPEN): + p = "explicit scope still open on exit"; + break; + case (EQUOT): + p = "unterminated quotation"; + break; case (ENOCTX): - c = mdoc_perr(mdoc, line, pos, - "closing macro has no prior context"); + p = "closure has no prior context"; break; case (ENOPARMS): - c = mdoc_perr(mdoc, line, pos, - "macro doesn't expect parameters"); + p = "unexpect line arguments"; break; - default: - abort(); - /* NOTREACHED */ } - return(c); + assert(p); + return(mdoc_perr(mdoc, line, pos, p)); } + static int -pwarn(struct mdoc *mdoc, int line, int pos, int type) +pwarn(struct mdoc *mdoc, int line, int pos, enum mwarn type) { - int c; + char *p; + p = NULL; switch (type) { case (WMACPARM): - c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, - "macro-like parameter"); + p = "macro-like parameter"; break; case (WOBS): - c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, - "macro is marked obsolete"); + p = "macro marked obsolete"; break; - default: - abort(); - /* NOTREACHED */ } - return(c); + assert(p); + return(mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, p)); } static int -scopewarn(struct mdoc *mdoc, enum mdoc_type type, +swarn(struct mdoc *mdoc, enum mdoc_type type, int line, int pos, const struct mdoc_node *p) { const char *n, *t, *tt; @@ -315,6 +293,35 @@ scopewarn(struct mdoc *mdoc, enum mdoc_type type, } +/* + * This is called at the end of parsing. It must traverse up the tree, + * closing out open [implicit] scopes. Obviously, open explicit scopes + * are errors. + */ +int +macro_end(struct mdoc *mdoc) +{ + struct mdoc_node *n; + + assert(mdoc->first); + assert(mdoc->last); + + /* Scan for open explicit scopes. */ + + n = MDOC_VALID & mdoc->last->flags ? + mdoc->last->parent : mdoc->last; + + for ( ; n; n = n->parent) { + if (MDOC_BLOCK != n->type) + continue; + if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags)) + continue; + return(nerr(mdoc, n, EOPEN)); + } + + return(rew_last(mdoc, mdoc->first)); +} + static int lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p) { @@ -332,7 +339,7 @@ lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p) static int -rewind_last(struct mdoc *mdoc, struct mdoc_node *to) +rew_last(struct mdoc *mdoc, struct mdoc_node *to) { assert(to); @@ -355,7 +362,7 @@ rewind_last(struct mdoc *mdoc, struct mdoc_node *to) static int -rewind_alt(int tok) +rew_alt(int tok) { switch (tok) { case (MDOC_Ac): @@ -399,7 +406,7 @@ rewind_alt(int tok) static int -rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) +rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) { if (MDOC_ROOT == p->type) @@ -524,7 +531,7 @@ rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) case (MDOC_Sc): /* FALLTHROUGH */ case (MDOC_Xc): - if (type == p->type && rewind_alt(tok) == p->tok) + if (type == p->type && rew_alt(tok) == p->tok) return(REWIND_REWIND); break; default: @@ -537,7 +544,7 @@ rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p) static int -rewind_dobreak(int tok, const struct mdoc_node *p) +rew_dobreak(int tok, const struct mdoc_node *p) { assert(MDOC_ROOT != p->type); @@ -569,7 +576,7 @@ rewind_dobreak(int tok, const struct mdoc_node *p) } if (MDOC_EXPLICIT & mdoc_macros[tok].flags) - return(p->tok == rewind_alt(tok)); + return(p->tok == rew_alt(tok)); else if (MDOC_BLOCK == p->type) return(1); @@ -578,7 +585,7 @@ rewind_dobreak(int tok, const struct mdoc_node *p) static int -rewind_elem(struct mdoc *mdoc, int tok) +rew_elem(struct mdoc *mdoc, int tok) { struct mdoc_node *n; @@ -588,12 +595,12 @@ rewind_elem(struct mdoc *mdoc, int tok) assert(MDOC_ELEM == n->type); assert(tok == n->tok); - return(rewind_last(mdoc, n)); + return(rew_last(mdoc, n)); } static int -rewind_subblock(enum mdoc_type type, struct mdoc *mdoc, +rew_subblock(enum mdoc_type type, struct mdoc *mdoc, int tok, int line, int ppos) { struct mdoc_node *n; @@ -601,67 +608,67 @@ rewind_subblock(enum mdoc_type type, struct mdoc *mdoc, /* LINTED */ for (n = mdoc->last; n; n = n->parent) { - c = rewind_dohalt(tok, type, n); + c = rew_dohalt(tok, type, n); if (REWIND_HALT == c) return(1); if (REWIND_REWIND == c) break; - else if (rewind_dobreak(tok, n)) + else if (rew_dobreak(tok, n)) continue; - if ( ! scopewarn(mdoc, type, line, ppos, n)) + if ( ! swarn(mdoc, type, line, ppos, n)) return(0); } assert(n); - return(rewind_last(mdoc, n)); + return(rew_last(mdoc, n)); } static int -rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos) +rew_expblock(struct mdoc *mdoc, int tok, int line, int ppos) { struct mdoc_node *n; int c; /* LINTED */ for (n = mdoc->last; n; n = n->parent) { - c = rewind_dohalt(tok, MDOC_BLOCK, n); + c = rew_dohalt(tok, MDOC_BLOCK, n); if (REWIND_HALT == c) return(perr(mdoc, line, ppos, ENOCTX)); if (REWIND_REWIND == c) break; - else if (rewind_dobreak(tok, n)) + else if (rew_dobreak(tok, n)) continue; - if ( ! scopewarn(mdoc, MDOC_BLOCK, line, ppos, n)) + if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n)) return(0); } assert(n); - return(rewind_last(mdoc, n)); + return(rew_last(mdoc, n)); } static int -rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos) +rew_impblock(struct mdoc *mdoc, int tok, int line, int ppos) { struct mdoc_node *n; int c; /* LINTED */ for (n = mdoc->last; n; n = n->parent) { - c = rewind_dohalt(tok, MDOC_BLOCK, n); + c = rew_dohalt(tok, MDOC_BLOCK, n); if (REWIND_HALT == c) return(1); else if (REWIND_REWIND == c) break; - else if (rewind_dobreak(tok, n)) + else if (rew_dobreak(tok, n)) continue; - if ( ! scopewarn(mdoc, MDOC_BLOCK, line, ppos, n)) + if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n)) return(0); } assert(n); - return(rewind_last(mdoc, n)); + return(rew_last(mdoc, n)); } @@ -694,13 +701,12 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) /* - * Close out an explicit scope. This optionally parses a TAIL type with - * a set number of TEXT children. + * Close out block partial/full explicit. */ static int -macro_scoped_close(MACRO_PROT_ARGS) +blk_exp_close(MACRO_PROT_ARGS) { - int tt, j, c, lastarg, maxargs, flushed; + int j, c, lastarg, maxargs, flushed; char *p; switch (tok) { @@ -712,44 +718,36 @@ macro_scoped_close(MACRO_PROT_ARGS) break; } - tt = rewind_alt(tok); - - mdoc_msg(mdoc, "parse: %s closing %s", - mdoc_macronames[tok], mdoc_macronames[tt]); - if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) { if (0 == buf[*pos]) { - if ( ! rewind_subblock(MDOC_BODY, mdoc, + if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos)) return(0); - return(rewind_expblock(mdoc, tok, line, ppos)); + return(rew_expblock(mdoc, tok, line, ppos)); } return(perr(mdoc, line, ppos, ENOPARMS)); } - if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos)) return(0); - lastarg = ppos; - flushed = 0; - if (maxargs > 0) { - if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt)) + if ( ! mdoc_tail_alloc(mdoc, line, + ppos, rew_alt(tok))) return(0); mdoc->next = MDOC_NEXT_CHILD; } - for (j = 0; /* No sentinel. */; j++) { + for (lastarg = ppos, flushed = j = 0; ; j++) { lastarg = *pos; if (j == maxargs && ! flushed) { - if ( ! rewind_expblock(mdoc, tok, line, ppos)) + if ( ! rew_expblock(mdoc, tok, line, ppos)) return(0); flushed = 1; } c = mdoc_args(mdoc, line, pos, buf, tok, &p); - assert(ARGS_PHRASE != c); if (ARGS_ERROR == c) return(0); @@ -762,7 +760,7 @@ macro_scoped_close(MACRO_PROT_ARGS) return(0); else if (MDOC_MAX != c) { if ( ! flushed) { - if ( ! rewind_expblock(mdoc, tok, + if ( ! rew_expblock(mdoc, tok, line, ppos)) return(0); flushed = 1; @@ -777,7 +775,7 @@ macro_scoped_close(MACRO_PROT_ARGS) mdoc->next = MDOC_NEXT_SIBLING; } - if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos)) + if ( ! flushed && ! rew_expblock(mdoc, tok, line, ppos)) return(0); if (ppos > 1) @@ -787,64 +785,40 @@ macro_scoped_close(MACRO_PROT_ARGS) /* - * A general text macro. This is a complex case because of punctuation. - * If a text macro is followed by words, then punctuation, the macro is - * "stopped" and "reopened" following the punctuation. Thus, the - * following arises: - * - * .Fl a ; b - * - * ELEMENT (.Fl) - * TEXT (`a') - * TEXT (`;') - * ELEMENT (.Fl) - * TEXT (`b') - * - * This must handle the following situations: - * - * .Fl Ar b ; ; - * - * ELEMENT (.Fl) - * ELEMENT (.Ar) - * TEXT (`b') - * TEXT (`;') - * TEXT (`;') + * In-line macros where reserved words cause scope close-reopen. */ static int -macro_text(MACRO_PROT_ARGS) +in_line(MACRO_PROT_ARGS) { int la, lastpunct, c, w; struct mdoc_arg *arg; char *p; - la = ppos; - lastpunct = 0; - arg = NULL; - - for (;;) { + for (la = ppos, arg = NULL;; ) { la = *pos; c = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (ARGV_EOLN == c) - break; + if (ARGV_WORD == c) { *pos = la; break; - } else if (ARGV_ARG == c) + } + + if (ARGV_EOLN == c) + break; + if (ARGV_ARG == c) continue; + mdoc_argv_free(arg); return(0); } if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg)) return(0); - mdoc->next = MDOC_NEXT_CHILD; - lastpunct = 0; - for (;;) { + for (lastpunct = 0;; ) { la = *pos; w = mdoc_args(mdoc, line, pos, buf, tok, &p); - assert(ARGS_PHRASE != w); if (ARGS_ERROR == w) return(0); @@ -861,7 +835,7 @@ macro_text(MACRO_PROT_ARGS) /* MDOC_MAX (not a macro) or -1 (error). */ if (MDOC_MAX != c && -1 != c) { - if (0 == lastpunct && ! rewind_elem(mdoc, tok)) + if (0 == lastpunct && ! rew_elem(mdoc, tok)) return(0); c = mdoc_macro(mdoc, c, line, la, pos, buf); if (0 == c) @@ -875,7 +849,7 @@ macro_text(MACRO_PROT_ARGS) /* Non-quote-enclosed punctuation. */ if (ARGS_QWORD != w && mdoc_isdelim(p)) { - if (0 == lastpunct && ! rewind_elem(mdoc, tok)) + if (0 == lastpunct && ! rew_elem(mdoc, tok)) return(0); lastpunct = 1; } else if (lastpunct) { @@ -893,7 +867,7 @@ macro_text(MACRO_PROT_ARGS) mdoc->next = MDOC_NEXT_SIBLING; } - if (0 == lastpunct && ! rewind_elem(mdoc, tok)) + if (0 == lastpunct && ! rew_elem(mdoc, tok)) return(0); if (ppos > 1) return(1); @@ -902,76 +876,49 @@ macro_text(MACRO_PROT_ARGS) /* - * Handle explicit-scope (having a different closure token) and implicit - * scope (closing out prior scopes when re-invoked) macros. These - * constitute the BLOCK type and usually span multiple lines. These - * always have HEAD and sometimes have BODY types. In the multi-line - * case: - * - * .Bd -ragged - * Text. - * .Fl macro - * Another. - * .Ed - * - * BLOCK (.Bd) - * HEAD - * BODY - * TEXT (`Text.') - * ELEMENT (.Fl) - * TEXT (`macro') - * TEXT (`Another.') - * - * Note that the `.It' macro, possibly the most difficult (as it has - * embedded scope, etc.) is handled by this routine. It handles - * columnar output, where columns are "phrases" and denote multiple - * block heads. + * Block full-explicit and full-implicit. */ static int -macro_scoped(MACRO_PROT_ARGS) +blk_full(MACRO_PROT_ARGS) { int c, lastarg, reopen; struct mdoc_arg *arg; char *p; - assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)); - - /* First rewind extant implicit scope. */ - if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) { - if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_BODY, mdoc, + tok, line, ppos)) return(0); - if ( ! rewind_impblock(mdoc, tok, line, ppos)) + if ( ! rew_impblock(mdoc, tok, line, ppos)) return(0); } - /* Parse arguments. */ - - arg = NULL; - - for (;;) { + for (arg = NULL;; ) { lastarg = *pos; c = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (ARGV_EOLN == c) - break; + if (ARGV_WORD == c) { *pos = lastarg; break; - } else if (ARGV_ARG == c) + } + + if (ARGV_EOLN == c) + break; + if (ARGV_ARG == c) continue; + mdoc_argv_free(arg); return(0); } if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg)) return(0); - mdoc->next = MDOC_NEXT_CHILD; if (0 == buf[*pos]) { if ( ! mdoc_head_alloc(mdoc, line, ppos, tok)) return(0); - if ( ! rewind_subblock(MDOC_HEAD, mdoc, + if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) return(0); if ( ! mdoc_body_alloc(mdoc, line, ppos, tok)) @@ -982,12 +929,9 @@ macro_scoped(MACRO_PROT_ARGS) if ( ! mdoc_head_alloc(mdoc, line, ppos, tok)) return(0); - - /* Indicate that columnar scope shouldn't be reopened. */ - reopen = 0; mdoc->next = MDOC_NEXT_CHILD; - for (;;) { + for (reopen = 0;; ) { lastarg = *pos; c = mdoc_args(mdoc, line, pos, buf, tok, &p); @@ -996,18 +940,19 @@ macro_scoped(MACRO_PROT_ARGS) if (ARGS_EOLN == c) break; if (ARGS_PHRASE == c) { - if (reopen && ! mdoc_head_alloc(mdoc, line, ppos, tok)) + if (reopen && ! mdoc_head_alloc + (mdoc, line, ppos, tok)) return(0); mdoc->next = MDOC_NEXT_CHILD; - /* * Phrases are self-contained macro phrases used * in the columnar output of a macro. They need * special handling. */ - if ( ! macro_phrase(mdoc, line, lastarg, buf)) + if ( ! phrase(mdoc, line, lastarg, buf)) return(0); - if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_HEAD, mdoc, + tok, line, ppos)) return(0); reopen = 1; @@ -1031,7 +976,7 @@ macro_scoped(MACRO_PROT_ARGS) if (1 == ppos && ! append_delims(mdoc, line, pos, buf)) return(0); - if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) return(0); if ( ! mdoc_body_alloc(mdoc, line, ppos, tok)) @@ -1043,26 +988,10 @@ macro_scoped(MACRO_PROT_ARGS) /* - * This handles a case of implicitly-scoped macro (BLOCK) limited to a - * single line. Instead of being closed out by a subsequent call to - * another macro, the scope is closed at the end of line. These don't - * have BODY or TAIL types. Notice that the punctuation falls outside - * of the HEAD type. - * - * .Qq a Fl b Ar d ; ; - * - * BLOCK (Qq) - * HEAD - * TEXT (`a') - * ELEMENT (.Fl) - * TEXT (`b') - * ELEMENT (.Ar) - * TEXT (`d') - * TEXT (`;') - * TEXT (`;') + * Block partial-imnplicit scope. */ static int -macro_scoped_line(MACRO_PROT_ARGS) +blk_part_imp(MACRO_PROT_ARGS) { int lastarg, c; char *p; @@ -1080,8 +1009,7 @@ macro_scoped_line(MACRO_PROT_ARGS) /* XXX - no known argument macros. */ - lastarg = ppos; - for (;;) { + for (lastarg = ppos;; ) { lastarg = *pos; c = mdoc_args(mdoc, line, pos, buf, tok, &p); assert(ARGS_PHRASE != c); @@ -1108,33 +1036,21 @@ macro_scoped_line(MACRO_PROT_ARGS) } if (1 == ppos) { - if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos)) return(0); if ( ! append_delims(mdoc, line, pos, buf)) return(0); - } else if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos)) + } else if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos)) return(0); - return(rewind_impblock(mdoc, tok, line, ppos)); + return(rew_impblock(mdoc, tok, line, ppos)); } /* - * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped) - * except that it doesn't handle implicit scopes and explicit ones have - * a fixed number of TEXT children to the BODY. - * - * .Fl a So b Sc ; - * - * ELEMENT (.Fl) - * TEXT (`a') - * BLOCK (.So) - * HEAD - * BODY - * TEXT (`b') - * TEXT (';') + * Block partial-explicit macros. */ static int -macro_constant_scoped(MACRO_PROT_ARGS) +blk_part_exp(MACRO_PROT_ARGS) { int lastarg, flushed, j, c, maxargs; char *p; @@ -1142,6 +1058,10 @@ macro_constant_scoped(MACRO_PROT_ARGS) lastarg = ppos; flushed = 0; + /* + * Number of arguments (head arguments). Only `Eo' has these, + */ + switch (tok) { case (MDOC_Eo): maxargs = 1; @@ -1158,7 +1078,8 @@ macro_constant_scoped(MACRO_PROT_ARGS) if (0 == maxargs) { if ( ! mdoc_head_alloc(mdoc, line, ppos, tok)) return(0); - if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_HEAD, mdoc, + tok, line, ppos)) return(0); if ( ! mdoc_body_alloc(mdoc, line, ppos, tok)) return(0); @@ -1168,11 +1089,11 @@ macro_constant_scoped(MACRO_PROT_ARGS) mdoc->next = MDOC_NEXT_CHILD; - for (j = 0; /* No sentinel. */; j++) { + for (j = 0; ; j++) { lastarg = *pos; - if (j == maxargs && ! flushed) { - if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_HEAD, mdoc, + tok, line, ppos)) return(0); flushed = 1; if ( ! mdoc_body_alloc(mdoc, line, ppos, tok)) @@ -1194,7 +1115,7 @@ macro_constant_scoped(MACRO_PROT_ARGS) return(0); else if (MDOC_MAX != c) { if ( ! flushed) { - if ( ! rewind_subblock(MDOC_HEAD, mdoc, + if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) return(0); flushed = 1; @@ -1210,7 +1131,7 @@ macro_constant_scoped(MACRO_PROT_ARGS) } if ( ! flushed && mdoc_isdelim(p)) { - if ( ! rewind_subblock(MDOC_HEAD, mdoc, + if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) return(0); flushed = 1; @@ -1225,7 +1146,7 @@ macro_constant_scoped(MACRO_PROT_ARGS) } if ( ! flushed) { - if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) + if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos)) return(0); if ( ! mdoc_body_alloc(mdoc, line, ppos, tok)) return(0); @@ -1239,32 +1160,20 @@ macro_constant_scoped(MACRO_PROT_ARGS) /* - * A delimited constant is very similar to the macros parsed by - * macro_text except that, in the event of punctuation, the macro isn't - * "re-opened" as it is in macro_text. Also, these macros have a fixed - * number of parameters. - * - * .Fl a No b - * - * ELEMENT (.Fl) - * TEXT (`a') - * ELEMENT (.No) - * TEXT (`b') + * In-line macros where reserved words signal closure of the macro. + * Macros also have a fixed number of arguments. */ static int -macro_constant_delimited(MACRO_PROT_ARGS) +in_line_argn(MACRO_PROT_ARGS) { - int lastarg, flushed, j, c, maxargs, - igndelim, ignargs; + int lastarg, flushed, j, c, maxargs; struct mdoc_arg *arg; char *p; - lastarg = ppos; - flushed = 0; /* - * Maximum arguments per macro. Some of these have none and - * exit as soon as they're parsed. + * Fixed maximum arguments per macro. Some of these have none + * and close as soon as the invocation is parsed. */ switch (tok) { @@ -1282,68 +1191,38 @@ macro_constant_delimited(MACRO_PROT_ARGS) break; } - /* - * Whether to ignore delimiter characters. `Pf' accepts its - * first token as a parameter no matter what it looks like (if - * it's text). - */ + for (lastarg = ppos, arg = NULL;; ) { + lastarg = *pos; + c = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - switch (tok) { - case (MDOC_Pf): - igndelim = 1; - break; - default: - igndelim = 0; - break; - } + if (ARGV_WORD == c) { + *pos = lastarg; + break; + } - /* - * Whether to ignore arguments: `St', for example, handles its - * argument-like parameters as regular parameters. - */ + if (ARGV_EOLN == c) + break; + if (ARGV_ARG == c) + continue; - switch (tok) { - case (MDOC_St): - ignargs = 1; - break; - default: - ignargs = 0; - break; + mdoc_argv_free(arg); + return(0); } - arg = NULL; - - if ( ! ignargs) - for (;;) { - lastarg = *pos; - c = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (ARGV_EOLN == c) - break; - if (ARGV_WORD == c) { - *pos = lastarg; - break; - } else if (ARGV_ARG == c) - continue; - mdoc_argv_free(arg); - return(0); - } - if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg)) return(0); - mdoc->next = MDOC_NEXT_CHILD; - for (j = 0; /* No sentinel. */; j++) { + for (flushed = j = 0; ; j++) { lastarg = *pos; if (j == maxargs && ! flushed) { - if ( ! rewind_elem(mdoc, tok)) + if ( ! rew_elem(mdoc, tok)) return(0); flushed = 1; } c = mdoc_args(mdoc, line, pos, buf, tok, &p); - assert(ARGS_PHRASE != c); if (ARGS_ERROR == c) return(0); @@ -1355,7 +1234,7 @@ macro_constant_delimited(MACRO_PROT_ARGS) if (-1 == (c = lookup(mdoc, line, lastarg, tok, p))) return(0); else if (MDOC_MAX != c) { - if ( ! flushed && ! rewind_elem(mdoc, tok)) + if ( ! flushed && ! rew_elem(mdoc, tok)) return(0); flushed = 1; if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf)) @@ -1363,8 +1242,9 @@ macro_constant_delimited(MACRO_PROT_ARGS) break; } - if ( ! flushed && mdoc_isdelim(p) && ! igndelim) { - if ( ! rewind_elem(mdoc, tok)) + if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && + ! flushed && mdoc_isdelim(p)) { + if ( ! rew_elem(mdoc, tok)) return(0); flushed = 1; } @@ -1374,7 +1254,7 @@ macro_constant_delimited(MACRO_PROT_ARGS) mdoc->next = MDOC_NEXT_SIBLING; } - if ( ! flushed && ! rewind_elem(mdoc, tok)) + if ( ! flushed && ! rew_elem(mdoc, tok)) return(0); if (ppos > 1) @@ -1384,28 +1264,33 @@ macro_constant_delimited(MACRO_PROT_ARGS) /* - * A constant macro is the simplest classification. It spans an entire - * line. + * In-line macro that spans an entire line. May be callable, but has no + * subsequent parsed arguments. */ static int -macro_constant(MACRO_PROT_ARGS) +in_line_eoln(MACRO_PROT_ARGS) { int c, w, la; struct mdoc_arg *arg; char *p; + assert( ! (MDOC_PARSED & mdoc_macros[tok].flags)); + arg = NULL; for (;;) { la = *pos; c = mdoc_argv(mdoc, line, tok, &arg, pos, buf); - if (ARGV_EOLN == c) - break; + if (ARGV_WORD == c) { *pos = la; break; - } else if (ARGV_ARG == c) + } + if (ARGV_EOLN == c) + break; + if (ARGV_ARG == c) continue; + mdoc_argv_free(arg); return(0); } @@ -1418,7 +1303,6 @@ macro_constant(MACRO_PROT_ARGS) for (;;) { la = *pos; w = mdoc_args(mdoc, line, pos, buf, tok, &p); - assert(ARGS_PHRASE != c); if (ARGS_ERROR == w) return(0); @@ -1429,7 +1313,7 @@ macro_constant(MACRO_PROT_ARGS) lookup(mdoc, line, la, tok, p); if (MDOC_MAX != c && -1 != c) { - if ( ! rewind_elem(mdoc, tok)) + if ( ! rew_elem(mdoc, tok)) return(0); return(mdoc_macro(mdoc, c, line, la, pos, buf)); } else if (-1 == c) @@ -1440,13 +1324,13 @@ macro_constant(MACRO_PROT_ARGS) mdoc->next = MDOC_NEXT_SIBLING; } - return(rewind_elem(mdoc, tok)); + return(rew_elem(mdoc, tok)); } /* ARGSUSED */ static int -macro_obsolete(MACRO_PROT_ARGS) +obsolete(MACRO_PROT_ARGS) { return(pwarn(mdoc, line, ppos, WOBS)); @@ -1454,42 +1338,76 @@ macro_obsolete(MACRO_PROT_ARGS) static int -macro_phrase(struct mdoc *mdoc, int line, int ppos, char *buf) +phrase(struct mdoc *mdoc, int line, int ppos, char *buf) { - int i, la, c; + int i, la, c, quoted; + + /* + * Parse over words in a phrase. We have to handle this + * specially because we assume no calling context -- in normal + * circumstances, we switch argument parsing based on whether + * the parent macro accepts quotes, tabs, etc. Here, anything + * goes. + */ for (i = ppos; buf[i]; ) { assert(' ' != buf[i]); - la = i; - if ('\"' == buf[i]) { - la = ++i; - while (buf[i] && '\"' != buf[i]) - i++; + quoted = 0; + + /* + * Read to next token. If quoted (check not escaped), + * scan ahead to next unescaped quote. If not quoted or + * escape-quoted, then scan ahead to next space. + */ + + if ((i && '\"' == buf[i] && '\\' != buf[i - 1]) || + (0 == i && '\"' == buf[i])) { + for (la = ++i; buf[i]; i++) + if ('\"' != buf[i]) + continue; + else if ('\\' != buf[i - 1]) + break; if (0 == buf[i]) - return(mdoc_err(mdoc, "unterminated quoted parameter")); + return(perr(mdoc, line, la, EQUOT)); + quoted = 1; } else - while (buf[i] && ! isspace ((unsigned char)buf[i])) - i++; + for ( ; buf[i]; i++) + if (i && ' ' == buf[i]) { + if ('\\' != buf[i - 1]) + break; + } else if (' ' == buf[i]) + break; + + /* If not end-of-line, terminate argument. */ if (buf[i]) buf[i++] = 0; - while (buf[i] && isspace((unsigned char)buf[i])) - i++; + /* Read to next argument. */ - if (MDOC_MAX != (c = mdoc_tokhash_find(mdoc->htab, &buf[la]))) { + for ( ; buf[i] && ' ' == buf[i]; i++) + /* Spin. */ ; + + /* + * If we're a non-quoted string, try to look up the + * value as a macro and execute it, if found. + */ + + c = quoted ? MDOC_MAX : + mdoc_tokhash_find(mdoc->htab, &buf[la]); + + if (MDOC_MAX != c) { if ( ! mdoc_macro(mdoc, c, line, la, &i, buf)) return(0); return(append_delims(mdoc, line, &i, buf)); } + /* A regular word or quoted string. */ + if ( ! mdoc_word_alloc(mdoc, line, la, &buf[la])) return(0); mdoc->next = MDOC_NEXT_SIBLING; - - while (buf[i] && isspace((unsigned char)buf[i])) - i++; } return(1); @@ -182,7 +182,10 @@ or after .Fn mdoc_endparse or .Fn mdoc_parseln -fail, it may be incomplete. This AST is governed by the ontological +fail, it may be incomplete. +.\" PARAGRAPH +.Pp +This AST is governed by the ontological rules dictated in .Xr mdoc 7 and derives its terminology accordingly. @@ -72,14 +72,16 @@ Within a macro line, the following characters are reserved: .It \&? .Pq question .It \&! -.Pq exclmamation +.Pq exclamation .El +.\" PARAGRAPH .Pp -Use of these characters must either be escaped with a non-breaking space -.Pq Sq \e& -or, if applicable, an appropriate escape-sequence used. Use of reserved -characters is described in +Use of reserved characters is described in .Sx Closure . +For general non-reserved use, characters must either be escaped with a +non-breaking space +.Pq Sq \e& +or, if applicable, an appropriate escape-sequence used. .\" SUB-SECTION .Ss Special Characters Special character sequences begin with the escape character @@ -121,6 +123,14 @@ Grammatic: .Pp Enclosures: .Bl -tag -width 12n -offset "XXXX" -compact +.It \\(lh +.Pq left hand +.It \\(rh +.Pq right hand +.It \\(<< +.Pq left guillemot +.It \\(>> +.Pq right guillemot .It \\(rC .Pq right brace .It \\(lC @@ -160,6 +170,18 @@ Indicatives: .Pq up arrow .It \\(da .Pq down arrow +.It \\(<> +.Pq left-right arrow +.It \\(lA +.Pq left double-arrow +.It \\(rA +.Pq right double-arrow +.It \\(uA +.Pq up double-arrow +.It \\(dA +.Pq down double-arrow +.It \\(hA +.Pq left-right double-arrow .El .\" PARAGRAPH .Pp @@ -200,12 +222,98 @@ Mathematical: .El .\" PARAGRAPH .Pp -Diacritics: +Diacritics and letter combinations: .Bl -tag -width 12n -offset "XXXX" -compact .It \\(ga .Pq accent grave .It \\(aa .Pq accent accute +.It \\(ad +.Pq accent dieresis +.It \\(a~ +.Pq accent tilde +.It \\(AE +.Pq upper-case AE +.It \\(ae +.Pq lower-case AE +.It \\(OE +.Pq upper-case OE +.It \\(oe +.Pq lower-case OE +.It \\('A +.Pq upper-case acute A +.It \\('E +.Pq upper-case acute E +.It \\('I +.Pq upper-case acute I +.It \\('O +.Pq upper-case acute O +.It \\('U +.Pq upper-case acute U +.It \\('a +.Pq lower-case acute a +.It \\('e +.Pq lower-case acute e +.It \\('i +.Pq lower-case acute i +.It \\('o +.Pq lower-case acute o +.It \\('u +.Pq lower-case acute u +.It \\(`A +.Pq upper-case grave A +.It \\(`E +.Pq upper-case grave E +.It \\(`I +.Pq upper-case grave I +.It \\(`O +.Pq upper-case grave O +.It \\(`U +.Pq upper-case grave U +.It \\(`a +.Pq lower-case grave a +.It \\(`e +.Pq lower-case grave e +.It \\(`i +.Pq lower-case grave i +.It \\(`o +.Pq lower-case grave o +.It \\(`u +.Pq lower-case grave u +.It \\(~A +.Pq upper-case tilde A +.It \\(~N +.Pq upper-case tilde N +.It \\(~O +.Pq upper-case tilde O +.It \\(~a +.Pq lower-case tilde a +.It \\(~n +.Pq lower-case tilde n +.It \\(~o +.Pq lower-case tilde o +.It \\(:A +.Pq upper-case dieresis A +.It \\(:E +.Pq upper-case dieresis E +.It \\(:I +.Pq upper-case dieresis I +.It \\(:O +.Pq upper-case dieresis O +.It \\(:U +.Pq upper-case dieresis U +.It \\(:a +.Pq lower-case dieresis a +.It \\(:e +.Pq lower-case dieresis e +.It \\(:i +.Pq lower-case dieresis i +.It \\(:o +.Pq lower-case dieresis o +.It \\(:u +.Pq lower-case dieresis u +.It \\(:y +.Pq lower-case dieresis y .El .\" PARAGRAPH .Pp @@ -219,6 +327,10 @@ Special symbols: .Pq bar, deprecated .It \\(co .Pq copyright +.It \\(rg +.Pq registered +.It \\(tm +.Pq trademarked .It \\& .Pq non-breaking space .It \\e @@ -239,17 +351,18 @@ may span multiple lines. .Bl -inset -offset XXXX .\" LIST-ITEM .It Em Full-block -macros always span multiple lines. They consist optionally of one or +macros always span multiple lines. They consist of zero or more .Qq heads , -subsequent macros or text on the same line following invocation; a +subsequent macros or text on the same line following invocation; an +optional .Qq body , which spans subsequent lines of text or macros; and an optional .Qq tail , macros or text on the same line following closure. .\" LIST-ITEM .It Em Partial-block -macros may span multiple lines. They consists optionally of a +macros may span multiple lines. They consists of a optional .Qq head , text immediately following invocation; always a .Qq body , @@ -307,95 +420,6 @@ are followed by non-reserved characters, the behaviour differs per macro. In general, scope of the macro is closed and re-opened: subsequent tokens are interpreted as if the scope had just been opened. In other circumstances, scope is simply closed out. -.\" .\" SUB-SECTION -.\" .Ss Examples -.\" The following examples illustrate each macro classification. -.\" .\" PARAGRAPH -.\" .Pp -.\" Implicit full-block. Has head, body and no tail. Scope closed by -.\" second -.\" .Sq \&Sh -.\" invocation. -.\" .Bd -literal -offset XXXX -.\" \&.Sh SECTION 1 -.\" body... -.\" \&.Sh SECTION 2 -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Nested implicit full-block, where the subsection -.\" .Sq \&Ss -.\" is within the scope of the parent section -.\" .Sq \&Sh -.\" and closed along with its parent by the subsequent -.\" .Sq \&Sh . -.\" .Bd -literal -offset XXXX -.\" \&.Sh SECTION 1 -.\" \&.Ss Subsection 1 -.\" body... -.\" \&.Sh SECTION 2 -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Explicit full-block. Has a head, a body and no tail. Scope closed by -.\" .Sq \&Ef -.\" invocation. -.\" .Bd -literal -offset XXXX -.\" \&.Bf symbolic -.\" body... -.\" \&.Ef -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Nested explicit/implicit scope. -.\" .Sq \&It -.\" macro is an implicit block whose scope is closed by the explicit -.\" .Sq \&El -.\" closure. -.\" .Bd -literal -offset XXXX -.\" \&.Bl \-bullet -.\" \&.It head -.\" body... -.\" \&.El -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Explicit partial-block. Has head, body and tail. Scope closed by -.\" .Sq \&Ec -.\" invocation. -.\" .Bd -literal -offset XXX -.\" \&.Eo head body... \&Ec tail -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Implicit partial-block. Has only body. Scope is closed by end-of-line. -.\" .Bd -literal -offset XXX -.\" \&.Sq body... -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Explicit partial-block with only body and scope closed by -.\" .Sq \&Ac -.\" invocation. -.\" .Bd -literal -offset XXXX -.\" \&.Ao body... \&Ac -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Implicit partial-block enclosing explicit partial-block. -.\" .Bd -literal -offset XXX -.\" \&.Sq body... \&Ao body... \&Ac -.\" .Ed -.\" .\" PARAGRAPH -.\" .Pp -.\" Inline macros, several in sequence. Scope is closed for -.\" .Sq \&Fl -.\" by the punctuation delimiter and -.\" .Sq \&Ar -.\" by the end-of-line. -.\" .Bd -literal -offset XXXX -.\" \&.Fl text0 text1 ; Ar text0 text1 -.\" .Ed .\" SECTION .Sh SYNTAX Macros are generally two and at times three characters in length. The @@ -640,6 +664,12 @@ compatibility with these systems. .Bl -dash -compact .\" LIST-ITEM .It +.Sq \&Fo +and +.Sq \&St +historically weren't always callable. Both are now correctly callable. +.\" LIST-ITEM +.It .Sq \&It \-nested is assumed for all lists: any list may be nested and .Sq \-enum @@ -689,3 +719,58 @@ The .Nm utility was written by .An Kristaps Dzonsons Aq kristaps@kth.se . +.\" SECTION +.Sh CAVEATS +There are several ambiguous parts of mdoc. +.Pp +.Bl -dash -compact +.\" LIST-ITEM +.It +.Sq \&Fa +should be +.Sq \&Va +as function arguments are variables. +.\" LIST-ITEM +.It +.Sq \&Ft +should be +.Sq \&Vt +as function return types are still types. Furthermore, the +.Sq \&Ft +should be removed and +.Sq \&Fo , +which ostensibly follows it, should follow the same convention as +.Sq \&Va . +.\" LIST-ITEM +.It +.Sq \&Va +should formalise that only one or two arguments are acceptable: a +variable name and optional, preceeding type. +.\" LIST-ITEM +.It +.Sq \&Fd +is ambiguous. It's commonly used to indicate an include file in the +synopsis section. +.Sq \&In +should be used, instead. +.\" LIST-ITEM +.It +Only the +.Sq \-literal +argument to +.Sq \&Bd +makes sense. The remaining ones should be removed. +.\" LIST-ITEM +.It +The +.Sq \&Xo +and +.Sq \&Xc +macros should be deprecated. +.\" LIST-ITEM +.It +The +.Sq \&Dt +macro lacks clarity. It should be absolutely clear which title will +render when formatting the manual page. +.El @@ -74,7 +74,8 @@ const char *const __mdoc_macronames[MDOC_MAX] = { "Fr", "Ud", "Lb", "Ap", "Lp", "Lk", "Mt", "Brq", /* LINTED */ - "Bro", "Brc", "\%C" + "Bro", "Brc", "\%C", "Es", + "En" }; const char *const __mdoc_argnames[MDOC_ARG_MAX] = { @@ -527,9 +528,9 @@ parsemacro(struct mdoc *m, int ln, char *buf) if (0 == buf[1]) return(1); - if (isspace((unsigned char)buf[1])) { + if (' ' == buf[1]) { i = 2; - while (buf[i] && isspace((unsigned char)buf[i])) + while (buf[i] && ' ' == buf[i]) i++; if (0 == buf[i]) return(1); @@ -545,7 +546,7 @@ parsemacro(struct mdoc *m, int ln, char *buf) for (i = 1; i < 5; i++) { if (0 == (mac[i - 1] = buf[i])) break; - else if (isspace((unsigned char)buf[i])) + else if (' ' == buf[i]) break; } @@ -565,7 +566,7 @@ parsemacro(struct mdoc *m, int ln, char *buf) /* The macro is sane. Jump to the next word. */ - while (buf[i] && isspace((unsigned char)buf[i])) + while (buf[i] && ' ' == buf[i]) i++; /* Begin recursive parse sequence. */ @@ -31,8 +31,6 @@ /* What follows is a list of ALL possible macros. */ -/* TODO: Brq et al. */ - #define MDOC___ 0 #define MDOC_Dd 1 #define MDOC_Dt 2 @@ -148,7 +146,9 @@ #define MDOC_Bro 112 #define MDOC_Brc 113 #define MDOC__C 114 -#define MDOC_MAX 115 +#define MDOC_Es 115 +#define MDOC_En 116 +#define MDOC_MAX 117 /* What follows is a list of ALL possible macro arguments. */ @@ -167,131 +167,20 @@ options may be grouped and delimited with a comma. Using for example, will try to ignore scope and character-escape errors. .\" SUB-SECTION .Ss Character Escapes -The following table shows all +The +.Nm +utility correctly renders all +.Sx Special Characters +in .Xr mdoc 7 -character escapes rendered by -.Nm . -Note that the -.Em Output -column will render differently whether executed with -.Xr mdocterm 1 -or another output filter. -.\" PARAGRAPH -.Pp -Grammatic: -.Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(em -\\(em (em-dash) -.It \(en -\\(en (en-dash) -.It \- -\\- (hyphen) -.It \\ -\\\\ (back-slash) -.El -.\" PARAGRAPH -.Pp -Enclosures: -.Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(rC -\\(rC (right brace) -.It \(lC -\\(lC (left brace) -.It \(ra -\\(ra (right angle) -.It \(la -\\(la (left angle) -.It \(rB -\\(rB (right bracket) -.It \(lB -\\(lB (left bracket) -.It \q -\\q (double-quote) -.It \(lq -\\(lq (left double-quote) -.It \(rq -\\(rq (right double-quote) -.It \(oq -\\(oq, \\` (left single-quote) -.It \(aq -\\(aq, \\' (right single-quote, apostrophe) -.El -.\" PARAGRAPH -.Pp -Indicatives: -.Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(<- -\\(<- (left arrow) -.It \(-> -\\(-> (right arrow) -.It \(ua -\\(ua (up arrow) -.It \(da -\\(da (down arrow) -.El -.\" PARAGRAPH -.Pp -Mathematical: -.Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(<= -\\(<= (less-than-equal) -.It \(>= -\\(>= (greater-than-equal) -.It \(== -\\(== (equal) -.It \(!= -\\(!= (not equal) -.It \(if -\\(if (infinity) -.It \(na -\\(na (NaN)* -.It \(+- -\\(+- (plus-minus) -.It \(** -\\(** (asterisk) -.El -.\" PARAGRAPH -.Pp -Diacritics: +in 7-bit ASCII. .Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(ga -\\(ga (accent grave) -.It \(aa -\\(aa (accent accute) -.El -.\" PARAGRAPH -.Pp -Special symbols: -.Pp -.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact -.It Em Output -.Em Input (Name) -.It \(bu -\\(bu (bullet) -.It \(ba -\\(ba (bar) -.It \(co -\\(co (copyright) -.El -.Pp -*This is a deviation from the standard, as NaN is usually rendered as -\\*(Na, which is a deprecated form. We introduce \\(na, which follows -the more general syntax. +In the general sense, +.Nm +will make a +.Pq best-effort +to render complex characters; however, if a manual is using considerable +special characters, some meaning may be lost in translation. .\" SECTION .Sh EXAMPLES To display this manual page: @@ -41,12 +41,7 @@ struct nroffopt { struct termp *termp; /* Ephemeral. */ }; -struct termseq { - const char *enc; - int sym; -}; - -dead_pre void punt(struct nroffopt *, char *) dead_post; +__dead void punt(struct nroffopt *, char *); static int option(void *, int, char *); static int optsopt(struct termp *, char *); static void body(struct termp *, @@ -66,125 +61,8 @@ static void nescape(struct termp *, static void chara(struct termp *, char); static void stringa(struct termp *, const char *, size_t); -static void symbola(struct termp *, enum tsym); static void sanity(const struct mdoc_node *); -#ifdef __linux__ -extern size_t strlcat(char *, const char *, size_t); -extern size_t strlcpy(char *, const char *, size_t); -#endif - -static struct termseq termenc1[] = { - { "\\", TERMSYM_SLASH }, - { "\'", TERMSYM_RSQUOTE }, - { "`", TERMSYM_LSQUOTE }, - { "-", TERMSYM_HYPHEN }, - { " ", TERMSYM_SPACE }, - { ".", TERMSYM_PERIOD }, - { "&", TERMSYM_BREAK }, - { "e", TERMSYM_SLASH }, - { "q", TERMSYM_DQUOTE }, - { "|", TERMSYM_BREAK }, - { NULL, 0 } -}; - -static struct termseq termenc2[] = { - { "rC", TERMSYM_RBRACE }, - { "lC", TERMSYM_LBRACE }, - { "rB", TERMSYM_RBRACK }, - { "lB", TERMSYM_LBRACK }, - { "ra", TERMSYM_RANGLE }, - { "la", TERMSYM_LANGLE }, - { "Lq", TERMSYM_LDQUOTE }, - { "lq", TERMSYM_LDQUOTE }, - { "Rq", TERMSYM_RDQUOTE }, - { "rq", TERMSYM_RDQUOTE }, - { "oq", TERMSYM_LSQUOTE }, - { "aq", TERMSYM_RSQUOTE }, - - { "<-", TERMSYM_LARROW }, - { "->", TERMSYM_RARROW }, - { "ua", TERMSYM_UARROW }, - { "da", TERMSYM_DARROW }, - - { "bu", TERMSYM_BULLET }, - { "Ba", TERMSYM_BAR }, - { "ba", TERMSYM_BAR }, - { "co", TERMSYM_COPY }, - { "Am", TERMSYM_AMP }, - - { "Le", TERMSYM_LE }, - { "<=", TERMSYM_LE }, - { "Ge", TERMSYM_GE }, - { ">=", TERMSYM_GE }, - { "==", TERMSYM_EQ }, - { "Ne", TERMSYM_NEQ }, - { "!=", TERMSYM_NEQ }, - { "Pm", TERMSYM_PLUSMINUS }, - { "+-", TERMSYM_PLUSMINUS }, - { "If", TERMSYM_INF2 }, - { "if", TERMSYM_INF }, - { "Na", TERMSYM_NAN }, - { "na", TERMSYM_NAN }, - { "**", TERMSYM_ASTERISK }, - { "Gt", TERMSYM_GT }, - { "Lt", TERMSYM_LT }, - - { "aa", TERMSYM_ACUTE }, - { "ga", TERMSYM_GRAVE }, - - { "en", TERMSYM_EN }, - { "em", TERMSYM_EM }, - - { "Pi", TERMSYM_PI }, - { NULL, 0 } -}; - -/* FIXME: abstract to dynamically-compiled table. */ -static struct termsym termsym_ascii[TERMSYM_MAX] = { - { "]", 1 }, /* TERMSYM_RBRACK */ - { "[", 1 }, /* TERMSYM_LBRACK */ - { "<-", 2 }, /* TERMSYM_LARROW */ - { "->", 2 }, /* TERMSYM_RARROW */ - { "^", 1 }, /* TERMSYM_UARROW */ - { "v", 1 }, /* TERMSYM_DARROW */ - { "`", 1 }, /* TERMSYM_LSQUOTE */ - { "\'", 1 }, /* TERMSYM_RSQUOTE */ - { "\'", 1 }, /* TERMSYM_SQUOTE */ - { "``", 2 }, /* TERMSYM_LDQUOTE */ - { "\'\'", 2 }, /* TERMSYM_RDQUOTE */ - { "\"", 1 }, /* TERMSYM_DQUOTE */ - { "<", 1 }, /* TERMSYM_LT */ - { ">", 1 }, /* TERMSYM_GT */ - { "<=", 2 }, /* TERMSYM_LE */ - { ">=", 2 }, /* TERMSYM_GE */ - { "==", 2 }, /* TERMSYM_EQ */ - { "!=", 2 }, /* TERMSYM_NEQ */ - { "\'", 1 }, /* TERMSYM_ACUTE */ - { "`", 1 }, /* TERMSYM_GRAVE */ - { "pi", 2 }, /* TERMSYM_PI */ - { "+=", 2 }, /* TERMSYM_PLUSMINUS */ - { "oo", 2 }, /* TERMSYM_INF */ - { "infinity", 8 }, /* TERMSYM_INF2 */ - { "NaN", 3 }, /* TERMSYM_NAN */ - { "|", 1 }, /* TERMSYM_BAR */ - { "o", 1 }, /* TERMSYM_BULLET */ - { "&", 1 }, /* TERMSYM_AMP */ - { "--", 2 }, /* TERMSYM_EM */ - { "-", 1 }, /* TERMSYM_EN */ - { "(C)", 3 }, /* TERMSYM_COPY */ - { "*", 1 }, /* TERMSYM_ASTERISK */ - { "\\", 1 }, /* TERMSYM_SLASH */ - { "-", 1 }, /* TERMSYM_HYPHEN */ - { " ", 1 }, /* TERMSYM_SPACE */ - { ".", 1 }, /* TERMSYM_PERIOD */ - { "", 0 }, /* TERMSYM_BREAK */ - { "<", 1 }, /* TERMSYM_LANGLE */ - { ">", 1 }, /* TERMSYM_RANGLE */ - { "{", 1 }, /* TERMSYM_LBRACE */ - { "}", 1 }, /* TERMSYM_RBRACE */ -}; - int main(int argc, char *argv[]) { @@ -200,9 +78,8 @@ main(int argc, char *argv[]) termp.maxrmargin = termp.rmargin = 78; /* FIXME */ termp.maxcols = 1024; /* FIXME */ - termp.offset = termp.col = 0; termp.flags = TERMP_NOSPACE; - termp.symtab = termsym_ascii; + termp.symtab = ascii2htab(); nroff.termp = &termp; @@ -374,7 +251,7 @@ flushln(struct termp *p) /* LINTED */ for (j = i, vsz = 0; j < p->col; j++) { - if (isspace((u_char)p->buf[j])) + if (' ' == p->buf[j]) break; else if (8 == p->buf[j]) j += 1; @@ -420,7 +297,7 @@ flushln(struct termp *p) */ for ( ; i < p->col; i++) { - if (isspace((u_char)p->buf[i])) + if (' ' == p->buf[i]) break; putchar(p->buf[i]); } @@ -523,14 +400,13 @@ word(struct termp *p, const char *word) /* LINTED */ for (j = i = 0; i < len; i++) { - if ( ! isspace((u_char)word[i])) { + if (' ' != word[i]) { j++; continue; } /* Escaped spaces don't delimit... */ - if (i > 0 && isspace((u_char)word[i]) && - '\\' == word[i - 1]) { + if (i && ' ' == word[i] && '\\' == word[i - 1]) { j++; continue; } @@ -737,27 +613,15 @@ header(struct termp *p, const struct mdoc_meta *meta) static void nescape(struct termp *p, const char *word, size_t len) { - struct termseq *enc; + const char *rhs; + size_t sz; - switch (len) { - case (1): - enc = termenc1; - break; - case (2): - enc = termenc2; - break; - default: + if (NULL == (rhs = a2ascii(p->symtab, word, len, &sz))) { warnx("unsupported %zu-byte escape sequence", len); return; } - for ( ; enc->enc; enc++) - if (0 == memcmp(enc->enc, word, len)) { - symbola(p, enc->sym); - return; - } - - warnx("unsupported %zu-byte escape sequence", len); + stringa(p, rhs, sz); } @@ -871,18 +735,6 @@ pword(struct termp *p, const char *word, size_t len) /* - * Add a symbol to the output line buffer. - */ -static void -symbola(struct termp *p, enum tsym sym) -{ - - assert(p->symtab[sym].sym); - stringa(p, p->symtab[sym].sym, p->symtab[sym].sz); -} - - -/* * Like chara() but for arbitrary-length buffers. Resize the buffer by * a factor of two (if the buffer is less than that) or the buffer's * size. @@ -1039,7 +891,7 @@ sanity(const struct mdoc_node *n) } -dead_pre void +__dead void punt(struct nroffopt *nroff, char *in) { char *args[32]; @@ -58,13 +58,6 @@ static int msg_err(void *, int, int, const char *); static int msg_warn(void *, int, int, enum mdoc_warn, const char *); -#ifdef __linux__ -extern int getsubopt(char **, char *const *, char **); -extern size_t strlcpy(char *, const char *, size_t); -extern size_t strlcat(char *, const char *, size_t); -#endif - - /* * Print our and our caller's usage message. */ @@ -176,7 +169,7 @@ mmain_free(struct mmain *p) } -dead_pre void +__dead void mmain_exit(struct mmain *p, int code) { @@ -28,24 +28,12 @@ #include "mdoc.h" -/* Rules for "dead" functions: */ -#if defined(__NetBSD__) -#define dead_pre __dead -#define dead_post __attribute__((__noreturn__)) -#elif defined(__OpenBSD__) -#define dead_pre __dead -#define dead_post /* Nothing. */ -#else -#define dead_pre /* Nothing. */ -#define dead_post __attribute__((__noreturn__)) -#endif - __BEGIN_DECLS struct mmain; struct mmain *mmain_alloc(void); -dead_pre void mmain_exit(struct mmain *, int) dead_post; +__dead void mmain_exit(struct mmain *, int); int mmain_getopt(struct mmain *, int, char *[], const char *, const char *, const char *, void *, @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2msec(const char *p) +{ + +#include "msec.in" + + return(NULL); +} @@ -1,24 +1,42 @@ -# $Id$ -# -# This file defines the `.Dt' macro 'volume' argument. Lines are -# composed of tab-delimited fields -- multiple tabs may delimit fields. -# Comment lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from OpenBSD-4.4's mdoc.samples(7). +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ -1 General Commands Manual -2 System Calls Manual -3 Library Functions Manual -3p Perl Library Functions Manual -4 Kernel Interfaces Manual -5 File Formats Manual -6 Games Manual -7 Miscellaneous Information Manual -8 System Manager\'s Manual -9 Kernel Developer\'s Manual -X11 X11 Developer\'s Manual -X11R6 X11 Developer\'s Manual -unass Unassociated -local Local -draft Draft -paper Paper +/* + * These are all possible manual-section macros and what they correspond + * to when rendered as the volume title. + * + * Be sure to escape strings. + */ + +LINE("1", "General Commands Manual") +LINE("2", "System Calls Manual") +LINE("3", "Library Functions Manual") +LINE("3p", "Perl Library Functions Manual") +LINE("4", "Kernel Interfaces Manual") +LINE("5", "File Formats Manual") +LINE("6", "Games Manual") +LINE("7", "Miscellaneous Information Manual") +LINE("8", "System Manager\'s Manual") +LINE("9", "Kernel Developer\'s Manual") +LINE("X11", "X11 Developer\'s Manual") +LINE("X11R6", "X11 Developer\'s Manual") +LINE("unass", "Unassociated") +LINE("local", "Local") +LINE("draft", "Draft") +LINE("paper", "Paper") @@ -53,6 +53,8 @@ struct mdoc_macro { #define MDOC_PARSED (1 << 1) #define MDOC_EXPLICIT (1 << 2) #define MDOC_PROLOGUE (1 << 3) +#define MDOC_IGNDELIM (1 << 4) + /* Reserved words in arguments treated as text. */ }; #define mdoc_nwarn(mdoc, node, type, fmt, ...) \ @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2st(const char *p) +{ + +#include "st.in" + + return(NULL); +} @@ -1,45 +1,48 @@ -# $Id$ -# -# This file defines the `.St' macro arguments. Lines are composed of -# tab-delimited fields -- multiple tabs may delimit fields. Comment -# lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from OpenBSD-4.4's mdoc.samples(7). +/* $Id$ */ --p1003.1-88 IEEE Std 1003.1-1988 (\\\\(lqPOSIX\\\\(rq) --p1003.1-90 IEEE Std 1003.1-1990 (\\\\(lqPOSIX\\\\(rq) --p1003.1-96 ISO/IEC 9945-1:1996 (\\\\(lqPOSIX\\\\(rq) --p1003.1-2001 IEEE Std 1003.1-2001 (\\\\(lqPOSIX\\\\(rq) --p1003.1-2004 IEEE Std 1003.1-2004 (\\\\(lqPOSIX\\\\(rq) --p1003.1 IEEE Std 1003.1 (\\\\(lqPOSIX\\\\(rq) --p1003.1b IEEE Std 1003.1b (\\\\(lqPOSIX\\\\(rq) --p1003.1b-93 IEEE Std 1003.1b-1993 (\\\\(lqPOSIX\\\\(rq) --p1003.1c-95 IEEE Std 1003.1c-1995 (\\\\(lqPOSIX\\\\(rq) --p1003.1g-2000 IEEE Std 1003.1g-2000 (\\\\(lqPOSIX\\\\(rq) --p1003.2-92 IEEE Std 1003.2-1992 (\\\\(lqPOSIX.2\\\\(rq) --p1387.2-95 IEEE Std 1387.2-1995 (\\\\(lqPOSIX.7.2\\\\(rq) --p1003.2 IEEE Std 1003.2 (\\\\(lqPOSIX.2\\\\(rq) --p1387.2 IEEE Std 1387.2 (\\\\(lqPOSIX.7.2\\\\(rq) --isoC-90 ISO/IEC 9899:1990 (\\\\(lqISO C90\\\\(rq) --isoC-amd1 ISO/IEC 9899/AMD1:1995 (\\\\(lqISO C90\\\\(rq) --isoC-tcor1 ISO/IEC 9899/TCOR1:1994 (\\\\(lqISO C90\\\\(rq) --isoC-tcor2 ISO/IEC 9899/TCOR2:1995 (\\\\(lqISO C90\\\\(rq) --isoC-99 ISO/IEC 9899:1999 (\\\\(lqISO C99\\\\(rq) --ansiC ANSI X3.159-1989 (\\\\(lqANSI C\\\\(rq) --ansiC-89 ANSI X3.159-1989 (\\\\(lqANSI C\\\\(rq) --ansiC-99 ANSI/ISO/IEC 9899-1999 (\\\\(lqANSI C99\\\\(rq) --ieee754 IEEE Std 754-1985 --iso8802-3 ISO 8802-3: 1989 --xpg3 X/Open Portability Guide Issue 3 (\\\\(lqXPG3\\\\(rq) --xpg4 X/Open Portability Guide Issue 4 (\\\\(lqXPG4\\\\(rq) --xpg4.2 X/Open Portability Guide Issue 4.2 (\\\\(lqXPG4.2\\\\(rq) --xpg4.3 X/Open Portability Guide Issue 4.3 (\\\\(lqXPG4.3\\\\(rq) --xbd5 X/Open System Interface Definitions Issue 5 (\\\\(lqXBD5\\\\(rq) --xcu5 X/Open Commands and Utilities Issue 5 (\\\\(lqXCU5\\\\(rq) --xsh5 X/Open System Interfaces and Headers Issue 5 (\\\\(lqXSH5\\\\(rq) --xns5 X/Open Networking Services Issue 5 (\\\\(lqXNS5\\\\(rq) --xns5.2d2.0 X/Open Networking Services Issue 5.2 Draft 2.0 (\\\\(lqXNS5.2D2.0\\\\(rq) --xcurses4.2 X/Open Curses Issue 4 Version 2 (\\\\(lqXCURSES4.2\\\\(rq) --susv2 Version 2 of the Single UNIX Specification --susv3 Version 3 of the Single UNIX Specification --svid4 System V Interface Definition, Fourth Edition (\\\\(lqSVID4\\\\(rq) +/* + * This file defines the .St macro arguments. If you add a new + * standard, make sure that the left-and side corresponds to the .St + * argument (like .St -p1003.1) and the right-hand side corresponds to + * the formatted output string. + * + * Be sure to escape strings. + */ + +LINE("-p1003.1-88", "IEEE Std 1003.1-1988 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1-90", "IEEE Std 1003.1-1990 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1-96", "ISO/IEC 9945-1:1996 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1", "IEEE Std 1003.1 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX\\(rq)") +LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX\\(rq)") +LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX\\(rq)") +LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)") +LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)") +LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)") +LINE("-p1387.2", "IEEE Std 1387.2 (\\(lqPOSIX.7.2\\(rq)") +LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO C90\\(rq)") +LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO C90\\(rq)") +LINE("-isoC-tcor1", "ISO/IEC 9899/TCOR1:1994 (\\(lqISO C90\\(rq)") +LINE("-isoC-tcor2", "ISO/IEC 9899/TCOR2:1995 (\\(lqISO C90\\(rq)") +LINE("-isoC-99", "ISO/IEC 9899:1999 (\\(lqISO C99\\(rq)") +LINE("-ansiC", "ANSI X3.159-1989 (\\(lqANSI C\\(rq)") +LINE("-ansiC-89", "ANSI X3.159-1989 (\\(lqANSI C\\(rq)") +LINE("-ansiC-99", "ANSI/ISO/IEC 9899-1999 (\\(lqANSI C99\\(rq)") +LINE("-ieee754", "IEEE Std 754-1985") +LINE("-iso8802-3", "ISO 8802-3: 1989") +LINE("-xpg3", "X/Open Portability Guide Issue 3 (\\(lqXPG3\\(rq)") +LINE("-xpg4", "X/Open Portability Guide Issue 4 (\\(lqXPG4\\(rq)") +LINE("-xpg4.2", "X/Open Portability Guide Issue 4.2 (\\(lqXPG4.2\\(rq)") +LINE("-xpg4.3", "X/Open Portability Guide Issue 4.3 (\\(lqXPG4.3\\(rq)") +LINE("-xbd5", "X/Open System Interface Definitions Issue 5 (\\(lqXBD5\\(rq)") +LINE("-xcu5", "X/Open Commands and Utilities Issue 5 (\\(lqXCU5\\(rq)") +LINE("-xsh5", "X/Open System Interfaces and Headers Issue 5 (\\(lqXSH5\\(rq)") +LINE("-xns5", "X/Open Networking Services Issue 5 (\\(lqXNS5\\(rq)") +LINE("-xns5.2d2.0", "X/Open Networking Services Issue 5.2 Draft 2.0 (\\(lqXNS5.2D2.0\\(rq)") +LINE("-xcurses4.2", "X/Open Curses Issue 4 Version 2 (\\(lqXCURSES4.2\\(rq)") +LINE("-susv2", "Version 2 of the Single UNIX Specification") +LINE("-susv3", "Version 3 of the Single UNIX Specification") +LINE("-svid4", "System V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)") diff --git a/strings.sh b/strings.sh deleted file mode 100644 index 4fdb5273..00000000 --- a/strings.sh +++ /dev/null @@ -1,89 +0,0 @@ -#! /bin/sh -# $Id$ - -# strings.sh [-o output] name input -# -# Generate the file of strings. This will contain the following -# function: -# -# const char * -# mdoc_a2NAME(const char *); -# -# The input file must be tab-delimited as follows: -# -# attnam0 A longer description -# attnam1 Another longer description - -input= -output= -args=`getopt o: $*` - -if [ $? -ne 0 ]; then - echo "usage: $0 [-o output] name input" 1>&2 - exit 1 -fi - -set -- $args - -while [ $# -ge 0 ] -do - case "$1" in - -o) - output="$2" ; shift; shift ;; - --) - shift ; break ;; - esac -done - -name=$1 - -if [ -z "$name" ]; then - echo "usage: $0 [-o output] name input" 1>&2 - exit 1 -fi - -input=$2 - -if [ "$output" ]; then - exec >$output -fi - -if [ "$input" ]; then - exec <$input -fi - -cat <<! -/* - * DO NOT EDIT! Automatically generated by $0. - */ -#include <stdlib.h> - -#include "private.h" - -const char * -mdoc_a2${name}(const char *p) -{ - -! - -while read in ; do - if [ -z "$in" ]; then - continue - fi - if [ "#" = `echo "$in" | cut -c1` ]; then - continue - fi - key=`printf "%s\n" "$in" | cut -f 1` - val=`printf "%s\n" "$in" | cut -f 2- | sed 's!^[ ]*!!'` - cat <<! - if (xstrcmp(p, "$key")) - return("$val"); -! -done - -cat <<! - - /* No keys found. */ - return(NULL); -} -! @@ -296,6 +296,8 @@ const struct termact __termacts[MDOC_MAX] = { { termp_brq_pre, termp_brq_post }, /* Bro */ { NULL, NULL }, /* Brc */ { NULL, NULL }, /* %C */ + { NULL, NULL }, /* Es */ + { NULL, NULL }, /* En */ }; const struct termact *termacts = __termacts; @@ -21,60 +21,12 @@ #include "mdoc.h" +/* XXX - clean up tabs. */ + #define INDENT 6 __BEGIN_DECLS -enum tsym { - TERMSYM_RBRACK = 0, - TERMSYM_LBRACK = 1, - TERMSYM_LARROW = 2, - TERMSYM_RARROW = 3, - TERMSYM_UARROW = 4, - TERMSYM_DARROW = 5, - TERMSYM_LSQUOTE = 6, - TERMSYM_RSQUOTE = 7, - TERMSYM_SQUOTE = 8, - TERMSYM_LDQUOTE = 9, - TERMSYM_RDQUOTE = 10, - TERMSYM_DQUOTE = 11, - TERMSYM_LT = 12, - TERMSYM_GT = 13, - TERMSYM_LE = 14, - TERMSYM_GE = 15, - TERMSYM_EQ = 16, - TERMSYM_NEQ = 17, - TERMSYM_ACUTE = 18, - TERMSYM_GRAVE = 19, - TERMSYM_PI = 20, - TERMSYM_PLUSMINUS = 21, - TERMSYM_INF = 22, - TERMSYM_INF2 = 23, - TERMSYM_NAN = 24, - TERMSYM_BAR = 25, - TERMSYM_BULLET = 26, - TERMSYM_AMP = 27, - TERMSYM_EM = 28, - TERMSYM_EN = 29, - TERMSYM_COPY = 30, - TERMSYM_ASTERISK = 31, - TERMSYM_SLASH = 32, - TERMSYM_HYPHEN = 33, - TERMSYM_SPACE = 34, - TERMSYM_PERIOD = 35, - TERMSYM_BREAK = 36, - TERMSYM_LANGLE = 37, - TERMSYM_RANGLE = 38, - TERMSYM_LBRACE = 39, - TERMSYM_RBRACE = 40, - TERMSYM_MAX = 41 -}; - -struct termsym { - const char *sym; - size_t sz; -}; - struct termp { size_t rmargin; size_t maxrmargin; @@ -95,9 +47,11 @@ struct termp { #define TERMP_BOLD (1 << 8) /* Styles... */ #define TERMP_UNDER (1 << 9) char *buf; - struct termsym *symtab; /* Special-symbol table. */ + void *symtab; }; +/* XXX - clean this up. */ + struct termpair { struct termpair *ppair; int type; @@ -117,26 +71,24 @@ struct termpair { } while (0) struct termact { - int (*pre)(struct termp *, - struct termpair *, - const struct mdoc_meta *, - const struct mdoc_node *); - void (*post)(struct termp *, - struct termpair *, - const struct mdoc_meta *, - const struct mdoc_node *); + int (*pre)(struct termp *, struct termpair *, + const struct mdoc_meta *, + const struct mdoc_node *); + void (*post)(struct termp *, struct termpair *, + const struct mdoc_meta *, + const struct mdoc_node *); }; -void newln(struct termp *); -void vspace(struct termp *); -void word(struct termp *, const char *); -void flushln(struct termp *); -void transcode(struct termp *, - const char *, size_t); -void subtree(struct termp *, - const struct mdoc_meta *, - const struct mdoc_node *); +void *ascii2htab(void); +const char *a2ascii(void *, const char *, size_t, size_t *); +void newln(struct termp *); +void vspace(struct termp *); +void word(struct termp *, const char *); +void flushln(struct termp *); +void transcode(struct termp *, const char *, size_t); +void subtree(struct termp *, const struct mdoc_meta *, + const struct mdoc_node *); const struct termact *termacts; @@ -40,6 +40,7 @@ #define POST_ARGS struct mdoc *mdoc enum merr { + EPRINT, ENODATA, ENOPROLOGUE, ELINE, @@ -81,16 +82,13 @@ struct valids { /* Utility checks. */ -static int nwarn(struct mdoc *, - const struct mdoc_node *, enum mwarn); -static int nerr(struct mdoc *, - const struct mdoc_node *, enum merr); +static int pwarn(struct mdoc *, int, int, enum mwarn); +static int perr(struct mdoc *, int, int, enum merr); static int check_parent(PRE_ARGS, int, enum mdoc_type); static int check_msec(PRE_ARGS, ...); static int check_sec(PRE_ARGS, ...); static int check_stdarg(PRE_ARGS); -static int check_text(struct mdoc *, - int, int, const char *); +static int check_text(struct mdoc *, int, int, const char *); static int check_argv(struct mdoc *, const struct mdoc_node *, const struct mdoc_argv *); @@ -151,6 +149,11 @@ static int post_sh_body(POST_ARGS); static int post_sh_head(POST_ARGS); static int post_st(POST_ARGS); +#define mwarn(m, t) nwarn((m), (m)->last, (t)) +#define merr(m, t) nerr((m), (m)->last, (t)) +#define nwarn(m, n, t) pwarn((m), (n)->line, (n)->pos, (t)) +#define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t)) + static v_pre pres_an[] = { pre_an, NULL }; static v_pre pres_bd[] = { pre_display, pre_bd, NULL }; static v_pre pres_bl[] = { pre_bl, NULL }; @@ -310,30 +313,32 @@ const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Bro */ { NULL, NULL }, /* Brc */ { NULL, posts_text }, /* %C */ + { NULL, NULL }, /* Es */ + { NULL, NULL }, /* En */ }; int mdoc_valid_pre(struct mdoc *mdoc, - const struct mdoc_node *node) + const struct mdoc_node *n) { v_pre *p; int line, pos; const char *tp; - if (MDOC_TEXT == node->type) { - tp = node->string; - line = node->line; - pos = node->pos; + if (MDOC_TEXT == n->type) { + tp = n->string; + line = n->line; + pos = n->pos; return(check_text(mdoc, line, pos, tp)); } - if ( ! check_args(mdoc, node)) + if ( ! check_args(mdoc, n)) return(0); - if (NULL == mdoc_valids[node->tok].pre) + if (NULL == mdoc_valids[n->tok].pre) return(1); - for (p = mdoc_valids[node->tok].pre; *p; p++) - if ( ! (*p)(mdoc, node)) + for (p = mdoc_valids[n->tok].pre; *p; p++) + if ( ! (*p)(mdoc, n)) return(0); return(1); } @@ -371,15 +376,16 @@ mdoc_valid_post(struct mdoc *mdoc) } -#define merr(m, t) nerr((m), (m)->last, (t)) static int -nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type) +perr(struct mdoc *m, int line, int pos, enum merr type) { char *p; p = NULL; - switch (type) { + case (EPRINT): + p = "invalid character"; + break; case (ENESTDISP): p = "displays may not be nested"; break; @@ -417,22 +423,19 @@ nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type) p = "default name not yet set"; break; } - assert(p); - return(mdoc_nerr(m, n, p)); + return(mdoc_perr(m, line, pos, p)); } -#define mwarn(m, t) nwarn((m), (m)->last, (t)) static int -nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type) +pwarn(struct mdoc *m, int line, int pos, enum mwarn type) { char *p; enum mdoc_warn c; c = WARN_SYNTAX; p = NULL; - switch (type) { case (WBADMSEC): p = "inappropriate manual section"; @@ -484,7 +487,7 @@ nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type) break; } assert(p); - return(mdoc_nwarn(m, n, c, p)); + return(mdoc_pwarn(m, line, pos, c, p)); } @@ -685,12 +688,12 @@ check_text(struct mdoc *mdoc, int line, int pos, const char *p) { size_t c; - /* XXX - indicate deprecated escapes \*(xx and \*x. */ + /* FIXME: indicate deprecated escapes \*(xx and \*x. */ + /* FIXME: don't allow tabs unless in literal mode. */ for ( ; *p; p++) { - if ( ! isprint((u_char)*p) && '\t' != *p) - return(mdoc_perr(mdoc, line, pos, - "invalid non-printing character")); + if ('\t' != *p && ! isprint((u_char)*p)) + return(perr(mdoc, line, pos, EPRINT)); if ('\\' != *p) continue; if ((c = mdoc_isescape(p))) { @@ -0,0 +1,34 @@ +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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 <stdlib.h> +#include <string.h> + +#include "private.h" + +#define LINE(x, y) \ + if (0 == strcmp(p, x)) return(y); + +const char * +mdoc_a2vol(const char *p) +{ + +#include "vol.in" + + return(NULL); +} @@ -1,20 +1,37 @@ -# $Id$ -# -# This file defines the `.Dt' macro 'volume' argument. Lines are -# composed of tab-delimited fields -- multiple tabs may delimit fields. -# Comment lines begin with '#'; blank lines are also ok. -# -# These were last grok'd from OpenBSD-4.4's mdoc.samples(7). +/* $Id$ */ +/* + * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org> + * + * 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. + */ -USD User's Supplementary Documents -PS1 Programmer's Supplementary Documents -AMD Ancestral Manual Documents -SMM System Manager's Manual -URM User's Reference Manual -PRM Programmer's Manual -KM Kernel Manual -IND Manual Master Index -MMI Manual Master Index -LOCAL Local Manual -LOC Local Manual -CON Contributed Software Manual +/* + * This file defines volume titles for .Dt. + * + * Be sure to escape strings. + */ + +LINE("USD", "User\'s Supplementary Documents") +LINE("PS1", "Programmer\'s Supplementary Documents") +LINE("AMD", "Ancestral Manual Documents") +LINE("SMM", "System Manager\'s Manual") +LINE("URM", "User\'s Reference Manual") +LINE("PRM", "Programmer\'s Manual") +LINE("KM", "Kernel Manual") +LINE("IND", "Manual Master Index") +LINE("MMI", "Manual Master Index") +LINE("LOCAL", "Local Manual") +LINE("LOC", "Local Manual") +LINE("CON", "Contributed Software Manual") @@ -28,12 +28,6 @@ * usage throughout this codebase. */ -#ifdef __linux__ -extern size_t strlcat(char *, const char *, size_t); -extern size_t strlcpy(char *, const char *, size_t); -#endif - - int xstrcmp(const char *p1, const char *p2) { @@ -105,81 +99,3 @@ xstrlcpys(char *buf, const struct mdoc_node *n, size_t sz) return(1); } - -#ifdef __linux__ -/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * - * 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 <sys/types.h> -#include <string.h> - - -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - -size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} -#endif |