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.
-# 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:
-       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)$(MANDIR)/man3
        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) 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)
 
-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/
 
-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:
-       ./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:
-       ./mandoc -Tps -Wall,stop $< > $@
+       ./mandoc -Tps -Wall,stop $< >$@
 
 .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:
-       ./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>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.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>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.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) 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
@@ -24,7 +25,7 @@
 #include <string.h>
 
 #include "mandoc.h"
-#include "chars.h"
+#include "out.h"
 
 #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).
         */
 
-       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;
@@ -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.
  */
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>
  *
@@ -187,7 +187,7 @@ CHAR(":U",                  "U",            220)
 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)
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
@@ -141,6 +141,10 @@ li.list-item       { }
 ol.list-enum   { padding-left: 2em; }
 li.list-enum   { }
 
+/* Equation modes.  See eqn(7). */
+
+span.eqn       { }
+
 /* 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
@@ -31,7 +32,6 @@
 
 #include "mandoc.h"
 #include "out.h"
-#include "chars.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 */
+       "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);
@@ -117,11 +119,7 @@ ml_alloc(char *outopts, enum htmltype type)
        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;
@@ -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)
@@ -332,6 +340,9 @@ print_encode(struct html *h, const char *p, int norecurse)
                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;
@@ -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)) {
-               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;
@@ -501,35 +508,10 @@ print_doctype(struct html *h)
                        name, doctype, dtd);
 }
 
-
 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)) {
@@ -557,21 +539,6 @@ print_text(struct html *h, const char *word)
        }
 
        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) {
+               /* 
+                * Remember to close out and nullify the current
+                * meta-font and table, if applicable.
+                */
                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);
@@ -600,8 +573,14 @@ print_stagq(struct html *h, const struct tag *suntil)
        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->tblt)
+                       h->tblt = NULL;
                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>
  *
@@ -67,6 +67,7 @@ enum  htmlattr {
        ATTR_ID,
        ATTR_SUMMARY,
        ATTR_ALIGN,
+       ATTR_COLSPAN,
        ATTR_MAX
 };
 
@@ -110,13 +111,15 @@ enum      htmltype {
 
 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_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 tag       *tblt; /* current open table scope */
        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_tblclose(struct html *);
 void             print_tbl(struct html *, const struct tbl_span *);
 
 void             bufcat_su(struct html *, const char *, 
index 7abc997..d4fd1ed 100644 (file)
                                        </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>
 
@@ -59,9 +58,8 @@
                                        </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>
                                                        </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">
-                                                               man macro compiler library
+                                                               mandoc macro compiler library
                                                                <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>
+                                               <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">
                                        </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>
                                        <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>:
                                                        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">
                                                        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>
                        <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>
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>
  *
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.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>
  *
 #ifndef LIBMAN_H
 #define LIBMAN_H
 
-#include "man.h"
-
 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. */
@@ -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_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 */
@@ -63,25 +61,19 @@ extern      const struct man_macro *const man_macros;
 __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) \
-                 (*(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_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);
-enum   mant      man_hash_find(const char *);
+enum mant        man_hash_find(const char *);
 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 *, 
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
 #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
 
+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 *);
-void           *mandoc_calloc(size_t, size_t);
 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_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
 
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>
  *
 #ifndef LIBMDOC_H
 #define LIBMDOC_H
 
-#include "mdoc.h"
-
 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 */
@@ -81,11 +78,21 @@ enum        margverr {
        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,
-       DELIM_CLOSE
+       DELIM_CLOSE,
+       DELIM_MAX
 };
 
 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) \
-                 (*(m)->msg)((t), (m)->data, (l), (p), NULL)
+                 mandoc_msg((t), (m)->parse, (l), (p), NULL)
 #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 *);
@@ -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 *);
-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 *);
@@ -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 *);
-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, 
@@ -142,6 +140,9 @@ enum margserr         mdoc_zargs(struct mdoc *, int,
 
 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*/
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
@@ -27,8 +27,7 @@ enum  tbl_part {
 };
 
 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;
@@ -36,16 +35,19 @@ struct      tbl_node {
        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;
 };
 
-#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 *);
@@ -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 *);
-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 *);
+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
 
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) 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
 #include "config.h"
 #endif
 
-#include <sys/mman.h>
-#include <sys/stat.h>
-
 #include <assert.h>
-#include <ctype.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.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)
@@ -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 *);
 
-struct buf {
-       char             *buf;
-       size_t            sz;
-};
-
-enum   intt {
-       INTT_AUTO,
-       INTT_MDOC,
-       INTT_MAN
-};
-
 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 {
-       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 */
@@ -99,154 +63,25 @@ struct     curparse {
        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 enum mandoclevel  file_status = MANDOCLEVEL_OK;
-static enum mandoclevel  exit_status = MANDOCLEVEL_OK;
 
 int
 main(int argc, char *argv[])
 {
        int              c;
        struct curparse  curp;
+       enum mparset     type;
+       enum mandoclevel rc;
 
        progname = strrchr(argv[0], '/');
        if (progname == NULL)
@@ -256,7 +91,7 @@ main(int argc, char *argv[])
 
        memset(&curp, 0, sizeof(struct curparse));
 
-       curp.inttype = INTT_AUTO;
+       type = MPARSE_AUTO;
        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'):
-                       if ( ! moptions(&curp.inttype, optarg))
+                       if ( ! moptions(&type, optarg))
                                return((int)MANDOCLEVEL_BADARG);
                        break;
                case ('O'):
@@ -287,56 +122,50 @@ main(int argc, char *argv[])
                        /* NOTREACHED */
                }
 
+       curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+
        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) {
-               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);
-       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)
 {
 
-       (void)printf("%s %s\n", progname, VERSION);
+       printf("%s %s\n", progname, VERSION);
        exit((int)MANDOCLEVEL_OK);
 }
 
-
 static void
 usage(void)
 {
 
-       (void)fprintf(stderr, "usage: %s "
+       fprintf(stderr, "usage: %s "
                        "[-V] "
                        "[-foption] "
                        "[-mformat] "
                        "[-Ooption] "
                        "[-Toutput] "
-                       "[-Werr] "
+                       "[-Wlevel] "
                        "[file...]\n", 
                        progname);
 
@@ -344,205 +173,31 @@ usage(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;
-       }
-
-       /* 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). */
@@ -596,347 +251,33 @@ fdesc(struct curparse *curp)
                }
        }
 
+       mparse_result(curp->mp, &mdoc, &man);
+
        /* 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:
 
-       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
-moptions(enum intt *tflags, char *arg)
+moptions(enum mparset *tflags, char *arg)
 {
 
        if (0 == strcmp(arg, "doc"))
-               *tflags = INTT_MDOC;
+               *tflags = MPARSE_MDOC;
        else if (0 == strcmp(arg, "andoc"))
-               *tflags = INTT_AUTO;
+               *tflags = MPARSE_AUTO;
        else if (0 == strcmp(arg, "an"))
-               *tflags = INTT_MAN;
+               *tflags = MPARSE_MAN;
        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, "tree"))
+       } else if (0 == strcmp(arg, "tree"))
                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);
 }
 
-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);
-       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>
 .\"
@@ -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.
 .\"
-.Dd $Mdocdate: January 4 2011 $
+.Dd $Mdocdate: March 7 2011 $
 .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.
-All manuals must have
-.Ux
-line termination.
 .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 ,
@@ -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.
-.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:
@@ -370,6 +361,13 @@ Thus, the following are equivalent:
 \&.\ \ \ 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.
@@ -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
-.Cm title section
-.Op Cm date Op Cm source Op Cm volume
+.Ar title section date
+.Op Ar source Op Ar volume
 .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
-.Cm volume
+.Ar volume
 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 ,
+.Xr eqn 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
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "man.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;
 
-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 *);
-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 *);
@@ -97,15 +96,14 @@ man_free(struct man *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();
-       p->data = data;
-       p->msg = msg;
+       p->parse = parse;
        p->regs = regs;
 
        man_alloc1(p);
@@ -129,8 +127,11 @@ int
 man_parseln(struct man *m, int ln, char *buf, int offs)
 {
 
+       m->flags |= MAN_NEWLINE;
+
        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));
 }
@@ -146,8 +147,8 @@ man_free1(struct man *man)
                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)
@@ -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;
+       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;
@@ -229,7 +234,8 @@ man_node_append(struct man *man, struct man_node *p)
 
 
 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;
 
@@ -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;
+
+       if (MAN_NEWLINE & m->flags)
+               p->flags |= MAN_LINE;
+       m->flags &= ~MAN_NEWLINE;
        return(p);
 }
 
@@ -247,7 +257,7 @@ man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
 {
        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;
@@ -256,11 +266,11 @@ man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 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;
 
-       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;
@@ -269,11 +279,11 @@ man_head_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 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;
 
-       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;
@@ -282,30 +292,27 @@ man_body_alloc(struct man *m, int line, int pos, enum mant tok)
 
 
 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;
 
-       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);
 }
 
-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);
-
-       m->next = MAN_NEXT_SIBLING;
+       m->next = MAN_NEXT_CHILD;
        return(1);
 }
 
@@ -317,7 +324,7 @@ man_word_alloc(struct man *m, int line, int pos, const char *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);
 
@@ -357,15 +364,38 @@ man_node_delete(struct man *m, struct man_node *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)
 {
+       struct man_node *n;
 
        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(man_descope(m, 0, 0));
+
+       m->next = MAN_NEXT_SIBLING;
+       return(man_descope(m, sp->line, 0));
 }
 
 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));
 }
 
-
 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) {
@@ -464,67 +484,54 @@ man_ptext(struct man *m, int line, char *buf, int offs)
        return(man_descope(m, line, 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;
 
-       /* 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);
 
-       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.
         */
 
-       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) {
-               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. */
 
-       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.
         */
 
-       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
@@ -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;
 
-               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;
@@ -561,10 +568,9 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
        /* 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;
 
-out:
        /* 
         * 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);
-       return(man_body_alloc(m, ln, offs, m->last->tok));
+       return(man_body_alloc(m, ln, ppos, m->last->tok));
 
 err:   /* Error out. */
 
@@ -609,21 +615,6 @@ err:       /* Error out. */
        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.
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
@@ -17,9 +17,6 @@
 #ifndef MAN_H
 #define MAN_H
 
-/* 
- * What follows is a list of ALL possible macros. 
- */
 enum   mant {
        MAN_br = 0,
        MAN_TH,
@@ -57,9 +54,6 @@ enum  mant {
        MAN_MAX
 };
 
-/* 
- * Type of a syntax node. 
- */
 enum   man_type {
        MAN_TEXT,
        MAN_ELEM,
@@ -67,24 +61,19 @@ enum        man_type {
        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.) */
-       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) */
 };
 
-/* 
- * Single node in tree-linked AST. 
- */
 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 */
+#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 */
+       struct man_node *tail; /* BLOCK node TAIL ptr */
        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;
 
-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 *);
 
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>
  *
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "man.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
@@ -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_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);
@@ -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 */
-       { NULL, NULL }, /* na */
+       { man_ign_pre, NULL }, /* na */
        { 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;
+       struct htmlpair  tag;
 
        child = 1;
        t = h->tags.head;
-
        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):
-               child = man_root_pre(m, n, mh, h);
+               man_root_pre(m, n, mh, h);
                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);
-               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;
+       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):
+               /*
+                * 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);
-               break;
+               return;
        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;
                }
+
+               /*
+                * 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;
@@ -231,7 +265,7 @@ print_man_node(MAN_ARGS)
        case (MAN_ROOT):
                man_root_post(m, n, mh, h);
                break;
-       case (MAN_TBL):
+       case (MAN_EQN):
                break;
        default:
                if (mans[n->tok].post)
@@ -255,7 +289,7 @@ a2width(const struct man_node *n, struct roffsu *su)
 
 
 /* ARGSUSED */
-static int
+static void
 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);
-       return(1);
 }
 
 
@@ -319,12 +352,6 @@ man_root_post(MAN_ARGS)
 {
        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");
@@ -342,7 +369,7 @@ man_root_post(MAN_ARGS)
        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");
@@ -638,7 +665,7 @@ man_literal_pre(MAN_ARGS)
        } 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>
  *
@@ -23,7 +23,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "man.h"
 #include "mandoc.h"
+#include "libmandoc.h"
 #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              man_args(struct man *, int, 
+                               int *, char *, char **);
 
 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 *);
-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] = {
@@ -88,17 +92,19 @@ const       struct man_macro * const man_macros = __man_macros;
 /*
  * 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)
-               return(1);
+               return;
        if (MAN_VALID & n->flags)
-               return(1);
+               return;
        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
-man_unscope(struct man *m, const struct man_node *n
+man_unscope(struct man *m, const struct man_node *to
                enum mandocerr er)
 {
+       struct man_node *n;
 
-       assert(n);
+       assert(to);
 
        /* 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);
-               m->last = m->last->parent;
+               m->last = n;
                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);
 
@@ -271,8 +283,7 @@ blk_close(MACRO_PROT_ARGS)
                        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);
@@ -287,7 +298,7 @@ blk_close(MACRO_PROT_ARGS)
 int
 blk_exp(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
 
        /* 
@@ -308,13 +319,8 @@ blk_exp(MACRO_PROT_ARGS)
 
        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);
        }
@@ -339,7 +345,7 @@ blk_exp(MACRO_PROT_ARGS)
 int
 blk_imp(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
        struct man_node *n;
 
@@ -363,13 +369,8 @@ blk_imp(MACRO_PROT_ARGS)
 
        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);
        }
@@ -397,7 +398,7 @@ blk_imp(MACRO_PROT_ARGS)
 int
 in_line_eoln(MACRO_PROT_ARGS)
 {
-       int              w, la;
+       int              la;
        char            *p;
        struct man_node *n;
 
@@ -408,11 +409,7 @@ in_line_eoln(MACRO_PROT_ARGS)
 
        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);
@@ -475,3 +472,18 @@ man_macroend(struct man *m)
        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
@@ -31,7 +31,6 @@
 #include "out.h"
 #include "man.h"
 #include "term.h"
-#include "chars.h"
 #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 */
-       { 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 */
@@ -212,6 +211,9 @@ print_bvspace(struct termp *p, const struct man_node *n)
 {
        term_newln(p);
 
+       if (n->body && n->body->child && MAN_TBL == n->body->child->type)
+               return;
+
        if (NULL == n->prev)
                return;
 
@@ -255,7 +257,7 @@ pre_literal(DECL_ARGS)
        else
                mt->fl &= ~MANT_LITERAL;
 
-       return(1);
+       return(0);
 }
 
 /* ARGSUSED */
@@ -397,6 +399,11 @@ pre_in(DECL_ARGS)
        else 
                p->offset = v;
 
+       /* Don't let this creep beyond the right margin. */
+
+       if (p->offset > p->rmargin)
+               p->offset = p->rmargin;
+
        return(0);
 }
 
@@ -850,20 +857,31 @@ print_man_node(DECL_ARGS)
        size_t           rm, rmax;
        int              c;
 
-       c = 1;
-
        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);
-                       break;
-               }
+                       return;
+               } else if (' ' == *n->string && MAN_LINE & n->flags)
+                       term_newln(p);
 
                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;
@@ -873,35 +891,40 @@ print_man_node(DECL_ARGS)
                        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):
+               /*
+                * 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);
-               break;
+               return;
        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;
        }
 
+       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);
 
-       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;
@@ -922,24 +945,18 @@ print_man_nodelist(DECL_ARGS)
 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);
 
-       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;
-       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. */
@@ -957,7 +974,7 @@ print_man_foot(struct termp *p, const void *arg)
        p->rmargin = p->maxrmargin;
        p->flags &= ~TERMP_NOBREAK;
 
-       term_word(p, buf);
+       term_word(p, meta->date);
        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
@@ -29,6 +30,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "man.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_title(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_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 };
 
@@ -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_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 }, /* IP */
-       { pres_bline, posts_par }, /* HP */
+       { pres_bline, NULL }, /* IP */
+       { pres_bline, NULL }, /* HP */
        { 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 */
+       case (MAN_EQN):
+               /* FALLTHROUGH */
        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));
+       case (MAN_EQN):
+               /* FALLTHROUGH */
        case (MAN_TBL):
                return(1);
        default:
@@ -191,37 +196,15 @@ check_root(CHKARGS)
                 */
 
                m->meta.title = mandoc_strdup("unknown");
-               m->meta.date = time(NULL);
                m->meta.msec = mandoc_strdup("1");
+               m->meta.date = mandoc_normdate
+                       (m->parse, NULL, n->line, n->pos);
        }
 
        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) 
 {
@@ -241,9 +224,8 @@ check_text(CHKARGS)
                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. */
@@ -266,10 +248,10 @@ check_##name(CHKARGS) \
 { \
        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); \
-       return(0); \
+       return(1); \
 }
 
 INEQ_DEFINE(0, ==, eq0)
@@ -318,14 +300,17 @@ check_ft(CHKARGS)
        }
 
        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)
-               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);
 }
@@ -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_NOBODY);
+               mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line, 
+                               n->pos, "want children (have none)");
 
        return(1);
 }
@@ -349,7 +335,8 @@ check_part(CHKARGS)
 {
 
        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);
 }
@@ -359,33 +346,22 @@ static int
 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);
 }
@@ -407,6 +383,8 @@ check_bline(CHKARGS)
 static int
 post_TH(CHKARGS)
 {
+       const char      *p;
+       int              line, pos;
 
        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);
-       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.date = 0;
 
        /* ->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 */
 
-       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 */
 
-       /*
-        * 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 */
 
@@ -489,7 +469,7 @@ post_fi(CHKARGS)
 {
 
        if ( ! (MAN_LITERAL & m->flags))
-               man_nmsg(m, n, MANDOCERR_NOSCOPE);
+               man_nmsg(m, n, MANDOCERR_WNOSCOPE);
 
        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>
 .\"
@@ -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.
 .\"
-.Dd $Mdocdate: January 4 2011 $
+.Dd $Mdocdate: February 9 2011 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -529,6 +529,7 @@ and
 lists render similarly.
 .El
 .Sh SEE ALSO
+.Xr eqn 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>
 #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)
@@ -294,7 +296,7 @@ mandoc_strdup(const char *ptr)
  * 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;
@@ -341,8 +343,8 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
        }
 
        /* 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)
@@ -352,16 +354,15 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
                while (' ' == *cp)
                        cp++;
        }
-       *pos += (cp - start) + (quoted ? 1 : 0);
+       *pos += (int)(cp - start) + (quoted ? 1 : 0);
        *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);
 }
 
-
 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);
 }
 
-
-/*
- * 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)
@@ -458,7 +479,6 @@ mandoc_eos(const char *p, size_t sz, int enclosed)
        return(found && !enclosed);
 }
 
-
 int
 mandoc_hyph(const char *start, const char *c)
 {
@@ -485,3 +505,29 @@ mandoc_hyph(const char *start, const char *c)
 
        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>
  *
@@ -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_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 */
@@ -68,10 +69,12 @@ enum        mandocerr {
        /* related to macros and nesting */
        MANDOCERR_MACROOBS, /* skipping obsolete macro */
        MANDOCERR_IGNPAR, /* skipping paragraph macro */
+       MANDOCERR_IGNNS, /* skipping no-space macro */
        MANDOCERR_SCOPENEST, /* blocks badly nested */
        MANDOCERR_CHILD, /* child violates parent syntax */
        MANDOCERR_NESTEDDISP, /* nested displays are not portable */
        MANDOCERR_SCOPEREP, /* already in literal mode */
+       MANDOCERR_LINESCOPE, /* line scope broken */
 
        /* related to missing macro arguments */
        MANDOCERR_MACROEMPTY, /* skipping empty macro */
@@ -80,6 +83,7 @@ enum  mandocerr {
        MANDOCERR_LISTFIRST, /* list type must come first */
        MANDOCERR_NOWIDTHARG, /* tag lists require a width argument */
        MANDOCERR_FONTTYPE, /* missing font type */
+       MANDOCERR_WNOSCOPE, /* skipping end of block that is not open */
 
        /* related to bad macro arguments */
        MANDOCERR_IGNARGV, /* skipping argument */
@@ -100,9 +104,6 @@ enum        mandocerr {
        MANDOCERR_BADESCAPE, /* unknown escape sequence */
        MANDOCERR_BADQUOTE, /* unterminated quoted string */
 
-       /* related to tables */
-       MANDOCERR_TBLEXTRADAT, /* extra data cells */
-
        MANDOCERR_ERROR, /* ===== start of errors ===== */
 
        /* related to tables */
@@ -113,13 +114,14 @@ enum      mandocerr {
        MANDOCERR_TBLNODATA, /* no table data cells specified */
        MANDOCERR_TBLIGNDATA, /* ignore data in cell */
        MANDOCERR_TBLBLOCK, /* data block still open */
+       MANDOCERR_TBLEXTRADAT, /* ignoring extra data cells */
 
        MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
        MANDOCERR_BADCHAR, /* skipping bad character */
+       MANDOCERR_NAMESC, /* escaped character not allowed in a name */
        MANDOCERR_NOTEXT, /* skipping text before the first section header */
        MANDOCERR_MACRO, /* skipping unknown macro */
        MANDOCERR_REQUEST, /* NOT IMPLEMENTED: skipping request */
-       MANDOCERR_LINESCOPE, /* line scope broken */
        MANDOCERR_ARGCOUNT, /* argument count wrong */
        MANDOCERR_NOSCOPE, /* skipping end of block that is not open */
        MANDOCERR_SCOPEBROKEN, /* missing end of block */
@@ -135,6 +137,7 @@ enum        mandocerr {
 
        MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
 
+       MANDOCERR_NOTMANUAL, /* manual isn't really a manual */
        MANDOCERR_COLUMNS, /* column syntax is inconsistent */
        MANDOCERR_BADDISP, /* NOT IMPLEMENTED: .Bd -file */
        MANDOCERR_SYNTLINESCOPE, /* line scope broken, syntax violated */
@@ -202,7 +205,7 @@ enum        tbl_cellt {
 struct tbl_cell {
        struct tbl_cell  *next;
        enum tbl_cellt    pos;
-       int               spacing;
+       size_t            spacing;
        int               flags;
 #define        TBL_CELL_TALIGN  (1 << 0) /* t, T */
 #define        TBL_CELL_BALIGN  (1 << 1) /* d, D */
@@ -224,12 +227,12 @@ struct    tbl_row {
 };
 
 enum   tbl_datt {
-       TBL_DATA_NONE,
-       TBL_DATA_DATA,
-       TBL_DATA_HORIZ,
-       TBL_DATA_DHORIZ,
-       TBL_DATA_NHORIZ,
-       TBL_DATA_NDHORIZ
+       TBL_DATA_NONE, /* has no data */
+       TBL_DATA_DATA, /* consists of data/string */
+       TBL_DATA_HORIZ, /* horizontal line */
+       TBL_DATA_DHORIZ, /* double-horizontal line */
+       TBL_DATA_NHORIZ, /* squeezed horizontal line */
+       TBL_DATA_NDHORIZ /* squeezed double-horizontal line */
 };
 
 /*
@@ -237,9 +240,10 @@ enum       tbl_datt {
  * string value that's in the cell.  The rest is layout.
  */
 struct tbl_dat {
-       struct tbl_cell  *layout; /* layout cell: CAN BE NULL */
+       struct tbl_cell  *layout; /* layout cell */
+       int               spans; /* how many spans follow */
        struct tbl_dat   *next;
-       char             *string;
+       char             *string; /* data (NULL if not TBL_DATA_DATA) */
        enum tbl_datt     pos;
 };
 
@@ -255,9 +259,10 @@ enum       tbl_spant {
 struct tbl_span {
        struct tbl       *tbl;
        struct tbl_head  *head;
-       struct tbl_row   *layout; /* layout row: CAN BE NULL */
+       struct tbl_row   *layout; /* layout row */
        struct tbl_dat   *first;
        struct tbl_dat   *last;
+       int               line; /* parse line */
        int               flags;
 #define        TBL_SPAN_FIRST   (1 << 0)
 #define        TBL_SPAN_LAST    (1 << 1)
@@ -265,50 +270,45 @@ struct    tbl_span {
        struct tbl_span  *next;
 };
 
-/*
- * Available registers (set in libroff, accessed elsewhere).
- */
-enum   regs {
-       REG_nS = 0,
-       REG__MAX
+struct eqn {
+       size_t            sz;
+       char             *data;
+       int               line; /* invocation line */
+       int               pos; /* invocation position */
 };
 
 /*
- * A register (struct reg) can consist of many types: this consists of
- * normalised types from the original string form.
+ * The type of parse sequence.  This value is usually passed via the
+ * mandoc(1) command line of -man and -mdoc.  It's almost exclusively
+ * -mandoc but the others have been retained for compatibility.
  */
-union  regval {
-       unsigned  u; /* unsigned integer */
+enum   mparset {
+       MPARSE_AUTO, /* magically determine the document type */
+       MPARSE_MDOC, /* assume -mdoc */
+       MPARSE_MAN /* assume -man */
 };
 
-/*
- * 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 */
-};
+typedef        void    (*mandocmsg)(enum mandocerr, enum mandoclevel,
+                       const char *, int, int, const char *);
 
-/*
- * 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];
-};
+struct mparse;
+struct mdoc;
+struct man;
 
 __BEGIN_DECLS
 
-/*
- * Callback function for warnings, errors, and fatal errors as they
- * occur in the compilers libroff, libmdoc, and libman.
- */
-typedef        int             (*mandocmsg)(enum mandocerr, void *,
-                               int, int, const char *);
+void             mparse_free(struct mparse *);
+void             mparse_reset(struct mparse *);
+struct mparse   *mparse_alloc(enum mparset, 
+                       enum mandoclevel, mandocmsg, void *);
+enum mandoclevel  mparse_readfd(struct mparse *, int, const char *);
+void             mparse_result(struct mparse *, struct mdoc **, struct man **);
+const char      *mparse_strerror(enum mandocerr);
+const char      *mparse_strlevel(enum mandoclevel);
+
+void            *mandoc_calloc(size_t, size_t);
+void            *mandoc_malloc(size_t);
+void            *mandoc_realloc(void *, size_t);
 
 __END_DECLS
 
index ff693d7..ec478e0 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc_char.7,v 1.40 2010/10/29 00:05:53 schwarze Exp $
+.\"    $Id: mandoc_char.7,v 1.42 2011/02/09 22:53:20 schwarze Exp $
 .\"
 .\" Copyright (c) 2009 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.
 .\"
-.Dd $Mdocdate: October 29 2010 $
+.Dd $Mdocdate: February 9 2011 $
 .Dt MANDOC_CHAR 7
 .Os
 .Sh NAME
@@ -513,31 +513,54 @@ implementations:
 .It \e*(aa   Ta \*(aa       Ta acute
 .It \e*(ga   Ta \*(ga       Ta grave
 .El
-.Sh COMPATIBILITY
-This section documents compatibility of
-.Nm
-with older or existing versions of groff.
+.Sh NUMBERED CHARACTERS
+For backward compatibility with existing manuals,
+.Xr mandoc 1
+also supports the
 .Pp
-The following render differently in
-.Fl T Ns Ar ascii
-output mode:
-.Bd -ragged -offset indent
-\e(ss, \e(nm, \e(nb, \e(nc, \e(ib, \e(ip, \e(pp, \e[sum], \e[product],
-\e[coproduct], \e(gr, \e(-h, \e(a.
-.Ed
+.Dl \eN\(aq Ns Ar number Ns \(aq
 .Pp
-The following render differently in
-.Fl T Ns Ar html
-output mode:
-.Bd -ragged -offset indent
-\e(~=, \e(nb, \e(nc
-.Ed
+escape sequence, inserting the character
+.Ar number
+from the current character set into the output.
+Of course, this is inherently non-portable and is already marked
+as deprecated in the Heirloom roff manual.
+For example, do not use \eN'34', use \e(dq, or even the plain
+.Sq \(dq
+character where possible.
+.Sh COMPATIBILITY
+This section documents compatibility between mandoc and other other
+troff implementations, at this time limited to GNU troff
+.Pq Qq groff .
 .Pp
-Finally, the following have been omitted by being poorly documented or
-having no known representation:
-.Bd -ragged -offset indent
-\e[radicalex], \e[sqrtex], \e(ru
-.Ed
+.Bl -dash -compact
+.It
+In
+.Fl T Ns Cm ascii ,
+the
+\e(ss, \e(nm, \e(nb, \e(nc, \e(ib, \e(ip, \e(pp, \e[sum], \e[product],
+\e[coproduct], \e(gr, \e(\-h, and \e(a. special characters render
+differently between mandoc and groff.
+.It
+In
+.Fl T Ns Cm html
+and
+.Fl T Ns Cm xhtml ,
+the \e(~=, \e(nb, and \e(nc special characters render differently
+between mandoc and groff.
+.It
+The
+.Fl T Ns Cm ps
+and
+.Fl T Ns Cm pdf
+modes format like
+.Fl T Ns Cm ascii
+instead of rendering glyphs as in groff.
+.It
+The \e[radicalex], \e[sqrtex], and \e(ru special characters have been omitted
+from mandoc either because they are poorly documented or they have no
+known representation.
+.El
 .Sh SEE ALSO
 .Xr mandoc 1
 .Sh AUTHORS
diff --git a/contrib/mdocml/mdoc.3 b/contrib/mdocml/mdoc.3
deleted file mode 100644 (file)
index 1a2fc9b..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-.\"    $Id: mdoc.3,v 1.55 2011/01/07 15:07:21 kristaps Exp $
-.\"
-.\" Copyright (c) 2009, 2010 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: January 7 2011 $
-.Dt MDOC 3
-.Os
-.Sh NAME
-.Nm mdoc ,
-.Nm mdoc_alloc ,
-.Nm mdoc_endparse ,
-.Nm mdoc_free ,
-.Nm mdoc_meta ,
-.Nm mdoc_node ,
-.Nm mdoc_parseln ,
-.Nm mdoc_reset
-.Nd mdoc macro compiler library
-.Sh SYNOPSIS
-.In mandoc.h
-.In mdoc.h
-.Vt extern const char * const * mdoc_macronames;
-.Vt extern const char * const * mdoc_argnames;
-.Ft int
-.Fo mdoc_addspan
-.Fa "struct mdoc *mdoc"
-.Fa "const struct tbl_span *span"
-.Fc
-.Ft "struct mdoc *"
-.Fo mdoc_alloc
-.Fa "struct regset *regs"
-.Fa "void *data"
-.Fa "mandocmsg msgs"
-.Fc
-.Ft int
-.Fn mdoc_endparse "struct mdoc *mdoc"
-.Ft void
-.Fn mdoc_free "struct mdoc *mdoc"
-.Ft "const struct mdoc_meta *"
-.Fn mdoc_meta "const struct mdoc *mdoc"
-.Ft "const struct mdoc_node *"
-.Fn mdoc_node "const struct mdoc *mdoc"
-.Ft int
-.Fo mdoc_parseln
-.Fa "struct mdoc *mdoc"
-.Fa "int line"
-.Fa "char *buf"
-.Fc
-.Ft int
-.Fn mdoc_reset "struct mdoc *mdoc"
-.Sh DESCRIPTION
-The
-.Nm mdoc
-library parses lines of
-.Xr mdoc 7
-input
-into an abstract syntax tree (AST).
-.Pp
-In general, applications initiate a parsing sequence with
-.Fn mdoc_alloc ,
-parse each line in a document with
-.Fn mdoc_parseln ,
-close the parsing session with
-.Fn mdoc_endparse ,
-operate over the syntax tree returned by
-.Fn mdoc_node
-and
-.Fn mdoc_meta ,
-then free all allocated memory with
-.Fn mdoc_free .
-The
-.Fn mdoc_reset
-function may be used in order to reset the parser for another input
-sequence.
-.Ss Types
-.Bl -ohang
-.It Vt struct mdoc
-An opaque type.
-Its values are only used privately within the library.
-.It Vt struct mdoc_node
-A parsed node.
-See
-.Sx Abstract Syntax Tree
-for details.
-.El
-.Ss Functions
-If
-.Fn mdoc_addspan ,
-.Fn mdoc_parseln ,
-or
-.Fn mdoc_endparse
-return 0, calls to any function but
-.Fn mdoc_reset
-or
-.Fn mdoc_free
-will raise an assertion.
-.Bl -ohang
-.It Fn mdoc_addspan
-Add a table span to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn mdoc_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 mdoc_free .
-.It Fn mdoc_reset
-Reset the parser for another parse routine.
-After its use,
-.Fn mdoc_parseln
-behaves as if invoked for the first time.
-If it returns 0, memory could not be allocated.
-.It Fn mdoc_free
-Free all resources of a parser.
-The pointer is no longer valid after invocation.
-.It Fn mdoc_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 mdoc_endparse
-Signals that the parse is complete.
-Returns 0 on failure, 1 on success.
-.It Fn mdoc_node
-Returns the first node of the parse.
-.It Fn mdoc_meta
-Returns the document's parsed meta-data.
-.El
-.Ss Variables
-.Bl -ohang
-.It Va mdoc_macronames
-An array of string-ified token names.
-.It Va mdoc_argnames
-An array of string-ified token argument 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 mdoc_nodes ;
-however, if called before
-.Fn mdoc_endparse ,
-or after
-.Fn mdoc_endparse
-or
-.Fn mdoc_parseln
-fail, it may be incomplete.
-.Pp
-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.
-.Ss Badly-nested Blocks
-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 :
-the
-.Fl T Ns Cm html
-and
-.Fl T Ns Cm xhtml
-front-ends 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 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 mdoc *mdoc;
-const struct mdoc_node *node;
-char *buf;
-size_t len;
-int line;
-
-bzero(&regs, sizeof(struct regset));
-line = 1;
-mdoc = mdoc_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 ( ! mdoc_parseln(mdoc, line, buf))
-        errx(1, "mdoc_parseln");
-    line++;
-}
-
-if ( ! mdoc_endparse(mdoc))
-    errx(1, "mdoc_endparse");
-if (NULL == (node = mdoc_node(mdoc)))
-    errx(1, "mdoc_node");
-
-parsed(mdoc, node);
-mdoc_free(mdoc);
-.Ed
-.Pp
-To compile this, execute
-.Pp
-.Dl % cc main.c libmdoc.a libmandoc.a
-.Pp
-where
-.Pa main.c
-is the example file.
-.Sh SEE ALSO
-.Xr mandoc 1 ,
-.Xr mdoc 7
-.Sh AUTHORS
-The
-.Nm
-library was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
index 6ecd5a7..3a68ca5 100644 (file)
@@ -1,6 +1,6 @@
-.\"    $Id: mdoc.7,v 1.174 2011/01/04 23:32:21 kristaps Exp $
+.\"    $Id: mdoc.7,v 1.184 2011/04/01 19:50:49 kristaps Exp $
 .\"
-.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" 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
@@ -15,7 +15,7 @@
 .\" 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: April 1 2011 $
 .Dt MDOC 7
 .Os
 .Sh NAME
@@ -52,9 +52,9 @@ Other lines are interpreted within the current state.
 .Nm
 documents may contain only graphable 7-bit ASCII characters, the space
 character, and, in certain circumstances, the tab character.
-All manuals must have
-.Ux
-line terminators.
+.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 ,
@@ -65,12 +65,14 @@ A macro line with only a control character and comment escape,
 is also ignored.
 Macro lines with only a control character and optional whitespace are
 stripped from input.
-.Ss Reserved Characters
-Within a macro line, the following characters are reserved:
+.Ss Reserved Terms
+Within a macro line, the following terms are reserved:
 .Pp
 .Bl -tag -width Ds -offset indent -compact
 .It \&.
 .Pq period
+.It \e.
+.Pq escaped period
 .It \&,
 .Pq comma
 .It \&:
@@ -91,14 +93,15 @@ Within a macro line, the following characters are reserved:
 .Pq exclamation
 .It \&|
 .Pq vertical bar
+.It \e*(Ba
+.Pq reserved-word vertical bar
 .El
 .Pp
-Use of reserved characters is described in
+Use of reserved terms is described in
 .Sx MACRO SYNTAX .
-For general use in macro lines, these characters can either be escaped
-with a non-breaking space
-.Pq Sq \e&
-or, if applicable, an appropriate escape sequence can be used.
+For general use in macro lines, these can be escaped with a non-breaking
+space
+.Pq Sq \e& .
 .Ss Special Characters
 Special characters may occur in both macro and free-form lines.
 Sequences begin with the escape character
@@ -197,34 +200,6 @@ Thus, the following produces
 .Ed
 .Pp
 In free-form mode, quotes are regarded as opaque text.
-.Ss Dates
-There are several macros in
-.Nm
-that require a date argument.
-The canonical form for dates is the American format:
-.Pp
-.D1 Cm Month Day , Year
-.Pp
-The
-.Cm Day
-value is an optionally zero-padded numeral.
-The
-.Cm Month
-value is the full month name.
-The
-.Cm Year
-value is the full four-digit year.
-.Pp
-Reduced form dates are broken-down canonical form dates:
-.Pp
-.D1 Cm Month , Year
-.D1 Cm Year
-.Pp
-Some examples of valid dates follow:
-.Pp
-.D1 "May, 2009" Pq reduced form
-.D1 "2009" Pq reduced form
-.D1 "May 20, 2009" Pq canonical form
 .Ss Scaling Widths
 Many macros support scaled widths for their arguments, such as
 stipulating a two-inch list indentation with the following:
@@ -283,11 +258,13 @@ a line.
 By doing so, front-ends will be able to apply the proper amount of
 spacing after the end of sentence (unescaped) period, exclamation mark,
 or question mark followed by zero or more non-sentence closing
-delimiters (
-.Ns Sq \&) ,
+delimiters
+.Po
+.Sq \&) ,
 .Sq \&] ,
 .Sq \&' ,
-.Sq \&" ) .
+.Sq \&"
+.Pc .
 .Pp
 The proper spacing is also intelligently preserved if a sentence ends at
 the boundary of a macro line.
@@ -732,7 +709,7 @@ and/or tail
 .El
 .Ss Block partial-implicit
 Like block full-implicit, but with single-line scope closed by
-.Sx Reserved Characters
+.Sx Reserved Terms
 or end of line.
 .Bd -literal -offset indent
 \&.Yo \(lB\-arg \(lBval...\(rB\(rB \(lBbody...\(rB \(lBres...\(rB
@@ -765,7 +742,7 @@ section line, else it is
 .Sx In-line .
 .Ss In-line
 Closed by
-.Sx Reserved Characters ,
+.Sx Reserved Terms ,
 end of line, fixed argument lengths, and/or subsequent macros.
 In-line macros have only text children.
 If a number (or inequality) of arguments is
@@ -795,8 +772,8 @@ then the macro accepts an arbitrary number of arguments.
 .It Sx \&%T  Ta    \&No     Ta    \&No     Ta    >0
 .It Sx \&%U  Ta    \&No     Ta    \&No     Ta    >0
 .It Sx \&%V  Ta    \&No     Ta    \&No     Ta    >0
-.It Sx \&Ad  Ta    Yes      Ta    Yes      Ta    n
-.It Sx \&An  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Ad  Ta    Yes      Ta    Yes      Ta    >0
+.It Sx \&An  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Ap  Ta    Yes      Ta    Yes      Ta    0
 .It Sx \&Ar  Ta    Yes      Ta    Yes      Ta    n
 .It Sx \&At  Ta    Yes      Ta    Yes      Ta    1
@@ -804,31 +781,31 @@ then the macro accepts an arbitrary number of arguments.
 .It Sx \&Bt  Ta    \&No     Ta    \&No     Ta    0
 .It Sx \&Bx  Ta    Yes      Ta    Yes      Ta    n
 .It Sx \&Cd  Ta    Yes      Ta    Yes      Ta    >0
-.It Sx \&Cm  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Cm  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Db  Ta    \&No     Ta    \&No     Ta    1
 .It Sx \&Dd  Ta    \&No     Ta    \&No     Ta    n
 .It Sx \&Dt  Ta    \&No     Ta    \&No     Ta    n
-.It Sx \&Dv  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Dv  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Dx  Ta    Yes      Ta    Yes      Ta    n
 .It Sx \&Em  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&En  Ta    \&No     Ta    \&No     Ta    0
 .It Sx \&Er  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Es  Ta    \&No     Ta    \&No     Ta    0
-.It Sx \&Ev  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Ev  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Ex  Ta    \&No     Ta    \&No     Ta    n
-.It Sx \&Fa  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Fa  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Fd  Ta    \&No     Ta    \&No     Ta    >0
 .It Sx \&Fl  Ta    Yes      Ta    Yes      Ta    n
 .It Sx \&Fn  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Fr  Ta    \&No     Ta    \&No     Ta    n
-.It Sx \&Ft  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Ft  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Fx  Ta    Yes      Ta    Yes      Ta    n
 .It Sx \&Hf  Ta    \&No     Ta    \&No     Ta    n
 .It Sx \&Ic  Ta    Yes      Ta    Yes      Ta    >0
-.It Sx \&In  Ta    \&No     Ta    \&No     Ta    n
+.It Sx \&In  Ta    \&No     Ta    \&No     Ta    1
 .It Sx \&Lb  Ta    \&No     Ta    \&No     Ta    1
-.It Sx \&Li  Ta    Yes      Ta    Yes      Ta    n
-.It Sx \&Lk  Ta    Yes      Ta    Yes      Ta    n
+.It Sx \&Li  Ta    Yes      Ta    Yes      Ta    >0
+.It Sx \&Lk  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Lp  Ta    \&No     Ta    \&No     Ta    0
 .It Sx \&Ms  Ta    Yes      Ta    Yes      Ta    >0
 .It Sx \&Mt  Ta    Yes      Ta    Yes      Ta    >0
@@ -884,8 +861,10 @@ block.
 Publication date of an
 .Sx \&Rs
 block.
-This should follow the reduced or canonical form syntax described in
-.Sx Dates .
+Recommended formats of arguments are
+.Ar month day , year
+or just
+.Ar year .
 .Ss \&%I
 Publisher or issuer name of an
 .Sx \&Rs
@@ -1467,17 +1446,36 @@ This is the mandatory first macro of any
 manual.
 Its syntax is as follows:
 .Pp
-.D1 Pf \. Sx \&Dd Op Ar date
+.D1 Pf \. Sx \&Dd Ar month day , year
 .Pp
 The
-.Ar date
-may be either
-.Ar $\&Mdocdate$ ,
-which signifies the current manual revision date dictated by
+.Ar month
+is the full English month name, the
+.Ar day
+is an optionally zero-padded numeral, and the
+.Ar year
+is the full four-digit year.
+.Pp
+Other arguments are not portable; the
+.Xr mandoc 1
+utility handles them as follows:
+.Bl -dash -offset 3n -compact
+.It
+To have the date automatically filled in by the
+.Ox
+version of
 .Xr cvs 1 ,
-or instead a valid canonical date as specified by
-.Sx Dates .
-If a date does not conform or is empty, the current date is used.
+the special string
+.Dq $\&Mdocdate$
+can be given as an argument.
+.It
+A few alternative date formats are accepted as well
+and converted to the standard form.
+.It
+If a date string cannot be parsed, it is used verbatim.
+.It
+If no date string is given, the current date is used.
+.El
 .Pp
 Examples:
 .Dl \&.Dd $\&Mdocdate$
@@ -1863,8 +1861,8 @@ are delimited by commas.
 If no arguments are specified, blank parenthesis are output.
 .Pp
 Examples:
-.Dl \&.Fn "int funcname" "int arg0" "int arg1"
-.Dl \&.Fn funcname "int arg0"
+.Dl \&.Fn \*qint funcname\*q \*qint arg0\*q \*qint arg1\*q
+.Dl \&.Fn funcname \*qint arg0\*q
 .Dl \&.Fn funcname arg0
 .Bd -literal -offset indent -compact
 \&.Ft functype
@@ -1894,7 +1892,7 @@ Invocations usually occur in the following context:
 .br
 .Pf \. Sx \&Fa Oo Cm argtype Oc Cm argname
 .br
-\.\.\.
+\&.\.\.
 .br
 .Pf \. Sx \&Fc
 .Ed
@@ -2203,6 +2201,8 @@ Suppress a space.
 Following invocation, text is interpreted as free-form text until a
 macro is encountered.
 .Pp
+This has no effect when invoked at the start of a macro line.
+.Pp
 Examples:
 .Dl \&.Fl o \&Ns \&Ar output
 .Pp
@@ -2767,9 +2767,12 @@ does not start a new line.
 \*[hist]
 .It
 .Sx \&Dd
-without an argument prints
-.Dq Epoch .
-In mandoc, it resolves to the current date.
+with non-standard arguments behaves very strangely.
+When there are three arguments, they are printed verbatim.
+Any other number of arguments is replaced by the current date,
+but without any arguments the string
+.Dq Epoch
+is printed.
 .It
 .Sx \&Fl
 does not print a dash for an empty argument.
@@ -2903,6 +2906,7 @@ This is not supported by mandoc.
 .Sh SEE ALSO
 .Xr man 1 ,
 .Xr mandoc 1 ,
+.Xr eqn 7 ,
 .Xr man 7 ,
 .Xr mandoc_char 7
 .Xr roff 7 ,
index af39521..ea3fda2 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc.c,v 1.177 2011/01/03 11:27:33 kristaps Exp $ */
+/*     $Id: mdoc.c,v 1.188 2011/03/28 23:52:13 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
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "mdoc.h"
 #include "mandoc.h"
 #include "libmdoc.h"
 #include "libmandoc.h"
@@ -98,9 +99,6 @@ static        int               node_append(struct mdoc *,
                                struct mdoc_node *);
 static int               mdoc_ptext(struct mdoc *, int, char *, int);
 static int               mdoc_pmacro(struct mdoc *, int, char *, int);
-static int               mdoc_span_alloc(struct mdoc *, 
-                               const struct tbl_span *);
-
 
 const struct mdoc_node *
 mdoc_node(const struct mdoc *m)
@@ -141,6 +139,8 @@ mdoc_free1(struct mdoc *mdoc)
                free(mdoc->meta.vol);
        if (mdoc->meta.msec)
                free(mdoc->meta.msec);
+       if (mdoc->meta.date)
+               free(mdoc->meta.date);
 }
 
 
@@ -193,14 +193,13 @@ mdoc_free(struct mdoc *mdoc)
  * Allocate volatile and non-volatile parse resources.  
  */
 struct mdoc *
-mdoc_alloc(struct regset *regs, void *data, mandocmsg msg)
+mdoc_alloc(struct regset *regs, struct mparse *parse)
 {
        struct mdoc     *p;
 
        p = mandoc_calloc(1, sizeof(struct mdoc));
 
-       p->msg = msg;
-       p->data = data;
+       p->parse = parse;
        p->regs = regs;
 
        mdoc_hash_init();
@@ -224,21 +223,52 @@ mdoc_endparse(struct mdoc *m)
        return(0);
 }
 
+int
+mdoc_addeqn(struct mdoc *m, const struct eqn *ep)
+{
+       struct mdoc_node *n;
+
+       assert( ! (MDOC_HALT & m->flags));
+
+       /* No text before an initial macro. */
+
+       if (SEC_NONE == m->lastnamed) {
+               mdoc_pmsg(m, ep->line, ep->pos, MANDOCERR_NOTEXT);
+               return(1);
+       }
+
+       n = node_alloc(m, ep->line, ep->pos, MDOC_MAX, MDOC_EQN);
+       n->eqn = ep;
+
+       if ( ! node_append(m, n))
+               return(0);
+
+       m->next = MDOC_NEXT_SIBLING;
+       return(1);
+}
+
 int
 mdoc_addspan(struct mdoc *m, const struct tbl_span *sp)
 {
+       struct mdoc_node *n;
 
        assert( ! (MDOC_HALT & m->flags));
 
        /* No text before an initial macro. */
 
        if (SEC_NONE == m->lastnamed) {
-               /* FIXME: grab from span. */
-               mdoc_pmsg(m, 0, 0, MANDOCERR_NOTEXT);
+               mdoc_pmsg(m, sp->line, 0, MANDOCERR_NOTEXT);
                return(1);
        }
 
-       return(mdoc_span_alloc(m, sp));
+       n = node_alloc(m, sp->line, 0, MDOC_MAX, MDOC_TBL);
+       n->span = sp;
+
+       if ( ! node_append(m, n))
+               return(0);
+
+       m->next = MDOC_NEXT_SIBLING;
+       return(1);
 }
 
 
@@ -267,27 +297,11 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
                        m->flags &= ~MDOC_SYNOPSIS;
        }
 
-       return(('.' == buf[offs] || '\'' == buf[offs]) ? 
+       return(mandoc_getcontrol(buf, &offs) ?
                        mdoc_pmacro(m, ln, buf, offs) :
                        mdoc_ptext(m, ln, buf, offs));
 }
 
-
-int
-mdoc_vmsg(struct mdoc *mdoc, 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((*mdoc->msg)(t, mdoc->data, ln, pos, buf));
-}
-
-
 int
 mdoc_macro(MACRO_PROT_ARGS)
 {
@@ -314,8 +328,9 @@ mdoc_macro(MACRO_PROT_ARGS)
                        m->meta.vol = mandoc_strdup("LOCAL");
                if (NULL == m->meta.os)
                        m->meta.os = mandoc_strdup("LOCAL");
-               if (0 == m->meta.date)
-                       m->meta.date = time(NULL);
+               if (NULL == m->meta.date)
+                       m->meta.date = mandoc_normdate
+                               (m->parse, NULL, line, ppos);
                m->flags |= MDOC_PBODY;
        }
 
@@ -546,23 +561,6 @@ mdoc_elem_alloc(struct mdoc *m, int line, int pos,
        return(1);
 }
 
-static int
-mdoc_span_alloc(struct mdoc *m, const struct tbl_span *sp)
-{
-       struct mdoc_node *n;
-
-       /* FIXME: grab from tbl_span. */
-       n = node_alloc(m, 0, 0, MDOC_MAX, MDOC_TBL);
-       n->span = sp;
-
-       if ( ! node_append(m, n))
-               return(0);
-
-       m->next = MDOC_NEXT_SIBLING;
-       return(1);
-}
-
-
 int
 mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
 {
@@ -663,15 +661,6 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
        char             *c, *ws, *end;
        struct mdoc_node *n;
 
-       /* Ignore bogus comments. */
-
-       if ('\\' == buf[offs] && 
-                       '.' == buf[offs + 1] && 
-                       '"' == buf[offs + 2]) {
-               mdoc_pmsg(m, line, offs, MANDOCERR_BADCOMMENT);
-               return(1);
-       }
-
        /* No text before an initial macro. */
 
        if (SEC_NONE == m->lastnamed) {
@@ -798,64 +787,57 @@ static int
 mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
 {
        enum mdoct        tok;
-       int               i, j, sv;
+       int               i, sv;
        char              mac[5];
        struct mdoc_node *n;
 
-       /* Empty lines are ignored. */
+       /* Empty post-control lines are ignored. */
 
-       offs++;
-
-       if ('\0' == buf[offs])
+       if ('"' == buf[offs]) {
+               mdoc_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+               return(1);
+       } else if ('\0' == buf[offs])
                return(1);
 
-       i = offs;
-
-       /* Accept tabs/whitespace after the initial control char. */
-
-       if (' ' == buf[i] || '\t' == buf[i]) {
-               i++;
-               while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
-                       i++;
-               if ('\0' == buf[i])
-                       return(1);
-       }
-
-       sv = i;
+       sv = offs;
 
        /* 
         * 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 > 1 || i < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
 
-       tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
        if (MDOC_MAX == tok) {
-               mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1);
+               mandoc_vmsg(MANDOCERR_MACRO, m->parse, 
+                               ln, sv, "%s", buf + sv - 1);
                return(1);
        }
 
        /* Disregard the first trailing tab, if applicable. */
 
-       if ('\t' == buf[i])
-               i++;
+       if ('\t' == buf[offs])
+               offs++;
 
        /* Jump to the next non-whitespace 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.
         */
 
-       if ('\0' == buf[i] && ' ' == buf[i - 1])
-               mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE);
+       if ('\0' == buf[offs] && ' ' == buf[offs - 1])
+               mdoc_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
 
        /*
         * If an initial macro or a list invocation, divert directly
@@ -863,7 +845,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
         */
 
        if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
-               if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) 
+               if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf)) 
                        goto err;
                return(1);
        }
@@ -902,7 +884,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
 
        /* Normal processing of a macro. */
 
-       if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) 
+       if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf)) 
                goto err;
 
        return(1);
@@ -913,4 +895,48 @@ err:       /* Error out. */
        return(0);
 }
 
+enum mdelim
+mdoc_isdelim(const char *p)
+{
+
+       if ('\0' == p[0])
+               return(DELIM_NONE);
 
+       if ('\0' == p[1])
+               switch (p[0]) {
+               case('('):
+                       /* FALLTHROUGH */
+               case('['):
+                       return(DELIM_OPEN);
+               case('|'):
+                       return(DELIM_MIDDLE);
+               case('.'):
+                       /* FALLTHROUGH */
+               case(','):
+                       /* FALLTHROUGH */
+               case(';'):
+                       /* FALLTHROUGH */
+               case(':'):
+                       /* FALLTHROUGH */
+               case('?'):
+                       /* FALLTHROUGH */
+               case('!'):
+                       /* FALLTHROUGH */
+               case(')'):
+                       /* FALLTHROUGH */
+               case(']'):
+                       return(DELIM_CLOSE);
+               default:
+                       return(DELIM_NONE);
+               }
+
+       if ('\\' != p[0])
+               return(DELIM_NONE);
+
+       if (0 == strcmp(p + 1, "."))
+               return(DELIM_CLOSE);
+       if (0 == strcmp(p + 1, "*(Ba"))
+               return(DELIM_MIDDLE);
+
+       return(DELIM_NONE);
+}
index 9c22c33..9cee098 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc.h,v 1.114 2011/01/01 12:18:37 kristaps Exp $ */
+/*     $Id: mdoc.h,v 1.122 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>
  *
  * 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 MDOC_H
 #define MDOC_H
 
-/* 
- * What follows is a list of ALL possible macros. 
- */
 enum   mdoct {
        MDOC_Ap = 0,
        MDOC_Dd,
@@ -146,43 +143,37 @@ enum      mdoct {
        MDOC_MAX
 };
 
-/* 
- * What follows is a list of ALL possible macro arguments. 
- */
 enum   mdocargt {
-       MDOC_Split,
-       MDOC_Nosplit,
-       MDOC_Ragged,
-       MDOC_Unfilled,
-       MDOC_Literal,
-       MDOC_File,
-       MDOC_Offset,
-       MDOC_Bullet,
-       MDOC_Dash,
-       MDOC_Hyphen,
-       MDOC_Item,
-       MDOC_Enum,
-       MDOC_Tag,
-       MDOC_Diag,
-       MDOC_Hang,
-       MDOC_Ohang,
-       MDOC_Inset,
-       MDOC_Column,
-       MDOC_Width,
-       MDOC_Compact,
-       MDOC_Std,
-       MDOC_Filled,
-       MDOC_Words,
-       MDOC_Emphasis,
-       MDOC_Symbolic,
-       MDOC_Nested,
-       MDOC_Centred,
+       MDOC_Split, /* -split */
+       MDOC_Nosplit, /* -nospli */
+       MDOC_Ragged, /* -ragged */
+       MDOC_Unfilled, /* -unfilled */
+       MDOC_Literal, /* -literal */
+       MDOC_File, /* -file */
+       MDOC_Offset, /* -offset */
+       MDOC_Bullet, /* -bullet */
+       MDOC_Dash, /* -dash */
+       MDOC_Hyphen, /* -hyphen */
+       MDOC_Item, /* -item */
+       MDOC_Enum, /* -enum */
+       MDOC_Tag, /* -tag */
+       MDOC_Diag, /* -diag */
+       MDOC_Hang, /* -hang */
+       MDOC_Ohang, /* -ohang */
+       MDOC_Inset, /* -inset */
+       MDOC_Column, /* -column */
+       MDOC_Width, /* -width */
+       MDOC_Compact, /* -compact */
+       MDOC_Std, /* -std */
+       MDOC_Filled, /* -filled */
+       MDOC_Words, /* -words */
+       MDOC_Emphasis, /* -emphasis */
+       MDOC_Symbolic, /* -symbolic */
+       MDOC_Nested, /* -nested */
+       MDOC_Centred, /* -centered */
        MDOC_ARG_MAX
 };
 
-/* 
- * Type of a syntax node. 
- */
 enum   mdoc_type {
        MDOC_TEXT,
        MDOC_ELEM,
@@ -191,47 +182,47 @@ enum      mdoc_type {
        MDOC_BODY,
        MDOC_BLOCK,
        MDOC_TBL,
+       MDOC_EQN,
        MDOC_ROOT
 };
 
 /* 
  * Section (named/unnamed) of `Sh'.   Note that these appear in the
- * conventional order imposed by mdoc.7.
+ * conventional order imposed by mdoc.7.  In the case of SEC_NONE, no
+ * section has been invoked (this shouldn't happen).  SEC_CUSTOM refers
+ * to other sections.
  */
 enum   mdoc_sec {
-       SEC_NONE = 0, /* No section, yet. */
-       SEC_NAME,
-       SEC_LIBRARY,
-       SEC_SYNOPSIS,
-       SEC_DESCRIPTION,
-       SEC_IMPLEMENTATION,
-       SEC_RETURN_VALUES,
-       SEC_ENVIRONMENT, 
-       SEC_FILES,
-       SEC_EXIT_STATUS,
-       SEC_EXAMPLES,
-       SEC_DIAGNOSTICS,
-       SEC_COMPATIBILITY,
-       SEC_ERRORS,
-       SEC_SEE_ALSO,
-       SEC_STANDARDS,
-       SEC_HISTORY,
-       SEC_AUTHORS,
-       SEC_CAVEATS,
-       SEC_BUGS,
-       SEC_SECURITY,
-       SEC_CUSTOM, /* User-defined. */
+       SEC_NONE = 0,
+       SEC_NAME, /* NAME */
+       SEC_LIBRARY, /* LIBRARY */
+       SEC_SYNOPSIS, /* SYNOPSIS */
+       SEC_DESCRIPTION, /* DESCRIPTION */
+       SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */
+       SEC_RETURN_VALUES, /* RETURN VALUES */
+       SEC_ENVIRONMENT,  /* ENVIRONMENT */
+       SEC_FILES, /* FILES */
+       SEC_EXIT_STATUS, /* EXIT STATUS */
+       SEC_EXAMPLES, /* EXAMPLES */
+       SEC_DIAGNOSTICS, /* DIAGNOSTICS */
+       SEC_COMPATIBILITY, /* COMPATIBILITY */
+       SEC_ERRORS, /* ERRORS */
+       SEC_SEE_ALSO, /* SEE ALSO */
+       SEC_STANDARDS, /* STANDARDS */
+       SEC_HISTORY, /* HISTORY */
+       SEC_AUTHORS, /* AUTHORS */
+       SEC_CAVEATS, /* CAVEATS */
+       SEC_BUGS, /* BUGS */
+       SEC_SECURITY, /* SECURITY */
+       SEC_CUSTOM, 
        SEC__MAX
 };
 
-/* 
- * Information from prologue. 
- */
 struct mdoc_meta {
        char             *msec; /* `Dt' section (1, 3p, etc.) */
        char             *vol; /* `Dt' volume (implied) */
        char             *arch; /* `Dt' arch (i386, etc.) */
-       time_t            date; /* `Dd' normalised date */
+       char             *date; /* `Dd' normalised date */
        char             *title; /* `Dt' title (FOO, etc.) */
        char             *os; /* `Os' system (OpenBSD, etc.) */
        char             *name; /* leading `Nm' name */
@@ -269,68 +260,50 @@ enum      mdoc_endbody {
        ENDBODY_NOSPACE /* is broken: don't append a space */
 };
 
-/*
- * Normalised `Bl' list type.
- */
 enum   mdoc_list {
        LIST__NONE = 0,
-       LIST_bullet,
-       LIST_column,
-       LIST_dash,
-       LIST_diag,
-       LIST_enum,
-       LIST_hang,
-       LIST_hyphen,
-       LIST_inset,
-       LIST_item,
-       LIST_ohang,
-       LIST_tag,
+       LIST_bullet, /* -bullet */
+       LIST_column, /* -column */
+       LIST_dash, /* -dash */
+       LIST_diag, /* -diag */
+       LIST_enum, /* -enum */
+       LIST_hang, /* -hang */
+       LIST_hyphen, /* -hyphen */
+       LIST_inset, /* -inset */
+       LIST_item, /* -item */
+       LIST_ohang, /* -ohang */
+       LIST_tag, /* -tag */
        LIST_MAX
 };
 
-/*
- * Normalised `Bd' display type.
- */
 enum   mdoc_disp {
        DISP__NONE = 0,
-       DISP_centred,
-       DISP_ragged,
-       DISP_unfilled,
-       DISP_filled,
-       DISP_literal
+       DISP_centred, /* -centered */
+       DISP_ragged, /* -ragged */
+       DISP_unfilled, /* -unfilled */
+       DISP_filled, /* -filled */
+       DISP_literal /* -literal */
 };
 
-/*
- * Normalised `An' splitting argument. 
- */
 enum   mdoc_auth {
        AUTH__NONE = 0,
-       AUTH_split,
-       AUTH_nosplit
+       AUTH_split, /* -split */
+       AUTH_nosplit /* -nosplit */
 };
 
-/*
- * Normalised `Bf' font type.
- */
 enum   mdoc_font {
        FONT__NONE = 0,
-       FONT_Em,
-       FONT_Li,
-       FONT_Sy
+       FONT_Em, /* Em, -emphasis */
+       FONT_Li, /* Li, -literal */
+       FONT_Sy /* Sy, -symbolic */
 };
 
-/*
- * Normalised arguments for `Bd'.
- */
 struct mdoc_bd {
        const char       *offs; /* -offset */
        enum mdoc_disp    type; /* -ragged, etc. */
        int               comp; /* -compact */
 };
 
-/*
- * Normalised arguments for `Bl'.
- */
 struct mdoc_bl {
        const char       *width; /* -width */
        const char       *offs; /* -offset */
@@ -340,22 +313,16 @@ struct    mdoc_bl {
        const char      **cols; /* -column val ptr */
 };
 
-/*
- * Normalised arguments for `Bf'.
- */
 struct mdoc_bf {
        enum mdoc_font    font; /* font */
 };
 
-/*
- * Normalised arguments for `An'.
- */
 struct mdoc_an {
        enum mdoc_auth    auth; /* -split, etc. */
 };
 
 struct mdoc_rs {
-       struct mdoc_node *child_J; /* pointer to %J */
+       int               quote_T; /* whether to quote %T */
 };
 
 /*
@@ -390,6 +357,8 @@ struct      mdoc_node {
 #define        MDOC_LINE        (1 << 3) /* first macro/text on line */
 #define        MDOC_SYNPRETTY   (1 << 4) /* SYNOPSIS-style formatting */
 #define        MDOC_ENDED       (1 << 5) /* rendering has been ended */
+#define        MDOC_DELIMO      (1 << 6)
+#define        MDOC_DELIMC      (1 << 7)
        enum mdoc_type    type; /* AST node type */
        enum mdoc_sec     sec; /* current named section */
        union mdoc_data  *norm; /* normalised args */
@@ -401,35 +370,22 @@ struct    mdoc_node {
        struct mdoc_node *tail; /* BLOCK */
        char             *string; /* TEXT */
        const struct tbl_span *span; /* TBL */
+       const struct eqn *eqn; /* EQN */
        enum mdoc_endbody end; /* BODY */
 };
 
-/*
- * Names of macros.  Index is enum mdoct.  Indexing into this returns
- * the normalised name, e.g., mdoc_macronames[MDOC_Sh] -> "Sh".
- */
+/* Names of macros.  Index is enum mdoct. */
 extern const char *const *mdoc_macronames;
 
-/*
- * Names of macro args.  Index is enum mdocargt.  Indexing into this
- * returns the normalised name, e.g., mdoc_argnames[MDOC_File] ->
- * "file".
- */
+/* Names of macro args.  Index is enum mdocargt. */
 extern const char *const *mdoc_argnames;
 
 __BEGIN_DECLS
 
 struct mdoc;
 
-void             mdoc_free(struct mdoc *);
-struct mdoc     *mdoc_alloc(struct regset *, void *, mandocmsg);
-void             mdoc_reset(struct mdoc *);
-int              mdoc_parseln(struct mdoc *, int, char *, int);
 const struct mdoc_node *mdoc_node(const struct mdoc *);
 const struct mdoc_meta *mdoc_meta(const struct mdoc *);
-int              mdoc_endparse(struct mdoc *);
-int              mdoc_addspan(struct mdoc *,
-                       const struct tbl_span *);
 
 __END_DECLS
 
index f68e55f..c3fd74b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_argv.c,v 1.62 2010/12/24 14:00:40 kristaps Exp $ */
+/*     $Id: mdoc_argv.c,v 1.73 2011/03/23 15:46:02 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #include <stdio.h>
 #include <string.h>
 
+#include "mdoc.h"
 #include "mandoc.h"
 #include "libmdoc.h"
 #include "libmandoc.h"
 
-/*
- * Routines to parse arguments of macros.  Arguments follow the syntax
- * of `-arg [val [valN...]]'.  Arguments come in all types:  quoted
- * arguments, multiple arguments per value, no-value arguments, etc.
- *
- * There's no limit to the number or arguments that may be allocated.
- */
-
-#define        ARGV_NONE       (1 << 0)
-#define        ARGV_SINGLE     (1 << 1)
-#define        ARGV_MULTI      (1 << 2)
-#define        ARGV_OPT_SINGLE (1 << 3)
-
-#define        MULTI_STEP       5
+#define        MULTI_STEP       5 /* pre-allocate argument values */
 
 static enum mdocargt    argv_a2arg(enum mdoct, const char *);
 static enum margserr    args(struct mdoc *, int, int *, 
                                char *, int, char **);
+static int              args_checkpunct(struct mdoc *,
+                               const char *, int, int, int);
 static int              argv(struct mdoc *, int, 
                                struct mdoc_argv *, int *, char *);
 static int              argv_single(struct mdoc *, int, 
@@ -56,10 +46,16 @@ static      int              argv_opt_single(struct mdoc *, int,
                                struct mdoc_argv *, int *, char *);
 static int              argv_multi(struct mdoc *, int, 
                                struct mdoc_argv *, int *, char *);
+static void             argn_free(struct mdoc_arg *, int);
 
-/* Per-argument flags. */
+enum   argvflag {
+       ARGV_NONE, /* no args to flag (e.g., -split) */
+       ARGV_SINGLE, /* one arg to flag (e.g., -file xxx)  */
+       ARGV_MULTI, /* multiple args (e.g., -column xxx yyy) */
+       ARGV_OPT_SINGLE /* optional arg (e.g., -offset [xxx]) */
+};
 
-static int mdoc_argvflags[MDOC_ARG_MAX] = {
+static const enum argvflag argvflags[MDOC_ARG_MAX] = {
        ARGV_NONE,      /* MDOC_Split */
        ARGV_NONE,      /* MDOC_Nosplit */
        ARGV_NONE,      /* MDOC_Ragged */
@@ -88,7 +84,7 @@ static        int mdoc_argvflags[MDOC_ARG_MAX] = {
        ARGV_NONE       /* MDOC_Symbolic */
 };
 
-static int mdoc_argflags[MDOC_MAX] = {
+static const int argflags[MDOC_MAX] = {
        0, /* Ap */
        0, /* Dd */
        0, /* Dt */
@@ -213,6 +209,59 @@ static     int mdoc_argflags[MDOC_MAX] = {
        0, /* Ta */
 };
 
+static const enum mdocargt args_Ex[] = {
+       MDOC_Std,
+       MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_An[] = {
+       MDOC_Split,
+       MDOC_Nosplit,
+       MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bd[] = {
+       MDOC_Ragged,
+       MDOC_Unfilled,
+       MDOC_Filled,
+       MDOC_Literal,
+       MDOC_File,
+       MDOC_Offset,
+       MDOC_Compact,
+       MDOC_Centred,
+       MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bf[] = {
+       MDOC_Emphasis,
+       MDOC_Literal,
+       MDOC_Symbolic,
+       MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bk[] = {
+       MDOC_Words,
+       MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bl[] = {
+       MDOC_Bullet,
+       MDOC_Dash,
+       MDOC_Hyphen,
+       MDOC_Item,
+       MDOC_Enum,
+       MDOC_Tag,
+       MDOC_Diag,
+       MDOC_Hang,
+       MDOC_Ohang,
+       MDOC_Inset,
+       MDOC_Column,
+       MDOC_Width,
+       MDOC_Offset,
+       MDOC_Compact,
+       MDOC_Nested,
+       MDOC_ARG_MAX
+};
 
 /*
  * Parse an argument from line text.  This comes in the form of -key
@@ -254,7 +303,7 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
                buf[(*pos)++] = '\0';
        }
 
-       (void)memset(&tmp, 0, sizeof(struct mdoc_argv));
+       memset(&tmp, 0, sizeof(struct mdoc_argv));
        tmp.line = line;
        tmp.pos = *pos;
 
@@ -280,13 +329,12 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
        arg->argv = mandoc_realloc
                (arg->argv, arg->argc * sizeof(struct mdoc_argv));
 
-       (void)memcpy(&arg->argv[(int)arg->argc - 1], 
+       memcpy(&arg->argv[(int)arg->argc - 1], 
                        &tmp, sizeof(struct mdoc_argv));
 
        return(ARGV_ARG);
 }
 
-
 void
 mdoc_argv_free(struct mdoc_arg *p)
 {
@@ -303,15 +351,14 @@ mdoc_argv_free(struct mdoc_arg *p)
        assert(p->argc);
 
        for (i = (int)p->argc - 1; i >= 0; i--)
-               mdoc_argn_free(p, i);
+               argn_free(p, i);
 
        free(p->argv);
        free(p);
 }
 
-
-void
-mdoc_argn_free(struct mdoc_arg *p, int iarg)
+static void
+argn_free(struct mdoc_arg *p, int iarg)
 {
        struct mdoc_argv *arg;
        int               j;
@@ -328,7 +375,6 @@ mdoc_argn_free(struct mdoc_arg *p, int iarg)
                p->argv[iarg] = p->argv[iarg+1];
 }
 
-
 enum margserr
 mdoc_zargs(struct mdoc *m, int line, int *pos, 
                char *buf, int flags, char **v)
@@ -337,7 +383,6 @@ mdoc_zargs(struct mdoc *m, int line, int *pos,
        return(args(m, line, pos, buf, flags, v));
 }
 
-
 enum margserr
 mdoc_args(struct mdoc *m, int line, int *pos, 
                char *buf, enum mdoct tok, char **v)
@@ -345,7 +390,7 @@ mdoc_args(struct mdoc *m, int line, int *pos,
        int               fl;
        struct mdoc_node *n;
 
-       fl = mdoc_argflags[tok];
+       fl = argflags[tok];
 
        if (MDOC_It != tok)
                return(args(m, line, pos, buf, fl, v));
@@ -369,15 +414,12 @@ mdoc_args(struct mdoc *m, int line, int *pos,
        return(args(m, line, pos, buf, fl, v));
 }
 
-
 static enum margserr
 args(struct mdoc *m, int line, int *pos, 
                char *buf, int fl, char **v)
 {
-       int              i;
        char            *p, *pp;
        enum margserr    rc;
-       enum mdelim      d;
 
        /*
         * Parse out the terms (like `val' in `.Xx -arg val' or simply
@@ -405,47 +447,17 @@ args(struct mdoc *m, int line, int *pos,
                 * is unterminated.
                 */
                if (MDOC_PHRASELIT & m->flags)
-                       if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE))
-                               return(ARGS_ERROR);
+                       mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
 
                m->flags &= ~MDOC_PHRASELIT;
                return(ARGS_EOLN);
        }
 
-       /* 
-        * If the first character is a closing delimiter and we're to
-        * look for delimited strings, then pass down the buffer seeing
-        * if it follows the pattern of [[::delim::][ ]+]+.  Note that
-        * we ONLY care about closing delimiters.
-        */
-
-       if ((fl & ARGS_DELIM) && DELIM_CLOSE == mdoc_iscdelim(buf[*pos])) {
-               for (i = *pos; buf[i]; ) {
-                       d = mdoc_iscdelim(buf[i]);
-                       if (DELIM_NONE == d || DELIM_OPEN == d)
-                               break;
-                       i++;
-                       if ('\0' == buf[i] || ' ' != buf[i])
-                               break;
-                       i++;
-                       while (buf[i] && ' ' == buf[i])
-                               i++;
-               }
-
-               if ('\0' == buf[i]) {
-                       *v = &buf[*pos];
-                       if (i && ' ' != buf[i - 1])
-                               return(ARGS_PUNCT);
-                       if (ARGS_NOWARN & fl)
-                               return(ARGS_PUNCT);
-                       if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
-                               return(ARGS_ERROR);
-                       return(ARGS_PUNCT);
-               }
-       }
-
        *v = &buf[*pos];
 
+       if (ARGS_DELIM & fl && args_checkpunct(m, buf, *pos, line, fl))
+               return(ARGS_PUNCT);
+
        /*
         * First handle TABSEP items, restricted to `Bl -column'.  This
         * ignores conventional token parsing and instead uses tabs or
@@ -493,8 +505,7 @@ args(struct mdoc *m, int line, int *pos,
 
                /* Whitespace check for eoln case... */
                if ('\0' == *p && ' ' == *(p - 1) && ! (ARGS_NOWARN & fl))
-                       if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
-                               return(ARGS_ERROR);
+                       mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
 
                *pos += (int)(p - *v);
 
@@ -538,8 +549,7 @@ args(struct mdoc *m, int line, int *pos,
                if ('\0' == buf[*pos]) {
                        if (ARGS_NOWARN & fl || MDOC_PPHRASE & m->flags)
                                return(ARGS_QWORD);
-                       if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE))
-                               return(ARGS_ERROR);
+                       mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
                        return(ARGS_QWORD);
                }
 
@@ -553,8 +563,7 @@ args(struct mdoc *m, int line, int *pos,
                        (*pos)++;
 
                if (0 == buf[*pos] && ! (ARGS_NOWARN & fl))
-                       if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
-                               return(ARGS_ERROR);
+