Import mdocml-1.11.1
authorSascha Wildner <saw@online.de>
Sat, 9 Apr 2011 21:38:59 +0000 (23:38 +0200)
committerSascha Wildner <saw@online.de>
Sat, 9 Apr 2011 21:38:59 +0000 (23:38 +0200)
69 files changed:
contrib/mdocml/ChangeLog.xsl [deleted file]
contrib/mdocml/Makefile
contrib/mdocml/arch.c
contrib/mdocml/att.c
contrib/mdocml/chars.c
contrib/mdocml/chars.h [deleted file]
contrib/mdocml/chars.in
contrib/mdocml/eqn.7 [new file with mode: 0644]
contrib/mdocml/eqn.c [new file with mode: 0644]
contrib/mdocml/example.style.css
contrib/mdocml/html.c
contrib/mdocml/html.h
contrib/mdocml/index.sgml
contrib/mdocml/lib.c
contrib/mdocml/libman.h
contrib/mdocml/libmandoc.h
contrib/mdocml/libmdoc.h
contrib/mdocml/libroff.h
contrib/mdocml/main.c
contrib/mdocml/man.3 [deleted file]
contrib/mdocml/man.7
contrib/mdocml/man.c
contrib/mdocml/man.h
contrib/mdocml/man_argv.c [deleted file]
contrib/mdocml/man_hash.c
contrib/mdocml/man_html.c
contrib/mdocml/man_macro.c
contrib/mdocml/man_term.c
contrib/mdocml/man_validate.c
contrib/mdocml/mandoc-db.1 [new file with mode: 0644]
contrib/mdocml/mandoc-db.c [new file with mode: 0644]
contrib/mdocml/mandoc.1
contrib/mdocml/mandoc.3 [new file with mode: 0644]
contrib/mdocml/mandoc.c
contrib/mdocml/mandoc.h
contrib/mdocml/mandoc_char.7
contrib/mdocml/mdoc.3 [deleted file]
contrib/mdocml/mdoc.7
contrib/mdocml/mdoc.c
contrib/mdocml/mdoc.h
contrib/mdocml/mdoc_argv.c
contrib/mdocml/mdoc_hash.c
contrib/mdocml/mdoc_html.c
contrib/mdocml/mdoc_macro.c
contrib/mdocml/mdoc_strings.c [deleted file]
contrib/mdocml/mdoc_term.c
contrib/mdocml/mdoc_validate.c
contrib/mdocml/msec.c
contrib/mdocml/out.c
contrib/mdocml/out.h
contrib/mdocml/read.c [new file with mode: 0644]
contrib/mdocml/roff.3 [deleted file]
contrib/mdocml/roff.7
contrib/mdocml/roff.c
contrib/mdocml/roff.h [deleted file]
contrib/mdocml/st.c
contrib/mdocml/style.css
contrib/mdocml/tbl.7
contrib/mdocml/tbl.c
contrib/mdocml/tbl_data.c
contrib/mdocml/tbl_html.c
contrib/mdocml/tbl_layout.c
contrib/mdocml/tbl_opts.c
contrib/mdocml/tbl_term.c
contrib/mdocml/term.c
contrib/mdocml/term_ascii.c
contrib/mdocml/term_ps.c
contrib/mdocml/tree.c
contrib/mdocml/vol.c

diff --git a/contrib/mdocml/ChangeLog.xsl b/contrib/mdocml/ChangeLog.xsl
deleted file mode 100644 (file)
index dccc79d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version='1.0' encoding="utf-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
-<xsl:output encoding="utf-8" method="html" indent="yes" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
-<xsl:template match="/changelog">
-<html>
-       <head>
-               <title>mdocml - CVS-ChangeLog</title>
-               <link rel="stylesheet" href="index.css" type="text/css" media="all" />
-       </head>
-       <body>
-                               <xsl:for-each select="entry">
-                                       <div class="clhead">
-                                               <xsl:text>Files modified by </xsl:text>
-                                               <xsl:value-of select="concat(author, ': ', date, ' (', time, ')')" />
-                                       </div>
-                                       <div class="clbody">
-                                               <strong>
-                                                       <xsl:text>Note: </xsl:text>
-                                               </strong>
-                                               <xsl:value-of select="msg"/>
-                                               <ul class="clbody">
-                                                       <xsl:for-each select="file">
-                                                               <li>
-                                                                       <xsl:value-of select="name"/>
-                                                                       <span class="rev">
-                                                                               <xsl:text> &#8212; Rev: </xsl:text>
-                                                                               <xsl:value-of select="revision"/>
-                                                                               <xsl:text>, Status: </xsl:text>
-                                                                               <xsl:value-of select="cvsstate"/>
-                                                                               <xsl:if test="tag">
-                                                                                       <xsl:text>, Tag: </xsl:text>
-                                                                                       <xsl:value-of select="tag" />
-                                                                               </xsl:if>
-                                                                       </span>
-                                                               </li>
-                                                       </xsl:for-each>
-                                               </ul>
-                                       </div>
-                               </xsl:for-each>
-       </body>
-</html>
-</xsl:template>
-</xsl:stylesheet>
index 2361592..3cc7dae 100644 (file)
-.SUFFIXES:     .html .xml .sgml .1 .3 .7 .md5 .tar.gz 
-.SUFFIXES:     .1.txt .3.txt .7.txt
-.SUFFIXES:     .1.xhtml .3.xhtml .7.xhtml
-.SUFFIXES:     .1.sgml .3.sgml .7.sgml 
-.SUFFIXES:     .h .h.html 
-.SUFFIXES:     .1.ps .3.ps .7.ps
-.SUFFIXES:     .1.pdf .3.pdf .7.pdf
-
-PREFIX         = /usr/local
-BINDIR         = $(PREFIX)/bin
-INCLUDEDIR     = $(PREFIX)/include
-LIBDIR         = $(PREFIX)/lib
-MANDIR         = $(PREFIX)/man
-EXAMPLEDIR     = $(PREFIX)/share/examples/mandoc
-INSTALL                = install
-INSTALL_PROGRAM        = $(INSTALL) -m 0755
-INSTALL_DATA   = $(INSTALL) -m 0444
-INSTALL_LIB    = $(INSTALL) -m 0644
-INSTALL_MAN    = $(INSTALL_DATA)
-
-VERSION           = 1.10.9
-VDATE     = 07 January 2010
-
-VFLAGS    = -DVERSION="\"$(VERSION)\""
-WFLAGS     = -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
-CFLAGS    += -g $(WFLAGS) $(VFLAGS) -DHAVE_CONFIG_H
+.PHONY:         clean install installwww
+.SUFFIXES:      .sgml .html .md5 .h .h.html
+.SUFFIXES:      .1       .3       .7
+.SUFFIXES:      .1.txt   .3.txt   .7.txt
+.SUFFIXES:      .1.pdf   .3.pdf   .7.pdf
+.SUFFIXES:      .1.ps    .3.ps    .7.ps
+.SUFFIXES:      .1.html  .3.html  .7.html 
+.SUFFIXES:      .1.xhtml .3.xhtml .7.xhtml 
 
 # Specify this if you want to hard-code the operating system to appear
 # in the lower-left hand corner of -mdoc manuals.
 
 # Specify this if you want to hard-code the operating system to appear
 # in the lower-left hand corner of -mdoc manuals.
-# CFLAGS += -DOSNAME="\"OpenBSD 4.5\""
-
-LINTFLAGS += $(VFLAGS)
-
-ROFFLNS    = roff.ln tbl.ln tbl_opts.ln tbl_layout.ln tbl_data.ln
-
-ROFFSRCS   = roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c
-
-ROFFOBJS   = roff.o tbl.o tbl_opts.o tbl_layout.o tbl_data.o
-
-MANDOCLNS  = mandoc.ln
-
-MANDOCSRCS = mandoc.c
-
-MANDOCOBJS = mandoc.o
-
-MDOCLNS           = mdoc_macro.ln mdoc.ln mdoc_hash.ln mdoc_strings.ln \
-            mdoc_argv.ln mdoc_validate.ln \
-            lib.ln att.ln arch.ln vol.ln msec.ln st.ln
-
-MDOCOBJS   = mdoc_macro.o mdoc.o mdoc_hash.o mdoc_strings.o \
-            mdoc_argv.o mdoc_validate.o lib.o att.o \
-            arch.o vol.o msec.o st.o
-
-MDOCSRCS   = mdoc_macro.c mdoc.c mdoc_hash.c mdoc_strings.c \
-            mdoc_argv.c mdoc_validate.c lib.c att.c \
-            arch.c vol.c msec.c st.c
-
-MANLNS    = man_macro.ln man.ln man_hash.ln man_validate.ln \
-            man_argv.ln
-
-MANOBJS           = man_macro.o man.o man_hash.o man_validate.o \
-            man_argv.o
-MANSRCS           = man_macro.c man.c man_hash.c man_validate.c \
-            man_argv.c
-
-MAINLNS           = main.ln mdoc_term.ln chars.ln term.ln tree.ln \
-            compat.ln man_term.ln html.ln mdoc_html.ln \
-            man_html.ln out.ln term_ps.ln term_ascii.ln \
-            tbl_term.ln tbl_html.ln
-
-MAINOBJS   = main.o mdoc_term.o chars.o term.o tree.o compat.o \
-            man_term.o html.o mdoc_html.o man_html.o out.o \
-            term_ps.o term_ascii.o tbl_term.o tbl_html.o
-
-MAINSRCS   = main.c mdoc_term.c chars.c term.c tree.c compat.c \
-            man_term.c html.c mdoc_html.c man_html.c out.c \
-            term_ps.c term_ascii.c tbl_term.c tbl_html.c
-
-LLNS      = llib-llibmdoc.ln llib-llibman.ln llib-lmandoc.ln \
-            llib-llibmandoc.ln llib-llibroff.ln
-
-LNS       = $(MAINLNS) $(MDOCLNS) $(MANLNS) \
-            $(MANDOCLNS) $(ROFFLNS)
-
-LIBS      = libmdoc.a libman.a libmandoc.a libroff.a
-
-OBJS      = $(MDOCOBJS) $(MAINOBJS) $(MANOBJS) \
-            $(MANDOCOBJS) $(ROFFOBJS)
-
-SRCS      = $(MDOCSRCS) $(MAINSRCS) $(MANSRCS) \
-            $(MANDOCSRCS) $(ROFFSRCS)
-
-DATAS     = arch.in att.in lib.in msec.in st.in \
-            vol.in chars.in
-
-HEADS     = mdoc.h libmdoc.h man.h libman.h term.h \
-            libmandoc.h html.h chars.h out.h main.h roff.h \
-            mandoc.h libroff.h
-
-GSGMLS    = mandoc.1.sgml mdoc.3.sgml mdoc.7.sgml \
-            mandoc_char.7.sgml man.7.sgml man.3.sgml roff.7.sgml \
-            roff.3.sgml tbl.7.sgml
-
-SGMLS     = index.sgml
-
-XHTMLS    = mandoc.1.xhtml mdoc.3.xhtml \
-            man.3.xhtml mdoc.7.xhtml man.7.xhtml mandoc_char.7.xhtml \
-            roff.7.xhtml roff.3.xhtml tbl.7.xhtml
-
-HTMLS     = ChangeLog.html index.html man.h.html mdoc.h.html \
-            mandoc.h.html roff.h.html mandoc.1.html mdoc.3.html \
-            man.3.html mdoc.7.html man.7.html mandoc_char.7.html \
-            roff.7.html roff.3.html tbl.7.html
-
-PSS       = mandoc.1.ps mdoc.3.ps man.3.ps mdoc.7.ps man.7.ps \
-            mandoc_char.7.ps roff.7.ps roff.3.ps tbl.7.ps
-
-PDFS      = mandoc.1.pdf mdoc.3.pdf man.3.pdf mdoc.7.pdf man.7.pdf \
-            mandoc_char.7.pdf roff.7.pdf roff.3.pdf tbl.7.pdf
-
-XSLS      = ChangeLog.xsl
-
-TEXTS     = mandoc.1.txt mdoc.3.txt man.3.txt mdoc.7.txt man.7.txt \
-            mandoc_char.7.txt ChangeLog.txt \
-            roff.7.txt roff.3.txt tbl.7.txt
-
-EXAMPLES   = example.style.css
-
-XMLS      = ChangeLog.xml
-
-STATICS           = index.css style.css external.png
-
-MD5S      = mdocml-$(VERSION).md5 
-
-TARGZS    = mdocml-$(VERSION).tar.gz
-
-MANS      = mandoc.1 mdoc.3 mdoc.7 mandoc_char.7 man.7 \
-            man.3 roff.7 roff.3 tbl.7
-
-BINS      = mandoc
-
-TESTS     = test-strlcat.c test-strlcpy.c
-
-CONFIGS           = config.h.pre config.h.post
-
-DOCLEAN           = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS) \
-            $(TARGZS) tags $(MD5S) $(XMLS) $(TEXTS) $(GSGMLS) \
-            config.h config.log $(PSS) $(PDFS) $(XHTMLS)
-
-DOINSTALL  = $(SRCS) $(HEADS) Makefile $(MANS) $(SGMLS) $(STATICS) \
-            $(DATAS) $(XSLS) $(EXAMPLES) $(TESTS) $(CONFIGS)
-
-all:   $(BINS)
-
-lint:  $(LLNS)
+# CFLAGS       += -DOSNAME="\"OpenBSD 4.5\""
+
+VERSION                 = 1.11.1
+VDATE           = 04 April 2011
+CFLAGS         += -g -DHAVE_CONFIG_H -DVERSION="\"$(VERSION)\""
+CFLAGS         += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
+PREFIX          = /usr/local
+BINDIR          = $(PREFIX)/bin
+INCLUDEDIR      = $(PREFIX)/include/mandoc
+LIBDIR          = $(PREFIX)/lib/mandoc
+MANDIR          = $(PREFIX)/man
+EXAMPLEDIR      = $(PREFIX)/share/examples/mandoc
+INSTALL                 = install
+INSTALL_PROGRAM         = $(INSTALL) -m 0755
+INSTALL_DATA    = $(INSTALL) -m 0444
+INSTALL_LIB     = $(INSTALL) -m 0644
+INSTALL_MAN     = $(INSTALL_DATA)
+
+all: mandoc
+
+SRCS            = Makefile \
+                  arch.c \
+                  arch.in \
+                  att.c \
+                  att.in \
+                  chars.c \
+                  chars.in \
+                  compat.c \
+                  config.h.post \
+                  config.h.pre \
+                  eqn.7 \
+                  eqn.c \
+                  example.style.css \
+                  external.png \
+                  html.c \
+                  html.h \
+                  index.css \
+                  index.sgml \
+                  lib.c \
+                  lib.in \
+                  libman.h \
+                  libmandoc.h \
+                  libmdoc.h \
+                  libroff.h \
+                  main.c \
+                  main.h \
+                  man.h \
+                  man.7 \
+                  man.c \
+                  man_hash.c \
+                  man_html.c \
+                  man_macro.c \
+                  man_term.c \
+                  man_validate.c \
+                  mandoc.1 \
+                  mandoc.3 \
+                  mandoc.c \
+                  mandoc.h \
+                  mandoc-db.1 \
+                  mandoc-db.c \
+                  mandoc_char.7 \
+                  mdoc.h \
+                  mdoc.7 \
+                  mdoc.c \
+                  mdoc_argv.c \
+                  mdoc_hash.c \
+                  mdoc_html.c \
+                  mdoc_macro.c \
+                  mdoc_term.c \
+                  mdoc_validate.c \
+                  msec.c \
+                  msec.in \
+                  out.c \
+                  out.h \
+                  read.c \
+                  roff.7 \
+                  roff.c \
+                  st.c \
+                  st.in \
+                  style.css \
+                  tbl.7 \
+                  tbl.c \
+                  tbl_data.c \
+                  tbl_html.c \
+                  tbl_layout.c \
+                  tbl_opts.c \
+                  tbl_term.c \
+                  term.c \
+                  term.h \
+                  term_ascii.c \
+                  term_ps.c \
+                  test-strlcat.c \
+                  test-strlcpy.c \
+                  tree.c \
+                  vol.c \
+                  vol.in
+
+LIBMAN_OBJS     = man.o \
+                  man_hash.o \
+                  man_macro.o \
+                  man_validate.o
+LIBMAN_LNS      = man.ln \
+                  man_hash.ln \
+                  man_macro.ln \
+                  man_validate.ln
+
+LIBMDOC_OBJS    = arch.o \
+                  att.o \
+                  lib.o \
+                  mdoc.o \
+                  mdoc_argv.o \
+                  mdoc_hash.o \
+                  mdoc_macro.o \
+                  mdoc_validate.o \
+                  msec.o \
+                  st.o \
+                  vol.o
+LIBMDOC_LNS     = arch.ln \
+                  att.ln \
+                  lib.ln \
+                  mdoc.ln \
+                  mdoc_argv.ln \
+                  mdoc_hash.ln \
+                  mdoc_macro.ln \
+                  mdoc_validate.ln \
+                  msec.ln \
+                  st.ln \
+                  vol.ln
+
+LIBROFF_OBJS    = eqn.o \
+                  roff.o \
+                  tbl.o \
+                  tbl_data.o \
+                  tbl_layout.o \
+                  tbl_opts.o
+LIBROFF_LNS     = eqn.ln \
+                  roff.ln \
+                  tbl.ln \
+                  tbl_data.ln \
+                  tbl_layout.ln \
+                  tbl_opts.ln
+
+LIBMANDOC_OBJS  = $(LIBMAN_OBJS) \
+                  $(LIBMDOC_OBJS) \
+                  $(LIBROFF_OBJS) \
+                  mandoc.o \
+                  read.o
+LIBMANDOC_LNS   = $(LIBMAN_LNS) \
+                  $(LIBMDOC_LNS) \
+                  $(LIBROFF_LNS) \
+                  mandoc.ln \
+                  read.ln
+
+arch.o arch.ln: arch.in
+att.o att.ln: att.in
+lib.o lib.ln: lib.in
+msec.o msec.ln: msec.in
+st.o st.ln: st.in
+vol.o vol.ln: vol.in
+
+$(LIBMAN_OBJS) $(LIBMAN_LNS): libman.h
+$(LIBMDOC_OBJS) $(LIBMDOC_LNS): libmdoc.h
+$(LIBROFF_OBJS) $(LIBROFF_LNS): libroff.h
+$(LIBMANDOC_OBJS) $(LIBMANDOC_LNS): mandoc.h mdoc.h man.h libmandoc.h config.h
+
+MANDOC_HTML_OBJS = html.o \
+                  man_html.o \
+                  mdoc_html.o \
+                  tbl_html.o
+MANDOC_HTML_LNS         = html.ln \
+                  man_html.ln \
+                  mdoc_html.ln \
+                  tbl_html.ln
+
+MANDOC_TERM_OBJS = man_term.o \
+                  mdoc_term.o \
+                  term.o \
+                  term_ascii.o \
+                  term_ps.o \
+                  tbl_term.o
+MANDOC_TERM_LNS         = man_term.ln \
+                  mdoc_term.ln \
+                  term.ln \
+                  term_ascii.ln \
+                  term_ps.ln \
+                  tbl_term.ln
+
+MANDOC_OBJS     = $(MANDOC_HTML_OBJS) \
+                  $(MANDOC_TERM_OBJS) \
+                  chars.o \
+                  main.o \
+                  out.o \
+                  tree.o
+MANDOC_LNS      = $(MANDOC_HTML_LNS) \
+                  $(MANDOC_TERM_LNS) \
+                  chars.ln \
+                  main.ln \
+                  out.ln \
+                  tree.ln
+
+chars.o chars.ln: chars.in
+
+$(MANDOC_HTML_OBJS) $(MANDOC_HTML_LNS): html.h
+$(MANDOC_TERM_OBJS) $(MANDOC_TERM_LNS): term.h
+$(MANDOC_OBJS) $(MANDOC_LNS): main.h mandoc.h mdoc.h man.h config.h out.h
+
+compat.o compat.ln: config.h
+
+MANDOCDB_OBJS   = mandoc-db.o
+MANDOCDB_LNS    = mandoc-db.ln
+
+$(MANDOCDB_OBJS) $(MANDOCDB_LNS): mandoc.h mdoc.h man.h config.h
+
+INDEX_MANS      = mandoc.1.html \
+                  mandoc.1.xhtml \
+                  mandoc.1.ps \
+                  mandoc.1.pdf \
+                  mandoc.1.txt \
+                  mandoc.3.html \
+                  mandoc.3.xhtml \
+                  mandoc.3.ps \
+                  mandoc.3.pdf \
+                  mandoc.3.txt \
+                  eqn.7.html \
+                  eqn.7.xhtml \
+                  eqn.7.ps \
+                  eqn.7.pdf \
+                  eqn.7.txt \
+                  man.7.html \
+                  man.7.xhtml \
+                  man.7.ps \
+                  man.7.pdf \
+                  man.7.txt \
+                  mandoc_char.7.html \
+                  mandoc_char.7.xhtml \
+                  mandoc_char.7.ps \
+                  mandoc_char.7.pdf \
+                  mandoc_char.7.txt \
+                  mdoc.7.html \
+                  mdoc.7.xhtml \
+                  mdoc.7.ps \
+                  mdoc.7.pdf \
+                  mdoc.7.txt \
+                  roff.7.html \
+                  roff.7.xhtml \
+                  roff.7.ps \
+                  roff.7.pdf \
+                  roff.7.txt \
+                  tbl.7.html \
+                  tbl.7.xhtml \
+                  tbl.7.ps \
+                  tbl.7.pdf \
+                  tbl.7.txt
+
+$(INDEX_MANS): mandoc
+
+INDEX_OBJS      = $(INDEX_MANS) \
+                  man.h.html \
+                  mandoc.h.html \
+                  mdoc.h.html \
+                  mdocml.tar.gz \
+                  mdocml.md5
+
+www: index.html
+
+lint: llib-llibmandoc.ln llib-lmandoc.ln
 
 clean:
 
 clean:
-       rm -f $(DOCLEAN)
-
-dist:  mdocml-$(VERSION).tar.gz
-
-www:   all $(GSGMLS) $(HTMLS) $(XHTMLS) $(TEXTS) $(MD5S) $(TARGZS) $(PSS) $(PDFS)
-
-ps:    $(PSS)
-
-pdf:   $(PDFS)
-
-installwww: www
-       $(INSTALL_DATA) $(HTMLS) $(XHTMLS) $(PSS) $(PDFS) $(TEXTS) $(STATICS) $(DESTDIR)$(PREFIX)/
-       $(INSTALL_DATA) mdocml-$(VERSION).tar.gz $(DESTDIR)$(PREFIX)/snapshots/
-       $(INSTALL_DATA) mdocml-$(VERSION).md5 $(DESTDIR)$(PREFIX)/snapshots/
-       $(INSTALL_DATA) mdocml-$(VERSION).tar.gz $(DESTDIR)$(PREFIX)/snapshots/mdocml.tar.gz
-       $(INSTALL_DATA) mdocml-$(VERSION).md5 $(DESTDIR)$(PREFIX)/snapshots/mdocml.md5
-
-install:
+       rm -f libmandoc.a $(LIBMANDOC_OBJS)
+       rm -f llib-llibmandoc.ln $(LIBMANDOC_LNS)
+       rm -f mandoc-db $(MANDOCDB_OBJS)
+       rm -f llib-lmandoc-db.ln $(MANDOCDB_LNS)
+       rm -f mandoc $(MANDOC_OBJS)
+       rm -f llib-lmandoc.ln $(MANDOC_LNS)
+       rm -f config.h config.log compat.o compat.ln
+       rm -f mdocml.tar.gz
+       rm -f index.html $(INDEX_OBJS)
+
+install: all
        mkdir -p $(DESTDIR)$(BINDIR)
        mkdir -p $(DESTDIR)$(EXAMPLEDIR)
        mkdir -p $(DESTDIR)$(MANDIR)/man1
        mkdir -p $(DESTDIR)$(BINDIR)
        mkdir -p $(DESTDIR)$(EXAMPLEDIR)
        mkdir -p $(DESTDIR)$(MANDIR)/man1
+       mkdir -p $(DESTDIR)$(MANDIR)/man3
        mkdir -p $(DESTDIR)$(MANDIR)/man7
        $(INSTALL_PROGRAM) mandoc $(DESTDIR)$(BINDIR)
        mkdir -p $(DESTDIR)$(MANDIR)/man7
        $(INSTALL_PROGRAM) mandoc $(DESTDIR)$(BINDIR)
+       $(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
        $(INSTALL_MAN) mandoc.1 $(DESTDIR)$(MANDIR)/man1
        $(INSTALL_MAN) mandoc.1 $(DESTDIR)$(MANDIR)/man1
-       $(INSTALL_MAN) man.7 mdoc.7 roff.7 tbl.7 mandoc_char.7 $(DESTDIR)$(MANDIR)/man7
+       $(INSTALL_MAN) mandoc.3 $(DESTDIR)$(MANDIR)/man3
+       $(INSTALL_MAN) man.7 mdoc.7 roff.7 eqn.7 tbl.7 mandoc_char.7 $(DESTDIR)$(MANDIR)/man7
        $(INSTALL_DATA) example.style.css $(DESTDIR)$(EXAMPLEDIR)
 
        $(INSTALL_DATA) example.style.css $(DESTDIR)$(EXAMPLEDIR)
 
-uninstall:
-       rm -f $(DESTDIR)$(BINDIR)/mandoc
-       rm -f $(DESTDIR)$(MANDIR)/man1/mandoc.1
-       rm -f $(DESTDIR)$(MANDIR)/man7/mdoc.7
-       rm -f $(DESTDIR)$(MANDIR)/man7/roff.7
-       rm -f $(DESTDIR)$(MANDIR)/man7/tbl.7
-       rm -f $(DESTDIR)$(MANDIR)/man7/man.7
-       rm -f $(DESTDIR)$(MANDIR)/man7/mandoc_char.7
-       rm -f $(DESTDIR)$(EXAMPLEDIR)/example.style.css
-
-$(OBJS): config.h
-
-$(LNS): config.h
-
-man_macro.ln man_macro.o: man_macro.c libman.h
-
-lib.ln lib.o: lib.c lib.in libmdoc.h
-
-att.ln att.o: att.c att.in libmdoc.h
-
-arch.ln arch.o: arch.c arch.in libmdoc.h
-
-vol.ln vol.o: vol.c vol.in libmdoc.h
-
-chars.ln chars.o: chars.c chars.in chars.h
-
-msec.ln msec.o: msec.c msec.in libmdoc.h
-
-st.ln st.o: st.c st.in libmdoc.h
-
-mdoc_macro.ln mdoc_macro.o: mdoc_macro.c libmdoc.h
-
-mdoc_term.ln mdoc_term.o: mdoc_term.c term.h mdoc.h
-
-mdoc_strings.ln mdoc_strings.o: mdoc_strings.c libmdoc.h
-
-man_hash.ln man_hash.o: man_hash.c libman.h
-
-mdoc_hash.ln mdoc_hash.o: mdoc_hash.c libmdoc.h
-
-mdoc.ln mdoc.o: mdoc.c libmdoc.h
-
-man.ln man.o: man.c libman.h
-
-main.ln main.o: main.c mdoc.h man.h roff.h
-
-compat.ln compat.o: compat.c 
-
-term.ln term.o: term.c term.h man.h mdoc.h chars.h
-
-term_ps.ln term_ps.o: term_ps.c term.h main.h
-
-term_ascii.ln term_ascii.o: term_ascii.c term.h main.h
-
-html.ln html.o: html.c html.h chars.h
-
-mdoc_html.ln mdoc_html.o: mdoc_html.c html.h mdoc.h
-
-man_html.ln man_html.o: man_html.c html.h man.h out.h
-
-out.ln out.o: out.c out.h
-
-mandoc.ln mandoc.o: mandoc.c libmandoc.h
-
-tree.ln tree.o: tree.c man.h mdoc.h
-
-mdoc_argv.ln mdoc_argv.o: mdoc_argv.c libmdoc.h
+installwww: www
+       mkdir -p $(PREFIX)/snapshots
+       $(INSTALL_DATA) index.html external.png index.css $(PREFIX)
+       $(INSTALL_DATA) $(INDEX_MANS) style.css $(PREFIX)
+       $(INSTALL_DATA) mandoc.h.html man.h.html mdoc.h.html $(PREFIX)
+       $(INSTALL_DATA) mdocml.tar.gz $(PREFIX)/snapshots
+       $(INSTALL_DATA) mdocml.md5 $(PREFIX)/snapshots
+       $(INSTALL_DATA) mdocml.tar.gz $(PREFIX)/snapshots/mdocml-$(VERSION).tar.gz
+       $(INSTALL_DATA) mdocml.md5 $(PREFIX)/snapshots/mdocml-$(VERSION).md5
 
 
-man_argv.ln man_argv.o: man_argv.c libman.h
+libmandoc.a: compat.o $(LIBMANDOC_OBJS)
+       $(AR) rs $@ compat.o $(LIBMANDOC_OBJS)
 
 
-man_validate.ln man_validate.o: man_validate.c libman.h
+llib-llibmandoc.ln: compat.ln $(LIBMANDOC_LNS)
+       $(LINT) $(LINTFLAGS) -Clibmandoc compat.ln $(LIBMANDOC_LNS)
 
 
-mdoc_validate.ln mdoc_validate.o: mdoc_validate.c libmdoc.h
+mandoc: $(MANDOC_OBJS) libmandoc.a
+       $(CC) -o $@ $(MANDOC_OBJS) libmandoc.a
 
 
-libmdoc.h: mdoc.h
+# You'll need -ldb for Linux.
+mandoc-db: $(MANDOCDB_OBJS) libmandoc.a
+       $(CC) -o $@ $(MANDOCDB_OBJS) libmandoc.a
 
 
-ChangeLog.xml:
-       cvs2cl --xml --xml-encoding iso-8859-15 -t --noxmlns -f $@
+llib-lmandoc.ln: $(MANDOC_LNS)
+       $(LINT) $(LINTFLAGS) -Cmandoc $(MANDOC_LNS)
 
 
-ChangeLog.txt:
-       cvs2cl -t -f $@
+llib-lmandoc-db.ln: $(MANDOCDB_LNS)
+       $(LINT) $(LINTFLAGS) -Cmandoc-db $(MANDOCDB_LNS)
 
 
-ChangeLog.html: ChangeLog.xml ChangeLog.xsl
-       xsltproc -o $@ ChangeLog.xsl ChangeLog.xml
+mdocml.md5: mdocml.tar.gz
+       md5 mdocml.tar.gz >$@
 
 
-mdocml-$(VERSION).tar.gz: $(DOINSTALL)
-       mkdir -p .dist/mdocml/mdocml-$(VERSION)/
-       cp -f $(DOINSTALL) .dist/mdocml/mdocml-$(VERSION)/
-       ( cd .dist/mdocml/ && tar zcf ../../$@ mdocml-$(VERSION)/ )
+mdocml.tar.gz: $(SRCS)
+       mkdir -p .dist/mdocml-$(VERSION)/
+       $(INSTALL) -m 0444 $(SRCS) .dist/mdocml-$(VERSION)
+       ( cd .dist/ && tar zcf ../$@ ./ )
        rm -rf .dist/
 
        rm -rf .dist/
 
-llib-llibmdoc.ln: $(MDOCLNS)
-       $(LINT) -Clibmdoc $(MDOCLNS)
-
-llib-llibman.ln: $(MANLNS)
-       $(LINT) -Clibman $(MANLNS)
-
-llib-llibmandoc.ln: $(MANDOCLNS)
-       $(LINT) -Clibmandoc $(MANDOCLNS)
-
-llib-llibroff.ln: $(ROFFLNS)
-       $(LINT) -Clibroff $(ROFFLNS)
+index.html: $(INDEX_OBJS)
 
 
-llib-lmandoc.ln: $(MAINLNS) llib-llibmdoc.ln llib-llibman.ln llib-llibmandoc.ln llib-llibroff.ln
-       $(LINT) -Cmandoc $(MAINLNS) llib-llibmdoc.ln llib-llibman.ln llib-llibmandoc.ln llib-llibroff.ln
-
-libmdoc.a: $(MDOCOBJS)
-       $(AR) rs $@ $(MDOCOBJS)
-
-libman.a: $(MANOBJS)
-       $(AR) rs $@ $(MANOBJS)
-
-libmandoc.a: $(MANDOCOBJS)
-       $(AR) rs $@ $(MANDOCOBJS)
-
-libroff.a: $(ROFFOBJS)
-       $(AR) rs $@ $(ROFFOBJS)
-
-mandoc: $(MAINOBJS) libroff.a libmdoc.a libman.a libmandoc.a
-       $(CC) $(CFLAGS) -o $@ $(MAINOBJS) libroff.a libmdoc.a libman.a libmandoc.a
+config.h: config.h.pre config.h.post
+       rm -f config.log
+       ( cat config.h.pre; \
+         echo; \
+         if $(CC) $(CFLAGS) -Werror -o test-strlcat test-strlcat.c >> config.log 2>&1; then \
+               echo '#define HAVE_STRLCAT'; \
+               rm test-strlcat; \
+         fi; \
+         if $(CC) $(CFLAGS) -Werror -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \
+               echo '#define HAVE_STRLCPY'; \
+               rm test-strlcpy; \
+         fi; \
+         echo; \
+         cat config.h.post \
+       ) > $@
 
 
-.sgml.html:
-       validate --warn $<
-       sed -e "s!@VERSION@!$(VERSION)!" -e "s!@VDATE@!$(VDATE)!" $< > $@
+.h.h.html:
+       highlight -I $< >$@
 
 .1.1.txt .3.3.txt .7.7.txt:
 
 .1.1.txt .3.3.txt .7.7.txt:
-       ./mandoc -Tascii -Wall,stop $< | col -b > $@
+       ./mandoc -Tascii -Wall,stop $< | col -b >$@
 
 
-.1.1.sgml .3.3.sgml .7.7.sgml:
-       ./mandoc -Thtml -Wall,stop -Ostyle=style.css,man=%N.%S.html,includes=%I.html $< > $@
+.1.1.html .3.3.html .7.7.html:
+       ./mandoc -Thtml -Wall,stop -Ostyle=style.css,man=%N.%S.html,includes=%I.html $< >$@
 
 .1.1.ps .3.3.ps .7.7.ps:
 
 .1.1.ps .3.3.ps .7.7.ps:
-       ./mandoc -Tps -Wall,stop $< > $@
+       ./mandoc -Tps -Wall,stop $< >$@
 
 .1.1.xhtml .3.3.xhtml .7.7.xhtml:
 
 .1.1.xhtml .3.3.xhtml .7.7.xhtml:
-       ./mandoc -Txhtml -Wall,stop -Ostyle=style.css,man=%N.%S.xhtml,includes=%I.html $< > $@
+       ./mandoc -Txhtml -Wall,stop -Ostyle=style.css,man=%N.%S.xhtml,includes=%I.html $< >$@
 
 .1.1.pdf .3.3.pdf .7.7.pdf:
 
 .1.1.pdf .3.3.pdf .7.7.pdf:
-       ./mandoc -Tpdf -Wall,stop $< > $@
-
-.tar.gz.md5:
-       md5 $< > $@
+       ./mandoc -Tpdf -Wall,stop $< >$@
 
 
-.h.h.html:
-       highlight -I $< >$@
-
-config.h: config.h.pre config.h.post
-       rm -f config.log
-       ( cat config.h.pre; \
-       echo; \
-       if $(CC) $(CFLAGS) -Werror -c test-strlcat.c >> config.log 2>&1; then \
-               echo '#define HAVE_STRLCAT'; \
-               rm test-strlcat.o; \
-       fi; \
-       if $(CC) $(CFLAGS) -Werror -c test-strlcpy.c >> config.log 2>&1; then \
-               echo '#define HAVE_STRLCPY'; \
-               rm test-strlcpy.o; \
-       fi; \
-       echo; \
-       cat config.h.post \
-       ) > $@
+.sgml.html:
+       validate --warn $<
+       sed -e "s!@VERSION@!$(VERSION)!" -e "s!@VDATE@!$(VDATE)!" $< >$@
index c3d7634..e764bfe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: arch.c,v 1.8 2010/06/19 20:46:27 kristaps Exp $ */
+/*     $Id: arch.c,v 1.9 2011/03/22 14:33:05 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.h"
 #include "mandoc.h"
 #include "libmdoc.h"
 
 #include "mandoc.h"
 #include "libmdoc.h"
 
index cfd6b44..24d757d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: att.c,v 1.8 2010/06/19 20:46:27 kristaps Exp $ */
+/*     $Id: att.c,v 1.9 2011/03/22 14:33:05 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.h"
 #include "mandoc.h"
 #include "libmdoc.h"
 
 #include "mandoc.h"
 #include "libmdoc.h"
 
index 5edf947..03e4491 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: chars.c,v 1.31 2011/01/02 10:10:57 kristaps Exp $ */
+/*     $Id: chars.c,v 1.34 2011/03/22 10:13:01 kristaps Exp $ */
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011 Ingo Schwarze <schwarze@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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -24,7 +25,7 @@
 #include <string.h>
 
 #include "mandoc.h"
 #include <string.h>
 
 #include "mandoc.h"
-#include "chars.h"
+#include "out.h"
 
 #define        PRINT_HI         126
 #define        PRINT_LO         32
 
 #define        PRINT_HI         126
 #define        PRINT_LO         32
@@ -91,17 +92,8 @@ chars_init(enum chars type)
         * (they're in-line re-ordered during lookup).
         */
 
         * (they're in-line re-ordered during lookup).
         */
 
-       tab = malloc(sizeof(struct ctab));
-       if (NULL == tab) {
-               perror(NULL);
-               exit((int)MANDOCLEVEL_SYSERR);
-       }
-
-       htab = calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
-       if (NULL == htab) {
-               perror(NULL);
-               exit((int)MANDOCLEVEL_SYSERR);
-       }
+       tab = mandoc_malloc(sizeof(struct ctab));
+       htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
 
        for (i = 0; i < LINES_MAX; i++) {
                hash = (int)lines[i].code[0] - PRINT_LO;
 
        for (i = 0; i < LINES_MAX; i++) {
                hash = (int)lines[i].code[0] - PRINT_LO;
@@ -152,6 +144,27 @@ chars_res2cp(void *arg, const char *p, size_t sz)
 }
 
 
 }
 
 
+/*
+ * Numbered character to literal character,
+ * represented as a null-terminated string for additional safety.
+ */
+const char *
+chars_num2char(const char *p, size_t sz)
+{
+       int               i;
+       static char       c[2];
+
+       if (sz > 3)
+               return(NULL);
+       i = atoi(p);
+       if (i < 0 || i > 255)
+               return(NULL);
+       c[0] = (char)i;
+       c[1] = '\0';
+       return(c);
+}
+
+
 /* 
  * Special character to string array.
  */
 /* 
  * Special character to string array.
  */
diff --git a/contrib/mdocml/chars.h b/contrib/mdocml/chars.h
deleted file mode 100644 (file)
index 894008b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*     $Id: chars.h,v 1.6 2010/07/31 23:52:58 schwarze Exp $ */
-/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
- *
- * 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.
- */
-#ifndef CHARS_H
-#define CHARS_H
-
-__BEGIN_DECLS
-
-enum   chars {
-       CHARS_ASCII,
-       CHARS_HTML
-};
-
-void            *chars_init(enum chars);
-const char      *chars_spec2str(void *, const char *, size_t, size_t *);
-int              chars_spec2cp(void *, const char *, size_t);
-const char      *chars_res2str(void *, const char *, size_t, size_t *);
-int              chars_res2cp(void *, const char *, size_t);
-void             chars_free(void *);
-
-__END_DECLS
-
-#endif /*!CHARS_H*/
index 63d9fb4..f628960 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: chars.in,v 1.35 2010/09/15 13:10:30 kristaps Exp $ */
+/*     $Id: chars.in,v 1.36 2011/03/16 22:49:55 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -187,7 +187,7 @@ CHAR(":U",                  "U",            220)
 CHAR(":a",                     "a",            228)
 CHAR(":e",                     "e",            235)
 CHAR(":i",                     "i",            239)
 CHAR(":a",                     "a",            228)
 CHAR(":e",                     "e",            235)
 CHAR(":i",                     "i",            239)
-CHAR(":o",                     "o",            245)
+CHAR(":o",                     "o",            246)
 CHAR(":u",                     "u",            252)
 CHAR(":y",                     "y",            255)
 CHAR("\'A",                    "A",            193)
 CHAR(":u",                     "u",            252)
 CHAR(":y",                     "y",            255)
 CHAR("\'A",                    "A",            193)
diff --git a/contrib/mdocml/eqn.7 b/contrib/mdocml/eqn.7
new file mode 100644 (file)
index 0000000..b2b66f4
--- /dev/null
@@ -0,0 +1,92 @@
+.\"    $Id: eqn.7,v 1.2 2011/03/17 15:12:42 kristaps Exp $
+.\"
+.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+.\"
+.\" 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.
+.\"
+.Dd $Mdocdate: March 17 2011 $
+.Dt EQN 7
+.Os
+.Sh NAME
+.Nm eqn
+.Nd eqn language reference for mandoc
+.Sh DESCRIPTION
+The
+.Nm eqn
+language is a equation-formatting language.
+It is used within
+.Xr mdoc 7
+and
+.Xr man 7
+.Ux
+manual pages.
+This manual describes the subset of the
+.Nm
+language accepted by the
+.Xr mandoc 1
+utility.
+.Pp
+Equations within
+.Xr mdoc 7
+or
+.Xr man 7
+are enclosed by the
+.Sq EQ
+and
+.Sq EN
+macro tags, whose precise syntax is documented in
+.Xr roff 7 .
+Equations consist of multi-line equation data.
+.Pp
+For the time being,
+.Xr mandoc 1
+reproduces the contents of
+.Nm
+equations verbatim in its output.
+.Pp
+The
+.Nm
+implementation in
+.Xr mandoc 1
+is
+.Ud
+.Sh SEE ALSO
+.Xr mandoc 1 ,
+.Xr man 7 ,
+.Xr mandoc_char 7 ,
+.Xr mdoc 7 ,
+.Xr roff 7
+.Rs
+.%A Brian W. Kernighan
+.%A Lorinda L. Cherry
+.%T System for Typesetting Mathematics
+.%J Communications of the ACM
+.%V 18
+.%P 151\(en157
+.%D March, 1975
+.Re
+.\" .Sh HISTORY
+.\" The tbl utility, a preprocessor for troff, was originally written by M.
+.\" E. Lesk at Bell Labs in 1975.
+.\" The GNU reimplementation of tbl, part of the groff package, was released
+.\" in 1990 by James Clark.
+.\" A standalone tbl implementation was written by Kristaps Dzonsons in
+.\" 2010.
+.\" This formed the basis of the implementation that is part of the
+.\" .Xr mandoc 1
+.\" utility.
+.Sh AUTHORS
+This partial
+.Nm
+reference was written by
+.An Kristaps Dzonsons Aq kristaps@bsd.lv .
diff --git a/contrib/mdocml/eqn.c b/contrib/mdocml/eqn.c
new file mode 100644 (file)
index 0000000..220f3f8
--- /dev/null
@@ -0,0 +1,81 @@
+/*     $Id: eqn.c,v 1.4 2011/03/22 09:48:13 kristaps Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "mandoc.h"
+#include "libmandoc.h"
+#include "libroff.h"
+
+/* ARGSUSED */
+enum rofferr
+eqn_read(struct eqn_node **epp, int ln, const char *p, int offs)
+{
+       size_t           sz;
+       struct eqn_node *ep;
+
+       if (0 == strcmp(p, ".EN")) {
+               *epp = NULL;
+               return(ROFF_EQN);
+       }
+
+       ep = *epp;
+
+       sz = strlen(&p[offs]);
+       ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1);
+       if (0 == ep->eqn.sz)
+               *ep->eqn.data = '\0';
+
+       ep->eqn.sz += sz;
+       strlcat(ep->eqn.data, &p[offs], ep->eqn.sz + 1);
+       return(ROFF_IGN);
+}
+
+struct eqn_node *
+eqn_alloc(int pos, int line)
+{
+       struct eqn_node *p;
+
+       p = mandoc_calloc(1, sizeof(struct eqn_node));
+       p->eqn.line = line;
+       p->eqn.pos = pos;
+
+       return(p);
+}
+
+/* ARGSUSED */
+void
+eqn_end(struct eqn_node *e)
+{
+
+       /* Nothing to do. */
+}
+
+void
+eqn_free(struct eqn_node *p)
+{
+
+       free(p->eqn.data);
+       free(p);
+}
index 7f640ee..c7cc484 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: example.style.css,v 1.41 2011/01/05 13:00:11 kristaps Exp $ */
+/* $Id: example.style.css,v 1.42 2011/02/09 09:52:47 kristaps Exp $ */
 
 /*
  * This is an example style-sheet provided for mandoc(1) and the -Thtml
 
 /*
  * This is an example style-sheet provided for mandoc(1) and the -Thtml
@@ -141,6 +141,10 @@ li.list-item       { }
 ol.list-enum   { padding-left: 2em; }
 li.list-enum   { }
 
 ol.list-enum   { padding-left: 2em; }
 li.list-enum   { }
 
+/* Equation modes.  See eqn(7). */
+
+span.eqn       { }
+
 /* Table modes.  See tbl(7). */
 
 table.tbl      { }
 /* Table modes.  See tbl(7). */
 
 table.tbl      { }
index 70403ff..ab57c37 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: html.c,v 1.124 2010/12/27 21:41:05 schwarze Exp $ */
+/*     $Id: html.c,v 1.131 2011/03/22 14:05:45 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011 Ingo Schwarze <schwarze@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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -31,7 +32,6 @@
 
 #include "mandoc.h"
 #include "out.h"
 
 #include "mandoc.h"
 #include "out.h"
-#include "chars.h"
 #include "html.h"
 #include "main.h"
 
 #include "html.h"
 #include "main.h"
 
@@ -90,8 +90,10 @@ static       const char      *const htmlattrs[ATTR_MAX] = {
        "id", /* ATTR_ID */
        "summary", /* ATTR_SUMMARY */
        "align", /* ATTR_ALIGN */
        "id", /* ATTR_ID */
        "summary", /* ATTR_SUMMARY */
        "align", /* ATTR_ALIGN */
+       "colspan", /* ATTR_COLSPAN */
 };
 
 };
 
+static void              print_num(struct html *, const char *, size_t);
 static void              print_spec(struct html *, enum roffdeco,
                                const char *, size_t);
 static void              print_res(struct html *, const char *, size_t);
 static void              print_spec(struct html *, enum roffdeco,
                                const char *, size_t);
 static void              print_res(struct html *, const char *, size_t);
@@ -117,11 +119,7 @@ ml_alloc(char *outopts, enum htmltype type)
        toks[2] = "includes";
        toks[3] = NULL;
 
        toks[2] = "includes";
        toks[3] = NULL;
 
-       h = calloc(1, sizeof(struct html));
-       if (NULL == h) {
-               perror(NULL);
-               exit((int)MANDOCLEVEL_SYSERR);
-       }
+       h = mandoc_calloc(1, sizeof(struct html));
 
        h->type = type;
        h->tags.head = NULL;
 
        h->type = type;
        h->tags.head = NULL;
@@ -211,6 +209,16 @@ print_gen_head(struct html *h)
        }
 }
 
        }
 }
 
+/* ARGSUSED */
+static void
+print_num(struct html *h, const char *p, size_t len)
+{
+       const char      *rhs;
+
+       rhs = chars_num2char(p, len);
+       if (rhs)
+               putchar((int)*rhs);
+}
 
 static void
 print_spec(struct html *h, enum roffdeco d, const char *p, size_t len)
 
 static void
 print_spec(struct html *h, enum roffdeco d, const char *p, size_t len)
@@ -332,6 +340,9 @@ print_encode(struct html *h, const char *p, int norecurse)
                len = a2roffdeco(&deco, &seq, &sz);
 
                switch (deco) {
                len = a2roffdeco(&deco, &seq, &sz);
 
                switch (deco) {
+               case (DECO_NUMBERED):
+                       print_num(h, seq, sz);
+                       break;
                case (DECO_RESERVED):
                        print_res(h, seq, sz);
                        break;
                case (DECO_RESERVED):
                        print_res(h, seq, sz);
                        break;
@@ -384,11 +395,7 @@ print_otag(struct html *h, enum htmltag tag,
        /* Push this tags onto the stack of open scopes. */
 
        if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
        /* Push this tags onto the stack of open scopes. */
 
        if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
-               t = malloc(sizeof(struct tag));
-               if (NULL == t) {
-                       perror(NULL);
-                       exit((int)MANDOCLEVEL_SYSERR);
-               }
+               t = mandoc_malloc(sizeof(struct tag));
                t->tag = tag;
                t->next = h->tags.head;
                h->tags.head = t;
                t->tag = tag;
                t->next = h->tags.head;
                h->tags.head = t;
@@ -501,35 +508,10 @@ print_doctype(struct html *h)
                        name, doctype, dtd);
 }
 
                        name, doctype, dtd);
 }
 
-
 void
 print_text(struct html *h, const char *word)
 {
 
 void
 print_text(struct html *h, const char *word)
 {
 
-       if (word[0] && '\0' == word[1])
-               switch (word[0]) {
-               case('.'):
-                       /* FALLTHROUGH */
-               case(','):
-                       /* FALLTHROUGH */
-               case(';'):
-                       /* FALLTHROUGH */
-               case(':'):
-                       /* FALLTHROUGH */
-               case('?'):
-                       /* FALLTHROUGH */
-               case('!'):
-                       /* FALLTHROUGH */
-               case(')'):
-                       /* FALLTHROUGH */
-               case(']'):
-                       if ( ! (HTML_IGNDELIM & h->flags))
-                               h->flags |= HTML_NOSPACE;
-                       break;
-               default:
-                       break;
-               }
-
        if ( ! (HTML_NOSPACE & h->flags)) {
                /* Manage keeps! */
                if ( ! (HTML_KEEP & h->flags)) {
        if ( ! (HTML_NOSPACE & h->flags)) {
                /* Manage keeps! */
                if ( ! (HTML_KEEP & h->flags)) {
@@ -557,21 +539,6 @@ print_text(struct html *h, const char *word)
        }
 
        h->flags &= ~HTML_IGNDELIM;
        }
 
        h->flags &= ~HTML_IGNDELIM;
-
-       /* 
-        * Note that we don't process the pipe: the parser sees it as
-        * punctuation, but we don't in terms of typography.
-        */
-       if (word[0] && '\0' == word[1])
-               switch (word[0]) {
-               case('('):
-                       /* FALLTHROUGH */
-               case('['):
-                       h->flags |= HTML_NOSPACE;
-                       break;
-               default:
-                       break;
-               }
 }
 
 
 }
 
 
@@ -581,8 +548,14 @@ print_tagq(struct html *h, const struct tag *until)
        struct tag      *tag;
 
        while ((tag = h->tags.head) != NULL) {
        struct tag      *tag;
 
        while ((tag = h->tags.head) != NULL) {
+               /* 
+                * Remember to close out and nullify the current
+                * meta-font and table, if applicable.
+                */
                if (tag == h->metaf)
                        h->metaf = NULL;
                if (tag == h->metaf)
                        h->metaf = NULL;
+               if (tag == h->tblt)
+                       h->tblt = NULL;
                print_ctag(h, tag->tag);
                h->tags.head = tag->next;
                free(tag);
                print_ctag(h, tag->tag);
                h->tags.head = tag->next;
                free(tag);
@@ -600,8 +573,14 @@ print_stagq(struct html *h, const struct tag *suntil)
        while ((tag = h->tags.head) != NULL) {
                if (suntil && tag == suntil)
                        return;
        while ((tag = h->tags.head) != NULL) {
                if (suntil && tag == suntil)
                        return;
+               /* 
+                * Remember to close out and nullify the current
+                * meta-font and table, if applicable.
+                */
                if (tag == h->metaf)
                        h->metaf = NULL;
                if (tag == h->metaf)
                        h->metaf = NULL;
+               if (tag == h->tblt)
+                       h->tblt = NULL;
                print_ctag(h, tag->tag);
                h->tags.head = tag->next;
                free(tag);
                print_ctag(h, tag->tag);
                h->tags.head = tag->next;
                free(tag);
index 8d9db89..561d06e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: html.h,v 1.38 2011/01/06 11:55:39 kristaps Exp $ */
+/*     $Id: html.h,v 1.40 2011/01/29 14:49:44 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -67,6 +67,7 @@ enum  htmlattr {
        ATTR_ID,
        ATTR_SUMMARY,
        ATTR_ALIGN,
        ATTR_ID,
        ATTR_SUMMARY,
        ATTR_ALIGN,
+       ATTR_COLSPAN,
        ATTR_MAX
 };
 
        ATTR_MAX
 };
 
@@ -110,13 +111,15 @@ enum      htmltype {
 
 struct html {
        int               flags;
 
 struct html {
        int               flags;
-#define        HTML_NOSPACE     (1 << 0)
+#define        HTML_NOSPACE     (1 << 0) /* suppress next space */
 #define        HTML_IGNDELIM    (1 << 1)
 #define        HTML_KEEP        (1 << 2)
 #define        HTML_PREKEEP     (1 << 3)
 #define        HTML_IGNDELIM    (1 << 1)
 #define        HTML_KEEP        (1 << 2)
 #define        HTML_PREKEEP     (1 << 3)
-#define        HTML_NONOSPACE   (1 << 4)
+#define        HTML_NONOSPACE   (1 << 4) /* never add spaces */
+#define        HTML_LITERAL     (1 << 5) /* literal (e.g., <PRE>) context */
        struct tagq       tags; /* stack of open tags */
        struct rofftbl    tbl; /* current table */
        struct tagq       tags; /* stack of open tags */
        struct rofftbl    tbl; /* current table */
+       struct tag       *tblt; /* current open table scope */
        void             *symtab; /* character-escapes */
        char             *base_man; /* base for manpage href */
        char             *base_includes; /* base for include href */
        void             *symtab; /* character-escapes */
        char             *base_man; /* base for manpage href */
        char             *base_includes; /* base for include href */
@@ -136,6 +139,7 @@ struct tag   *print_otag(struct html *, enum htmltag,
 void             print_tagq(struct html *, const struct tag *);
 void             print_stagq(struct html *, const struct tag *);
 void             print_text(struct html *, const char *);
 void             print_tagq(struct html *, const struct tag *);
 void             print_stagq(struct html *, const struct tag *);
 void             print_text(struct html *, const char *);
+void             print_tblclose(struct html *);
 void             print_tbl(struct html *, const struct tbl_span *);
 
 void             bufcat_su(struct html *, const char *, 
 void             print_tbl(struct html *, const struct tbl_span *);
 
 void             bufcat_su(struct html *, const char *, 
index 7abc997..d4fd1ed 100644 (file)
                                        </P>
 
                                        <P>
                                        </P>
 
                                        <P>
-                                       <SPAN CLASS="nm">mdocml</SPAN> consists of the <A HREF="mdoc.3.html">libmdoc</A>, <A
-                                       HREF="man.3.html">libman</A>, and <A HREF="roff.3.html">libroff</A> validating compilers; and <A
-                                       HREF="mandoc.1.html">mandoc</A>, which interfaces with the compiler libraries to format output for UNIX
-                                       terminals, XHTML, HTML, PostScript, and PDF.  It is a <A CLASS="external"
+                                       <SPAN CLASS="nm">mdocml</SPAN> consists of the <A HREF="mandoc.3.html">libmandoc</A> validating
+                                       compiler and <A HREF="mandoc.1.html">mandoc</A>, which interfaces with the compiler library to format
+                                       output for UNIX terminals, XHTML, HTML, PostScript, and PDF.  It is a <A CLASS="external"
                                        HREF="http://bsd.lv/">BSD.lv</A> project.  
                                        </P>
 
                                        HREF="http://bsd.lv/">BSD.lv</A> project.  
                                        </P>
 
@@ -59,9 +58,8 @@
                                        </H1>
 
                                        <P>
                                        </H1>
 
                                        <P>
-                                       <SPAN CLASS="nm">mdocml</SPAN> is architecture- and system-neutral, written in plain-old C.  The most
-                                       current version is <SPAN CLASS="attn">@VERSION@</SPAN>, dated <SPAN class="attn">@VDATE@</SPAN>.  A full
-                                       <A HREF="ChangeLog.html">ChangeLog</A> (<A HREF="ChangeLog.txt">txt</A>) is written with each release.
+                                       <SPAN CLASS="nm">mdocml</SPAN> is in plain-old ANSI C and should build and run on any UNIX system.
+                                       The most current version is <SPAN CLASS="attn">@VERSION@</SPAN>, dated <SPAN class="attn">@VDATE@</SPAN>.
                                        </P>
 
                                        <H2>
                                        </P>
 
                                        <H2>
                                                        </TD>
                                                </TR>
                                                <TR>
                                                        </TD>
                                                </TR>
                                                <TR>
-                                                       <TD VALIGN="top"><A HREF="man.3.html">man(3)</A></TD>
+                                                       <TD VALIGN="top"><A HREF="mandoc.3.html">mandoc(3)</A></TD>
                                                        <TD VALIGN="top">
                                                        <TD VALIGN="top">
-                                                               man macro compiler library
+                                                               mandoc macro compiler library
                                                                <SPAN STYLE="font-size: smaller;">
                                                                <SPAN STYLE="font-size: smaller;">
-                                                                       (<A HREF="man.3.txt">text</A> | 
-                                                                       <A HREF="man.3.xhtml">xhtml</A> |
-                                                                       <A HREF="man.3.pdf">pdf</A> |
-                                                                       <A HREF="man.3.ps">postscript</A>)
-                                                               </SPAN>
-                                                       </TD>
-                                               </TR>
-                                               <TR>
-                                                       <TD VALIGN="top"><A HREF="mdoc.3.html">mdoc(3)</A></TD>
-                                                       <TD VALIGN="top">
-                                                               mdoc macro compiler library
-                                                               <SPAN STYLE="font-size: smaller;">
-                                                                       (<A HREF="mdoc.3.txt">text</A> | 
-                                                                       <A HREF="mdoc.3.xhtml">xhtml</A> |
-                                                                       <A HREF="mdoc.3.pdf">pdf</A> |
-                                                                       <A HREF="mdoc.3.ps">postscript</A>)
-                                                               </SPAN>
-                                                       </TD>
-                                               </TR>
-                                               <TR>
-                                                       <TD VALIGN="top"><A HREF="roff.3.html">roff(3)</A></TD>
-                                                       <TD VALIGN="top">
-                                                               roff macro compiler library
-                                                               <SPAN STYLE="font-size: smaller;">
-                                                                       (<A HREF="roff.3.txt">text</A> | 
-                                                                       <A HREF="roff.3.xhtml">xhtml</A> |
-                                                                       <A HREF="roff.3.pdf">pdf</A> |
-                                                                       <A HREF="roff.3.ps">postscript</A>)
+                                                                       (<A HREF="mandoc.3.txt">text</A> | 
+                                                                       <A HREF="mandoc.3.xhtml">xhtml</A> |
+                                                                       <A HREF="mandoc.3.pdf">pdf</A> |
+                                                                       <A HREF="mandoc.3.ps">postscript</A>)
                                                                </SPAN>
                                                        </TD>
                                                </TR>
                                                                </SPAN>
                                                        </TD>
                                                </TR>
                                                                </SPAN>
                                                        </TD>
                                                </TR>
                                                                </SPAN>
                                                        </TD>
                                                </TR>
+                                               <TR>
+                                                       <TD VALIGN="top"><A HREF="eqn.7.html">eqn(7)</A></TD>
+                                                       <TD VALIGN="top">
+                                                               eqn-mandoc language reference
+                                                               <SPAN STYLE="font-size: smaller;">
+                                                                       (<A HREF="eqn.7.txt">text</A> | 
+                                                                       <A HREF="eqn.7.xhtml">xhtml</A> |
+                                                                       <A HREF="eqn.7.pdf">pdf</A> |
+                                                                       <A HREF="eqn.7.ps">postscript</A>)
+                                                               </SPAN>
+                                                       </TD>
+                                               </TR>
                                                <TR>
                                                        <TD VALIGN="top"><A HREF="mandoc_char.7.html">mandoc_char(7)</A></TD>
                                                        <TD VALIGN="top">
                                                <TR>
                                                        <TD VALIGN="top"><A HREF="mandoc_char.7.html">mandoc_char(7)</A></TD>
                                                        <TD VALIGN="top">
                                        </H1>
 
                                        <P>
                                        </H1>
 
                                        <P>
-                                               Please use the mailing lists for bug-reports, patches, questions, etc. (these require
-                                               subscription).  Beyond that, contact Kristaps at <A
+                                               Use the mailing lists for bug-reports, patches, questions, etc. (these require
+                                               subscription).
+                                               Please check the
+                                               <A HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/TODO?cvsroot=mdocml">TODO</A> for known issues
+                                               before posting.
+                                               Beyond that, contact Kristaps at <A
                                                HREF="http://mailhide.recaptcha.net/d?k=01M6h_w7twDp58ZgH57eWC_w==&amp;c=Q2DBUt401ePlSeupJFrq_Q=="
                                                TITLE="Reveal this e-mail address">kris...</A>@bsd.lv.
                                        </P>
                                                HREF="http://mailhide.recaptcha.net/d?k=01M6h_w7twDp58ZgH57eWC_w==&amp;c=Q2DBUt401ePlSeupJFrq_Q=="
                                                TITLE="Reveal this e-mail address">kris...</A>@bsd.lv.
                                        </P>
                                        <H1>
                                        <A NAME="news">NEWS</A>
                                        </H1>
                                        <H1>
                                        <A NAME="news">NEWS</A>
                                        </H1>
+                                       <DIV CLASS="news">
+                                               <P>
+                                                       <SPAN CLASS="date">04-04-2011</SPAN>:
+                                                       version 1.11.1
+                                               </P>
+                                               <P>
+                                                       The earlier <I>libroff</I>, <I>libmdoc</I>, and <I>libman</I> soup have been merged into
+                                                       a single library, <A HREF="mandoc.3.html">libmandoc</A>, which manages all aspects of
+                                                       parsing real manuals (from line-handling to <A HREF="tbl.7.html">tbl</A> parsing).
+                                               </P>
+                                               <P>
+                                                       Beyond this structural change, initial <A HREF="eqn.7.html">eqn</A> functionality is in
+                                                       place.  For the time being, this is limited to the recognition of equation blocks;
+                                                       future version of <SPAN CLASS="nm">mdocml</SPAN> will expand upon this framework.
+                                               </P>
+                                               <P>
+                                                       As usual, many general fixes and improvements have also occured.  In particular, a great
+                                                       deal of redundancy and superfluous code has been removed with the merging of the backend
+                                                       libraries.
+                                               </P>
+                                       </DIV>
                                        <DIV CLASS="news">
                                                <P>
                                                        <SPAN CLASS="date">07-01-2011</SPAN>:
                                        <DIV CLASS="news">
                                                <P>
                                                        <SPAN CLASS="date">07-01-2011</SPAN>:
                                                        still minimal, especially for <SPAN CLASS="flag">-Thtml</SPAN> and <SPAN
                                                        CLASS="flag">-Txhtml</SPAN>, but manages to at least display data.  This means that <A
                                                        HREF="mandoc.1.html">mandoc</A> now has built-in support for two troff preprocessors via
                                                        still minimal, especially for <SPAN CLASS="flag">-Thtml</SPAN> and <SPAN
                                                        CLASS="flag">-Txhtml</SPAN>, but manages to at least display data.  This means that <A
                                                        HREF="mandoc.1.html">mandoc</A> now has built-in support for two troff preprocessors via
-                                                       <A HREF="roff.3.html">libroff</A>: soelim and tbl.
+                                                       <DEL>libroff</DEL>: soelim and tbl.
                                                </P>
                                        </DIV>
                                        <DIV CLASS="news">
                                                </P>
                                        </DIV>
                                        <DIV CLASS="news">
                                                        HREF="#documentation">DOCUMENTATION</A> section for examples.  <SPAN
                                                        CLASS="attn">Attention: available style-sheet classes have been considerably
                                                        changed!</SPAN> See the <SPAN CLASS="file">example.style.css</SPAN> file for details.
                                                        HREF="#documentation">DOCUMENTATION</A> section for examples.  <SPAN
                                                        CLASS="attn">Attention: available style-sheet classes have been considerably
                                                        changed!</SPAN> See the <SPAN CLASS="file">example.style.css</SPAN> file for details.
-                                                       Lastly, <A HREF="mdoc.3.html">libmdoc</A> and <A HREF="man.3.html">libman</A> have been
+                                                       Lastly, <DEL>libmdoc</DEL> and <DEL>libman</DEL> have been
                                                        cleaned up and reduced in size and complexity.
                                                </P>
                                        </DIV>
                                                        cleaned up and reduced in size and complexity.
                                                </P>
                                        </DIV>
                        <TR>
                                <TD>
                                        <DIV CLASS="foot">
                        <TR>
                                <TD>
                                        <DIV CLASS="foot">
-                                               Copyright &#169; 2008&#8211;2010 Kristaps Dzonsons, $Date: 2011/01/07 13:10:03 $
+                                               Copyright &#169; 2008&#8211;2011 Kristaps Dzonsons, $Date: 2011/04/04 21:07:20 $
                                        </DIV>
                                </TD>
                        </TR>
                                        </DIV>
                                </TD>
                        </TR>
index bbf2aec..7a18a5d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: lib.c,v 1.8 2010/06/19 20:46:27 kristaps Exp $ */
+/*     $Id: lib.c,v 1.9 2011/03/22 14:33:05 kristaps Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.h"
 #include "mandoc.h"
 #include "libmdoc.h"
 
 #include "mandoc.h"
 #include "libmdoc.h"
 
index e1a9aec..30c159f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: libman.h,v 1.44 2010/11/30 15:36:28 kristaps Exp $ */
+/*     $Id: libman.h,v 1.51 2011/03/23 15:33:57 kristaps Exp $ */
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #ifndef LIBMAN_H
 #define LIBMAN_H
 
 #ifndef LIBMAN_H
 #define LIBMAN_H
 
-#include "man.h"
-
 enum   man_next {
        MAN_NEXT_SIBLING = 0,
        MAN_NEXT_CHILD
 };
 
 struct man {
 enum   man_next {
        MAN_NEXT_SIBLING = 0,
        MAN_NEXT_CHILD
 };
 
 struct man {
-       void            *data; /* private application data */
-       mandocmsg        msg; /* output message handler */
+       struct mparse   *parse; /* parse pointer */
        int              flags; /* parse flags */
 #define        MAN_HALT        (1 << 0) /* badness happened: die */
 #define        MAN_ELINE       (1 << 1) /* Next-line element scope. */
        int              flags; /* parse flags */
 #define        MAN_HALT        (1 << 0) /* badness happened: die */
 #define        MAN_ELINE       (1 << 1) /* Next-line element scope. */
@@ -34,6 +31,7 @@ struct        man {
 #define        MAN_ILINE       (1 << 3) /* Ignored in next-line scope. */
 #define        MAN_LITERAL     (1 << 4) /* Literal input. */
 #define        MAN_BPLINE      (1 << 5)
 #define        MAN_ILINE       (1 << 3) /* Ignored in next-line scope. */
 #define        MAN_LITERAL     (1 << 4) /* Literal input. */
 #define        MAN_BPLINE      (1 << 5)
+#define        MAN_NEWLINE     (1 << 6) /* first macro/text in a line */
        enum man_next    next; /* where to put the next node */
        struct man_node *last; /* the last parsed node */
        struct man_node *first; /* the first parsed node */
        enum man_next    next; /* where to put the next node */
        struct man_node *last; /* the last parsed node */
        struct man_node *first; /* the first parsed node */
@@ -63,25 +61,19 @@ extern      const struct man_macro *const man_macros;
 __BEGIN_DECLS
 
 #define                  man_pmsg(m, l, p, t) \
 __BEGIN_DECLS
 
 #define                  man_pmsg(m, l, p, t) \
-                 (*(m)->msg)((t), (m)->data, (l), (p), NULL)
+                 mandoc_msg((t), (m)->parse, (l), (p), NULL)
 #define                  man_nmsg(m, n, t) \
 #define                  man_nmsg(m, n, t) \
-                 (*(m)->msg)((t), (m)->data, (n)->line, (n)->pos, NULL)
+                 mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
 int              man_word_alloc(struct man *, int, int, const char *);
 int              man_block_alloc(struct man *, int, int, enum mant);
 int              man_head_alloc(struct man *, int, int, enum mant);
 int              man_word_alloc(struct man *, int, int, const char *);
 int              man_block_alloc(struct man *, int, int, enum mant);
 int              man_head_alloc(struct man *, int, int, enum mant);
+int              man_tail_alloc(struct man *, int, int, enum mant);
 int              man_body_alloc(struct man *, int, int, enum mant);
 int              man_elem_alloc(struct man *, int, int, enum mant);
 void             man_node_delete(struct man *, struct man_node *);
 void             man_hash_init(void);
 int              man_body_alloc(struct man *, int, int, enum mant);
 int              man_elem_alloc(struct man *, int, int, enum mant);
 void             man_node_delete(struct man *, struct man_node *);
 void             man_hash_init(void);
-enum   mant      man_hash_find(const char *);
+enum mant        man_hash_find(const char *);
 int              man_macroend(struct man *);
 int              man_macroend(struct man *);
-int              man_args(struct man *, int, int *, char *, char **);
-#define        ARGS_ERROR      (-1)
-#define        ARGS_EOLN       (0)
-#define        ARGS_WORD       (1)
-#define        ARGS_QWORD      (1)
-int              man_vmsg(struct man *, enum mandocerr,
-                       int, int, const char *, ...);
 int              man_valid_post(struct man *);
 int              man_valid_pre(struct man *, struct man_node *);
 int              man_unscope(struct man *, 
 int              man_valid_post(struct man *);
 int              man_valid_pre(struct man *, struct man_node *);
 int              man_unscope(struct man *, 
index 0e9a749..3157f29 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: libmandoc.h,v 1.10 2011/01/03 22:42:37 schwarze Exp $ */
+/*     $Id: libmandoc.h,v 1.17 2011/03/28 23:52:13 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #ifndef LIBMANDOC_H
 #define LIBMANDOC_H
 
 #ifndef LIBMANDOC_H
 #define LIBMANDOC_H
 
+enum   rofferr {
+       ROFF_CONT, /* continue processing line */
+       ROFF_RERUN, /* re-run roff interpreter with offset */
+       ROFF_APPEND, /* re-run main parser, appending next line */
+       ROFF_REPARSE, /* re-run main parser on the result */
+       ROFF_SO, /* include another file */
+       ROFF_IGN, /* ignore current line */
+       ROFF_TBL, /* a table row was successfully parsed */
+       ROFF_EQN, /* an equation was successfully parsed */
+       ROFF_ERR /* badness: puke and stop */
+};
+
+enum   regs {
+       REG_nS = 0, /* nS register */
+       REG__MAX
+};
+
+/*
+ * A register (struct reg) can consist of many types: this consists of
+ * normalised types from the original string form.  For the time being,
+ * there's only an unsigned integer type.
+ */
+union  regval {
+       unsigned  u; /* unsigned integer */
+};
+
+/*
+ * A single register entity.  If "set" is zero, the value of the
+ * register should be the default one, which is per-register.  It's
+ * assumed that callers know which type in "v" corresponds to which
+ * register value.
+ */
+struct reg {
+       int               set; /* whether set or not */
+       union regval      v; /* parsed data */
+};
+
+/*
+ * The primary interface to setting register values is in libroff,
+ * although libmdoc and libman from time to time will manipulate
+ * registers (such as `.Sh SYNOPSIS' enabling REG_nS).
+ */
+struct regset {
+       struct reg        regs[REG__MAX];
+};
+
 __BEGIN_DECLS
 
 __BEGIN_DECLS
 
+struct roff;
+struct mdoc;
+struct man;
+
+void            mandoc_msg(enum mandocerr, struct mparse *, 
+                       int, int, const char *);
+void            mandoc_vmsg(enum mandocerr, struct mparse *, 
+                       int, int, const char *, ...);
 int             mandoc_special(char *);
 int             mandoc_special(char *);
-void           *mandoc_calloc(size_t, size_t);
 char           *mandoc_strdup(const char *);
 char           *mandoc_strdup(const char *);
-void           *mandoc_malloc(size_t);
-void           *mandoc_realloc(void *, size_t);
-char           *mandoc_getarg(char **, mandocmsg, void *, int, int *);
-time_t          mandoc_a2time(int, const char *);
-#define                 MTIME_CANONICAL        (1 << 0)
-#define                 MTIME_REDUCED          (1 << 1)
-#define                 MTIME_MDOCDATE         (1 << 2)
-#define                 MTIME_ISO_8601         (1 << 3)
+char           *mandoc_getarg(struct mparse *, char **, int, int *);
+char           *mandoc_normdate(struct mparse *, char *, int, int);
 int             mandoc_eos(const char *, size_t, int);
 int             mandoc_hyph(const char *, const char *);
 int             mandoc_eos(const char *, size_t, int);
 int             mandoc_hyph(const char *, const char *);
+int             mandoc_getcontrol(const char *, int *);
+
+void            mdoc_free(struct mdoc *);
+struct mdoc    *mdoc_alloc(struct regset *, struct mparse *);
+void            mdoc_reset(struct mdoc *);
+int             mdoc_parseln(struct mdoc *, int, char *, int);
+int             mdoc_endparse(struct mdoc *);
+int             mdoc_addspan(struct mdoc *, const struct tbl_span *);
+int             mdoc_addeqn(struct mdoc *, const struct eqn *);
+
+void            man_free(struct man *);
+struct man     *man_alloc(struct regset *, struct mparse *);
+void            man_reset(struct man *);
+int             man_parseln(struct man *, int, char *, int);
+int             man_endparse(struct man *);
+int             man_addspan(struct man *, const struct tbl_span *);
+int             man_addeqn(struct man *, const struct eqn *);
+
+void            roff_free(struct roff *);
+struct roff    *roff_alloc(struct regset *, struct mparse *);
+void            roff_reset(struct roff *);
+enum rofferr    roff_parseln(struct roff *, int, 
+                       char **, size_t *, int, int *);
+void            roff_endparse(struct roff *);
+
+const struct tbl_span  *roff_span(const struct roff *);
+const struct eqn       *roff_eqn(const struct roff *);
 
 __END_DECLS
 
 
 __END_DECLS
 
index 5a46d1c..2a55eb3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: libmdoc.h,v 1.63 2010/11/30 13:04:14 kristaps Exp $ */
+/*     $Id: libmdoc.h,v 1.72 2011/03/22 14:33:05 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #ifndef LIBMDOC_H
 #define LIBMDOC_H
 
 #ifndef LIBMDOC_H
 #define LIBMDOC_H
 
-#include "mdoc.h"
-
 enum   mdoc_next {
        MDOC_NEXT_SIBLING = 0,
        MDOC_NEXT_CHILD
 };
 
 struct mdoc {
 enum   mdoc_next {
        MDOC_NEXT_SIBLING = 0,
        MDOC_NEXT_CHILD
 };
 
 struct mdoc {
-       void             *data; /* private application data */
-       mandocmsg         msg; /* message callback */
-       int               flags;
+       struct mparse    *parse; /* parse pointer */
+       int               flags; /* parse flags */
 #define        MDOC_HALT        (1 << 0) /* error in parse: halt */
 #define        MDOC_LITERAL     (1 << 1) /* in a literal scope */
 #define        MDOC_PBODY       (1 << 2) /* in the document body */
 #define        MDOC_HALT        (1 << 0) /* error in parse: halt */
 #define        MDOC_LITERAL     (1 << 1) /* in a literal scope */
 #define        MDOC_PBODY       (1 << 2) /* in the document body */
@@ -81,11 +78,21 @@ enum        margverr {
        ARGV_WORD
 };
 
        ARGV_WORD
 };
 
+/*
+ * A punctuation delimiter is opening, closing, or "middle mark"
+ * punctuation.  These govern spacing.
+ * Opening punctuation (e.g., the opening parenthesis) suppresses the
+ * following space; closing punctuation (e.g., the closing parenthesis)
+ * suppresses the leading space; middle punctuation (e.g., the vertical
+ * bar) can do either.  The middle punctuation delimiter bends the rules
+ * depending on usage.
+ */
 enum   mdelim {
        DELIM_NONE = 0,
        DELIM_OPEN,
        DELIM_MIDDLE,
 enum   mdelim {
        DELIM_NONE = 0,
        DELIM_OPEN,
        DELIM_MIDDLE,
-       DELIM_CLOSE
+       DELIM_CLOSE,
+       DELIM_MAX
 };
 
 extern const struct mdoc_macro *const mdoc_macros;
 };
 
 extern const struct mdoc_macro *const mdoc_macros;
@@ -93,11 +100,9 @@ extern      const struct mdoc_macro *const mdoc_macros;
 __BEGIN_DECLS
 
 #define                  mdoc_pmsg(m, l, p, t) \
 __BEGIN_DECLS
 
 #define                  mdoc_pmsg(m, l, p, t) \
-                 (*(m)->msg)((t), (m)->data, (l), (p), NULL)
+                 mandoc_msg((t), (m)->parse, (l), (p), NULL)
 #define                  mdoc_nmsg(m, n, t) \
 #define                  mdoc_nmsg(m, n, t) \
-                 (*(m)->msg)((t), (m)->data, (n)->line, (n)->pos, NULL)
-int              mdoc_vmsg(struct mdoc *, enum mandocerr, 
-                       int, int, const char *, ...);
+                 mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
 int              mdoc_macro(MACRO_PROT_ARGS);
 int              mdoc_word_alloc(struct mdoc *, 
                        int, int, const char *);
 int              mdoc_macro(MACRO_PROT_ARGS);
 int              mdoc_word_alloc(struct mdoc *, 
                        int, int, const char *);
@@ -114,12 +119,6 @@ int                  mdoc_endbody_alloc(struct mdoc *m, int line, int pos,
 void             mdoc_node_delete(struct mdoc *, struct mdoc_node *);
 void             mdoc_hash_init(void);
 enum mdoct       mdoc_hash_find(const char *);
 void             mdoc_node_delete(struct mdoc *, struct mdoc_node *);
 void             mdoc_hash_init(void);
 enum mdoct       mdoc_hash_find(const char *);
-enum mdelim      mdoc_iscdelim(char);
-enum mdelim      mdoc_isdelim(const char *);
-size_t           mdoc_isescape(const char *);
-enum   mdoc_sec  mdoc_str2sec(const char *);
-time_t           mdoc_atotime(const char *);
-size_t           mdoc_macro2len(enum mdoct);
 const char      *mdoc_a2att(const char *);
 const char      *mdoc_a2lib(const char *);
 const char      *mdoc_a2st(const char *);
 const char      *mdoc_a2att(const char *);
 const char      *mdoc_a2lib(const char *);
 const char      *mdoc_a2st(const char *);
@@ -131,7 +130,6 @@ int           mdoc_valid_post(struct mdoc *);
 enum margverr    mdoc_argv(struct mdoc *, int, enum mdoct,
                        struct mdoc_arg **, int *, char *);
 void             mdoc_argv_free(struct mdoc_arg *);
 enum margverr    mdoc_argv(struct mdoc *, int, enum mdoct,
                        struct mdoc_arg **, int *, char *);
 void             mdoc_argv_free(struct mdoc_arg *);
-void             mdoc_argn_free(struct mdoc_arg *, int);
 enum margserr    mdoc_args(struct mdoc *, int,
                        int *, char *, enum mdoct, char **);
 enum margserr    mdoc_zargs(struct mdoc *, int, 
 enum margserr    mdoc_args(struct mdoc *, int,
                        int *, char *, enum mdoct, char **);
 enum margserr    mdoc_zargs(struct mdoc *, int, 
@@ -142,6 +140,9 @@ enum margserr         mdoc_zargs(struct mdoc *, int,
 
 int              mdoc_macroend(struct mdoc *);
 
 
 int              mdoc_macroend(struct mdoc *);
 
+#define        DELIMSZ   6 /* hint: max possible size of a delimiter */
+enum mdelim      mdoc_isdelim(const char *);
+
 __END_DECLS
 
 #endif /*!LIBMDOC_H*/
 __END_DECLS
 
 #endif /*!LIBMDOC_H*/
index b4e043a..d013688 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: libroff.h,v 1.16 2011/01/04 15:02:00 kristaps Exp $ */
+/*     $Id: libroff.h,v 1.20 2011/03/20 16:02:05 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -27,8 +27,7 @@ enum  tbl_part {
 };
 
 struct tbl_node {
 };
 
 struct tbl_node {
-       mandocmsg         msg; /* status messages */
-       void             *data; /* privdata for messages */
+       struct mparse    *parse; /* parse point */
        int               pos; /* invocation column */
        int               line; /* invocation line */
        enum tbl_part     part;
        int               pos; /* invocation column */
        int               line; /* invocation line */
        enum tbl_part     part;
@@ -36,16 +35,19 @@ struct      tbl_node {
        struct tbl_row   *first_row;
        struct tbl_row   *last_row;
        struct tbl_span  *first_span;
        struct tbl_row   *first_row;
        struct tbl_row   *last_row;
        struct tbl_span  *first_span;
+       struct tbl_span  *current_span;
        struct tbl_span  *last_span;
        struct tbl_head  *first_head;
        struct tbl_head  *last_head;
        struct tbl_node  *next;
 };
 
        struct tbl_span  *last_span;
        struct tbl_head  *first_head;
        struct tbl_head  *last_head;
        struct tbl_node  *next;
 };
 
-#define        TBL_MSG(tblp, type, line, col) \
-       (*(tblp)->msg)((type), (tblp)->data, (line), (col), NULL)
+struct eqn_node {
+       struct eqn        eqn;
+       struct eqn_node  *next;
+};
 
 
-struct tbl_node        *tbl_alloc(int, int, void *, mandocmsg);
+struct tbl_node        *tbl_alloc(int, int, struct mparse *);
 void            tbl_restart(int, int, struct tbl_node *);
 void            tbl_free(struct tbl_node *);
 void            tbl_reset(struct tbl_node *);
 void            tbl_restart(int, int, struct tbl_node *);
 void            tbl_free(struct tbl_node *);
 void            tbl_reset(struct tbl_node *);
@@ -54,8 +56,12 @@ int           tbl_option(struct tbl_node *, int, const char *);
 int             tbl_layout(struct tbl_node *, int, const char *);
 int             tbl_data(struct tbl_node *, int, const char *);
 int             tbl_cdata(struct tbl_node *, int, const char *);
 int             tbl_layout(struct tbl_node *, int, const char *);
 int             tbl_data(struct tbl_node *, int, const char *);
 int             tbl_cdata(struct tbl_node *, int, const char *);
-const struct tbl_span *tbl_span(const struct tbl_node *);
+const struct tbl_span  *tbl_span(struct tbl_node *);
 void            tbl_end(struct tbl_node *);
 void            tbl_end(struct tbl_node *);
+struct eqn_node        *eqn_alloc(int, int);
+void            eqn_end(struct eqn_node *);
+void            eqn_free(struct eqn_node *);
+enum rofferr    eqn_read(struct eqn_node **, int, const char *, int);
 
 __END_DECLS
 
 
 __END_DECLS
 
index 2be68a9..bbbb884 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: main.c,v 1.135 2011/01/04 15:02:00 kristaps Exp $ */
+/*     $Id: main.c,v 1.161 2011/03/31 10:53:43 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "config.h"
 #endif
 
 #include "config.h"
 #endif
 
-#include <sys/mman.h>
-#include <sys/stat.h>
-
 #include <assert.h>
 #include <assert.h>
-#include <ctype.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include "main.h"
 #include "mdoc.h"
 #include "man.h"
 #include "main.h"
 #include "mdoc.h"
 #include "man.h"
-#include "roff.h"
-
-#ifndef MAP_FILE
-#define        MAP_FILE        0
-#endif
-
-#define        REPARSE_LIMIT   1000
-#define        UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))
-
-/* FIXME: Intel's compiler?  LLVM?  pcc?  */
 
 #if !defined(__GNUC__) || (__GNUC__ < 2)
 # if !defined(lint)
 
 #if !defined(__GNUC__) || (__GNUC__ < 2)
 # if !defined(lint)
@@ -56,41 +41,20 @@ typedef     void            (*out_mdoc)(void *, const struct mdoc *);
 typedef        void            (*out_man)(void *, const struct man *);
 typedef        void            (*out_free)(void *);
 
 typedef        void            (*out_man)(void *, const struct man *);
 typedef        void            (*out_free)(void *);
 
-struct buf {
-       char             *buf;
-       size_t            sz;
-};
-
-enum   intt {
-       INTT_AUTO,
-       INTT_MDOC,
-       INTT_MAN
-};
-
 enum   outt {
 enum   outt {
-       OUTT_ASCII = 0,
-       OUTT_TREE,
-       OUTT_HTML,
-       OUTT_XHTML,
-       OUTT_LINT,
-       OUTT_PS,
-       OUTT_PDF
+       OUTT_ASCII = 0, /* -Tascii */
+       OUTT_TREE,      /* -Ttree */
+       OUTT_HTML,      /* -Thtml */
+       OUTT_XHTML,     /* -Txhtml */
+       OUTT_LINT,      /* -Tlint */
+       OUTT_PS,        /* -Tps */
+       OUTT_PDF        /* -Tpdf */
 };
 
 struct curparse {
 };
 
 struct curparse {
-       const char       *file;         /* Current parse. */
-       int               fd;           /* Current parse. */
-       int               line;         /* Line number in the file. */
-       enum mandoclevel  wlevel;       /* Ignore messages below this. */
-       int               wstop;        /* Stop after a file with a warning. */
-       enum intt         inttype;      /* which parser to use */
-       struct man       *pman;         /* persistent man parser */
-       struct mdoc      *pmdoc;        /* persistent mdoc parser */
-       struct man       *man;          /* man parser */
-       struct mdoc      *mdoc;         /* mdoc parser */
-       struct roff      *roff;         /* roff parser (!NULL) */
-       struct regset     regs;         /* roff registers */
-       int               reparse_count; /* finite interpolation stack */
+       struct mparse    *mp;
+       enum mandoclevel  wlevel;       /* ignore messages below this */
+       int               wstop;        /* stop after a file with a warning */
        enum outt         outtype;      /* which output to use */
        out_mdoc          outmdoc;      /* mdoc output ptr */
        out_man           outman;       /* man output ptr */
        enum outt         outtype;      /* which output to use */
        out_mdoc          outmdoc;      /* mdoc output ptr */
        out_man           outman;       /* man output ptr */
@@ -99,154 +63,25 @@ struct     curparse {
        char              outopts[BUFSIZ]; /* buf of output opts */
 };
 
        char              outopts[BUFSIZ]; /* buf of output opts */
 };
 
-static const char * const      mandoclevels[MANDOCLEVEL_MAX] = {
-       "SUCCESS",
-       "RESERVED",
-       "WARNING",
-       "ERROR",
-       "FATAL",
-       "BADARG",
-       "SYSERR"
-};
-
-static const enum mandocerr    mandoclimits[MANDOCLEVEL_MAX] = {
-       MANDOCERR_OK,
-       MANDOCERR_WARNING,
-       MANDOCERR_WARNING,
-       MANDOCERR_ERROR,
-       MANDOCERR_FATAL,
-       MANDOCERR_MAX,
-       MANDOCERR_MAX
-};
-
-static const char * const      mandocerrs[MANDOCERR_MAX] = {
-       "ok",
-
-       "generic warning",
-
-       /* related to the prologue */
-       "no title in document",
-       "document title should be all caps",
-       "unknown manual section",
-       "cannot parse date argument",
-       "prologue macros out of order",
-       "duplicate prologue macro",
-       "macro not allowed in prologue",
-       "macro not allowed in body",
-
-       /* related to document structure */
-       ".so is fragile, better use ln(1)",
-       "NAME section must come first",
-       "bad NAME section contents",
-       "manual name not yet set",
-       "sections out of conventional order",
-       "duplicate section name",
-       "section not in conventional manual section",
-
-       /* related to macros and nesting */
-       "skipping obsolete macro",
-       "skipping paragraph macro",
-       "blocks badly nested",
-       "child violates parent syntax",
-       "nested displays are not portable",
-       "already in literal mode",
-
-       /* related to missing macro arguments */
-       "skipping empty macro",
-       "argument count wrong",
-       "missing display type",
-       "list type must come first",
-       "tag lists require a width argument",
-       "missing font type",
-
-       /* related to bad macro arguments */
-       "skipping argument",
-       "duplicate argument",
-       "duplicate display type",
-       "duplicate list type",
-       "unknown AT&T UNIX version",
-       "bad Boolean value",
-       "unknown font",
-       "unknown standard specifier",
-       "bad width argument",
-
-       /* related to plain text */
-       "blank line in non-literal context",
-       "tab in non-literal context",
-       "end of line whitespace",
-       "bad comment style",
-       "unknown escape sequence",
-       "unterminated quoted string",
-       
-       /* related to tables */
-       "extra data cells",
-
-       "generic error",
-
-       /* related to tables */
-       "bad table syntax",
-       "bad table option",
-       "bad table layout",
-       "no table layout cells specified",
-       "no table data cells specified",
-       "ignore data in cell",
-       "data block still open",
-
-       "input stack limit exceeded, infinite loop?",
-       "skipping bad character",
-       "skipping text before the first section header",
-       "skipping unknown macro",
-       "NOT IMPLEMENTED: skipping request",
-       "line scope broken",
-       "argument count wrong",
-       "skipping end of block that is not open",
-       "missing end of block",
-       "scope open on exit",
-       "uname(3) system call failed",
-       "macro requires line argument(s)",
-       "macro requires body argument(s)",
-       "macro requires argument(s)",
-       "missing list type",
-       "line argument(s) will be lost",
-       "body argument(s) will be lost",
-
-       "generic fatal error",
-
-       "column syntax is inconsistent",
-       "NOT IMPLEMENTED: .Bd -file",
-       "line scope broken, syntax violated",
-       "argument count wrong, violates syntax",
-       "child violates parent syntax",
-       "argument count wrong, violates syntax",
-       "NOT IMPLEMENTED: .so with absolute path or \"..\"",
-       "no document body",
-       "no document prologue",
-       "static buffer exhausted",
-};
-
-static void              parsebuf(struct curparse *, struct buf, int);
-static void              pdesc(struct curparse *);
-static void              fdesc(struct curparse *);
-static void              ffile(const char *, struct curparse *);
-static int               pfile(const char *, struct curparse *);
-static int               moptions(enum intt *, char *);
-static int               mmsg(enum mandocerr, void *, 
-                               int, int, const char *);
-static void              pset(const char *, int, struct curparse *);
+static int               moptions(enum mparset *, char *);
+static void              mmsg(enum mandocerr, enum mandoclevel,
+                               const char *, int, int, const char *);
+static void              parse(struct curparse *, int, 
+                               const char *, enum mandoclevel *);
 static int               toptions(struct curparse *, char *);
 static void              usage(void) __attribute__((noreturn));
 static void              version(void) __attribute__((noreturn));
 static int               woptions(struct curparse *, char *);
 
 static const char       *progname;
 static int               toptions(struct curparse *, char *);
 static void              usage(void) __attribute__((noreturn));
 static void              version(void) __attribute__((noreturn));
 static int               woptions(struct curparse *, char *);
 
 static const char       *progname;
-static enum mandoclevel  file_status = MANDOCLEVEL_OK;
-static enum mandoclevel  exit_status = MANDOCLEVEL_OK;
 
 int
 main(int argc, char *argv[])
 {
        int              c;
        struct curparse  curp;
 
 int
 main(int argc, char *argv[])
 {
        int              c;
        struct curparse  curp;
+       enum mparset     type;
+       enum mandoclevel rc;
 
        progname = strrchr(argv[0], '/');
        if (progname == NULL)
 
        progname = strrchr(argv[0], '/');
        if (progname == NULL)
@@ -256,7 +91,7 @@ main(int argc, char *argv[])
 
        memset(&curp, 0, sizeof(struct curparse));
 
 
        memset(&curp, 0, sizeof(struct curparse));
 
-       curp.inttype = INTT_AUTO;
+       type = MPARSE_AUTO;
        curp.outtype = OUTT_ASCII;
        curp.wlevel  = MANDOCLEVEL_FATAL;
 
        curp.outtype = OUTT_ASCII;
        curp.wlevel  = MANDOCLEVEL_FATAL;
 
@@ -264,7 +99,7 @@ main(int argc, char *argv[])
        while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
                switch (c) {
                case ('m'):
        while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
                switch (c) {
                case ('m'):
-                       if ( ! moptions(&curp.inttype, optarg))
+                       if ( ! moptions(&type, optarg))
                                return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('O'):
                                return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('O'):
@@ -287,56 +122,50 @@ main(int argc, char *argv[])
                        /* NOTREACHED */
                }
 
                        /* NOTREACHED */
                }
 
+       curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
-       if (NULL == *argv) {
-               curp.file = "<stdin>";
-               curp.fd = STDIN_FILENO;
+       rc = MANDOCLEVEL_OK;
 
 
-               fdesc(&curp);
-       }
+       if (NULL == *argv)
+               parse(&curp, STDIN_FILENO, "<stdin>", &rc);
 
        while (*argv) {
 
        while (*argv) {
-               ffile(*argv, &curp);
-               if (MANDOCLEVEL_OK != exit_status && curp.wstop)
+               parse(&curp, -1, *argv, &rc);
+               if (MANDOCLEVEL_OK != rc && curp.wstop)
                        break;
                ++argv;
        }
 
        if (curp.outfree)
                (*curp.outfree)(curp.outdata);
                        break;
                ++argv;
        }
 
        if (curp.outfree)
                (*curp.outfree)(curp.outdata);
-       if (curp.pmdoc)
-               mdoc_free(curp.pmdoc);
-       if (curp.pman)
-               man_free(curp.pman);
-       if (curp.roff)
-               roff_free(curp.roff);
+       if (curp.mp)
+               mparse_free(curp.mp);
 
 
-       return((int)exit_status);
+       return((int)rc);
 }
 
 }
 
-
 static void
 version(void)
 {
 
 static void
 version(void)
 {
 
-       (void)printf("%s %s\n", progname, VERSION);
+       printf("%s %s\n", progname, VERSION);
        exit((int)MANDOCLEVEL_OK);
 }
 
        exit((int)MANDOCLEVEL_OK);
 }
 
-
 static void
 usage(void)
 {
 
 static void
 usage(void)
 {
 
-       (void)fprintf(stderr, "usage: %s "
+       fprintf(stderr, "usage: %s "
                        "[-V] "
                        "[-foption] "
                        "[-mformat] "
                        "[-Ooption] "
                        "[-Toutput] "
                        "[-V] "
                        "[-foption] "
                        "[-mformat] "
                        "[-Ooption] "
                        "[-Toutput] "
-                       "[-Werr] "
+                       "[-Wlevel] "
                        "[file...]\n", 
                        progname);
 
                        "[file...]\n", 
                        progname);
 
@@ -344,205 +173,31 @@ usage(void)
 }
 
 static void
 }
 
 static void
-ffile(const char *file, struct curparse *curp)
-{
-
-       /*
-        * Called once per input file.  Get the file ready for reading,
-        * pass it through to the parser-driver, then close it out.
-        * XXX: don't do anything special as this is only called for
-        * files; stdin goes directly to fdesc().
-        */
-
-       curp->file = file;
-
-       if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
-               perror(curp->file);
-               exit_status = MANDOCLEVEL_SYSERR;
-               return;
-       }
-
-       fdesc(curp);
-
-       if (-1 == close(curp->fd))
-               perror(curp->file);
-}
-
-static int
-pfile(const char *file, struct curparse *curp)
-{
-       const char      *savefile;
-       int              fd, savefd;
-
-       if (-1 == (fd = open(file, O_RDONLY, 0))) {
-               perror(file);
-               file_status = MANDOCLEVEL_SYSERR;
-               return(0);
-       }
-
-       savefile = curp->file;
-       savefd = curp->fd;
-
-       curp->file = file;
-       curp->fd = fd;
-
-       pdesc(curp);
-
-       curp->file = savefile;
-       curp->fd = savefd;
-
-       if (-1 == close(fd))
-               perror(file);
-
-       return(MANDOCLEVEL_FATAL > file_status ? 1 : 0);
-}
-
-
-static void
-resize_buf(struct buf *buf, size_t initial)
-{
-
-       buf->sz = buf->sz > initial/2 ? 2 * buf->sz : initial;
-       buf->buf = realloc(buf->buf, buf->sz);
-       if (NULL == buf->buf) {
-               perror(NULL);
-               exit((int)MANDOCLEVEL_SYSERR);
-       }
-}
-
-
-static int
-read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
-{
-       struct stat      st;
-       size_t           off;
-       ssize_t          ssz;
-
-       if (-1 == fstat(curp->fd, &st)) {
-               perror(curp->file);
-               return(0);
-       }
-
-       /*
-        * If we're a regular file, try just reading in the whole entry
-        * via mmap().  This is faster than reading it into blocks, and
-        * since each file is only a few bytes to begin with, I'm not
-        * concerned that this is going to tank any machines.
-        */
-
-       if (S_ISREG(st.st_mode)) {
-               if (st.st_size >= (1U << 31)) {
-                       fprintf(stderr, "%s: input too large\n", 
-                                       curp->file);
-                       return(0);
-               }
-               *with_mmap = 1;
-               fb->sz = (size_t)st.st_size;
-               fb->buf = mmap(NULL, fb->sz, PROT_READ, 
-                               MAP_FILE|MAP_SHARED, curp->fd, 0);
-               if (fb->buf != MAP_FAILED)
-                       return(1);
-       }
-
-       /*
-        * If this isn't a regular file (like, say, stdin), then we must
-        * go the old way and just read things in bit by bit.
-        */
-
-       *with_mmap = 0;
-       off = 0;
-       fb->sz = 0;
-       fb->buf = NULL;
-       for (;;) {
-               if (off == fb->sz) {
-                       if (fb->sz == (1U << 31)) {
-                               fprintf(stderr, "%s: input too large\n", 
-                                               curp->file);
-                               break;
-                       }
-                       resize_buf(fb, 65536);
-               }
-               ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
-               if (ssz == 0) {
-                       fb->sz = off;
-                       return(1);
-               }
-               if (ssz == -1) {
-                       perror(curp->file);
-                       break;
-               }
-               off += (size_t)ssz;
-       }
-
-       free(fb->buf);
-       fb->buf = NULL;
-       return(0);
-}
-
-
-static void
-fdesc(struct curparse *curp)
+parse(struct curparse *curp, int fd, 
+               const char *file, enum mandoclevel *level)
 {
 {
+       enum mandoclevel  rc;
+       struct mdoc      *mdoc;
+       struct man       *man;
 
 
-       /*
-        * Called once per file with an opened file descriptor.  All
-        * pre-file-parse operations (whether stdin or a file) should go
-        * here.
-        *
-        * This calls down into the nested parser, which drills down and
-        * fully parses a file and all its dependences (i.e., `so').  It
-        * then runs the cleanup validators and pushes to output.
-        */
-
-       /* Zero the parse type. */
-
-       curp->mdoc = NULL;
-       curp->man = NULL;
-       file_status = MANDOCLEVEL_OK;
-
-       /* Make sure the mandotory roff parser is initialised. */
+       /* Begin by parsing the file itself. */
 
 
-       if (NULL == curp->roff) {
-               curp->roff = roff_alloc(&curp->regs, curp, mmsg);
-               assert(curp->roff);
-       }
-
-       /* Fully parse the file. */
-
-       pdesc(curp);
+       assert(file);
+       assert(fd >= -1);
 
 
-       if (MANDOCLEVEL_FATAL <= file_status)
-               goto cleanup;
+       rc = mparse_readfd(curp->mp, fd, file);
 
 
-       /* NOTE a parser may not have been assigned, yet. */
+       /* Stop immediately if the parse has failed. */
 
 
-       if ( ! (curp->man || curp->mdoc)) {
-               fprintf(stderr, "%s: Not a manual\n", curp->file);
-               file_status = MANDOCLEVEL_FATAL;
+       if (MANDOCLEVEL_FATAL <= rc)
                goto cleanup;
                goto cleanup;
-       }
-
-       /* Clean up the parse routine ASTs. */
-
-       if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
-               assert(MANDOCLEVEL_FATAL <= file_status);
-               goto cleanup;
-       }
-
-       if (curp->man && ! man_endparse(curp->man)) {
-               assert(MANDOCLEVEL_FATAL <= file_status);
-               goto cleanup;
-       }
-
-       assert(curp->roff);
-       roff_endparse(curp->roff);
 
        /*
 
        /*
-        * With -Wstop and warnings or errors of at least
-        * the requested level, do not produce output.
+        * With -Wstop and warnings or errors of at least the requested
+        * level, do not produce output.
         */
 
         */
 
-       if (MANDOCLEVEL_OK != file_status && curp->wstop)
+       if (MANDOCLEVEL_OK != rc && curp->wstop)
                goto cleanup;
 
        /* If unset, allocate output dev now (if applicable). */
                goto cleanup;
 
        /* If unset, allocate output dev now (if applicable). */
@@ -596,347 +251,33 @@ fdesc(struct curparse *curp)
                }
        }
 
                }
        }
 
+       mparse_result(curp->mp, &mdoc, &man);
+
        /* Execute the out device, if it exists. */
 
        /* Execute the out device, if it exists. */
 
-       if (curp->man && curp->outman)
-               (*curp->outman)(curp->outdata, curp->man);
-       if (curp->mdoc && curp->outmdoc)
-               (*curp->outmdoc)(curp->outdata, curp->mdoc);
+       if (man && curp->outman)
+               (*curp->outman)(curp->outdata, man);
+       if (mdoc && curp->outmdoc)
+               (*curp->outmdoc)(curp->outdata, mdoc);
 
  cleanup:
 
 
  cleanup:
 
-       memset(&curp->regs, 0, sizeof(struct regset));
-
-       /* Reset the current-parse compilers. */
-
-       if (curp->mdoc)
-               mdoc_reset(curp->mdoc);
-       if (curp->man)
-               man_reset(curp->man);
-
-       assert(curp->roff);
-       roff_reset(curp->roff);
-
-       if (exit_status < file_status)
-               exit_status = file_status;
-
-       return;
-}
-
-static void
-pdesc(struct curparse *curp)
-{
-       struct buf       blk;
-       int              with_mmap;
-
-       /*
-        * Run for each opened file; may be called more than once for
-        * each full parse sequence if the opened file is nested (i.e.,
-        * from `so').  Simply sucks in the whole file and moves into
-        * the parse phase for the file.
-        */
-
-       if ( ! read_whole_file(curp, &blk, &with_mmap)) {
-               file_status = MANDOCLEVEL_SYSERR;
-               return;
-       }
-
-       /* Line number is per-file. */
-
-       curp->line = 1;
-
-       parsebuf(curp, blk, 1);
+       mparse_reset(curp->mp);
 
 
-       if (with_mmap)
-               munmap(blk.buf, blk.sz);
-       else
-               free(blk.buf);
-}
-
-static void
-parsebuf(struct curparse *curp, struct buf blk, int start)
-{
-       struct buf       ln;
-       enum rofferr     rr;
-       int              i, of, rc;
-       int              pos; /* byte number in the ln buffer */
-       int              lnn; /* line number in the real file */
-       unsigned char    c;
-
-       /*
-        * Main parse routine for an opened file.  This is called for
-        * each opened file and simply loops around the full input file,
-        * possibly nesting (i.e., with `so').
-        */
-
-       memset(&ln, 0, sizeof(struct buf));
-
-       lnn = curp->line; 
-       pos = 0; 
-
-       for (i = 0; i < (int)blk.sz; ) {
-               if (0 == pos && '\0' == blk.buf[i])
-                       break;
-
-               if (start) {
-                       curp->line = lnn;
-                       curp->reparse_count = 0;
-               }
-
-               while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
-                       if ('\n' == blk.buf[i]) {
-                               ++i;
-                               ++lnn;
-                               break;
-                       }
-
-                       /* 
-                        * Warn about bogus characters.  If you're using
-                        * non-ASCII encoding, you're screwing your
-                        * readers.  Since I'd rather this not happen,
-                        * I'll be helpful and drop these characters so
-                        * we don't display gibberish.  Note to manual
-                        * writers: use special characters.
-                        */
-
-                       c = (unsigned char) blk.buf[i];
-
-                       if ( ! (isascii(c) && 
-                                       (isgraph(c) || isblank(c)))) {
-                               mmsg(MANDOCERR_BADCHAR, curp, 
-                                   curp->line, pos, "ignoring byte");
-                               i++;
-                               continue;
-                       }
-
-                       /* Trailing backslash = a plain char. */
-
-                       if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
-                               if (pos >= (int)ln.sz)
-                                       resize_buf(&ln, 256);
-                               ln.buf[pos++] = blk.buf[i++];
-                               continue;
-                       }
-
-                       /* Found escape & at least one other char. */
-
-                       if ('\n' == blk.buf[i + 1]) {
-                               i += 2;
-                               /* Escaped newlines are skipped over */
-                               ++lnn;
-                               continue;
-                       }
-
-                       if ('"' == blk.buf[i + 1]) {
-                               i += 2;
-                               /* Comment, skip to end of line */
-                               for (; i < (int)blk.sz; ++i) {
-                                       if ('\n' == blk.buf[i]) {
-                                               ++i;
-                                               ++lnn;
-                                               break;
-                                       }
-                               }
-
-                               /* Backout trailing whitespaces */
-                               for (; pos > 0; --pos) {
-                                       if (ln.buf[pos - 1] != ' ')
-                                               break;
-                                       if (pos > 2 && ln.buf[pos - 2] == '\\')
-                                               break;
-                               }
-                               break;
-                       }
-
-                       /* Some other escape sequence, copy & cont. */
-
-                       if (pos + 1 >= (int)ln.sz)
-                               resize_buf(&ln, 256);
-
-                       ln.buf[pos++] = blk.buf[i++];
-                       ln.buf[pos++] = blk.buf[i++];
-               }
-
-               if (pos >= (int)ln.sz)
-                       resize_buf(&ln, 256);
-
-               ln.buf[pos] = '\0';
-
-               /*
-                * A significant amount of complexity is contained by
-                * the roff preprocessor.  It's line-oriented but can be
-                * expressed on one line, so we need at times to
-                * readjust our starting point and re-run it.  The roff
-                * preprocessor can also readjust the buffers with new
-                * data, so we pass them in wholesale.
-                */
-
-               of = 0;
-
-rerun:
-               rr = roff_parseln
-                       (curp->roff, curp->line, 
-                        &ln.buf, &ln.sz, of, &of);
-
-               switch (rr) {
-               case (ROFF_REPARSE):
-                       if (REPARSE_LIMIT >= ++curp->reparse_count)
-                               parsebuf(curp, ln, 0);
-                       else
-                               mmsg(MANDOCERR_ROFFLOOP, curp, 
-                                   curp->line, pos, NULL);
-                       pos = 0;
-                       continue;
-               case (ROFF_APPEND):
-                       pos = strlen(ln.buf);
-                       continue;
-               case (ROFF_RERUN):
-                       goto rerun;
-               case (ROFF_IGN):
-                       pos = 0;
-                       continue;
-               case (ROFF_ERR):
-                       assert(MANDOCLEVEL_FATAL <= file_status);
-                       break;
-               case (ROFF_SO):
-                       if (pfile(ln.buf + of, curp)) {
-                               pos = 0;
-                               continue;
-                       } else
-                               break;
-               default:
-                       break;
-               }
-
-               /*
-                * If we encounter errors in the recursive parsebuf()
-                * call, make sure we don't continue parsing.
-                */
-
-               if (MANDOCLEVEL_FATAL <= file_status)
-                       break;
-
-               /*
-                * If input parsers have not been allocated, do so now.
-                * We keep these instanced betwen parsers, but set them
-                * locally per parse routine since we can use different
-                * parsers with each one.
-                */
-
-               if ( ! (curp->man || curp->mdoc))
-                       pset(ln.buf + of, pos - of, curp);
-
-               /* 
-                * Lastly, push down into the parsers themselves.  One
-                * of these will have already been set in the pset()
-                * routine.
-                * If libroff returns ROFF_TBL, then add it to the
-                * currently open parse.  Since we only get here if
-                * there does exist data (see tbl_data.c), we're
-                * guaranteed that something's been allocated.
-                */
-
-               if (ROFF_TBL == rr) {
-                       assert(curp->man || curp->mdoc);
-                       if (curp->man)
-                               man_addspan(curp->man, roff_span(curp->roff));
-                       else
-                               mdoc_addspan(curp->mdoc, roff_span(curp->roff));
-
-               } else if (curp->man || curp->mdoc) {
-                       rc = curp->man ?
-                               man_parseln(curp->man, 
-                                       curp->line, ln.buf, of) :
-                               mdoc_parseln(curp->mdoc, 
-                                       curp->line, ln.buf, of);
-
-                       if ( ! rc) {
-                               assert(MANDOCLEVEL_FATAL <= file_status);
-                               break;
-                       }
-               }
-
-               /* Temporary buffers typically are not full. */
-
-               if (0 == start && '\0' == blk.buf[i])
-                       break;
-
-               /* Start the next input line. */
-
-               pos = 0;
-       }
-
-       free(ln.buf);
-}
-
-static void
-pset(const char *buf, int pos, struct curparse *curp)
-{
-       int              i;
-
-       /*
-        * Try to intuit which kind of manual parser should be used.  If
-        * passed in by command-line (-man, -mdoc), then use that
-        * explicitly.  If passed as -mandoc, then try to guess from the
-        * line: either skip dot-lines, use -mdoc when finding `.Dt', or
-        * default to -man, which is more lenient.
-        *
-        * Separate out pmdoc/pman from mdoc/man: the first persists
-        * through all parsers, while the latter is used per-parse.
-        */
-
-       if ('.' == buf[0] || '\'' == buf[0]) {
-               for (i = 1; buf[i]; i++)
-                       if (' ' != buf[i] && '\t' != buf[i])
-                               break;
-               if ('\0' == buf[i])
-                       return;
-       }
-
-       switch (curp->inttype) {
-       case (INTT_MDOC):
-               if (NULL == curp->pmdoc) 
-                       curp->pmdoc = mdoc_alloc
-                               (&curp->regs, curp, mmsg);
-               assert(curp->pmdoc);
-               curp->mdoc = curp->pmdoc;
-               return;
-       case (INTT_MAN):
-               if (NULL == curp->pman) 
-                       curp->pman = man_alloc
-                               (&curp->regs, curp, mmsg);
-               assert(curp->pman);
-               curp->man = curp->pman;
-               return;
-       default:
-               break;
-       }
-
-       if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3))  {
-               if (NULL == curp->pmdoc) 
-                       curp->pmdoc = mdoc_alloc
-                               (&curp->regs, curp, mmsg);
-               assert(curp->pmdoc);
-               curp->mdoc = curp->pmdoc;
-               return;
-       } 
-
-       if (NULL == curp->pman) 
-               curp->pman = man_alloc(&curp->regs, curp, mmsg);
-       assert(curp->pman);
-       curp->man = curp->pman;
+       if (*level < rc)
+               *level = rc;
 }
 
 static int
 }
 
 static int
-moptions(enum intt *tflags, char *arg)
+moptions(enum mparset *tflags, char *arg)
 {
 
        if (0 == strcmp(arg, "doc"))
 {
 
        if (0 == strcmp(arg, "doc"))
-               *tflags = INTT_MDOC;
+               *tflags = MPARSE_MDOC;
        else if (0 == strcmp(arg, "andoc"))
        else if (0 == strcmp(arg, "andoc"))
-               *tflags = INTT_AUTO;
+               *tflags = MPARSE_AUTO;
        else if (0 == strcmp(arg, "an"))
        else if (0 == strcmp(arg, "an"))
-               *tflags = INTT_MAN;
+               *tflags = MPARSE_MAN;
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
@@ -954,8 +295,7 @@ toptions(struct curparse *curp, char *arg)
        else if (0 == strcmp(arg, "lint")) {
                curp->outtype = OUTT_LINT;
                curp->wlevel  = MANDOCLEVEL_WARNING;
        else if (0 == strcmp(arg, "lint")) {
                curp->outtype = OUTT_LINT;
                curp->wlevel  = MANDOCLEVEL_WARNING;
-       }
-       else if (0 == strcmp(arg, "tree"))
+       } else if (0 == strcmp(arg, "tree"))
                curp->outtype = OUTT_TREE;
        else if (0 == strcmp(arg, "html"))
                curp->outtype = OUTT_HTML;
                curp->outtype = OUTT_TREE;
        else if (0 == strcmp(arg, "html"))
                curp->outtype = OUTT_HTML;
@@ -1012,29 +352,18 @@ woptions(struct curparse *curp, char *arg)
        return(1);
 }
 
        return(1);
 }
 
-static int
-mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
+static void
+mmsg(enum mandocerr t, enum mandoclevel lvl, 
+               const char *file, int line, int col, const char *msg)
 {
 {
-       struct curparse *cp;
-       enum mandoclevel level;
 
 
-       level = MANDOCLEVEL_FATAL;
-       while (t < mandoclimits[level])
-               /* LINTED */
-               level--;
+       fprintf(stderr, "%s:%d:%d: %s: %s", 
+                       file, line, col + 1, 
+                       mparse_strlevel(lvl),
+                       mparse_strerror(t));
 
 
-       cp = (struct curparse *)arg;
-       if (level < cp->wlevel)
-               return(1);
-
-       fprintf(stderr, "%s:%d:%d: %s: %s",
-           cp->file, ln, col + 1, mandoclevels[level], mandocerrs[t]);
        if (msg)
                fprintf(stderr, ": %s", msg);
        if (msg)
                fprintf(stderr, ": %s", msg);
-       fputc('\n', stderr);
 
 
-       if (file_status < level)
-               file_status = level;
-       
-       return(level < MANDOCLEVEL_FATAL);
+       fputc('\n', stderr);
 }
 }
diff --git a/contrib/mdocml/man.3 b/contrib/mdocml/man.3
deleted file mode 100644 (file)
index 2b2d0a9..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-.\"    $Id: man.3,v 1.29 2011/01/03 11:31:26 kristaps Exp $
-.\"
-.\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
-.\"
-.\" 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.
-.\"
-.Dd $Mdocdate: January 3 2011 $
-.Dt MAN 3
-.Os
-.Sh NAME
-.Nm man ,
-.Nm man_alloc ,
-.Nm man_endparse ,
-.Nm man_free ,
-.Nm man_meta ,
-.Nm man_node ,
-.Nm man_parseln ,
-.Nm man_reset
-.Nd man macro compiler library
-.Sh SYNOPSIS
-.In mandoc.h
-.In man.h
-.Vt extern const char * const * man_macronames;
-.Ft int
-.Fo man_addspan
-.Fa "struct man *man"
-.Fa "const struct tbl_span *span"
-.Fc
-.Ft "struct man *"
-.Fo man_alloc
-.Fa "struct regset *regs"
-.Fa "void *data"
-.Fa "mandocmsg msgs"
-.Fc
-.Ft int
-.Fn man_endparse "struct man *man"
-.Ft void
-.Fn man_free "struct man *man"
-.Ft "const struct man_meta *"
-.Fn man_meta "const struct man *man"
-.Ft "const struct man_node *"
-.Fn man_node "const struct man *man"
-.Ft int
-.Fo man_parseln
-.Fa "struct man *man"
-.Fa "int line"
-.Fa "char *buf"
-.Fc
-.Ft void
-.Fn man_reset "struct man *man"
-.Sh DESCRIPTION
-The
-.Nm
-library parses lines of
-.Xr man 7
-input into an abstract syntax tree (AST).
-.Pp
-In general, applications initiate a parsing sequence with
-.Fn man_alloc ,
-parse each line in a document with
-.Fn man_parseln ,
-close the parsing session with
-.Fn man_endparse ,
-operate over the syntax tree returned by
-.Fn man_node
-and
-.Fn man_meta ,
-then free all allocated memory with
-.Fn man_free .
-The
-.Fn man_reset
-function may be used in order to reset the parser for another input
-sequence.
-.Pp
-Beyond the full set of macros defined in
-.Xr man 7 ,
-the
-.Nm
-library also accepts the following macro:
-.Pp
-.Bl -tag -width Ds -compact
-.It PD
-Has no effect.
-Handled as a current-scope line macro.
-.El
-.Ss Types
-.Bl -ohang
-.It Vt struct man
-An opaque type.
-Its values are only used privately within the library.
-.It Vt struct man_node
-A parsed node.
-See
-.Sx Abstract Syntax Tree
-for details.
-.El
-.Ss Functions
-If
-.Fn man_addspan ,
-.Fn man_parseln ,
-or
-.Fn man_endparse
-return 0, calls to any function but
-.Fn man_reset
-or
-.Fn man_free
-will raise an assertion.
-.Bl -ohang
-.It Fn man_addspan
-Add a table span to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn man_alloc
-Allocates a parsing structure.
-The
-.Fa data
-pointer is passed to
-.Fa msgs .
-Always returns a valid pointer.
-The pointer must be freed with
-.Fn man_free .
-.It Fn man_reset
-Reset the parser for another parse routine.
-After its use,
-.Fn man_parseln
-behaves as if invoked for the first time.
-.It Fn man_free
-Free all resources of a parser.
-The pointer is no longer valid after invocation.
-.It Fn man_parseln
-Parse a nil-terminated line of input.
-This line should not contain the trailing newline.
-Returns 0 on failure, 1 on success.
-The input buffer
-.Fa buf
-is modified by this function.
-.It Fn man_endparse
-Signals that the parse is complete.
-Returns 0 on failure, 1 on success.
-.It Fn man_node
-Returns the first node of the parse.
-.It Fn man_meta
-Returns the document's parsed meta-data.
-.El
-.Ss Variables
-The following variables are also defined:
-.Bl -ohang
-.It Va man_macronames
-An array of string-ified token names.
-.El
-.Ss Abstract Syntax Tree
-The
-.Nm
-functions produce an abstract syntax tree (AST) describing input in a
-regular form.
-It may be reviewed at any time with
-.Fn man_nodes ;
-however, if called before
-.Fn man_endparse ,
-or after
-.Fn man_endparse
-or
-.Fn man_parseln
-fail, it may be incomplete.
-.Pp
-This AST is governed by the ontological rules dictated in
-.Xr man 7
-and derives its terminology accordingly.
-.Pp
-The AST is composed of
-.Vt struct man_node
-nodes with element, root and text types as declared by the
-.Va type
-field.
-Each node also provides its parse point (the
-.Va line ,
-.Va sec ,
-and
-.Va pos
-fields), its position in the tree (the
-.Va parent ,
-.Va child ,
-.Va next
-and
-.Va prev
-fields) and some type-specific data.
-.Pp
-The tree itself is arranged according to the following normal form,
-where capitalised non-terminals represent nodes.
-.Pp
-.Bl -tag -width "ELEMENTXX" -compact
-.It ROOT
-\(<- mnode+
-.It mnode
-\(<- ELEMENT | TEXT | BLOCK
-.It BLOCK
-\(<- HEAD BODY
-.It HEAD
-\(<- mnode*
-.It BODY
-\(<- mnode*
-.It ELEMENT
-\(<- ELEMENT | TEXT*
-.It TEXT
-\(<- [[:alpha:]]*
-.El
-.Pp
-The only elements capable of nesting other elements are those with
-next-lint scope as documented in
-.Xr man 7 .
-.Sh EXAMPLES
-The following example reads lines from stdin and parses them, operating
-on the finished parse tree with
-.Fn parsed .
-This example does not error-check nor free memory upon failure.
-.Bd -literal -offset indent
-struct regset regs;
-struct man *man;
-struct man_node *node;
-char *buf;
-size_t len;
-int line;
-
-bzero(&regs, sizeof(struct regset));
-line = 1;
-man = man_alloc(&regs, NULL, NULL);
-buf = NULL;
-alloc_len = 0;
-
-while ((len = getline(&buf, &alloc_len, stdin)) >= 0) {
-    if (len && buflen[len - 1] = '\en')
-        buf[len - 1] = '\e0';
-    if ( ! man_parseln(man, line, buf))
-        errx(1, "man_parseln");
-    line++;
-}
-
-free(buf);
-
-if ( ! man_endparse(man))
-    errx(1, "man_endparse");
-if (NULL == (node = man_node(man)))
-    errx(1, "man_node");
-
-parsed(man, node);
-man_free(man);
-.Ed
-.Pp
-To compile this, execute
-.Pp
-.Dl % cc main.c libman.a libmandoc.a
-.Pp
-where
-.Pa main.c
-is the example file.
-.Sh SEE ALSO
-.Xr mandoc 1 ,
-.Xr man 7
-.Sh AUTHORS
-The
-.Nm
-library was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
index d8bd6ee..876f32a 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: man.7,v 1.94 2011/01/04 23:32:21 kristaps Exp $
+.\"    $Id: man.7,v 1.99 2011/03/07 01:35:51 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\"
 .\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: January 4 2011 $
+.Dd $Mdocdate: March 7 2011 $
 .Dt MAN 7
 .Os
 .Sh NAME
 .Dt MAN 7
 .Os
 .Sh NAME
@@ -53,12 +53,12 @@ Other lines are interpreted within the current state.
 .Nm
 documents may contain only graphable 7-bit ASCII characters, the
 space character, and the tab character.
 .Nm
 documents may contain only graphable 7-bit ASCII characters, the
 space character, and the tab character.
-All manuals must have
-.Ux
-line termination.
 .Pp
 Blank lines are acceptable; where found, the output will assert a
 vertical space.
 .Pp
 Blank lines are acceptable; where found, the output will assert a
 vertical space.
+.Pp
+If the first character of a line is a space, that line is printed
+with a leading newline.
 .Ss Comments
 Text following a
 .Sq \e\*q ,
 .Ss Comments
 Text following a
 .Sq \e\*q ,
@@ -118,15 +118,6 @@ rendered as an empty line.
 .Pp
 In macro lines, whitespace delimits arguments and is discarded.
 If arguments are quoted, whitespace within the quotes is retained.
 .Pp
 In macro lines, whitespace delimits arguments and is discarded.
 If arguments are quoted, whitespace within the quotes is retained.
-.Ss Dates
-The
-.Sx \&TH
-macro is the only
-.Nm
-macro that requires a date.
-The form for this date is the ISO-8601
-standard
-.Cm YYYY-MM-DD .
 .Ss Scaling Widths
 Many macros support scaled widths for their arguments, such as
 stipulating a two-inch paragraph indentation with the following:
 .Ss Scaling Widths
 Many macros support scaled widths for their arguments, such as
 stipulating a two-inch paragraph indentation with the following:
@@ -370,6 +361,13 @@ Thus, the following are equivalent:
 \&.\ \ \ PP
 .Ed
 .Pp
 \&.\ \ \ PP
 .Ed
 .Pp
+To include space characters in macro arguments, arguments may be quoted;
+see the
+.Sq MACRO SYNTAX
+section in the
+.Xr roff 7
+manual for details.
+.Pp
 The
 .Nm
 macros are classified by scope: line scope or block scope.
 The
 .Nm
 macros are classified by scope: line scope or block scope.
@@ -756,26 +754,27 @@ The paragraph left-margin width is reset to the default.
 Sets the title of the manual page with the following syntax:
 .Bd -filled -offset indent
 .Pf \. Sx \&TH
 Sets the title of the manual page with the following syntax:
 .Bd -filled -offset indent
 .Pf \. Sx \&TH
-.Cm title section
-.Op Cm date Op Cm source Op Cm volume
+.Ar title section date
+.Op Ar source Op Ar volume
 .Ed
 .Pp
 .Ed
 .Pp
-At least the upper-case document
-.Cm title
-and the manual
-.Cm section
-arguments must be provided.
-The
-.Cm date
-argument should be formatted as described in
-.Sx Dates ,
-but will be printed verbatim if it is not.
-If the date is not specified, the current date is used.
-The
-.Cm source
+Conventionally, the document
+.Ar title
+is given in all caps.
+The recommended
+.Ar date
+format is
+.Sy YYYY-MM-DD
+as specified in the ISO-8601 standard;
+if the argument does not conform, it is printed verbatim.
+If the
+.Ar date
+is empty or not specified, the current date is used.
+The optional
+.Ar source
 string specifies the organisation providing the utility.
 The
 string specifies the organisation providing the utility.
 The
-.Cm volume
+.Ar volume
 string replaces the default rendered volume, which is dictated by the
 manual section.
 .Pp
 string replaces the default rendered volume, which is dictated by the
 manual section.
 .Pp
@@ -912,6 +911,7 @@ In GNU troff, this would result in strange behaviour.
 .Sh SEE ALSO
 .Xr man 1 ,
 .Xr mandoc 1 ,
 .Sh SEE ALSO
 .Xr man 1 ,
 .Xr mandoc 1 ,
+.Xr eqn 7 ,
 .Xr mandoc_char 7 ,
 .Xr mdoc 7 ,
 .Xr roff 7 ,
 .Xr mandoc_char 7 ,
 .Xr mdoc 7 ,
 .Xr roff 7 ,
index 6788c92..50a0cf0 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man.c,v 1.96 2011/01/03 11:31:26 kristaps Exp $ */
+/*     $Id: man.c,v 1.107 2011/03/29 08:30:49 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
 
+#include "man.h"
 #include "mandoc.h"
 #include "libman.h"
 #include "libmandoc.h"
 #include "mandoc.h"
 #include "libman.h"
 #include "libmandoc.h"
@@ -44,12 +45,10 @@ const       char *const __man_macronames[MAN_MAX] = {
 
 const  char * const *man_macronames = __man_macronames;
 
 
 const  char * const *man_macronames = __man_macronames;
 
-static struct man_node *man_node_alloc(int, int, 
+static struct man_node *man_node_alloc(struct man *, int, int, 
                                enum man_type, enum mant);
 static int              man_node_append(struct man *, 
                                struct man_node *);
                                enum man_type, enum mant);
 static int              man_node_append(struct man *, 
                                struct man_node *);
-static int              man_span_alloc(struct man *, 
-                               const struct tbl_span *);
 static void             man_node_free(struct man_node *);
 static void             man_node_unlink(struct man *, 
                                struct man_node *);
 static void             man_node_free(struct man_node *);
 static void             man_node_unlink(struct man *, 
                                struct man_node *);
@@ -97,15 +96,14 @@ man_free(struct man *man)
 
 
 struct man *
 
 
 struct man *
-man_alloc(struct regset *regs, void *data, mandocmsg msg)
+man_alloc(struct regset *regs, struct mparse *parse)
 {
        struct man      *p;
 
        p = mandoc_calloc(1, sizeof(struct man));
 
        man_hash_init();
 {
        struct man      *p;
 
        p = mandoc_calloc(1, sizeof(struct man));
 
        man_hash_init();
-       p->data = data;
-       p->msg = msg;
+       p->parse = parse;
        p->regs = regs;
 
        man_alloc1(p);
        p->regs = regs;
 
        man_alloc1(p);
@@ -129,8 +127,11 @@ int
 man_parseln(struct man *m, int ln, char *buf, int offs)
 {
 
 man_parseln(struct man *m, int ln, char *buf, int offs)
 {
 
+       m->flags |= MAN_NEWLINE;
+
        assert( ! (MAN_HALT & m->flags));
        assert( ! (MAN_HALT & m->flags));
-       return(('.' == buf[offs] || '\'' == buf[offs]) ? 
+
+       return (mandoc_getcontrol(buf, &offs) ?
                        man_pmacro(m, ln, buf, offs) : 
                        man_ptext(m, ln, buf, offs));
 }
                        man_pmacro(m, ln, buf, offs) : 
                        man_ptext(m, ln, buf, offs));
 }
@@ -146,8 +147,8 @@ man_free1(struct man *man)
                free(man->meta.title);
        if (man->meta.source)
                free(man->meta.source);
                free(man->meta.title);
        if (man->meta.source)
                free(man->meta.source);
-       if (man->meta.rawdate)
-               free(man->meta.rawdate);
+       if (man->meta.date)
+               free(man->meta.date);
        if (man->meta.vol)
                free(man->meta.vol);
        if (man->meta.msec)
        if (man->meta.vol)
                free(man->meta.vol);
        if (man->meta.msec)
@@ -203,6 +204,10 @@ man_node_append(struct man *man, struct man_node *p)
                assert(MAN_BLOCK == p->parent->type);
                p->parent->head = p;
                break;
                assert(MAN_BLOCK == p->parent->type);
                p->parent->head = p;
                break;
+       case (MAN_TAIL):
+               assert(MAN_BLOCK == p->parent->type);
+               p->parent->tail = p;
+               break;
        case (MAN_BODY):
                assert(MAN_BLOCK == p->parent->type);
                p->parent->body = p;
        case (MAN_BODY):
                assert(MAN_BLOCK == p->parent->type);
                p->parent->body = p;
@@ -229,7 +234,8 @@ man_node_append(struct man *man, struct man_node *p)
 
 
 static struct man_node *
 
 
 static struct man_node *
-man_node_alloc(int line, int pos, enum man_type type, enum mant tok)
+man_node_alloc(struct man *m, int line, int pos, 
+               enum man_type type, enum mant tok)
 {
        struct man_node *p;
 
 {
        struct man_node *p;
 
@@ -238,6 +244,10 @@ man_node_alloc(int line, int pos, enum man_type type, enum mant tok)
        p->pos = pos;
        p->type = type;
        p->tok = tok;
        p->pos = pos;
        p->type = type;
        p->tok = tok;
+
+       if (MAN_NEWLINE & m->flags)
+               p->flags |= MAN_LINE;
+       m->flags &= ~MAN_NEWLINE;
        return(p);
 }
 
        return(p);
 }
 
@@ -247,7 +257,7 @@ man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
 {
        struct man_node *p;
 
-       p = man_node_alloc(line, pos, MAN_ELEM, tok);
+       p = man_node_alloc(m, line, pos, MAN_ELEM, tok);
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
@@ -256,11 +266,11 @@ man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 int
 
 
 int
-man_head_alloc(struct man *m, int line, int pos, enum mant tok)
+man_tail_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
 {
        struct man_node *p;
 
-       p = man_node_alloc(line, pos, MAN_HEAD, tok);
+       p = man_node_alloc(m, line, pos, MAN_TAIL, tok);
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
@@ -269,11 +279,11 @@ man_head_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 int
 
 
 int
-man_body_alloc(struct man *m, int line, int pos, enum mant tok)
+man_head_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
 {
        struct man_node *p;
 
-       p = man_node_alloc(line, pos, MAN_BODY, tok);
+       p = man_node_alloc(m, line, pos, MAN_HEAD, tok);
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
@@ -282,30 +292,27 @@ man_body_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 int
 
 
 int
-man_block_alloc(struct man *m, int line, int pos, enum mant tok)
+man_body_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        struct man_node *p;
 
 {
        struct man_node *p;
 
-       p = man_node_alloc(line, pos, MAN_BLOCK, tok);
+       p = man_node_alloc(m, line, pos, MAN_BODY, tok);
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
        return(1);
 }
 
        if ( ! man_node_append(m, p))
                return(0);
        m->next = MAN_NEXT_CHILD;
        return(1);
 }
 
-static int
-man_span_alloc(struct man *m, const struct tbl_span *span)
-{
-       struct man_node *n;
 
 
-       /* FIXME: grab from span */
-       n = man_node_alloc(0, 0, MAN_TBL, MAN_MAX);
-       n->span = span;
+int
+man_block_alloc(struct man *m, int line, int pos, enum mant tok)
+{
+       struct man_node *p;
 
 
-       if ( ! man_node_append(m, n))
+       p = man_node_alloc(m, line, pos, MAN_BLOCK, tok);
+       if ( ! man_node_append(m, p))
                return(0);
                return(0);
-
-       m->next = MAN_NEXT_SIBLING;
+       m->next = MAN_NEXT_CHILD;
        return(1);
 }
 
        return(1);
 }
 
@@ -317,7 +324,7 @@ man_word_alloc(struct man *m, int line, int pos, const char *word)
 
        len = strlen(word);
 
 
        len = strlen(word);
 
-       n = man_node_alloc(line, pos, MAN_TEXT, MAN_MAX);
+       n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX);
        n->string = mandoc_malloc(len + 1);
        sv = strlcpy(n->string, word, len + 1);
 
        n->string = mandoc_malloc(len + 1);
        sv = strlcpy(n->string, word, len + 1);
 
@@ -357,15 +364,38 @@ man_node_delete(struct man *m, struct man_node *p)
        man_node_free(p);
 }
 
        man_node_free(p);
 }
 
+int
+man_addeqn(struct man *m, const struct eqn *ep)
+{
+       struct man_node *n;
+
+       assert( ! (MAN_HALT & m->flags));
+
+       n = man_node_alloc(m, ep->line, ep->pos, MAN_EQN, MAN_MAX);
+       n->eqn = ep;
+
+       if ( ! man_node_append(m, n))
+               return(0);
+
+       m->next = MAN_NEXT_SIBLING;
+       return(man_descope(m, ep->line, ep->pos));
+}
 
 int
 man_addspan(struct man *m, const struct tbl_span *sp)
 {
 
 int
 man_addspan(struct man *m, const struct tbl_span *sp)
 {
+       struct man_node *n;
 
        assert( ! (MAN_HALT & m->flags));
 
        assert( ! (MAN_HALT & m->flags));
-       if ( ! man_span_alloc(m, sp))
+
+       n = man_node_alloc(m, sp->line, 0, MAN_TBL, MAN_MAX);
+       n->span = sp;
+
+       if ( ! man_node_append(m, n))
                return(0);
                return(0);
-       return(man_descope(m, 0, 0));
+
+       m->next = MAN_NEXT_SIBLING;
+       return(man_descope(m, sp->line, 0));
 }
 
 static int
 }
 
 static int
@@ -392,21 +422,11 @@ man_descope(struct man *m, int line, int offs)
        return(man_body_alloc(m, line, offs, m->last->tok));
 }
 
        return(man_body_alloc(m, line, offs, m->last->tok));
 }
 
-
 static int
 man_ptext(struct man *m, int line, char *buf, int offs)
 {
        int              i;
 
 static int
 man_ptext(struct man *m, int line, char *buf, int offs)
 {
        int              i;
 
-       /* Ignore bogus comments. */
-
-       if ('\\' == buf[offs] && 
-                       '.' == buf[offs + 1] && 
-                       '"' == buf[offs + 2]) {
-               man_pmsg(m, line, offs, MANDOCERR_BADCOMMENT);
-               return(1);
-       }
-
        /* Literal free-form text whitespace is preserved. */
 
        if (MAN_LITERAL & m->flags) {
        /* Literal free-form text whitespace is preserved. */
 
        if (MAN_LITERAL & m->flags) {
@@ -464,67 +484,54 @@ man_ptext(struct man *m, int line, char *buf, int offs)
        return(man_descope(m, line, offs));
 }
 
        return(man_descope(m, line, offs));
 }
 
-
 static int
 man_pmacro(struct man *m, int ln, char *buf, int offs)
 {
 static int
 man_pmacro(struct man *m, int ln, char *buf, int offs)
 {
-       int              i, j, ppos;
+       int              i, ppos;
        enum mant        tok;
        char             mac[5];
        struct man_node *n;
 
        enum mant        tok;
        char             mac[5];
        struct man_node *n;
 
-       /* Comments and empties are quickly ignored. */
-
-       offs++;
-
-       if ('\0' == buf[offs])
+       if ('"' == buf[offs]) {
+               man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+               return(1);
+       } else if ('\0' == buf[offs])
                return(1);
 
                return(1);
 
-       i = offs;
-
-       /*
-        * Skip whitespace between the control character and initial
-        * text.  "Whitespace" is both spaces and tabs.
-        */
-
-       if (' ' == buf[i] || '\t' == buf[i]) {
-               i++;
-               while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
-                       i++;
-               if ('\0' == buf[i])
-                       goto out;
-       }
-
-       ppos = i;
+       ppos = offs;
 
        /*
         * Copy the first word into a nil-terminated buffer.
         * Stop copying when a tab, space, or eoln is encountered.
         */
 
 
        /*
         * Copy the first word into a nil-terminated buffer.
         * Stop copying when a tab, space, or eoln is encountered.
         */
 
-       j = 0;
-       while (j < 4 && '\0' != buf[i] && ' ' != buf[i] && '\t' != buf[i])
-               mac[j++] = buf[i++];
-       mac[j] = '\0';
+       i = 0;
+       while (i < 4 && '\0' != buf[offs] && 
+                       ' ' != buf[offs] && '\t' != buf[offs])
+               mac[i++] = buf[offs++];
+
+       mac[i] = '\0';
+
+       tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
 
 
-       tok = (j > 0 && j < 4) ? man_hash_find(mac) : MAN_MAX;
        if (MAN_MAX == tok) {
        if (MAN_MAX == tok) {
-               man_vmsg(m, MANDOCERR_MACRO, ln, ppos, "%s", buf + ppos - 1);
+               mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln, 
+                               ppos, "%s", buf + ppos - 1);
                return(1);
        }
 
        /* The macro is sane.  Jump to the next word. */
 
                return(1);
        }
 
        /* The macro is sane.  Jump to the next word. */
 
-       while (buf[i] && ' ' == buf[i])
-               i++;
+       while (buf[offs] && ' ' == buf[offs])
+               offs++;
 
        /* 
         * Trailing whitespace.  Note that tabs are allowed to be passed
         * into the parser as "text", so we only warn about spaces here.
         */
 
 
        /* 
         * Trailing whitespace.  Note that tabs are allowed to be passed
         * into the parser as "text", so we only warn about spaces here.
         */
 
-       if ('\0' == buf[i] && ' ' == buf[i - 1])
-               man_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE);
+       if ('\0' == buf[offs] && ' ' == buf[offs - 1])
+               man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
 
        /* 
         * Remove prior ELINE macro, as it's being clobbered by a new
 
        /* 
         * Remove prior ELINE macro, as it's being clobbered by a new
@@ -542,8 +549,8 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
                if (MAN_NSCOPED & man_macros[n->tok].flags)
                        n = n->parent;
 
                if (MAN_NSCOPED & man_macros[n->tok].flags)
                        n = n->parent;
 
-               man_vmsg(m, MANDOCERR_LINESCOPE, n->line, n->pos,
-                               "%s", man_macronames[n->tok]);
+               mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line, 
+                               n->pos, "%s", man_macronames[n->tok]);
 
                man_node_delete(m, n);
                m->flags &= ~MAN_ELINE;
 
                man_node_delete(m, n);
                m->flags &= ~MAN_ELINE;
@@ -561,10 +568,9 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
        /* Call to handler... */
 
        assert(man_macros[tok].fp);
        /* Call to handler... */
 
        assert(man_macros[tok].fp);
-       if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &i, buf))
+       if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf))
                goto err;
 
                goto err;
 
-out:
        /* 
         * We weren't in a block-line scope when entering the
         * above-parsed macro, so return.
        /* 
         * We weren't in a block-line scope when entering the
         * above-parsed macro, so return.
@@ -601,7 +607,7 @@ out:
 
        if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
                return(0);
 
        if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
                return(0);
-       return(man_body_alloc(m, ln, offs, m->last->tok));
+       return(man_body_alloc(m, ln, ppos, m->last->tok));
 
 err:   /* Error out. */
 
 
 err:   /* Error out. */
 
@@ -609,21 +615,6 @@ err:       /* Error out. */
        return(0);
 }
 
        return(0);
 }
 
-
-int
-man_vmsg(struct man *man, enum mandocerr t, 
-               int ln, int pos, const char *fmt, ...)
-{
-       char             buf[256];
-       va_list          ap;
-
-       va_start(ap, fmt);
-       vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
-       va_end(ap);
-       return((*man->msg)(t, man->data, ln, pos, buf));
-}
-
-
 /*
  * Unlink a node from its context.  If "m" is provided, the last parse
  * point will also be adjusted accordingly.
 /*
  * Unlink a node from its context.  If "m" is provided, the last parse
  * point will also be adjusted accordingly.
index 581f55f..1b0bb68 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man.h,v 1.50 2011/01/01 12:59:17 kristaps Exp $ */
+/*     $Id: man.h,v 1.58 2011/03/23 12:33:01 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,9 +17,6 @@
 #ifndef MAN_H
 #define MAN_H
 
 #ifndef MAN_H
 #define MAN_H
 
-/* 
- * What follows is a list of ALL possible macros. 
- */
 enum   mant {
        MAN_br = 0,
        MAN_TH,
 enum   mant {
        MAN_br = 0,
        MAN_TH,
@@ -57,9 +54,6 @@ enum  mant {
        MAN_MAX
 };
 
        MAN_MAX
 };
 
-/* 
- * Type of a syntax node. 
- */
 enum   man_type {
        MAN_TEXT,
        MAN_ELEM,
 enum   man_type {
        MAN_TEXT,
        MAN_ELEM,
@@ -67,24 +61,19 @@ enum        man_type {
        MAN_BLOCK,
        MAN_HEAD,
        MAN_BODY,
        MAN_BLOCK,
        MAN_HEAD,
        MAN_BODY,
-       MAN_TBL
+       MAN_TAIL,
+       MAN_TBL,
+       MAN_EQN
 };
 
 };
 
-/* 
- * Information from prologue. 
- */
 struct man_meta {
        char            *msec; /* `TH' section (1, 3p, etc.) */
 struct man_meta {
        char            *msec; /* `TH' section (1, 3p, etc.) */
-       time_t           date; /* `TH' normalised date */
-       char            *rawdate; /* raw `TH' date */
+       char            *date; /* `TH' normalised date */
        char            *vol; /* `TH' volume */
        char            *title; /* `TH' title (e.g., FOO) */
        char            *source; /* `TH' source (e.g., GNU) */
 };
 
        char            *vol; /* `TH' volume */
        char            *title; /* `TH' title (e.g., FOO) */
        char            *source; /* `TH' source (e.g., GNU) */
 };
 
-/* 
- * Single node in tree-linked AST. 
- */
 struct man_node {
        struct man_node *parent; /* parent AST node */
        struct man_node *child; /* first child AST node */
 struct man_node {
        struct man_node *parent; /* parent AST node */
        struct man_node *child; /* first child AST node */
@@ -97,31 +86,23 @@ struct      man_node {
        int              flags;
 #define        MAN_VALID       (1 << 0) /* has been validated */
 #define        MAN_EOS         (1 << 2) /* at sentence boundary */
        int              flags;
 #define        MAN_VALID       (1 << 0) /* has been validated */
 #define        MAN_EOS         (1 << 2) /* at sentence boundary */
+#define        MAN_LINE        (1 << 3) /* first macro/text on line */
        enum man_type    type; /* AST node type */
        char            *string; /* TEXT node argument */
        struct man_node *head; /* BLOCK node HEAD ptr */
        enum man_type    type; /* AST node type */
        char            *string; /* TEXT node argument */
        struct man_node *head; /* BLOCK node HEAD ptr */
+       struct man_node *tail; /* BLOCK node TAIL ptr */
        struct man_node *body; /* BLOCK node BODY ptr */
        const struct tbl_span *span; /* TBL */
        struct man_node *body; /* BLOCK node BODY ptr */
        const struct tbl_span *span; /* TBL */
+       const struct eqn *eqn; /* EQN */
 };
 
 };
 
-/*
- * Names of macros.  Index is enum mant.  Indexing into this returns
- * the normalised name, e.g., man_macronames[MAN_SH] -> "SH".
- */
+/* Names of macros.  Index is enum mant. */
 extern const char *const *man_macronames;
 
 __BEGIN_DECLS
 
 struct man;
 
 extern const char *const *man_macronames;
 
 __BEGIN_DECLS
 
 struct man;
 
-void             man_free(struct man *);
-struct man      *man_alloc(struct regset *, void *, mandocmsg);
-void             man_reset(struct man *);
-int              man_parseln(struct man *, int, char *, int);
-int              man_endparse(struct man *);
-int              man_addspan(struct man *,
-                       const struct tbl_span *);
-
 const struct man_node *man_node(const struct man *);
 const struct man_meta *man_meta(const struct man *);
 
 const struct man_node *man_node(const struct man *);
 const struct man_meta *man_meta(const struct man *);
 
diff --git a/contrib/mdocml/man_argv.c b/contrib/mdocml/man_argv.c
deleted file mode 100644 (file)
index 37aac03..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*     $Id: man_argv.c,v 1.5 2011/01/03 22:42:37 schwarze Exp $ */
-/*
- * Copyright (c) 2011 Ingo Schwarze <schwarze@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.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#include <assert.h>
-
-#include "mandoc.h"
-#include "libman.h"
-#include "libmandoc.h"
-
-
-int
-man_args(struct man *m, int line, int *pos, char *buf, char **v)
-{
-       char     *start;
-
-       assert(*pos);
-       *v = start = buf + *pos;
-       assert(' ' != *start);
-
-       if ('\0' == *start)
-               return(ARGS_EOLN);
-
-       *v = mandoc_getarg(v, m->msg, m->data, line, pos);
-       return('"' == *start ? ARGS_QWORD : ARGS_WORD);
-}
index 6524f36..c52640e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_hash.c,v 1.23 2010/07/31 23:52:58 schwarze Exp $ */
+/*     $Id: man_hash.c,v 1.24 2011/03/22 14:33:05 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 
 #include <stdlib.h>
 #include <string.h>
 
+#include "man.h"
 #include "mandoc.h"
 #include "libman.h"
 
 #include "mandoc.h"
 #include "libman.h"
 
index da6880a..610e58f 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_html.c,v 1.62 2011/01/07 13:20:58 kristaps Exp $ */
+/*     $Id: man_html.c,v 1.70 2011/03/07 01:35:51 schwarze Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -67,7 +67,7 @@ static        int               man_ign_pre(MAN_ARGS);
 static int               man_in_pre(MAN_ARGS);
 static int               man_literal_pre(MAN_ARGS);
 static void              man_root_post(MAN_ARGS);
 static int               man_in_pre(MAN_ARGS);
 static int               man_literal_pre(MAN_ARGS);
 static void              man_root_post(MAN_ARGS);
-static int               man_root_pre(MAN_ARGS);
+static void              man_root_pre(MAN_ARGS);
 static int               man_B_pre(MAN_ARGS);
 static int               man_HP_pre(MAN_ARGS);
 static int               man_I_pre(MAN_ARGS);
 static int               man_B_pre(MAN_ARGS);
 static int               man_HP_pre(MAN_ARGS);
 static int               man_I_pre(MAN_ARGS);
@@ -100,7 +100,7 @@ static      const struct htmlman mans[MAN_MAX] = {
        { man_I_pre, NULL }, /* I */
        { man_alt_pre, NULL }, /* IR */
        { man_alt_pre, NULL }, /* RI */
        { man_I_pre, NULL }, /* I */
        { man_alt_pre, NULL }, /* IR */
        { man_alt_pre, NULL }, /* RI */
-       { NULL, NULL }, /* na */
+       { man_ign_pre, NULL }, /* na */
        { man_br_pre, NULL }, /* sp */
        { man_literal_pre, NULL }, /* nf */
        { man_literal_pre, NULL }, /* fi */
        { man_br_pre, NULL }, /* sp */
        { man_literal_pre, NULL }, /* nf */
        { man_literal_pre, NULL }, /* fi */
@@ -180,40 +180,74 @@ print_man_node(MAN_ARGS)
 {
        int              child;
        struct tag      *t;
 {
        int              child;
        struct tag      *t;
+       struct htmlpair  tag;
 
        child = 1;
        t = h->tags.head;
 
        child = 1;
        t = h->tags.head;
-
        bufinit(h);
 
        bufinit(h);
 
-       /*
-        * FIXME: embedded elements within next-line scopes (e.g., `br'
-        * within an empty `B') will cause formatting to be forgotten
-        * due to scope closing out.
-        */
-
        switch (n->type) {
        case (MAN_ROOT):
        switch (n->type) {
        case (MAN_ROOT):
-               child = man_root_pre(m, n, mh, h);
+               man_root_pre(m, n, mh, h);
                break;
        case (MAN_TEXT):
                break;
        case (MAN_TEXT):
+               /*
+                * If we have a blank line, output a vertical space.
+                * If we have a space as the first character, break
+                * before printing the line's data.
+                */
+               if ('\0' == *n->string) {
+                       print_otag(h, TAG_P, 0, NULL);
+                       return;
+               } else if (' ' == *n->string && MAN_LINE & n->flags)
+                       print_otag(h, TAG_BR, 0, NULL);
+
                print_text(h, n->string);
                print_text(h, n->string);
-               if (MANH_LITERAL & mh->fl)
+
+               /*
+                * If we're in a literal context, make sure that words
+                * togehter on the same line stay together.  This is a
+                * POST-printing call, so we check the NEXT word.  Since
+                * -man doesn't have nested macros, we don't need to be
+                * more specific than this.
+                */
+               if (MANH_LITERAL & mh->fl &&
+                               (NULL == n->next ||
+                                n->next->line > n->line))
                        print_otag(h, TAG_BR, 0, NULL);
                return;
                        print_otag(h, TAG_BR, 0, NULL);
                return;
+       case (MAN_EQN):
+               PAIR_CLASS_INIT(&tag, "eqn");
+               print_otag(h, TAG_SPAN, 1, &tag);
+               print_text(h, n->eqn->data);
+               break;
        case (MAN_TBL):
        case (MAN_TBL):
+               /*
+                * This will take care of initialising all of the table
+                * state data for the first table, then tearing it down
+                * for the last one.
+                */
                print_tbl(h, n->span);
                print_tbl(h, n->span);
-               break;
+               return;
        default:
                /* 
                 * Close out scope of font prior to opening a macro
        default:
                /* 
                 * Close out scope of font prior to opening a macro
-                * scope.  Assert that the metafont is on the top of the
-                * stack (it's never nested).
+                * scope.
                 */
                if (HTMLFONT_NONE != h->metac) {
                        h->metal = h->metac;
                        h->metac = HTMLFONT_NONE;
                }
                 */
                if (HTMLFONT_NONE != h->metac) {
                        h->metal = h->metac;
                        h->metac = HTMLFONT_NONE;
                }
+
+               /*
+                * Close out the current table, if it's open, and unset
+                * the "meta" table state.  This will be reopened on the
+                * next table element.
+                */
+               if (h->tblt) {
+                       print_tblclose(h);
+                       t = h->tags.head;
+               }
                if (mans[n->tok].pre)
                        child = (*mans[n->tok].pre)(m, n, mh, h);
                break;
                if (mans[n->tok].pre)
                        child = (*mans[n->tok].pre)(m, n, mh, h);
                break;
@@ -231,7 +265,7 @@ print_man_node(MAN_ARGS)
        case (MAN_ROOT):
                man_root_post(m, n, mh, h);
                break;
        case (MAN_ROOT):
                man_root_post(m, n, mh, h);
                break;
-       case (MAN_TBL):
+       case (MAN_EQN):
                break;
        default:
                if (mans[n->tok].post)
                break;
        default:
                if (mans[n->tok].post)
@@ -255,7 +289,7 @@ a2width(const struct man_node *n, struct roffsu *su)
 
 
 /* ARGSUSED */
 
 
 /* ARGSUSED */
-static int
+static void
 man_root_pre(MAN_ARGS)
 {
        struct htmlpair  tag[3];
 man_root_pre(MAN_ARGS)
 {
        struct htmlpair  tag[3];
@@ -309,7 +343,6 @@ man_root_pre(MAN_ARGS)
 
        print_text(h, title);
        print_tagq(h, t);
 
        print_text(h, title);
        print_tagq(h, t);
-       return(1);
 }
 
 
 }
 
 
@@ -319,12 +352,6 @@ man_root_post(MAN_ARGS)
 {
        struct htmlpair  tag[3];
        struct tag      *t, *tt;
 {
        struct htmlpair  tag[3];
        struct tag      *t, *tt;
-       char             b[DATESIZ];
-
-       if (m->rawdate)
-               strlcpy(b, m->rawdate, DATESIZ);
-       else
-               time2a(m->date, b, DATESIZ);
 
        PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
        PAIR_CLASS_INIT(&tag[1], "foot");
 
        PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
        PAIR_CLASS_INIT(&tag[1], "foot");
@@ -342,7 +369,7 @@ man_root_post(MAN_ARGS)
        PAIR_CLASS_INIT(&tag[0], "foot-date");
        print_otag(h, TAG_TD, 1, tag);
 
        PAIR_CLASS_INIT(&tag[0], "foot-date");
        print_otag(h, TAG_TD, 1, tag);
 
-       print_text(h, b);
+       print_text(h, m->date);
        print_stagq(h, tt);
 
        PAIR_CLASS_INIT(&tag[0], "foot-os");
        print_stagq(h, tt);
 
        PAIR_CLASS_INIT(&tag[0], "foot-os");
@@ -638,7 +665,7 @@ man_literal_pre(MAN_ARGS)
        } else
                mh->fl &= ~MANH_LITERAL;
 
        } else
                mh->fl &= ~MANH_LITERAL;
 
-       return(1);
+       return(0);
 }
 
 
 }
 
 
index bd0ca99..b3212e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_macro.c,v 1.54 2010/12/08 10:58:22 kristaps Exp $ */
+/*     $Id: man_macro.c,v 1.60 2011/03/23 15:33:57 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -23,7 +23,9 @@
 #include <stdlib.h>
 #include <string.h>
 
 #include <stdlib.h>
 #include <string.h>
 
+#include "man.h"
 #include "mandoc.h"
 #include "mandoc.h"
+#include "libmandoc.h"
 #include "libman.h"
 
 enum   rew {
 #include "libman.h"
 
 enum   rew {
@@ -36,6 +38,8 @@ static        int              blk_close(MACRO_PROT_ARGS);
 static int              blk_exp(MACRO_PROT_ARGS);
 static int              blk_imp(MACRO_PROT_ARGS);
 static int              in_line_eoln(MACRO_PROT_ARGS);
 static int              blk_exp(MACRO_PROT_ARGS);
 static int              blk_imp(MACRO_PROT_ARGS);
 static int              in_line_eoln(MACRO_PROT_ARGS);
+static int              man_args(struct man *, int, 
+                               int *, char *, char **);
 
 static int              rew_scope(enum man_type, 
                                struct man *, enum mant);
 
 static int              rew_scope(enum man_type, 
                                struct man *, enum mant);
@@ -43,7 +47,7 @@ static        enum rew         rew_dohalt(enum mant, enum man_type,
                                const struct man_node *);
 static enum rew         rew_block(enum mant, enum man_type, 
                                const struct man_node *);
                                const struct man_node *);
 static enum rew         rew_block(enum mant, enum man_type, 
                                const struct man_node *);
-static int              rew_warn(struct man *, 
+static void             rew_warn(struct man *, 
                                struct man_node *, enum mandocerr);
 
 const  struct man_macro __man_macros[MAN_MAX] = {
                                struct man_node *, enum mandocerr);
 
 const  struct man_macro __man_macros[MAN_MAX] = {
@@ -88,17 +92,19 @@ const       struct man_macro * const man_macros = __man_macros;
 /*
  * Warn when "n" is an explicit non-roff macro.
  */
 /*
  * Warn when "n" is an explicit non-roff macro.
  */
-static int
+static void
 rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
 {
 
        if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
 rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
 {
 
        if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
-               return(1);
+               return;
        if (MAN_VALID & n->flags)
        if (MAN_VALID & n->flags)
-               return(1);
+               return;
        if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
        if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))
-               return(1);
-       return(man_nmsg(m, n, er));
+               return;
+
+       assert(er < MANDOCERR_FATAL);
+       man_nmsg(m, n, er);
 }
 
 
 }
 
 
@@ -107,24 +113,30 @@ rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
  * will be used if an explicit block scope is being closed out.
  */
 int
  * will be used if an explicit block scope is being closed out.
  */
 int
-man_unscope(struct man *m, const struct man_node *n
+man_unscope(struct man *m, const struct man_node *to
                enum mandocerr er)
 {
                enum mandocerr er)
 {
+       struct man_node *n;
 
 
-       assert(n);
+       assert(to);
 
        /* LINTED */
 
        /* LINTED */
-       while (m->last != n) {
-               if ( ! rew_warn(m, m->last, er))
-                       return(0);
+       while (m->last != to) {
+               /*
+                * Save the parent here, because we may delete the
+                * m->last node in the post-validation phase and reset
+                * it to m->last->parent, causing a step in the closing
+                * out to be lost.
+                */
+               n = m->last->parent;
+               rew_warn(m, m->last, er);
                if ( ! man_valid_post(m))
                        return(0);
                if ( ! man_valid_post(m))
                        return(0);
-               m->last = m->last->parent;
+               m->last = n;
                assert(m->last);
        }
 
                assert(m->last);
        }
 
-       if ( ! rew_warn(m, m->last, er))
-               return(0);
+       rew_warn(m, m->last, er);
        if ( ! man_valid_post(m))
                return(0);
 
        if ( ! man_valid_post(m))
                return(0);
 
@@ -271,8 +283,7 @@ blk_close(MACRO_PROT_ARGS)
                        break;
 
        if (NULL == nn)
                        break;
 
        if (NULL == nn)
-               if ( ! man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE))
-                       return(0);
+               man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
 
        if ( ! rew_scope(MAN_BODY, m, ntok))
                return(0);
 
        if ( ! rew_scope(MAN_BODY, m, ntok))
                return(0);
@@ -287,7 +298,7 @@ blk_close(MACRO_PROT_ARGS)
 int
 blk_exp(MACRO_PROT_ARGS)
 {
 int
 blk_exp(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
 
        /* 
        char            *p;
 
        /* 
@@ -308,13 +319,8 @@ blk_exp(MACRO_PROT_ARGS)
 
        for (;;) {
                la = *pos;
 
        for (;;) {
                la = *pos;
-               w = man_args(m, line, pos, buf, &p);
-
-               if (-1 == w)
-                       return(0);
-               if (0 == w)
+               if ( ! man_args(m, line, pos, buf, &p))
                        break;
                        break;
-
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
        }
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
        }
@@ -339,7 +345,7 @@ blk_exp(MACRO_PROT_ARGS)
 int
 blk_imp(MACRO_PROT_ARGS)
 {
 int
 blk_imp(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
        struct man_node *n;
 
        char            *p;
        struct man_node *n;
 
@@ -363,13 +369,8 @@ blk_imp(MACRO_PROT_ARGS)
 
        for (;;) {
                la = *pos;
 
        for (;;) {
                la = *pos;
-               w = man_args(m, line, pos, buf, &p);
-
-               if (-1 == w)
-                       return(0);
-               if (0 == w)
+               if ( ! man_args(m, line, pos, buf, &p))
                        break;
                        break;
-
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
        }
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
        }
@@ -397,7 +398,7 @@ blk_imp(MACRO_PROT_ARGS)
 int
 in_line_eoln(MACRO_PROT_ARGS)
 {
 int
 in_line_eoln(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
        struct man_node *n;
 
        char            *p;
        struct man_node *n;
 
@@ -408,11 +409,7 @@ in_line_eoln(MACRO_PROT_ARGS)
 
        for (;;) {
                la = *pos;
 
        for (;;) {
                la = *pos;
-               w = man_args(m, line, pos, buf, &p);
-
-               if (-1 == w)
-                       return(0);
-               if (0 == w)
+               if ( ! man_args(m, line, pos, buf, &p))
                        break;
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
                        break;
                if ( ! man_word_alloc(m, line, la, p))
                        return(0);
@@ -475,3 +472,18 @@ man_macroend(struct man *m)
        return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
 }
 
        return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
 }
 
+static int
+man_args(struct man *m, int line, int *pos, char *buf, char **v)
+{
+       char     *start;
+
+       assert(*pos);
+       *v = start = buf + *pos;
+       assert(' ' != *start);
+
+       if ('\0' == *start)
+               return(0);
+
+       *v = mandoc_getarg(m->parse, v, line, pos);
+       return(1);
+}
index c0ef70d..cb0b08d 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_term.c,v 1.94 2011/01/04 01:23:18 schwarze Exp $ */
+/*     $Id: man_term.c,v 1.105 2011/03/22 10:13:01 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -31,7 +31,6 @@
 #include "out.h"
 #include "man.h"
 #include "term.h"
 #include "out.h"
 #include "man.h"
 #include "term.h"
-#include "chars.h"
 #include "main.h"
 
 #define        INDENT            7
 #include "main.h"
 
 #define        INDENT            7
@@ -126,7 +125,7 @@ static      const struct termact termacts[MAN_MAX] = {
        { pre_I, NULL, 0 }, /* I */
        { pre_alternate, NULL, 0 }, /* IR */
        { pre_alternate, NULL, 0 }, /* RI */
        { pre_I, NULL, 0 }, /* I */
        { pre_alternate, NULL, 0 }, /* IR */
        { pre_alternate, NULL, 0 }, /* RI */
-       { NULL, NULL, MAN_NOTEXT }, /* na */
+       { pre_ign, NULL, MAN_NOTEXT }, /* na */
        { pre_sp, NULL, MAN_NOTEXT }, /* sp */
        { pre_literal, NULL, 0 }, /* nf */
        { pre_literal, NULL, 0 }, /* fi */
        { pre_sp, NULL, MAN_NOTEXT }, /* sp */
        { pre_literal, NULL, 0 }, /* nf */
        { pre_literal, NULL, 0 }, /* fi */
@@ -212,6 +211,9 @@ print_bvspace(struct termp *p, const struct man_node *n)
 {
        term_newln(p);
 
 {
        term_newln(p);
 
+       if (n->body && n->body->child && MAN_TBL == n->body->child->type)
+               return;
+
        if (NULL == n->prev)
                return;
 
        if (NULL == n->prev)
                return;
 
@@ -255,7 +257,7 @@ pre_literal(DECL_ARGS)
        else
                mt->fl &= ~MANT_LITERAL;
 
        else
                mt->fl &= ~MANT_LITERAL;
 
-       return(1);
+       return(0);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -397,6 +399,11 @@ pre_in(DECL_ARGS)
        else 
                p->offset = v;
 
        else 
                p->offset = v;
 
+       /* Don't let this creep beyond the right margin. */
+
+       if (p->offset > p->rmargin)
+               p->offset = p->rmargin;
+
        return(0);
 }
 
        return(0);
 }
 
@@ -850,20 +857,31 @@ print_man_node(DECL_ARGS)
        size_t           rm, rmax;
        int              c;
 
        size_t           rm, rmax;
        int              c;
 
-       c = 1;
-
        switch (n->type) {
        case(MAN_TEXT):
        switch (n->type) {
        case(MAN_TEXT):
-               if (0 == *n->string) {
+               /*
+                * If we have a blank line, output a vertical space.
+                * If we have a space as the first character, break
+                * before printing the line's data.
+                */
+               if ('\0' == *n->string) {
                        term_vspace(p);
                        term_vspace(p);
-                       break;
-               }
+                       return;
+               } else if (' ' == *n->string && MAN_LINE & n->flags)
+                       term_newln(p);
 
                term_word(p, n->string);
 
 
                term_word(p, n->string);
 
-               /* FIXME: this means that macro lines are munged!  */
-
-               if (MANT_LITERAL & mt->fl) {
+               /*
+                * If we're in a literal context, make sure that words
+                * togehter on the same line stay together.  This is a
+                * POST-printing call, so we check the NEXT word.  Since
+                * -man doesn't have nested macros, we don't need to be
+                * more specific than this.
+                */
+               if (MANT_LITERAL & mt->fl && 
+                               (NULL == n->next || 
+                                n->next->line > n->line)) {
                        rm = p->rmargin;
                        rmax = p->maxrmargin;
                        p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
                        rm = p->rmargin;
                        rmax = p->maxrmargin;
                        p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
@@ -873,35 +891,40 @@ print_man_node(DECL_ARGS)
                        p->rmargin = rm;
                        p->maxrmargin = rmax;
                }
                        p->rmargin = rm;
                        p->maxrmargin = rmax;
                }
-               break;
+
+               if (MAN_EOS & n->flags)
+                       p->flags |= TERMP_SENTENCE;
+               return;
+       case (MAN_EQN):
+               term_word(p, n->eqn->data);
+               return;
        case (MAN_TBL):
        case (MAN_TBL):
+               /*
+                * Tables are preceded by a newline.  Then process a
+                * table line, which will cause line termination,
+                */
                if (TBL_SPAN_FIRST & n->span->flags) 
                        term_newln(p);
                term_tbl(p, n->span);
                if (TBL_SPAN_FIRST & n->span->flags) 
                        term_newln(p);
                term_tbl(p, n->span);
-               break;
+               return;
        default:
        default:
-               if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
-                       term_fontrepl(p, TERMFONT_NONE);
-               if (termacts[n->tok].pre)
-                       c = (*termacts[n->tok].pre)(p, mt, n, m);
                break;
        }
 
                break;
        }
 
+       if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+               term_fontrepl(p, TERMFONT_NONE);
+
+       c = 1;
+       if (termacts[n->tok].pre)
+               c = (*termacts[n->tok].pre)(p, mt, n, m);
+
        if (c && n->child)
                print_man_nodelist(p, mt, n->child, m);
 
        if (c && n->child)
                print_man_nodelist(p, mt, n->child, m);
 
-       switch (n->type) {
-       case (MAN_TEXT):
-               /* FALLTHROUGH */
-       case (MAN_TBL):
-               break;
-       default:
-               if (termacts[n->tok].post)
-                       (*termacts[n->tok].post)(p, mt, n, m);
-               if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
-                       term_fontrepl(p, TERMFONT_NONE);
-               break;
-       }
+       if (termacts[n->tok].post)
+               (*termacts[n->tok].post)(p, mt, n, m);
+       if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+               term_fontrepl(p, TERMFONT_NONE);
 
        if (MAN_EOS & n->flags)
                p->flags |= TERMP_SENTENCE;
 
        if (MAN_EOS & n->flags)
                p->flags |= TERMP_SENTENCE;
@@ -922,24 +945,18 @@ print_man_nodelist(DECL_ARGS)
 static void
 print_man_foot(struct termp *p, const void *arg)
 {
 static void
 print_man_foot(struct termp *p, const void *arg)
 {
-       char            buf[DATESIZ];
        const struct man_meta *meta;
 
        meta = (const struct man_meta *)arg;
 
        term_fontrepl(p, TERMFONT_NONE);
 
        const struct man_meta *meta;
 
        meta = (const struct man_meta *)arg;
 
        term_fontrepl(p, TERMFONT_NONE);
 
-       if (meta->rawdate)
-               strlcpy(buf, meta->rawdate, DATESIZ);
-       else
-               time2a(meta->date, buf, DATESIZ);
-
        term_vspace(p);
        term_vspace(p);
        term_vspace(p);
 
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
        term_vspace(p);
        term_vspace(p);
        term_vspace(p);
 
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
-       p->rmargin = p->maxrmargin - term_strlen(p, buf);
+       p->rmargin = p->maxrmargin - term_strlen(p, meta->date);
        p->offset = 0;
 
        /* term_strlen() can return zero. */
        p->offset = 0;
 
        /* term_strlen() can return zero. */
@@ -957,7 +974,7 @@ print_man_foot(struct termp *p, const void *arg)
        p->rmargin = p->maxrmargin;
        p->flags &= ~TERMP_NOBREAK;
 
        p->rmargin = p->maxrmargin;
        p->flags &= ~TERMP_NOBREAK;
 
-       term_word(p, buf);
+       term_word(p, meta->date);
        term_flushln(p);
 }
 
        term_flushln(p);
 }
 
index bcfcbac..03bb120 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: man_validate.c,v 1.57 2011/01/01 12:59:17 kristaps Exp $ */
+/*     $Id: man_validate.c,v 1.67 2011/03/22 15:30:30 kristaps Exp $ */
 /*
 /*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 Ingo Schwarze <schwarze@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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -29,6 +30,7 @@
 #include <string.h>
 #include <time.h>
 
 #include <string.h>
 #include <time.h>
 
+#include "man.h"
 #include "mandoc.h"
 #include "libman.h"
 #include "libmandoc.h"
 #include "mandoc.h"
 #include "libman.h"
 #include "libmandoc.h"
@@ -53,7 +55,6 @@ static        int       check_part(CHKARGS);
 static int       check_root(CHKARGS);
 static int       check_sec(CHKARGS);
 static int       check_text(CHKARGS);
 static int       check_root(CHKARGS);
 static int       check_sec(CHKARGS);
 static int       check_text(CHKARGS);
-static int       check_title(CHKARGS);
 
 static int       post_AT(CHKARGS);
 static int       post_fi(CHKARGS);
 
 static int       post_AT(CHKARGS);
 static int       post_fi(CHKARGS);
@@ -70,7 +71,7 @@ static        v_check   posts_nf[] = { check_eq0, post_nf, NULL };
 static v_check   posts_par[] = { check_par, NULL };
 static v_check   posts_part[] = { check_part, NULL };
 static v_check   posts_sec[] = { check_sec, NULL };
 static v_check   posts_par[] = { check_par, NULL };
 static v_check   posts_part[] = { check_part, NULL };
 static v_check   posts_sec[] = { check_sec, NULL };
-static v_check   posts_th[] = { check_ge2, check_le5, check_title, post_TH, NULL };
+static v_check   posts_th[] = { check_ge2, check_le5, post_TH, NULL };
 static v_check   posts_uc[] = { post_UC, NULL };
 static v_check   pres_bline[] = { check_bline, NULL };
 
 static v_check   posts_uc[] = { post_UC, NULL };
 static v_check   pres_bline[] = { check_bline, NULL };
 
@@ -80,12 +81,12 @@ static      const struct man_valid man_valids[MAN_MAX] = {
        { pres_bline, posts_th }, /* TH */
        { pres_bline, posts_sec }, /* SH */
        { pres_bline, posts_sec }, /* SS */
        { pres_bline, posts_th }, /* TH */
        { pres_bline, posts_sec }, /* SH */
        { pres_bline, posts_sec }, /* SS */
-       { pres_bline, posts_par }, /* TP */
+       { pres_bline, NULL }, /* TP */
        { pres_bline, posts_par }, /* LP */
        { pres_bline, posts_par }, /* PP */
        { pres_bline, posts_par }, /* P */
        { pres_bline, posts_par }, /* LP */
        { pres_bline, posts_par }, /* PP */
        { pres_bline, posts_par }, /* P */
-       { pres_bline, posts_par }, /* IP */
-       { pres_bline, posts_par }, /* HP */
+       { pres_bline, NULL }, /* IP */
+       { pres_bline, NULL }, /* HP */
        { NULL, NULL }, /* SM */
        { NULL, NULL }, /* SB */
        { NULL, NULL }, /* BI */
        { NULL, NULL }, /* SM */
        { NULL, NULL }, /* SB */
        { NULL, NULL }, /* BI */
@@ -122,6 +123,8 @@ man_valid_pre(struct man *m, struct man_node *n)
                /* FALLTHROUGH */
        case (MAN_ROOT):
                /* FALLTHROUGH */
                /* FALLTHROUGH */
        case (MAN_ROOT):
                /* FALLTHROUGH */
+       case (MAN_EQN):
+               /* FALLTHROUGH */
        case (MAN_TBL):
                return(1);
        default:
        case (MAN_TBL):
                return(1);
        default:
@@ -151,6 +154,8 @@ man_valid_post(struct man *m)
                return(check_text(m, m->last));
        case (MAN_ROOT):
                return(check_root(m, m->last));
                return(check_text(m, m->last));
        case (MAN_ROOT):
                return(check_root(m, m->last));
+       case (MAN_EQN):
+               /* FALLTHROUGH */
        case (MAN_TBL):
                return(1);
        default:
        case (MAN_TBL):
                return(1);
        default:
@@ -191,37 +196,15 @@ check_root(CHKARGS)
                 */
 
                m->meta.title = mandoc_strdup("unknown");
                 */
 
                m->meta.title = mandoc_strdup("unknown");
-               m->meta.date = time(NULL);
                m->meta.msec = mandoc_strdup("1");
                m->meta.msec = mandoc_strdup("1");
+               m->meta.date = mandoc_normdate
+                       (m->parse, NULL, n->line, n->pos);
        }
 
        return(1);
 }
 
 
        }
 
        return(1);
 }
 
 
-static int
-check_title(CHKARGS) 
-{
-       const char      *p;
-
-       assert(n->child);
-       /* FIXME: is this sufficient? */
-       if ('\0' == *n->child->string) {
-               man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
-               return(0);
-       }
-
-       for (p = n->child->string; '\0' != *p; p++)
-               /* Only warn about this once... */
-               if (isalpha((u_char)*p) && ! isupper((u_char)*p)) {
-                       man_nmsg(m, n, MANDOCERR_UPPERCASE);
-                       break;
-               }
-
-       return(1);
-}
-
-
 static int
 check_text(CHKARGS) 
 {
 static int
 check_text(CHKARGS) 
 {
@@ -241,9 +224,8 @@ check_text(CHKARGS)
                if ('\t' == *p) {
                        if (MAN_LITERAL & m->flags)
                                continue;
                if ('\t' == *p) {
                        if (MAN_LITERAL & m->flags)
                                continue;
-                       if (man_pmsg(m, n->line, pos, MANDOCERR_BADTAB))
-                               continue;
-                       return(0);
+                       man_pmsg(m, n->line, pos, MANDOCERR_BADTAB);
+                       continue;
                }
 
                /* Check the special character. */
                }
 
                /* Check the special character. */
@@ -266,10 +248,10 @@ check_##name(CHKARGS) \
 { \
        if (n->nchild ineq (x)) \
                return(1); \
 { \
        if (n->nchild ineq (x)) \
                return(1); \
-       man_vmsg(m, MANDOCERR_SYNTARGCOUNT, n->line, n->pos, \
+       mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \
                        "line arguments %s %d (have %d)", \
                        #ineq, (x), n->nchild); \
                        "line arguments %s %d (have %d)", \
                        #ineq, (x), n->nchild); \
-       return(0); \
+       return(1); \
 }
 
 INEQ_DEFINE(0, ==, eq0)
 }
 
 INEQ_DEFINE(0, ==, eq0)
@@ -318,14 +300,17 @@ check_ft(CHKARGS)
        }
 
        if (0 == ok) {
        }
 
        if (0 == ok) {
-               man_vmsg(m, MANDOCERR_BADFONT, 
-                               n->line, n->pos, "%s", cp);
+               mandoc_vmsg
+                       (MANDOCERR_BADFONT, m->parse,
+                        n->line, n->pos, "%s", cp);
                *cp = '\0';
        }
 
        if (1 < n->nchild)
                *cp = '\0';
        }
 
        if (1 < n->nchild)
-               man_vmsg(m, MANDOCERR_ARGCOUNT, n->line, n->pos,
-                               "want one child (have %d)", n->nchild);
+               mandoc_vmsg
+                       (MANDOCERR_ARGCOUNT, m->parse, n->line, 
+                        n->pos, "want one child (have %d)", 
+                        n->nchild);
 
        return(1);
 }
 
        return(1);
 }
@@ -338,7 +323,8 @@ check_sec(CHKARGS)
                man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
                return(0);
        } else if (MAN_BODY == n->type && 0 == n->nchild)
                man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
                return(0);
        } else if (MAN_BODY == n->type && 0 == n->nchild)
-               man_nmsg(m, n, MANDOCERR_NOBODY);
+               mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line, 
+                               n->pos, "want children (have none)");
 
        return(1);
 }
 
        return(1);
 }
@@ -349,7 +335,8 @@ check_part(CHKARGS)
 {
 
        if (MAN_BODY == n->type && 0 == n->nchild)
 {
 
        if (MAN_BODY == n->type && 0 == n->nchild)
-               man_nmsg(m, n, MANDOCERR_NOBODY);
+               mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line, 
+                               n->pos, "want children (have none)");
 
        return(1);
 }
 
        return(1);
 }
@@ -359,33 +346,22 @@ static int
 check_par(CHKARGS)
 {
 
 check_par(CHKARGS)
 {
 
-       if (MAN_BODY == n->type) 
-               switch (n->tok) {
-               case (MAN_IP):
-                       /* FALLTHROUGH */
-               case (MAN_HP):
-                       /* FALLTHROUGH */
-               case (MAN_TP):
-                       /* Body-less lists are ok. */
-                       break;
-               default:
-                       if (0 == n->nchild)
-                               man_nmsg(m, n, MANDOCERR_NOBODY);
-                       break;
-               }
-       if (MAN_HEAD == n->type)
-               switch (n->tok) {
-               case (MAN_PP):
-                       /* FALLTHROUGH */
-               case (MAN_P):
-                       /* FALLTHROUGH */
-               case (MAN_LP):
-                       if (n->nchild)
-                               man_nmsg(m, n, MANDOCERR_ARGSLOST);
-                       break;
-               default:
-                       break;
-               }
+       switch (n->type) {
+       case (MAN_BLOCK):
+               if (0 == n->body->nchild)
+                       man_node_delete(m, n);
+               break;
+       case (MAN_BODY):
+               if (0 == n->nchild)
+                       man_nmsg(m, n, MANDOCERR_IGNPAR);
+               break;
+       case (MAN_HEAD):
+               if (n->nchild)
+                       man_nmsg(m, n, MANDOCERR_ARGSLOST);
+               break;
+       default:
+               break;
+       }
 
        return(1);
 }
 
        return(1);
 }
@@ -407,6 +383,8 @@ check_bline(CHKARGS)
 static int
 post_TH(CHKARGS)
 {
 static int
 post_TH(CHKARGS)
 {
+       const char      *p;
+       int              line, pos;
 
        if (m->meta.title)
                free(m->meta.title);
 
        if (m->meta.title)
                free(m->meta.title);
@@ -416,44 +394,46 @@ post_TH(CHKARGS)
                free(m->meta.source);
        if (m->meta.msec)
                free(m->meta.msec);
                free(m->meta.source);
        if (m->meta.msec)
                free(m->meta.msec);
-       if (m->meta.rawdate)
-               free(m->meta.rawdate);
+       if (m->meta.date)
+               free(m->meta.date);
 
 
-       m->meta.title = m->meta.vol = m->meta.rawdate =
+       line = n->line;
+       pos = n->pos;
+       m->meta.title = m->meta.vol = m->meta.date =
                m->meta.msec = m->meta.source = NULL;
                m->meta.msec = m->meta.source = NULL;
-       m->meta.date = 0;
 
        /* ->TITLE<- MSEC DATE SOURCE VOL */
 
        n = n->child;
 
        /* ->TITLE<- MSEC DATE SOURCE VOL */
 
        n = n->child;
-       assert(n);
-       m->meta.title = mandoc_strdup(n->string);
+       if (n && n->string) {
+               for (p = n->string; '\0' != *p; p++) {
+                       /* Only warn about this once... */
+                       if (isalpha((u_char)*p) && ! isupper((u_char)*p)) {
+                               man_nmsg(m, n, MANDOCERR_UPPERCASE);
+                               break;
+                       }
+               }
+               m->meta.title = mandoc_strdup(n->string);
+       } else
+               m->meta.title = mandoc_strdup("");
 
        /* TITLE ->MSEC<- DATE SOURCE VOL */
 
 
        /* TITLE ->MSEC<- DATE SOURCE VOL */
 
-       n = n->next;
-       assert(n);
-       m->meta.msec = mandoc_strdup(n->string);
+       if (n)
+               n = n->next;
+       if (n && n->string)
+               m->meta.msec = mandoc_strdup(n->string);
+       else
+               m->meta.msec = mandoc_strdup("");
 
        /* TITLE MSEC ->DATE<- SOURCE VOL */
 
 
        /* TITLE MSEC ->DATE<- SOURCE VOL */
 
-       /*
-        * Try to parse the date.  If this works, stash the epoch (this
-        * is optimal because we can reformat it in the canonical form).
-        * If it doesn't parse, isn't specified at all, or is an empty
-        * string, then use the current date.
-        */
-
-       n = n->next;
-       if (n && n->string && *n->string) {
-               m->meta.date = mandoc_a2time
-                       (MTIME_ISO_8601, n->string);
-               if (0 == m->meta.date) {
-                       man_nmsg(m, n, MANDOCERR_BADDATE);
-                       m->meta.rawdate = mandoc_strdup(n->string);
-               }
-       } else
-               m->meta.date = time(NULL);
+       if (n)
+               n = n->next;
+       if (n)
+               pos = n->pos;
+       m->meta.date = mandoc_normdate
+               (m->parse, n ? n->string : NULL, line, pos);
 
        /* TITLE MSEC DATE ->SOURCE<- VOL */
 
 
        /* TITLE MSEC DATE ->SOURCE<- VOL */
 
@@ -489,7 +469,7 @@ post_fi(CHKARGS)
 {
 
        if ( ! (MAN_LITERAL & m->flags))
 {
 
        if ( ! (MAN_LITERAL & m->flags))
-               man_nmsg(m, n, MANDOCERR_NOSCOPE);
+               man_nmsg(m, n, MANDOCERR_WNOSCOPE);
 
        m->flags &= ~MAN_LITERAL;
        return(1);
 
        m->flags &= ~MAN_LITERAL;
        return(1);
diff --git a/contrib/mdocml/mandoc-db.1 b/contrib/mdocml/mandoc-db.1
new file mode 100644 (file)
index 0000000..24d147c
--- /dev/null
@@ -0,0 +1,132 @@
+.\"    $Id: mandoc-db.1,v 1.1 2011/04/04 10:53:15 kristaps Exp $
+.\"
+.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+.\"
+.\" 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.
+.\"
+.Dd $Mdocdate: April 4 2011 $
+.Dt MANDOC-DB 1
+.Os
+.Sh NAME
+.Nm mandoc-db
+.Nd index UNIX manuals
+.Sh SYNOPSIS
+.Nm
+.Op Fl d Ar dir
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility extracts keywords from
+.Ux
+manuals and indexes them for fast retrieval.
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl d Ar dir
+The directory into which to write the keyword and index databases.
+.It Ar
+Read input from zero or more files in
+.Xr mdoc 7
+or
+.Xr man 7
+.Ux
+manual format.
+.El
+.Pp
+By default,
+.Nm
+constructs the
+.Sx Index Database
+and
+.Sx Keyword Database
+in the current working directory.
+.Pp
+If fatal parse errors are encountered, the offending file is printed to
+stderr, omitted from the index, and the parse continues with the next
+input file.
+.Ss Index Database
+The index database,
+.Pa mandoc.index ,
+is a
+.Xr recno 3
+database of nil-terminated filenames (record length is non-zero string
+length plus one) passed to
+.Nm .
+Entries are sequentially-numbered, but the filenames are unordered.
+.Ss Keyword Database
+The keyword database,
+.Pa mandoc.db ,
+is a
+.Xr btree 3
+database of nil-terminated keywords (record length is non-zero string
+length plus one) mapping to a 8-byte binary field consisting of the
+keyword type and source
+.Sx Index Database
+record number.
+The type, an unsigned 32-bit integer in host order, is one of the
+following:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Li 0x01
+The name of a manual page as given in the NAME section.
+.It Li 0x02
+A function prototype name as given in the SYNOPSIS section.
+.It Li 0x03
+A utility name as given in the SYNOPSIS section.
+.It Li 0x04
+An include file as given in the SYNOPSIS section.
+.It Li 0x05
+A variable name as given in the SYNOPSIS section.
+.El
+.Pp
+If a value is encountered outside of this range, the database is
+corrupt.
+.Pp
+The latter four bytes are a host-ordered record number within the
+.Sx Index Database .
+.Pp
+The
+.Nm
+utility is
+.Ud
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa mandoc.db
+A
+.Xr btree 3
+keyword database mapping keywords to a type and file reference in
+.Pa mandoc.index .
+.It Pa mandoc.db~
+Working copy of
+.Pa mandoc.db .
+.It Pa mandoc.index
+A
+.Xr recno 3
+database of indexed file-names.
+.It Pa mandoc.index~
+Working copy of
+.Pa mandoc.index .
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr mandoc 1
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Kristaps Dzonsons Aq kristaps@bsd.lv .
+.Sh CAVEATS
+Only
+.Xr mdoc 7
+manuals are processed.
diff --git a/contrib/mdocml/mandoc-db.c b/contrib/mdocml/mandoc-db.c
new file mode 100644 (file)
index 0000000..0c66efa
--- /dev/null
@@ -0,0 +1,669 @@
+/*     $Id: mandoc-db.c,v 1.5 2011/04/04 16:49:03 kristaps Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+
+#include <assert.h>
+#ifdef __linux__
+# include <db_185.h>
+#else
+# include <db.h>
+#endif
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "man.h"
+#include "mdoc.h"
+#include "mandoc.h"
+
+#define        MANDOC_DB        "mandoc.db"
+#define        MANDOC_IDX       "mandoc.index"
+#define        MANDOC_BUFSZ      BUFSIZ
+#define        MANDOC_FLAGS      O_CREAT|O_TRUNC|O_RDWR
+
+enum   type {
+       MANDOC_NONE = 0,
+       MANDOC_NAME,
+       MANDOC_FUNCTION,
+       MANDOC_UTILITY,
+       MANDOC_INCLUDES,
+       MANDOC_VARIABLE
+};
+
+#define        MDOC_ARGS         DB *db, \
+                         const char *dbn, \
+                         DBT *key, size_t *ksz, \
+                         DBT *val, \
+                         const struct mdoc_node *n
+
+static void              dbt_append(DBT *, size_t *, const char *);
+static void              dbt_appendb(DBT *, size_t *, 
+                               const void *, size_t);
+static void              dbt_init(DBT *, size_t *);
+static void              usage(void);
+static void              pmdoc(DB *, const char *, 
+                               DBT *, size_t *, DBT *, 
+                               const char *, struct mdoc *);
+static void              pmdoc_node(MDOC_ARGS);
+static void              pmdoc_Fd(MDOC_ARGS);
+static void              pmdoc_In(MDOC_ARGS);
+static void              pmdoc_Fn(MDOC_ARGS);
+static void              pmdoc_Fo(MDOC_ARGS);
+static void              pmdoc_Nm(MDOC_ARGS);
+static void              pmdoc_Vt(MDOC_ARGS);
+
+typedef        void            (*pmdoc_nf)(MDOC_ARGS);
+
+static const char       *progname;
+
+static const pmdoc_nf    mdocs[MDOC_MAX] = {
+       NULL, /* Ap */
+       NULL, /* Dd */
+       NULL, /* Dt */
+       NULL, /* Os */
+       NULL, /* Sh */ 
+       NULL, /* Ss */ 
+       NULL, /* Pp */ 
+       NULL, /* D1 */
+       NULL, /* Dl */
+       NULL, /* Bd */
+       NULL, /* Ed */
+       NULL, /* Bl */ 
+       NULL, /* El */
+       NULL, /* It */
+       NULL, /* Ad */ 
+       NULL, /* An */ 
+       NULL, /* Ar */
+       NULL, /* Cd */ 
+       NULL, /* Cm */
+       NULL, /* Dv */ 
+       NULL, /* Er */ 
+       NULL, /* Ev */ 
+       NULL, /* Ex */ 
+       NULL, /* Fa */ 
+       pmdoc_Fd, /* Fd */
+       NULL, /* Fl */
+       pmdoc_Fn, /* Fn */ 
+       NULL, /* Ft */ 
+       NULL, /* Ic */ 
+       pmdoc_In, /* In */ 
+       NULL, /* Li */
+       NULL, /* Nd */
+       pmdoc_Nm, /* Nm */
+       NULL, /* Op */
+       NULL, /* Ot */
+       NULL, /* Pa */
+       NULL, /* Rv */
+       NULL, /* St */ 
+       pmdoc_Vt, /* Va */
+       pmdoc_Vt, /* Vt */ 
+       NULL, /* Xr */ 
+       NULL, /* %A */
+       NULL, /* %B */
+       NULL, /* %D */
+       NULL, /* %I */
+       NULL, /* %J */
+       NULL, /* %N */
+       NULL, /* %O */
+       NULL, /* %P */
+       NULL, /* %R */
+       NULL, /* %T */
+       NULL, /* %V */
+       NULL, /* Ac */
+       NULL, /* Ao */
+       NULL, /* Aq */
+       NULL, /* At */ 
+       NULL, /* Bc */
+       NULL, /* Bf */
+       NULL, /* Bo */
+       NULL, /* Bq */
+       NULL, /* Bsx */
+       NULL, /* Bx */
+       NULL, /* Db */
+       NULL, /* Dc */
+       NULL, /* Do */
+       NULL, /* Dq */
+       NULL, /* Ec */
+       NULL, /* Ef */ 
+       NULL, /* Em */ 
+       NULL, /* Eo */
+       NULL, /* Fx */
+       NULL, /* Ms */ 
+       NULL, /* No */
+       NULL, /* Ns */
+       NULL, /* Nx */
+       NULL, /* Ox */
+       NULL, /* Pc */
+       NULL, /* Pf */
+       NULL, /* Po */
+       NULL, /* Pq */
+       NULL, /* Qc */
+       NULL, /* Ql */
+       NULL, /* Qo */
+       NULL, /* Qq */
+       NULL, /* Re */
+       NULL, /* Rs */
+       NULL, /* Sc */
+       NULL, /* So */
+       NULL, /* Sq */
+       NULL, /* Sm */ 
+       NULL, /* Sx */
+       NULL, /* Sy */
+       NULL, /* Tn */
+       NULL, /* Ux */
+       NULL, /* Xc */
+       NULL, /* Xo */
+       pmdoc_Fo, /* Fo */ 
+       NULL, /* Fc */ 
+       NULL, /* Oo */
+       NULL, /* Oc */
+       NULL, /* Bk */
+       NULL, /* Ek */
+       NULL, /* Bt */
+       NULL, /* Hf */
+       NULL, /* Fr */
+       NULL, /* Ud */
+       NULL, /* Lb */
+       NULL, /* Lp */ 
+       NULL, /* Lk */ 
+       NULL, /* Mt */ 
+       NULL, /* Brq */ 
+       NULL, /* Bro */ 
+       NULL, /* Brc */ 
+       NULL, /* %C */
+       NULL, /* Es */
+       NULL, /* En */
+       NULL, /* Dx */
+       NULL, /* %Q */
+       NULL, /* br */
+       NULL, /* sp */
+       NULL, /* %U */
+       NULL, /* Ta */
+};
+
+int
+main(int argc, char *argv[])
+{
+       struct mparse   *mp; /* parse sequence */
+       struct mdoc     *mdoc; /* resulting mdoc */
+       char            *fn;
+       const char      *dir; /* result dir (default: cwd) */
+       char             ibuf[MAXPATHLEN], /* index fname */
+                        ibbuf[MAXPATHLEN], /* index backup fname */
+                        fbuf[MAXPATHLEN],  /* btree fname */
+                        fbbuf[MAXPATHLEN]; /* btree backup fname */
+       int              c;
+       DB              *index, /* index database */
+                       *db; /* keyword database */
+       DBT              rkey, rval, /* recno entries */
+                        key, val; /* persistent keyword entries */
+       size_t           ksz; /* entry buffer size */
+       char             vbuf[8];
+       BTREEINFO        info; /* btree configuration */
+       recno_t          rec;
+       extern int       optind;
+       extern char     *optarg;
+
+       progname = strrchr(argv[0], '/');
+       if (progname == NULL)
+               progname = argv[0];
+       else
+               ++progname;
+
+       dir = "";
+
+       while (-1 != (c = getopt(argc, argv, "d:")))
+               switch (c) {
+               case ('d'):
+                       dir = optarg;
+                       break;
+               default:
+                       usage();
+                       return((int)MANDOCLEVEL_BADARG);
+               }
+
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * Set up temporary file-names into which we're going to write
+        * all of our data (both for the index and database).  These
+        * will be securely renamed to the real file-names after we've
+        * written all of our data.
+        */
+
+       ibuf[0] = ibuf[MAXPATHLEN - 2] =
+               ibbuf[0] = ibbuf[MAXPATHLEN - 2] = 
+               fbuf[0] = fbuf[MAXPATHLEN - 2] = 
+               fbbuf[0] = fbbuf[MAXPATHLEN - 2] = '\0';
+
+       strlcat(fbuf, dir, MAXPATHLEN);
+       strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
+
+       strlcat(fbbuf, fbuf, MAXPATHLEN);
+       strlcat(fbbuf, "~", MAXPATHLEN);
+
+       strlcat(ibuf, dir, MAXPATHLEN);
+       strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
+
+       strlcat(ibbuf, ibuf, MAXPATHLEN);
+       strlcat(ibbuf, "~", MAXPATHLEN);
+
+       if ('\0' != fbuf[MAXPATHLEN - 2] ||
+                       '\0' != fbbuf[MAXPATHLEN - 2] ||
+                       '\0' != ibuf[MAXPATHLEN - 2] ||
+                       '\0' != ibbuf[MAXPATHLEN - 2]) {
+               fprintf(stderr, "%s: Path too long\n", progname);
+               exit((int)MANDOCLEVEL_SYSERR);
+       }
+
+       /*
+        * For the keyword database, open a BTREE database that allows
+        * duplicates.  For the index database, use a standard RECNO
+        * database type.
+        */
+
+       memset(&info, 0, sizeof(BTREEINFO));
+       info.flags = R_DUP;
+       db = dbopen(fbbuf, MANDOC_FLAGS, 0644, DB_BTREE, &info);
+
+       if (NULL == db) {
+               perror(fbbuf);
+               exit((int)MANDOCLEVEL_SYSERR);
+       }
+
+       index = dbopen(ibbuf, MANDOC_FLAGS, 0644, DB_RECNO, NULL);
+
+       if (NULL == db) {
+               perror(ibbuf);
+               (*db->close)(db);
+               exit((int)MANDOCLEVEL_SYSERR);
+       }
+
+       /*
+        * Try parsing the manuals given on the command line.  If we
+        * totally fail, then just keep on going.  Take resulting trees
+        * and push them down into the database code.
+        * Use the auto-parser and don't report any errors.
+        */
+
+       mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+
+       memset(&key, 0, sizeof(DBT));
+       memset(&val, 0, sizeof(DBT));
+       memset(&rkey, 0, sizeof(DBT));
+       memset(&rval, 0, sizeof(DBT));
+
+       val.size = sizeof(vbuf);
+       val.data = vbuf;
+       rkey.size = sizeof(recno_t);
+
+       rec = 1;
+       ksz = 0;
+
+       while (NULL != (fn = *argv++)) {
+               mparse_reset(mp);
+
+               if (mparse_readfd(mp, -1, fn) >= MANDOCLEVEL_FATAL) {
+                       fprintf(stderr, "%s: Parse failure\n", fn);
+                       continue;
+               }
+
+               mparse_result(mp, &mdoc, NULL);
+               if (NULL == mdoc)
+                       continue;
+
+               rkey.data = &rec;
+               rval.data = fn;
+               rval.size = strlen(fn) + 1;
+
+               if (-1 == (*index->put)(index, &rkey, &rval, 0)) {
+                       perror(ibbuf);
+                       break;
+               }
+
+               memset(val.data, 0, sizeof(uint32_t));
+               memcpy(val.data + 4, &rec, sizeof(uint32_t));
+
+               pmdoc(db, fbbuf, &key, &ksz, &val, fn, mdoc);
+               rec++;
+       }
+
+       (*db->close)(db);
+       (*index->close)(index);
+
+       mparse_free(mp);
+
+       free(key.data);
+
+       /* Atomically replace the file with our temporary one. */
+
+       if (-1 == rename(fbbuf, fbuf))
+               perror(fbuf);
+       if (-1 == rename(ibbuf, ibuf))
+               perror(fbuf);
+
+       return((int)MANDOCLEVEL_OK);
+}
+
+/*
+ * Initialise the stored database key whose data buffer is shared
+ * between uses (as the key must sometimes be constructed from an array
+ * of 
+ */
+static void
+dbt_init(DBT *key, size_t *ksz)
+{
+
+       if (0 == *ksz) {
+               assert(0 == key->size);
+               assert(NULL == key->data);
+               key->data = mandoc_malloc(MANDOC_BUFSZ);
+               *ksz = MANDOC_BUFSZ;
+       }
+
+       key->size = 0;
+}
+
+/*
+ * Append a binary value to a database entry.  This can be invoked
+ * multiple times; the buffer is automatically resized.
+ */
+static void
+dbt_appendb(DBT *key, size_t *ksz, const void *cp, size_t sz)
+{
+
+       assert(key->data);
+
+       /* Overshoot by MANDOC_BUFSZ. */
+
+       while (key->size + sz >= *ksz) {
+               *ksz = key->size + sz + MANDOC_BUFSZ;
+               key->data = mandoc_realloc(key->data, *ksz);
+       }
+
+       memcpy(key->data + (int)key->size, cp, sz);
+       key->size += sz;
+}
+
+/*
+ * Append a nil-terminated string to the database entry.  This can be
+ * invoked multiple times.  The database entry will be nil-terminated as
+ * well; if invoked multiple times, a space is put between strings.
+ */
+static void
+dbt_append(DBT *key, size_t *ksz, const char *cp)
+{
+       size_t           sz;
+
+       if (0 == (sz = strlen(cp)))
+               return;
+
+       assert(key->data);
+
+       if (key->size)
+               ((char *)key->data)[(int)key->size - 1] = ' ';
+
+       dbt_appendb(key, ksz, cp, sz + 1);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_Fd(MDOC_ARGS)
+{
+       uint32_t         fl;
+       const char      *start, *end;
+       size_t           sz;
+       char             nil;
+       
+       if (SEC_SYNOPSIS != n->sec)
+               return;
+       if (NULL == (n = n->child) || MDOC_TEXT != n->type)
+               return;
+
+       /*
+        * Only consider those `Fd' macro fields that begin with an
+        * "inclusion" token (versus, e.g., #define).
+        */
+       if (strcmp("#include", n->string))
+               return;
+
+       if (NULL == (n = n->next) || MDOC_TEXT != n->type)
+               return;
+
+       /*
+        * Strip away the enclosing angle brackets and make sure we're
+        * not zero-length.
+        */
+
+       start = n->string;
+       if ('<' == *start || '"' == *start)
+               start++;
+
+       if (0 == (sz = strlen(start)))
+               return;
+
+       end = &start[(int)sz - 1];
+       if ('>' == *end || '"' == *end)
+               end--;
+
+       nil = '\0';
+       dbt_appendb(key, ksz, start, end - start + 1);
+       dbt_appendb(key, ksz, &nil, 1);
+
+       fl = MANDOC_INCLUDES;
+       memcpy(val->data, &fl, 4);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_In(MDOC_ARGS)
+{
+       uint32_t         fl;
+       
+       if (SEC_SYNOPSIS != n->sec)
+               return;
+       if (NULL == n->child || MDOC_TEXT != n->child->type)
+               return;
+
+       dbt_append(key, ksz, n->child->string);
+       fl = MANDOC_INCLUDES;
+       memcpy(val->data, &fl, 4);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_Fn(MDOC_ARGS)
+{
+       uint32_t         fl;
+       const char      *cp;
+       
+       if (SEC_SYNOPSIS != n->sec)
+               return;
+       if (NULL == n->child || MDOC_TEXT != n->child->type)
+               return;
+
+       /* .Fn "struct type *arg" "foo" */
+
+       cp = strrchr(n->child->string, ' ');
+       if (NULL == cp)
+               cp = n->child->string;
+
+       /* Strip away pointer symbol. */
+
+       while ('*' == *cp)
+               cp++;
+
+       dbt_append(key, ksz, cp);
+       fl = MANDOC_FUNCTION;
+       memcpy(val->data, &fl, 4);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_Vt(MDOC_ARGS)
+{
+       uint32_t         fl;
+       const char      *start, *end;
+       size_t           sz;
+       char             nil;
+       
+       if (SEC_SYNOPSIS != n->sec)
+               return;
+       if (MDOC_Vt == n->tok && MDOC_BODY != n->type)
+               return;
+       if (NULL == n->child || MDOC_TEXT != n->child->type)
+               return;
+
+       /*
+        * Strip away leading pointer symbol '*' and trailing ';'.
+        */
+
+       start = n->last->string;
+
+       while ('*' == *start)
+               start++;
+
+       if (0 == (sz = strlen(start)))
+               return;
+
+       end = &start[sz - 1];
+       while (end > start && ';' == *end)
+               end--;
+
+       if (end == start)
+               return;
+
+       nil = '\0';
+       dbt_appendb(key, ksz, start, end - start + 1);
+       dbt_appendb(key, ksz, &nil, 1);
+       fl = MANDOC_VARIABLE;
+       memcpy(val->data, &fl, 4);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_Fo(MDOC_ARGS)
+{
+       uint32_t         fl;
+       
+       if (SEC_SYNOPSIS != n->sec || MDOC_HEAD != n->type)
+               return;
+       if (NULL == n->child || MDOC_TEXT != n->child->type)
+               return;
+
+       dbt_append(key, ksz, n->child->string);
+       fl = MANDOC_FUNCTION;
+       memcpy(val->data, &fl, 4);
+}
+
+/* ARGSUSED */
+static void
+pmdoc_Nm(MDOC_ARGS)
+{
+       uint32_t         fl;
+       
+       if (SEC_NAME == n->sec) {
+               for (n = n->child; n; n = n->next) {
+                       if (MDOC_TEXT != n->type)
+                               continue;
+                       dbt_append(key, ksz, n->string);
+               }
+               fl = MANDOC_NAME;
+               memcpy(val->data, &fl, 4);
+               return;
+       } else if (SEC_SYNOPSIS != n->sec || MDOC_HEAD != n->type)
+               return;
+
+       for (n = n->child; n; n = n->next) {
+               if (MDOC_TEXT != n->type)
+                       continue;
+               dbt_append(key, ksz, n->string);
+       }
+
+       fl = MANDOC_UTILITY;
+       memcpy(val->data, &fl, 4);
+}
+
+/*
+ * Call out to per-macro handlers after clearing the persistent database
+ * key.  If the macro sets the database key, flush it to the database.
+ */
+static void
+pmdoc_node(MDOC_ARGS)
+{
+
+       if (NULL == n)
+               return;
+
+       switch (n->type) {
+       case (MDOC_HEAD):
+               /* FALLTHROUGH */
+       case (MDOC_BODY):
+               /* FALLTHROUGH */
+       case (MDOC_TAIL):
+               /* FALLTHROUGH */
+       case (MDOC_BLOCK):
+               /* FALLTHROUGH */
+       case (MDOC_ELEM):
+               if (NULL == mdocs[n->tok])
+                       break;
+
+               dbt_init(key, ksz);
+               (*mdocs[n->tok])(db, dbn, key, ksz, val, n);
+
+               if (0 == key->size)
+                       break;
+               if (0 == (*db->put)(db, key, val, 0))
+                       break;
+               
+               perror(dbn);
+               exit((int)MANDOCLEVEL_SYSERR);
+               /* NOTREACHED */
+       default:
+               break;
+       }
+
+       pmdoc_node(db, dbn, key, ksz, val, n->child);
+       pmdoc_node(db, dbn, key, ksz, val, n->next);
+}
+
+static void
+pmdoc(DB *db, const char *dbn, 
+               DBT *key, size_t *ksz, DBT *val, 
+               const char *path, struct mdoc *m)
+{
+
+       pmdoc_node(db, dbn, key, ksz, val, mdoc_node(m));
+}
+
+static void
+usage(void)
+{
+
+       fprintf(stderr, "usage: %s "
+                       "[-d path] "
+                       "[file...]\n", 
+                       progname);
+}
index 843f3d7..91cb8fe 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc.1,v 1.84 2011/01/04 23:32:21 kristaps Exp $
+.\"    $Id: mandoc.1,v 1.85 2011/02/09 10:03:02 kristaps Exp $
 .\"
 .\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\"
 .\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: January 4 2011 $
+.Dd $Mdocdate: February 9 2011 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -529,6 +529,7 @@ and
 lists render similarly.
 .El
 .Sh SEE ALSO
 lists render similarly.
 .El
 .Sh SEE ALSO
+.Xr eqn 7 ,
 .Xr man 7 ,
 .Xr mandoc_char 7 ,
 .Xr mdoc 7 ,
 .Xr man 7 ,
 .Xr mandoc_char 7 ,
 .Xr mdoc 7 ,
diff --git a/contrib/mdocml/mandoc.3 b/contrib/mdocml/mandoc.3
new file mode 100644 (file)
index 0000000..2fd887b
--- /dev/null
@@ -0,0 +1,333 @@
+.\"    $Id: mandoc.3,v 1.2 2011/03/28 21:49:42 kristaps Exp $
+.\"
+.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010 Ingo Schwarze <schwarze@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.
+.\"
+.Dd $Mdocdate: March 28 2011 $
+.Dt MANDOC 3
+.Os
+.Sh NAME
+.Nm mandoc ,
+.Nm man_meta ,
+.Nm man_node ,
+.Nm mdoc_meta ,
+.Nm mdoc_node ,
+.Nm mparse_alloc ,
+.Nm mparse_free ,
+.Nm mparse_readfd ,
+.Nm mparse_reset ,
+.Nm mparse_result ,
+.Nm mparse_strerror ,
+.Nm mparse_strlevel
+.Nd mandoc macro compiler library
+.Sh SYNOPSIS
+.In man.h
+.In mdoc.h
+.In mandoc.h
+.Ft "const struct man_meta *"
+.Fo man_meta
+.Fa "const struct man *man"
+.Fc
+.Ft "const struct man_node *"
+.Fo man_node
+.Fa "const struct man *man"
+.Fc
+.Ft "const struct mdoc_meta *"
+.Fo mdoc_meta
+.Fa "const struct mdoc *mdoc"
+.Fc
+.Ft "const struct mdoc_node *"
+.Fo mdoc_node
+.Fa "const struct mdoc *mdoc"
+.Fc
+.Ft void
+.Fo mparse_alloc
+.Fa "enum mparset type"
+.Fa "enum mandoclevel wlevel"
+.Fa "mandocmsg msg"
+.Fa "void *msgarg"
+.Fc
+.Ft void
+.Fo mparse_free
+.Fa "struct mparse *parse"
+.Fc
+.Ft "enum mandoclevel"
+.Fo mparse_readfd
+.Fa "struct mparse *parse"
+.Fa "int fd"
+.Fa "const char *fname"
+.Fc
+.Ft void
+.Fo mparse_reset
+.Fa "struct mparse *parse"
+.Fc
+.Ft void
+.Fo mparse_result
+.Fa "struct mparse *parse"
+.Fa "struct mdoc **mdoc"
+.Fa "struct man **man"
+.Fc
+.Ft "const char *"
+.Fo mparse_strerror
+.Fa "enum mandocerr"
+.Fc
+.Ft "const char *"
+.Fo mparse_strlevel
+.Fa "enum mandoclevel"
+.Fc
+.Vt extern const char * const * man_macronames;
+.Vt extern const char * const * mdoc_argnames;
+.Vt extern const char * const * mdoc_macronames;
+.Sh DESCRIPTION
+The
+.Nm mandoc
+library parses a
+.Ux
+manual into an abstract syntax tree (AST).
+.Ux
+manuals are composed of
+.Xr mdoc 7
+or
+.Xr man 7 ,
+and may be mixed with
+.Xr roff 7 ,
+.Xr tbl 7 ,
+and
+.Xr eqn 7
+invocations.
+.Pp
+The following describes a general parse sequence:
+.Bl -enum
+.It
+initiate a parsing sequence with
+.Fn mparse_alloc ;
+.It
+parse files or file descriptors with
+.Fn mparse_readfd ;
+.It
+retrieve a parsed syntax tree, if the parse was successful, with
+.Fn mparse_result ;
+.It
+iterate over parse nodes with
+.Fn mdoc_node
+or
+.Fn man_node ;
+.It
+free all allocated memory with
+.Fn mparse_free ,
+or invoke
+.Fn mparse_reset
+and parse new files.
+.El
+.Sh IMPLEMENTATION NOTES
+This section consists of structural documentation for
+.Xr mdoc 7
+and
+.Xr man 7
+syntax trees.
+.Ss Man Abstract Syntax Tree
+This AST is governed by the ontological rules dictated in
+.Xr man 7
+and derives its terminology accordingly.
+.Pp
+The AST is composed of
+.Vt struct man_node
+nodes with element, root and text types as declared by the
+.Va type
+field.
+Each node also provides its parse point (the
+.Va line ,
+.Va sec ,
+and
+.Va pos
+fields), its position in the tree (the
+.Va parent ,
+.Va child ,
+.Va next
+and
+.Va prev
+fields) and some type-specific data.
+.Pp
+The tree itself is arranged according to the following normal form,
+where capitalised non-terminals represent nodes.
+.Pp
+.Bl -tag -width "ELEMENTXX" -compact
+.It ROOT
+\(<- mnode+
+.It mnode
+\(<- ELEMENT | TEXT | BLOCK
+.It BLOCK
+\(<- HEAD BODY
+.It HEAD
+\(<- mnode*
+.It BODY
+\(<- mnode*
+.It ELEMENT
+\(<- ELEMENT | TEXT*
+.It TEXT
+\(<- [[:alpha:]]*
+.El
+.Pp
+The only elements capable of nesting other elements are those with
+next-lint scope as documented in
+.Xr man 7 .
+.Ss Mdoc Abstract Syntax Tree
+This AST is governed by the ontological
+rules dictated in
+.Xr mdoc 7
+and derives its terminology accordingly.
+.Qq In-line
+elements described in
+.Xr mdoc 7
+are described simply as
+.Qq elements .
+.Pp
+The AST is composed of
+.Vt struct mdoc_node
+nodes with block, head, body, element, root and text types as declared
+by the
+.Va type
+field.
+Each node also provides its parse point (the
+.Va line ,
+.Va sec ,
+and
+.Va pos
+fields), its position in the tree (the
+.Va parent ,
+.Va child ,
+.Va nchild ,
+.Va next
+and
+.Va prev
+fields) and some type-specific data, in particular, for nodes generated
+from macros, the generating macro in the
+.Va tok
+field.
+.Pp
+The tree itself is arranged according to the following normal form,
+where capitalised non-terminals represent nodes.
+.Pp
+.Bl -tag -width "ELEMENTXX" -compact
+.It ROOT
+\(<- mnode+
+.It mnode
+\(<- BLOCK | ELEMENT | TEXT
+.It BLOCK
+\(<- HEAD [TEXT] (BODY [TEXT])+ [TAIL [TEXT]]
+.It ELEMENT
+\(<- TEXT*
+.It HEAD
+\(<- mnode*
+.It BODY
+\(<- mnode* [ENDBODY mnode*]
+.It TAIL
+\(<- mnode*
+.It TEXT
+\(<- [[:printable:],0x1e]*
+.El
+.Pp
+Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of
+the BLOCK production: these refer to punctuation marks.
+Furthermore, although a TEXT node will generally have a non-zero-length
+string, in the specific case of
+.Sq \&.Bd \-literal ,
+an empty line will produce a zero-length string.
+Multiple body parts are only found in invocations of
+.Sq \&Bl \-column ,
+where a new body introduces a new phrase.
+.Pp
+The
+.Xr mdoc 7
+syntax tree accomodates for broken block structures as well.
+The ENDBODY node is available to end the formatting associated
+with a given block before the physical end of that block.
+It has a non-null
+.Va end
+field, is of the BODY
+.Va type ,
+has the same
+.Va tok
+as the BLOCK it is ending, and has a
+.Va pending
+field pointing to that BLOCK's BODY node.
+It is an indirect child of that BODY node
+and has no children of its own.
+.Pp
+An ENDBODY node is generated when a block ends while one of its child
+blocks is still open, like in the following example:
+.Bd -literal -offset indent
+\&.Ao ao
+\&.Bo bo ac
+\&.Ac bc
+\&.Bc end
+.Ed
+.Pp
+This example results in the following block structure:
+.Bd -literal -offset indent
+BLOCK Ao
+    HEAD Ao
+    BODY Ao
+        TEXT ao
+        BLOCK Bo, pending -> Ao
+            HEAD Bo
+            BODY Bo
+                TEXT bo
+                TEXT ac
+                ENDBODY Ao, pending -> Ao
+                TEXT bc
+TEXT end
+.Ed
+.Pp
+Here, the formatting of the
+.Sq \&Ao
+block extends from TEXT ao to TEXT ac,
+while the formatting of the
+.Sq \&Bo
+block extends from TEXT bo to TEXT bc.
+It renders as follows in
+.Fl T Ns Cm ascii
+mode:
+.Pp
+.Dl <ao [bo ac> bc] end
+.Pp
+Support for badly-nested blocks is only provided for backward
+compatibility with some older
+.Xr mdoc 7
+implementations.
+Using badly-nested blocks is
+.Em strongly discouraged ;
+for example, the
+.Fl T Ns Cm html
+and
+.Fl T Ns Cm xhtml
+front-ends to
+.Xr mandoc 1
+are unable to render them in any meaningful way.
+Furthermore, behaviour when encountering badly-nested blocks is not
+consistent across troff implementations, especially when using  multiple
+levels of badly-nested blocks.
+.Sh SEE ALSO
+.Xr mandoc 1 ,
+.Xr eqn 7 ,
+.Xr man 7 ,
+.Xr mdoc 7 ,
+.Xr roff 7 ,
+.Xr tbl 7
+.Sh AUTHORS
+The
+.Nm
+library was written by
+.An Kristaps Dzonsons Aq kristaps@bsd.lv .
index 4faa5a7..da4a160 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.c,v 1.36 2011/01/03 22:42:37 schwarze Exp $ */
+/*     $Id: mandoc.c,v 1.44 2011/03/28 23:52:13 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 #include "mandoc.h"
 #include "libmandoc.h"
 
 #include "mandoc.h"
 #include "libmandoc.h"
 
-static int      a2time(time_t *, const char *, const char *);
+#define DATESIZE 32
 
 
+static int      a2time(time_t *, const char *, const char *);
+static char    *time2a(time_t);
 
 int
 mandoc_special(char *p)
 
 int
 mandoc_special(char *p)
@@ -294,7 +296,7 @@ mandoc_strdup(const char *ptr)
  * or to the null byte terminating the argument line.
  */
 char *
  * or to the null byte terminating the argument line.
  */
 char *
-mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
+mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
 {
        char     *start, *cp;
        int       quoted, pairs, white;
 {
        char     *start, *cp;
        int       quoted, pairs, white;
@@ -341,8 +343,8 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
        }
 
        /* Quoted argument without a closing quote. */
        }
 
        /* Quoted argument without a closing quote. */
-       if (1 == quoted && msg)
-               (*msg)(MANDOCERR_BADQUOTE, data, ln, *pos, NULL);
+       if (1 == quoted)
+               mandoc_msg(MANDOCERR_BADQUOTE, parse, ln, *pos, NULL);
 
        /* Null-terminate this argument and move to the next one. */
        if (pairs)
 
        /* Null-terminate this argument and move to the next one. */
        if (pairs)
@@ -352,16 +354,15 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
                while (' ' == *cp)
                        cp++;
        }
                while (' ' == *cp)
                        cp++;
        }
-       *pos += (cp - start) + (quoted ? 1 : 0);
+       *pos += (int)(cp - start) + (quoted ? 1 : 0);
        *cpp = cp;
 
        *cpp = cp;
 
-       if ('\0' == *cp && msg && (white || ' ' == cp[-1]))
-               (*msg)(MANDOCERR_EOLNSPACE, data, ln, *pos, NULL);
+       if ('\0' == *cp && (white || ' ' == cp[-1]))
+               mandoc_msg(MANDOCERR_EOLNSPACE, parse, ln, *pos, NULL);
 
        return(start);
 }
 
 
        return(start);
 }
 
-
 static int
 a2time(time_t *t, const char *fmt, const char *p)
 {
 static int
 a2time(time_t *t, const char *fmt, const char *p)
 {
@@ -379,41 +380,61 @@ a2time(time_t *t, const char *fmt, const char *p)
        return(0);
 }
 
        return(0);
 }
 
-
-/*
- * Convert from a manual date string (see mdoc(7) and man(7)) into a
- * date according to the stipulated date type.
- */
-time_t
-mandoc_a2time(int flags, const char *p)
+static char *
+time2a(time_t t)
 {
 {
-       time_t           t;
+       struct tm        tm;
+       char            *buf, *p;
+       size_t           ssz;
+       int              isz;
 
 
-       if (MTIME_MDOCDATE & flags) {
-               if (0 == strcmp(p, "$" "Mdocdate$"))
-                       return(time(NULL));
-               if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
-                       return(t);
-       }
+       localtime_r(&t, &tm);
 
 
-       if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags) 
-               if (a2time(&t, "%b %d, %Y", p))
-                       return(t);
+       /*
+        * Reserve space:
+        * up to 9 characters for the month (September) + blank
+        * up to 2 characters for the day + comma + blank
+        * 4 characters for the year and a terminating '\0'
+        */
+       p = buf = mandoc_malloc(10 + 4 + 4 + 1);
 
 
-       if (MTIME_ISO_8601 & flags) 
-               if (a2time(&t, "%Y-%m-%d", p))
-                       return(t);
+       if (0 == (ssz = strftime(p, 10 + 1, "%B ", &tm)))
+               goto fail;
+       p += (int)ssz;
 
 
-       if (MTIME_REDUCED & flags) {
-               if (a2time(&t, "%d, %Y", p))
-                       return(t);
-               if (a2time(&t, "%Y", p))
-                       return(t);
-       }
+       if (-1 == (isz = snprintf(p, 4 + 1, "%d, ", tm.tm_mday)))
+               goto fail;
+       p += isz;
 
 
-       return(0);
+       if (0 == strftime(p, 4 + 1, "%Y", &tm))
+               goto fail;
+       return(buf);
+
+fail:
+       free(buf);
+       return(NULL);
 }
 
 }
 
+char *
+mandoc_normdate(struct mparse *parse, char *in, int ln, int pos)
+{
+       char            *out;
+       time_t           t;
+
+       if (NULL == in || '\0' == *in ||
+           0 == strcmp(in, "$" "Mdocdate$")) {
+               mandoc_msg(MANDOCERR_NODATE, parse, ln, pos, NULL);
+               time(&t);
+       }
+       else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) &&
+           !a2time(&t, "%b %d, %Y", in) &&
+           !a2time(&t, "%Y-%m-%d", in)) {
+               mandoc_msg(MANDOCERR_BADDATE, parse, ln, pos, NULL);
+               t = 0;
+       }
+       out = t ? time2a(t) : NULL;
+       return(out ? out : mandoc_strdup(in));
+}
 
 int
 mandoc_eos(const char *p, size_t sz, int enclosed)
 
 int
 mandoc_eos(const char *p, size_t sz, int enclosed)
@@ -458,7 +479,6 @@ mandoc_eos(const char *p, size_t sz, int enclosed)
        return(found && !enclosed);
 }
 
        return(found && !enclosed);
 }
 
-
 int
 mandoc_hyph(const char *start, const char *c)
 {
 int
 mandoc_hyph(const char *start, const char *c)
 {
@@ -485,3 +505,29 @@ mandoc_hyph(const char *start, const char *c)
 
        return(1);
 }
 
        return(1);
 }
+
+/*
+ * Find out whether a line is a macro line or not.  If it is, adjust the
+ * current position and return one; if it isn't, return zero and don't
+ * change the current position.
+ */
+int
+mandoc_getcontrol(const char *cp, int *ppos)
+{
+       int             pos;
+
+       pos = *ppos;
+
+       if ('\\' == cp[pos] && '.' == cp[pos + 1])
+               pos += 2;
+       else if ('.' == cp[pos] || '\'' == cp[pos])
+               pos++;
+       else
+               return(0);
+
+       while (' ' == cp[pos] || '\t' == cp[pos])
+               pos++;
+
+       *ppos = pos;
+       return(1);
+}
index 9dd448e..185c10b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.h,v 1.49 2011/01/06 13:45:47 kristaps Exp $ */
+/*     $Id: mandoc.h,v 1.69 2011/03/28 21:49:42 kristaps Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -50,7 +50,8 @@ enum  mandocerr {
        MANDOCERR_NOTITLE, /* no title in document */
        MANDOCERR_UPPERCASE, /* document title should be all caps */
        MANDOCERR_BADMSEC, /* unknown manual section */
        MANDOCERR_NOTITLE, /* no title in document */
        MANDOCERR_UPPERCASE, /* document title should be all caps */
        MANDOCERR_BADMSEC, /* unknown manual section */
-       MANDOCERR_BADDATE, /* cannot parse date argument */
+       MANDOCERR_NODATE, /* date missing, using today's date */
+       MANDOCERR_BADDATE, /* cannot parse date, using it verbatim */
        MANDOCERR_PROLOGOOO, /* prologue macros out of order */
        MANDOCERR_PROLOGREP, /* duplicate prologue macro */
        MANDOCERR_BADPROLOG, /* macro not allowed in prologue */
        MANDOCERR_PROLOGOOO, /*&