diff options
-rw-r--r-- | Makefile | 134 | ||||
-rw-r--r-- | ascii.in | 48 | ||||
-rw-r--r-- | mdoc.7 | 124 | ||||
-rw-r--r-- | mdoc.c | 33 | ||||
-rw-r--r-- | mdoc.h | 4 | ||||
-rw-r--r-- | mdocterm.1 | 69 | ||||
-rw-r--r-- | mdocterm.c | 550 | ||||
-rw-r--r-- | mmain.c | 75 | ||||
-rw-r--r-- | term.h | 20 |
9 files changed, 628 insertions, 429 deletions
@@ -1,78 +1,47 @@ .SUFFIXES: .html .sgml -VERSION = 1.5.3 -VDATE = 17 March 2009 - BINDIR = $(PREFIX)/bin INCLUDEDIR = $(PREFIX)/include LIBDIR = $(PREFIX)/lib MANDIR = $(PREFIX)/man - INSTALL_PROGRAM = install -m 0755 INSTALL_DATA = install -m 0444 INSTALL_LIB = install -m 0644 INSTALL_MAN = $(INSTALL_DATA) -VFLAGS = -DVERSION=\"$(VERSION)\" -CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -g +VERSION = 1.5.5 +VDATE = 19 March 2009 +VFLAGS = -DVERSION=\"$(VERSION)\" +CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -g LINTFLAGS += $(VFLAGS) CFLAGS += $(VFLAGS) - -LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \ - validate.ln action.ln lib.ln att.ln arch.ln vol.ln \ - msec.ln st.ln - -TREELNS = mdoctree.ln mmain.ln - -TERMLNS = mdoctree.ln mmain.ln term.ln ascii.ln - -LINTLNS = mdoclint.ln mmain.ln - -LNS = $(LIBLNS) $(TREELNS) $(TERMLNS) - -LLNS = llib-llibmdoc.ln llib-lmdoctree.ln llib-lmdocterm.ln - -LIBS = libmdoc.a - -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 ascii.o - -TREEOBJS= mdoctree.o mmain.o - -LINTOBJS= mdoclint.o mmain.o - -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 \ - lib.c att.c arch.c vol.c msec.c st.c ascii.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 - -SGMLS = index.sgml - -HTMLS = index.html - -STATICS = style.css external.png - -TARGZS = mdocml-$(VERSION).tar.gz mdocml-oport-$(VERSION).tar.gz \ - mdocml-nport-$(VERSION).tar.gz - -MANS = mdoctree.1 mdocterm.1 mdoclint.1 mdoc.3 mdoc.7 - -BINS = mdocterm mdoctree mdoclint - -CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS) \ - $(TARGZS) - -INSTALL = $(SRCS) $(HEADS) Makefile DESCR $(MANS) $(SGMLS) \ - $(STATICS) Makefile.netbsd Makefile.openbsd $(DATAS) +LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \ + validate.ln action.ln lib.ln att.ln arch.ln vol.ln \ + msec.ln st.ln +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 +TERMLNS = mdocterm.ln term.ln ascii.ln +TERMOBJS = mdocterm.o term.o ascii.o +LLNS = llib-llibmdoc.ln llib-lmdocterm.ln +LNS = $(TERMLNS) $(LIBLNS) +LIBS = libmdoc.a +OBJS = $(LIBOBJS) $(TERMOBJS) +SRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \ + action.c term.c mdocterm.c lib.c att.c arch.c vol.c \ + msec.c st.c ascii.c +DATAS = arch.in att.in lib.in msec.in st.in vol.in ascii.in +HEADS = mdoc.h private.h term.h +SGMLS = index.sgml +HTMLS = index.html +STATICS = style.css external.png +TARGZS = mdocml-$(VERSION).tar.gz mdocml-oport-$(VERSION).tar.gz \ + mdocml-nport-$(VERSION).tar.gz +MANS = mdocterm.1 mdoc.3 mdoc.7 +BINS = mdocterm +CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS) $(TARGZS) +INSTALL = $(SRCS) $(HEADS) Makefile DESCR $(MANS) $(SGMLS) \ + $(STATICS) Makefile.netbsd Makefile.openbsd $(DATAS) all: $(BINS) @@ -105,24 +74,19 @@ install: mkdir -p $(LIBDIR)/lib mkdir -p $(MANDIR)/man1 mkdir -p $(MANDIR)/man3 + mkdir -p $(MANDIR)/man7 $(INSTALL_PROGRAM) mdocterm $(BINDIR) - $(INSTALL_PROGRAM) mdoctree $(BINDIR) - $(INSTALL_PROGRAM) mdoclint $(BINDIR) $(INSTALL_MAN) mdocterm.1 $(MANDIR)/man1 - $(INSTALL_MAN) mdoctree.1 $(MANDIR)/man1 - $(INSTALL_MAN) mdoclint.1 $(MANDIR)/man1 $(INSTALL_MAN) mdoc.3 $(MANDIR)/man3 + $(INSTALL_MAN) mdoc.7 $(MANDIR)/man7 $(INSTALL_LIB) libmdoc.a $(LIBDIR) $(INSTALL_DATA) mdoc.h $(INCLUDEDIR) uninstall: rm -f $(BINDIR)/mdocterm - rm -f $(BINDIR)/mdoctree - rm -f $(BINDIR)/mdoclint rm -f $(MANDIR)/man1/mdocterm.1 - rm -f $(MANDIR)/man1/mdoctree.1 - rm -f $(MANDIR)/man1/mdoclint.1 rm -f $(MANDIR)/man3/mdoc.3 + rm -f $(MANDIR)/man7/mdoc.7 rm -f $(LIBDIR)/libmdoc.a rm -f $(INCLUDEDIR)/mdoc.h @@ -162,14 +126,8 @@ hash.o: hash.c private.h mdoc.ln: mdoc.c private.h mdoc.o: mdoc.c private.h -mdocterm.ln: mdocterm.c mmain.h -mdocterm.o: mdocterm.c mmain.h - -mdoclint.ln: mdoclint.c mmain.h -mdoclint.o: mdoclint.c mmain.h - -mdoctree.ln: mdoctree.c mmain.h -mdoctree.o: mdoctree.c mmain.h +mdocterm.ln: mdocterm.c +mdocterm.o: mdocterm.c xstd.ln: xstd.c private.h xstd.o: xstd.c private.h @@ -183,13 +141,8 @@ validate.o: validate.c private.h action.ln: action.c private.h action.o: action.c private.h -mmain.ln: mmain.c mmain.h -mmain.o: mmain.c mmain.h - private.h: mdoc.h -mmain.h: mdoc.h - term.h: mdoc.h mdocml-nport-$(VERSION).tar.gz: mdocml-$(VERSION).tar.gz Makefile.netbsd DESCR @@ -202,13 +155,9 @@ mdocml-nport-$(VERSION).tar.gz: mdocml-$(VERSION).tar.gz Makefile.netbsd DESCR install -m 0644 DESCR .dist/mdocml/ echo @comment $$NetBSD$$ > .dist/mdocml/PLIST echo bin/mdocterm >> .dist/mdocml/PLIST - echo bin/mdoctree >> .dist/mdocml/PLIST - echo bin/mdoclint >> .dist/mdocml/PLIST echo lib/libmdoc.a >> .dist/mdocml/PLIST echo include/mdoc.h >> .dist/mdocml/PLIST - echo man/man1/mdoctree.1 >> .dist/mdocml/PLIST echo man/man1/mdocterm.1 >> .dist/mdocml/PLIST - echo man/man1/mdoclint.1 >> .dist/mdocml/PLIST echo man/man3/mdoc.3 >> .dist/mdocml/PLIST ( cd .dist/ && tar zcf ../$@ mdocml/ ) rm -rf .dist/ @@ -223,13 +172,9 @@ mdocml-oport-$(VERSION).tar.gz: mdocml-$(VERSION).tar.gz Makefile.openbsd DESCR install -m 0644 DESCR .dist/mdocml/pkg/DESCR echo @comment $$OpenBSD$$ > .dist/mdocml/pkg/PLIST echo bin/mdocterm >> .dist/mdocml/pkg/PLIST - echo bin/mdoctree >> .dist/mdocml/pkg/PLIST - echo bin/mdoclint >> .dist/mdocml/pkg/PLIST echo lib/libmdoc.a >> .dist/mdocml/pkg/PLIST echo include/mdoc.h >> .dist/mdocml/pkg/PLIST - echo @man man/man1/mdoctree.1 >> .dist/mdocml/pkg/PLIST echo @man man/man1/mdocterm.1 >> .dist/mdocml/pkg/PLIST - echo @man man/man1/mdoclint.1 >> .dist/mdocml/pkg/PLIST echo @man man/man3/mdoc.3 >> .dist/mdocml/pkg/PLIST ( cd .dist/ && tar zcf ../$@ mdocml/ ) rm -rf .dist/ @@ -243,9 +188,6 @@ mdocml-$(VERSION).tar.gz: $(INSTALL) llib-llibmdoc.ln: $(LIBLNS) $(LINT) $(LINTFLAGS) -Clibmdoc $(LIBLNS) -llib-lmdoctree.ln: $(TREELNS) llib-llibmdoc.ln - $(LINT) $(LINTFLAGS) -Cmdoctree $(TREELNS) llib-llibmdoc.ln - llib-lmdocterm.ln: $(TERMLNS) llib-llibmdoc.ln $(LINT) $(LINTFLAGS) -Cmdocterm $(TERMLNS) llib-llibmdoc.ln @@ -255,12 +197,6 @@ libmdoc.a: $(LIBOBJS) mdocterm: $(TERMOBJS) libmdoc.a $(CC) $(CFLAGS) -o $@ $(TERMOBJS) libmdoc.a -mdoctree: $(TREEOBJS) libmdoc.a - $(CC) $(CFLAGS) -o $@ $(TREEOBJS) libmdoc.a - -mdoclint: $(LINTOBJS) libmdoc.a - $(CC) $(CFLAGS) -o $@ $(LINTOBJS) libmdoc.a - .sgml.html: validate $< sed -e "s!@VERSION@!$(VERSION)!" -e "s!@VDATE@!$(VDATE)!" $< > $@ @@ -82,14 +82,17 @@ LINE("ga", 2, "`", 1) LINE("en", 2, "-", 1) LINE("em", 2, "--", 2) LINE("Pi", 2, "pi", 2) -LINE("<<", 2, "<<", 2) -LINE(">>", 2, ">>", 2) +LINE("Fo", 2, "<<", 2) +LINE("Fc", 2, ">>", 2) +LINE("fo", 2, "<", 1) +LINE("fc", 2, ">", 1) 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("ss", 2, "B", 1) LINE("\'A", 2, "A", 1) LINE("\'E", 2, "E", 1) LINE("\'I", 2, "I", 1) @@ -132,3 +135,44 @@ LINE(":i", 2, "i", 1) LINE(":o", 2, "o", 1) LINE(":u", 2, "u", 1) LINE(":y", 2, "y", 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("-D", 2, "D", 1) +LINE("Sd", 2, "o", 1) +LINE("TP", 2, "b", 1) +LINE("Tp", 2, "b", 1) +LINE(",C", 2, "C", 1) +LINE(",c", 2, "c", 1) +LINE("/L", 2, "L", 1) +LINE("/l", 2, "l", 1) +LINE("/O", 2, "O", 1) +LINE("/o", 2, "o", 1) +LINE("oA", 2, "A", 1) +LINE("oa", 2, "a", 1) +LINE("a^", 2, "^", 1) +LINE("ac", 2, ",", 1) +LINE("ad", 2, "\"", 1) +LINE("ah", 2, "v", 1) +LINE("ao", 2, "o", 1) +LINE("ho", 2, ",", 1) +LINE("ab", 2, "`", 1) +LINE("a-", 2, "-", 1) +LINE("Cs", 2, "x", 1) +LINE("Do", 2, "$", 1) +LINE("Po", 2, "L", 1) +LINE("Ye", 2, "Y", 1) +LINE("Fn", 2, "f", 1) +LINE("ct", 2, "c", 1) +LINE("ff", 2, "ff", 2) +LINE("fi", 2, "fi", 2) +LINE("fl", 2, "fl", 2) +LINE("Fi", 2, "ffi", 3) +LINE("Fl", 2, "ffl", 3) @@ -127,9 +127,15 @@ Enclosures: .It \\(rh .Pq right hand .It \\(<< -.Pq left guillemot -.It \\(>> -.Pq right guillemot +.Pq left guillemet +.It \\(Fc +.Pq right guillemet +.It \\(Fo +.Pq left guilsing +.It \\(fc +.Pq right guilsing +.It \\(fo +.Pq right guilsing .It \\(rC .Pq right brace .It \\(lC @@ -221,16 +227,10 @@ Mathematical: .El .\" PARAGRAPH .Pp -Diacritics and letter combinations: +Ligatures: .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 \\(ss +.Pq German eszett .It \\(AE .Pq upper-case AE .It \\(ae @@ -239,6 +239,53 @@ Diacritics and letter combinations: .Pq upper-case OE .It \\(oe .Pq lower-case OE +.It \\(ff +.Pq ff ligature +.It \\(fi +.Pq fi ligature +.It \\(fl +.Pq fl ligature +.It \\(Fi +.Pq ffi ligature +.It \\(Fl +.Pq ffl ligature +.El +.\" PARAGRAPH +.Pp +Diacritics and letters: +.Bl -tag -width 12n -offset "XXXX" -compact +.It \\(ga +.Pq grave accent +.It \\(aa +.Pq accute accent +.It \\(ad +.Pq dieresis accent +.It \\(a~ +.Pq tilde accent +.It \\(a^ +.Pq circumflex accent +.It \\(ac +.Pq cedilla accent +.It \\(ad +.Pq dieresis accent +.It \\(ah +.Pq caron accent +.It \\(ao +.Pq ring accent +.It \\(ho +.Pq hook accent +.It \\(ab +.Pq breve accent +.It \\(a- +.Pq macron accent +.It \\(-D +.Pq upper-case eth +.It \\(Sd +.Pq lower-case eth +.It \\(TP +.Pq upper-case thorn +.It \\(Tp +.Pq lower-case thorn .It \\('A .Pq upper-case acute A .It \\('E @@ -313,6 +360,59 @@ Diacritics and letter combinations: .Pq lower-case dieresis u .It \\(:y .Pq lower-case dieresis y +.It \\(^A +.Pq upper-case circumflex A +.It \\(^E +.Pq upper-case circumflex E +.It \\(^I +.Pq upper-case circumflex I +.It \\(^O +.Pq upper-case circumflex O +.It \\(^U +.Pq upper-case circumflex U +.It \\(^a +.Pq lower-case circumflex a +.It \\(^e +.Pq lower-case circumflex e +.It \\(^i +.Pq lower-case circumflex i +.It \\(^o +.Pq lower-case circumflex o +.It \\(^u +.Pq lower-case circumflex u +.It \\(,C +.Pq upper-case cedilla C +.It \\(,c +.Pq lower-case cedilla c +.It \\(/L +.Pq upper-case stroke L +.It \\(/l +.Pq lower-case stroke l +.It \\(/O +.Pq upper-case stroke O +.It \\(/o +.Pq lower-case stroke o +.It \\(oA +.Pq upper-case ring A +.It \\(oa +.Pq lower-case ring a +.El +.\" PARAGRAPH +.Pp +Monetary: +.Bl -tag -width 12n -offset "XXXX" -compact +.It \\(Cs +.Pq Scandinavian +.It \\(Do +.Pq dollar +.It \\(Po +.Pq pound +.It \\(Ye +.Pq yen +.It \\(Fn +.Pq florin +.It \\(ct +.Pq cent .El .\" PARAGRAPH .Pp @@ -111,6 +111,34 @@ mdoc_meta(const struct mdoc *mdoc) void +mdoc_reset(struct mdoc *mdoc) +{ + + if (mdoc->first) + mdoc_node_freelist(mdoc->first); + if (mdoc->meta.title) + free(mdoc->meta.title); + if (mdoc->meta.os) + free(mdoc->meta.os); + if (mdoc->meta.name) + free(mdoc->meta.name); + if (mdoc->meta.arch) + free(mdoc->meta.arch); + if (mdoc->meta.vol) + free(mdoc->meta.vol); + + bzero(&mdoc->meta, sizeof(struct mdoc_meta)); + mdoc->flags = 0; + mdoc->lastnamed = mdoc->lastsec = 0; + + mdoc->first = mdoc->last = + xcalloc(1, sizeof(struct mdoc_node)); + mdoc->last->type = MDOC_ROOT; + mdoc->next = MDOC_NEXT_CHILD; +} + + +void mdoc_free(struct mdoc *mdoc) { @@ -144,13 +172,12 @@ mdoc_alloc(void *data, int pflags, const struct mdoc_cb *cb) if (cb) (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb)); - p->last = xcalloc(1, sizeof(struct mdoc_node)); + p->last = p->first = + xcalloc(1, sizeof(struct mdoc_node)); p->last->type = MDOC_ROOT; - p->first = p->last; p->pflags = pflags; p->next = MDOC_NEXT_CHILD; p->htab = mdoc_tokhash_alloc(); - return(p); } @@ -300,8 +300,8 @@ void mdoc_free(struct mdoc *); /* Allocate a new parser instance. */ struct mdoc *mdoc_alloc(void *, int, const struct mdoc_cb *); -/* Set parse options. */ -void mdoc_setflags(struct mdoc *, int); +/* Gets system ready for another parse. */ +void mdoc_reset(struct mdoc *); /* Parse a single line in a stream (boolean retval). */ int mdoc_parseln(struct mdoc *, int, char *buf); @@ -26,19 +26,10 @@ .\" SECTION .Sh SYNOPSIS .Nm mdocterm -.Op Fl vV +.Op Fl V .Op Fl f Ns Ar option... -.Op Fl O Ns Ar option... .Op Fl W Ns Ar err... -.Op Ar infile -.Nm mdocterm -.Op Fl hi -.Op Fl m Ns Ar name -.Op Fl n Ns Ar num -.Op Fl o Ns Ar list -.Op Fl r Ns Ar cn -.Op Fl T Ns Ar name -.Op Ar infile +.Op Ar infile... .\" SECTION .Sh DESCRIPTION The @@ -48,10 +39,7 @@ utility formats a BSD manual page for display on the terminal. The arguments are as follows: .Bl -tag -width XXXXXXXXXXXX .\" ITEM -.It Fl v -Print verbose parsing output. -.\" ITEM -.It Fl v +.It Fl V Print version and exit. .\" ITEM .It Fl f Ns Ar option... @@ -59,11 +47,6 @@ Override default compiler behaviour. See .Sx Compiler Options for details. .\" ITEM -.It Fl O Ns Ar option... -Front-end options. See -.Sx Front-end Options -for details. -.\" ITEM .It Fl W Ns Ar err... Print warning messages. May be set to .Fl W Ns Ar all @@ -79,24 +62,13 @@ termination. Multiple arguments may be comma-separated, such as .Fl W Ns Ar error,all . .\" ITEM -.It Ar infile -Read input from -.Ar infile , -which may be -.Dq \- -for stdin. +.It Ar infile... +Read input from zero or more +.Ar infile . +If unspecified, reads from stdin. .El .\" PARAGRAPH .Pp -If -.Xr nroff 1 -arguments are supplied on the command line -.Pq Fl himnorT , -these are ignored unless -.Xr nroff 1 -is invoked on parse failure. -.\" PARAGRAPH -.Pp The .Nm utility is a formatting front-end for @@ -115,32 +87,11 @@ By default, reads from stdin and prints nroff .Qq backspace terminal-encoded output to stdout, at this time to a fixed column with -of 78 characters. If -.Ar infile -can't be parsed (isn't valid mdoc, doesn't contain valid syntax, etc.), -.Xr nroff 1 -is invoked. If no -.Xr nroff 1 -command-line argumnets aren't provided, -.Fl m Ns Ar andoc -is implied. +of 78 characters. .\" PARAGRAPH .Pp .Ex -std mdocterm .\" SUB-SECTION -.Ss Front-end Options -The default behaviour may be overriden with the -.Fl O -flag. The available options are as follows: -.Bl -tag -width XXXXXXXXXXXX -offset XXXX -.It Fl O Ns Ar nopunt -Don't punt to -.Xr nroff 1 -if -.Ar infile -may not be parsed. -.El -.\" SUB-SECTION .Ss Compiler Options Default compiler behaviour may be overriden with the .Fl f @@ -160,8 +111,6 @@ As with the .Fl W flag, multiple .Fl f -and -.Fl O options may be grouped and delimited with a comma. Using .Fl f Ns Ar ign-scope,ign-escape , for example, will try to ignore scope and character-escape errors. @@ -194,8 +143,6 @@ To pipe a manual page to the pager: .D1 % mdocterm mdocterm.1 | less .\" SECTION .Sh SEE ALSO -.Xr mdoctree 1 , -.Xr mdoclint 1 , .Xr mdoc 7 , .Xr mdoc 3 .\" @@ -17,45 +17,57 @@ * PERFORMANCE OF THIS SOFTWARE. */ #include <sys/types.h> +#include <sys/stat.h> #include <assert.h> -#include <ctype.h> #include <err.h> +#include <fcntl.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "mmain.h" #include "term.h" -struct nroffopt { - int fl_h; - int fl_i; - char *arg_m; - char *arg_n; - char *arg_o; - char *arg_r; - char *arg_T; - struct termp *termp; /* Ephemeral. */ +#define WARN_WALL 0x03 /* All-warnings mask. */ +#define WARN_WCOMPAT (1 << 0) /* Compatibility warnings. */ +#define WARN_WSYNTAX (1 << 1) /* Syntax warnings. */ +#define WARN_WERR (1 << 2) /* Warnings->errors. */ + +enum termt { + TERMT_ASCII, + TERMT_LINT, + TERMT_TREE }; -__dead void punt(struct nroffopt *, char *); -static int option(void *, int, char *); -static int optsopt(struct termp *, char *); -static void body(struct termp *, - struct termpair *, +extern char *__progname; + +__dead static void version(void); +__dead static void usage(void); +#if 0 +__dead static void punt(struct cmdargs *, char **); +#endif +static int foptions(int *, char *); +static int toptions(enum termt *, char *); +static int woptions(int *, char *); +static int merr(void *, int, int, const char *); +static int mwarn(void *, int, int, + enum mdoc_warn, const char *); +static void body(struct termp *, struct termpair *, const struct mdoc_meta *, const struct mdoc_node *); static void header(struct termp *, const struct mdoc_meta *); static void footer(struct termp *, const struct mdoc_meta *); - -static void pword(struct termp *, const char *, size_t); -static void pescape(struct termp *, const char *, - size_t *, size_t); +static int file(char **, size_t *, char **, size_t *, + const char *, struct mdoc *); +static int fdesc(char **, size_t *, char **, size_t *, + const char *, int, struct mdoc *); +static void pword(struct termp *, const char *, int); +static void pescape(struct termp *, + const char *, int *, int); static void nescape(struct termp *, const char *, size_t); static void chara(struct termp *, char); @@ -63,76 +75,267 @@ static void stringa(struct termp *, const char *, size_t); static void sanity(const struct mdoc_node *); + int main(int argc, char *argv[]) { - struct mmain *p; - const struct mdoc *mdoc; - struct nroffopt nroff; - struct termp termp; - int c; - char *in; - - (void)memset(&termp, 0, sizeof(struct termp)); - (void)memset(&nroff, 0, sizeof(struct nroffopt)); - - termp.maxrmargin = termp.rmargin = 78; /* FIXME */ - termp.maxcols = 1024; /* FIXME */ - termp.flags = TERMP_NOSPACE; - termp.symtab = ascii2htab(); - - nroff.termp = &termp; - - p = mmain_alloc(); - - c = mmain_getopt(p, argc, argv, "[-Ooption...]", - "[infile]", "him:n:o:r:T:O:", &nroff, option); - - /* FIXME: this needs to accept multiple outputs. */ - argv += c; - if ((argc -= c) > 0) - in = *argv++; - else - in = "-"; - - mmain_prepare(p, in); - - if (NULL == (mdoc = mmain_process(p))) { - if (TERMP_NOPUNT & termp.iflags) - mmain_exit(p, 1); - mmain_free(p); - punt(&nroff, in); - /* NOTREACHED */ + struct termp termp; + int c, fflags, wflags; + struct mdoc_cb cb; + struct mdoc *mdoc; + char *buf, *line; + size_t bufsz, linesz; + enum termt termt; + + bzero(&termp, sizeof(struct termp)); + bzero(&cb, sizeof(struct mdoc_cb)); + + termt = TERMT_ASCII; + fflags = wflags = 0; + + /* LINTED */ + while (-1 != (c = getopt(argc, argv, "f:VW:T:"))) + switch (c) { + case ('f'): + if ( ! foptions(&fflags, optarg)) + return(0); + break; + case ('T'): + if ( ! toptions(&termt, optarg)) + return(0); + break; + case ('W'): + if ( ! woptions(&wflags, optarg)) + return(0); + break; + case ('V'): + version(); + /* NOTREACHED */ + default: + usage(); + /* NOTREACHED */ + } + + argc -= optind; + argv += optind; + + termp.maxrmargin = 78; /* FIXME */ + + cb.mdoc_err = merr; + cb.mdoc_warn = mwarn; + + /* Line and block buffers persist between parses. */ + + buf = line = NULL; + bufsz = linesz = 0; + + /* Overall mdoc persists between parses. */ + + mdoc = mdoc_alloc(&wflags, fflags, &cb); + + while (*argv) { + if ( ! file(&line, &linesz, &buf, &bufsz, *argv, mdoc)) + break; + + switch (termt) { + case (TERMT_ASCII): + if (NULL == termp.symtab) + termp.symtab = ascii2htab(); + header(&termp, mdoc_meta(mdoc)); + body(&termp, NULL, mdoc_meta(mdoc), + mdoc_node(mdoc)); + footer(&termp, mdoc_meta(mdoc)); + break; + default: + break; + } + + mdoc_reset(mdoc); + argv++; } - if (NULL == (termp.buf = malloc(termp.maxcols))) - err(1, "malloc"); + if (buf) + free(buf); + if (line) + free(line); + if (termp.buf) + free(termp.buf); + if (termp.symtab) + asciifree(termp.symtab); - header(&termp, mdoc_meta(mdoc)); - body(&termp, NULL, mdoc_meta(mdoc), mdoc_node(mdoc)); - footer(&termp, mdoc_meta(mdoc)); + mdoc_free(mdoc); + + return(0); +} - free(termp.buf); - asciifree(termp.symtab); - mmain_exit(p, 0); +__dead static void +version(void) +{ + + (void)printf("%s %s\n", __progname, VERSION); + exit(0); + /* NOTREACHED */ +} + + +__dead static void +usage(void) +{ + + (void)fprintf(stderr, "usage: %s\n", __progname); + exit(1); /* NOTREACHED */ } static int -optsopt(struct termp *p, char *arg) +file(char **ln, size_t *lnsz, char **buf, size_t *bufsz, + const char *file, struct mdoc *mdoc) +{ + int fd, c; + + if (-1 == (fd = open(file, O_RDONLY, 0))) { + warn("%s", file); + return(0); + } + + c = fdesc(ln, lnsz, buf, bufsz, file, fd, mdoc); + + if (-1 == close(fd)) + warn("%s", file); + + return(c); +} + + +static int +fdesc(char **lnp, size_t *lnsz, char **bufp, size_t *bufsz, + const char *f, int fd, struct mdoc *mdoc) +{ + size_t sz; + ssize_t ssz; + struct stat st; + int j, i, pos, lnn; + char *ln, *buf; + + buf = *bufp; + ln = *lnp; + + /* + * Two buffers: ln and buf. buf is the input buffer, optimised + * for each file's block size. ln is a line buffer. Both + * growable, hence passed in by ptr-ptr. + */ + + if (-1 == fstat(fd, &st)) { + warnx("%s", f); + sz = BUFSIZ; + } else + sz = (unsigned)BUFSIZ > st.st_blksize ? + (size_t)BUFSIZ : st.st_blksize; + + if (sz > *bufsz) { + if (NULL == (buf = realloc(buf, sz))) + err(1, "realloc"); + *bufp = buf; + *bufsz = sz; + } + + /* + * Fill buf with file blocksize and parse newlines into ln. + */ + + for (lnn = 1, pos = 0; ; ) { + if (-1 == (ssz = read(fd, buf, sz))) { + warn("%s", f); + return(0); + } else if (0 == ssz) + break; + + for (i = 0; i < (int)ssz; i++) { + if (pos >= (int)*lnsz) { + *lnsz += 256; /* Step-size. */ + ln = realloc(ln, *lnsz); + if (NULL == ln) + err(1, "realloc"); + *lnp = ln; + } + + if ('\n' != buf[i]) { + ln[pos++] = buf[i]; + continue; + } + + /* Check for CPP-escaped newline. */ + + if (pos > 0 && '\\' == ln[pos - 1]) { + for (j = pos - 1; j >= 0; j--) + if ('\\' != ln[j]) + break; + + if ( ! ((pos - j) % 2)) { + pos--; + lnn++; + continue; + } + } + + ln[pos] = 0; + if ( ! mdoc_parseln(mdoc, lnn, ln)) + return(0); + lnn++; + pos = 0; + } + } + + return(mdoc_endparse(mdoc)); +} + + +static int +toptions(enum termt *tflags, char *arg) +{ + + if (0 == strcmp(arg, "ascii")) + *tflags = TERMT_ASCII; + else if (0 == strcmp(arg, "lint")) + *tflags = TERMT_LINT; + else if (0 == strcmp(arg, "tree")) + *tflags = TERMT_TREE; + else { + warnx("bad argument: -T%s", arg); + return(0); + } + + return(1); +} + + +/* + * Parse out the options for [-fopt...] setting compiler options. These + * can be comma-delimited or called again. + */ +static int +foptions(int *fflags, char *arg) { char *v; - char *toks[] = { "nopunt", NULL }; + char *toks[] = { "ign-scope", "ign-escape", + "ign-macro", NULL }; while (*arg) switch (getsubopt(&arg, toks, &v)) { case (0): - p->iflags |= TERMP_NOPUNT; + *fflags |= MDOC_IGN_SCOPE; + break; + case (1): + *fflags |= MDOC_IGN_ESCAPE; + break; + case (2): + *fflags |= MDOC_IGN_MACRO; break; default: - warnx("unknown -O argument"); + warnx("bad argument: -f%s", arg); return(0); } @@ -140,42 +343,36 @@ optsopt(struct termp *p, char *arg) } +/* + * Parse out the options for [-Werr...], which sets warning modes. + * These can be comma-delimited or called again. XXX - should this be + * using -w like troff? + */ static int -option(void *ptr, int c, char *arg) +woptions(int *wflags, char *arg) { - struct termp *termp; - struct nroffopt *nroff; - - nroff = (struct nroffopt *)ptr; - termp = nroff->termp; + char *v; + char *toks[] = { "all", "compat", + "syntax", "error", NULL }; - switch (c) { - case ('h'): - nroff->fl_h = 1; - break; - case ('i'): - nroff->fl_i = 1; - break; - case ('m'): - nroff->arg_m = arg; - break; - case ('n'): - nroff->arg_n = arg; - break; - case ('o'): - nroff->arg_o = arg; - break; - case ('r'): - nroff->arg_r = arg; - break; - case ('T'): - nroff->arg_T = arg; - break; - case ('O'): - return(optsopt(termp, arg)); - default: - break; - } + while (*arg) + switch (getsubopt(&arg, toks, &v)) { + case (0): + *wflags |= WARN_WALL; + break; + case (1): + *wflags |= WARN_WCOMPAT; + break; + case (2): + *wflags |= WARN_WSYNTAX; + break; + case (3): + *wflags |= WARN_WERR; + break; + default: + warnx("bad argument: -W%s", arg); + return(0); + } return(1); } @@ -201,6 +398,8 @@ option(void *ptr, int c, char *arg) * columns. In short: don't print a newline and instead pad to the * right margin. Used in conjunction with TERMP_NOLPAD. * + * - TERMP_NONOBREAK: don't newline when TERMP_NOBREAK is specified. + * * In-line line breaking: * * If TERMP_NOBREAK is specified and the line overruns the right @@ -216,7 +415,8 @@ option(void *ptr, int c, char *arg) void flushln(struct termp *p) { - size_t i, j, vsz, vis, maxvis, mmax, bp; + int i, j; + size_t vsz, vis, maxvis, mmax, bp; /* * First, establish the maximum columns of "visible" content. @@ -239,10 +439,10 @@ flushln(struct termp *p) if ( ! (p->flags & TERMP_NOLPAD)) /* LINTED */ - for (j = 0; j < p->offset; j++) + for (j = 0; j < (int)p->offset; j++) putchar(' '); - for (i = 0; i < p->col; i++) { + for (i = 0; i < (int)p->col; i++) { /* * Count up visible word characters. Control sequences * (starting with the CSI) aren't counted. A space @@ -251,7 +451,7 @@ flushln(struct termp *p) */ /* LINTED */ - for (j = i, vsz = 0; j < p->col; j++) { + for (j = i, vsz = 0; j < (int)p->col; j++) { if (' ' == p->buf[j]) break; else if (8 == p->buf[j]) @@ -271,7 +471,7 @@ flushln(struct termp *p) if ( ! (TERMP_NOBREAK & p->flags)) { if (vis && vis + vsz > bp) { putchar('\n'); - for (j = 0; j < p->offset; j++) + for (j = 0; j < (int)p->offset; j++) putchar(' '); vis = 0; } else if (vis + vsz > bp) @@ -282,7 +482,7 @@ flushln(struct termp *p) } else { if (vis && vis + vsz > bp) { putchar('\n'); - for (j = 0; j < p->rmargin; j++) + for (j = 0; j < (int)p->rmargin; j++) putchar(' '); vis = p->rmargin - p->offset; } else if (vis + vsz > bp) @@ -297,13 +497,13 @@ flushln(struct termp *p) * our breakpoint. */ - for ( ; i < p->col; i++) { + for ( ; i < (int)p->col; i++) { if (' ' == p->buf[i]) break; putchar(p->buf[i]); } vis += vsz; - if (i < p->col && vis <= bp) { + if (i < (int)p->col && vis <= bp) { putchar(' '); vis++; } @@ -317,7 +517,7 @@ flushln(struct termp *p) if ((TERMP_NOBREAK & p->flags) && vis >= maxvis) { if ( ! (TERMP_NONOBREAK & p->flags)) { putchar('\n'); - for (i = 0; i < p->rmargin; i++) + for (i = 0; i < (int)p->rmargin; i++) putchar(' '); } p->col = 0; @@ -383,14 +583,14 @@ vspace(struct termp *p) void word(struct termp *p, const char *word) { - size_t i, j, len; + int i, j, len; if (p->flags & TERMP_LITERAL) { - pword(p, word, strlen(word)); + pword(p, word, (int)strlen(word)); return; } - if (0 == (len = strlen(word))) + if (0 == (len = (int)strlen(word))) errx(1, "blank line not in literal context"); if (mdoc_isdelim(word)) { @@ -537,7 +737,7 @@ footer(struct termp *p, const struct mdoc_meta *meta) static void header(struct termp *p, const struct mdoc_meta *meta) { - char *buf, *title, *bufp; + char *buf, *title; p->rmargin = p->maxrmargin; p->offset = 0; @@ -572,9 +772,6 @@ header(struct termp *p, const struct mdoc_meta *meta) (void)snprintf(title, p->rmargin, "%s(%d)", meta->title, meta->msec); - for (bufp = title; *bufp; bufp++) - *bufp = toupper((u_char)*bufp); - p->offset = 0; p->rmargin = (p->maxrmargin - strlen(buf)) / 2; p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; @@ -617,11 +814,8 @@ nescape(struct termp *p, const char *word, size_t len) const char *rhs; size_t sz; - if (NULL == (rhs = a2ascii(p->symtab, word, len, &sz))) { - warnx("unsupported %zu-byte escape sequence", len); + if (NULL == (rhs = a2ascii(p->symtab, word, len, &sz))) return; - } - stringa(p, rhs, sz); } @@ -632,38 +826,33 @@ nescape(struct termp *p, const char *word, size_t len) * the escape sequence (we assert upon badly-formed escape sequences). */ static void -pescape(struct termp *p, const char *word, size_t *i, size_t len) +pescape(struct termp *p, const char *word, int *i, int len) { - size_t j; + int j; - if (++(*i) >= len) { - warnx("ignoring bad escape sequence"); + if (++(*i) >= len) return; - } if ('(' == word[*i]) { (*i)++; - if (*i + 1 >= len) { - warnx("ignoring bad escape sequence"); + if (*i + 1 >= len) return; - } + nescape(p, &word[*i], 2); (*i)++; return; } else if ('*' == word[*i]) { (*i)++; - if (*i >= len) { - warnx("ignoring bad escape sequence"); + if (*i >= len) return; - } + switch (word[*i]) { case ('('): (*i)++; - if (*i + 1 >= len) { - warnx("ignoring bad escape sequence"); + if (*i + 1 >= len) return; - } + nescape(p, &word[*i], 2); (*i)++; return; @@ -683,11 +872,10 @@ pescape(struct termp *p, const char *word, size_t *i, size_t len) for (j = 0; word[*i] && ']' != word[*i]; (*i)++, j++) /* Loop... */ ; - if (0 == word[*i]) { - warnx("ignoring bad escape sequence"); + if (0 == word[*i]) return; - } - nescape(p, &word[*i - j], j); + + nescape(p, &word[*i - j], (size_t)j); } @@ -697,9 +885,9 @@ pescape(struct termp *p, const char *word, size_t *i, size_t len) * handles word styling. */ static void -pword(struct termp *p, const char *word, size_t len) +pword(struct termp *p, const char *word, int len) { - size_t i; + int i; if ( ! (TERMP_NOSPACE & p->flags) && ! (TERMP_LITERAL & p->flags)) @@ -748,17 +936,18 @@ stringa(struct termp *p, const char *c, size_t sz) if (0 == sz) return; - s = sz > p->maxcols * 2 ? sz : p->maxcols * 2; - assert(c); if (p->col + sz >= p->maxcols) { + if (0 == p->maxcols) + p->maxcols = 256; + s = sz > p->maxcols * 2 ? sz : p->maxcols * 2; p->buf = realloc(p->buf, s); if (NULL == p->buf) err(1, "realloc"); p->maxcols = s; } - (void)memcpy(&p->buf[p->col], c, sz); + (void)memcpy(&p->buf[(int)p->col], c, sz); p->col += sz; } @@ -771,14 +960,18 @@ stringa(struct termp *p, const char *c, size_t sz) static void chara(struct termp *p, char c) { + size_t s; if (p->col + 1 >= p->maxcols) { - p->buf = realloc(p->buf, p->maxcols * 2); + if (0 == p->maxcols) + p->maxcols = 256; + s = p->maxcols * 2; + p->buf = realloc(p->buf, s); if (NULL == p->buf) - err(1, "malloc"); - p->maxcols *= 2; + err(1, "realloc"); + p->maxcols = s; } - p->buf[(p->col)++] = c; + p->buf[(int)(p->col)++] = c; } @@ -892,37 +1085,48 @@ sanity(const struct mdoc_node *n) } -__dead void -punt(struct nroffopt *nroff, char *in) +static int +merr(void *arg, int line, int col, const char *msg) { - char *args[32]; - char arg0[32], argm[32]; - int i; - warnx("punting to nroff!"); + warnx("error: %s (line %d, column %d)", msg, line, col); + return(0); +} + - i = 0; +static int +mwarn(void *arg, int line, int col, + enum mdoc_warn type, const char *msg) +{ + int flags; + char *wtype; - (void)strlcpy(arg0, "nroff", 32); - args[i++] = arg0; + flags = *(int *)arg; + wtype = NULL; - if (nroff->fl_h) - args[i++] = "-h"; - if (nroff->fl_i) - args[i++] = "-i"; + switch (type) { + case (WARN_COMPAT): + wtype = "compat"; + if (flags & WARN_WCOMPAT) + break; + return(1); + case (WARN_SYNTAX): + wtype = "syntax"; + if (flags & WARN_WSYNTAX) + break; + return(1); + } - if (nroff->arg_m) { - (void)strlcpy(argm, "-m", 32); - (void)strlcat(argm, nroff->arg_m, 32); - args[i++] = argm; - } else - args[i++] = "-mandoc"; + assert(wtype); + warnx("%s warning: %s (line %d, column %d)", + wtype, msg, line, col); - args[i++] = in; - args[i++] = (char *)NULL; + if ( ! (flags & WARN_WERR)) + return(1); - (void)execvp("nroff", args); - errx(1, "exec"); - /* NOTREACHED */ + warnx("%s: considering warnings as errors", + __progname); + return(0); } + @@ -183,26 +183,25 @@ mmain_prepare(struct mmain *p, const char *in) { struct stat st; - p->in = in; - p->fdin = STDIN_FILENO; - - if (0 != strcmp(p->in, "-")) + if ((p->in = in)) { if (-1 == (p->fdin = open(p->in, O_RDONLY, 0))) { warn("%s", p->in); mmain_exit(p, 1); } - - /* Allocate a buffer to be BUFSIZ/block size. */ + } else { + p->fdin = STDIN_FILENO; + p->in = "-"; + } if (-1 == fstat(p->fdin, &st)) { warn("%s", p->in); p->bufsz = BUFSIZ; } else - p->bufsz = (size_t)MAX(st.st_blksize, BUFSIZ); + p->bufsz = (unsigned)BUFSIZ > st.st_blksize ? + (size_t)BUFSIZ : st.st_blksize; - p->buf = malloc(p->bufsz); - if (NULL == p->buf) - err(1, "malloc"); + if (NULL == (p->buf = realloc(p->buf, p->bufsz))) + err(1, "realloc"); } @@ -359,59 +358,3 @@ parse(struct mmain *p) } -static int -msg_err(void *arg, int line, int col, const char *msg) -{ - struct mmain *p; - - p = (struct mmain *)arg; - - warnx("%s:%d: error: %s (column %d)", - p->in, line, msg, col); - return(0); -} - - -static void -msg_msg(void *arg, int line, int col, const char *msg) -{ - struct mmain *p; - - p = (struct mmain *)arg; - - if (0 == p->dbg) - return; - - warnx("%s:%d: debug: %s (column %d)", - p->in, line, msg, col); -} - - -static int -msg_warn(void *arg, int line, int col, - enum mdoc_warn type, const char *msg) -{ - struct mmain *p; - - p = (struct mmain *)arg; - - switch (type) { - case (WARN_COMPAT): - if (p->warn & MD_WARN_COMPAT) - break; - return(1); - case (WARN_SYNTAX): - if (p->warn & MD_WARN_SYNTAX) - break; - return(1); - } - - warnx("%s:%d: warning: %s (column %d)", - p->in, line, msg, col); - - if ( ! (p->warn & MD_WARN_ERR)) - return(1); - - warnx("%s: considering warnings as errors", __progname); - return(0); -} @@ -21,20 +21,18 @@ #include "mdoc.h" -/* XXX - clean up tabs. */ +/* FIXME - clean up tabs. */ #define INDENT 6 __BEGIN_DECLS struct termp { - size_t rmargin; - size_t maxrmargin; - size_t maxcols; - size_t offset; - size_t col; - int iflags; -#define TERMP_NOPUNT (1 << 0) + size_t rmargin; /* Current right margin. */ + size_t maxrmargin; /* Max right margin. */ + size_t maxcols; /* Max size of buf. */ + size_t offset; /* Margin offest. */ + size_t col; /* Bytes in buf. */ int flags; #define TERMP_NOSPACE (1 << 0) /* No space before words. */ #define TERMP_NOLPAD (1 << 1) /* No leftpad before flush. */ @@ -43,11 +41,11 @@ struct termp { #define TERMP_IGNDELIM (1 << 4) /* Delims like regulars. */ #define TERMP_NONOSPACE (1 << 5) /* No space (no autounset). */ #define TERMP_NONOBREAK (1 << 7) /* Don't newln NOBREAK. */ -#define TERMP_STYLE 0x0300 /* Style mask. */ +#define TERMP_STYLE 0x0300 /* Style mask. */ #define TERMP_BOLD (1 << 8) /* Styles... */ #define TERMP_UNDER (1 << 9) - char *buf; - void *symtab; + char *buf; /* Output buffer. */ + void *symtab; /* Encoded-symbol table. */ }; /* XXX - clean this up. */ |