]> git.cameronkatri.com Git - mandoc.git/blobdiff - xml.c
Added warnings for using macros in the wrong sections.
[mandoc.git] / xml.c
diff --git a/xml.c b/xml.c
index 257192c701c27510cee65db04b2962eba4d407ef..6d7da207e231043522481021aebb157b79937e5c 100644 (file)
--- a/xml.c
+++ b/xml.c
@@ -1,4 +1,4 @@
-/* $Id: xml.c,v 1.2 2008/11/30 23:05:57 kristaps Exp $ */
+/* $Id: xml.c,v 1.20 2008/12/08 12:46:28 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.
  */
-#include <sys/param.h>
-
 #include <assert.h>
-#include <ctype.h>
-#include <err.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "libmdocml.h"
 #include "private.h"
-
-#define        INDENT           4
-#define        COLUMNS          60
-
-#ifdef __linux__ /* FIXME */
-#define        strlcat          strncat
-#endif
-
-enum   md_tok {
-       MD_BLKIN,
-       MD_BLKOUT,
-       MD_IN,
-       MD_OUT,
-       MD_TEXT
-};
-
-struct md_xml {
-       const struct md_args    *args;
-       const struct md_rbuf    *rbuf;
-
-       struct md_mbuf  *mbuf;
-       struct rofftree *tree;
-       size_t           indent;
-       size_t           pos;
-       enum md_tok      last;
-       int              flags;
-#define        MD_LITERAL      (1 << 0) /* FIXME */
-};
-
-static void             roffmsg(void *arg, enum roffmsg, 
-                               const char *, const char *, char *);
-static int              roffhead(void *);
-static int              rofftail(void *);
-static int              roffin(void *, int, int *, char **);
-static int              roffdata(void *, int, char *);
-static int              roffout(void *, int);
-static int              roffblkin(void *, int, int *, char **);
-static int              roffblkout(void *, int);
-static int              roffspecial(void *, int);
-
-static int              mbuf_newline(struct md_xml *);
-static int              mbuf_indent(struct md_xml *);
-static int              mbuf_data(struct md_xml *, int, char *);
-static int              mbuf_putstring(struct md_xml *, 
-                               const char *);
-static int              mbuf_nputstring(struct md_xml *, 
+#include "ml.h"
+
+
+static int             xml_alloc(void **);
+static void            xml_free(void *);
+static ssize_t         xml_endtag(struct md_mbuf *, void *,
+                               const struct md_args *, 
+                               enum md_ns, int);
+static ssize_t         xml_begintag(struct md_mbuf *, void *,
+                               const struct md_args *, 
+                               enum md_ns, int, 
+                               const int *, const char **);
+static ssize_t         xml_beginstring(struct md_mbuf *, 
+                               const struct md_args *, 
                                const char *, size_t);
-static int              mbuf_puts(struct md_xml *, const char *);
-static int              mbuf_nputs(struct md_xml *, 
+static ssize_t         xml_endstring(struct md_mbuf *, 
+                               const struct md_args *, 
                                const char *, size_t);
+static int             xml_begin(struct md_mbuf *,
+                               const struct md_args *, 
+                               const struct tm *, 
+                               const char *, const char *, 
+                               enum roffmsec, const char *);
+static int             xml_end(struct md_mbuf *, 
+                               const struct md_args *);
+static ssize_t         xml_printtagname(struct md_mbuf *, 
+                               enum md_ns, int);
+static ssize_t         xml_printtagargs(struct md_mbuf *, 
+                               const int *, const char **);
 
 
-static int
-mbuf_putstring(struct md_xml *p, const char *buf)
+static ssize_t 
+xml_printtagargs(struct md_mbuf *mbuf, const int *argc,
+               const char **argv)
 {
+       int              i, c;
+       size_t           res;
 
-       return(mbuf_nputstring(p, buf, strlen(buf)));
-}
-
+       if (NULL == argc || NULL == argv)
+               return(0);
+       assert(argc && argv);
 
-static int
-mbuf_nputstring(struct md_xml *p, const char *buf, size_t sz)
-{
-       size_t           i;
-
-       for (i = 0; i < sz; i++) {
-               switch (buf[i]) {
-               case ('&'):
-                       if ( ! md_buf_puts(p->mbuf, "&amp;", 5))
-                               return(0);
-                       p->pos += 5;
-                       break;
-               case ('"'):
-                       if ( ! md_buf_puts(p->mbuf, "&quot;", 6))
-                               return(0);
-                       p->pos += 6;
-                       break;
-               default:
-                       if ( ! md_buf_putchar(p->mbuf, buf[i]))
-                               return(0);
-                       p->pos++;
-                       break;
-               }
+       /* LINTED */
+       for (res = 0, i = 0; ROFF_ARGMAX != (c = argc[i]); i++) {
+               if ( ! ml_nputs(mbuf, " ", 1, &res))
+                       return(-1);
+
+               if ( ! ml_puts(mbuf, tokargnames[c], &res))
+                       return(-1);
+               if ( ! ml_nputs(mbuf, "=\"", 2, &res))
+                       return(-1);
+               if (argv[i]) {
+                       if ( ! ml_putstring(mbuf, argv[i], &res))
+                               return(-1);
+               } else if ( ! ml_nputs(mbuf, "true", 4, &res))
+                       return(-1);
+               if ( ! ml_nputs(mbuf, "\"", 1, &res))
+                       return(-1);
        }
-       return(1);
-}
-
-
-static int
-mbuf_nputs(struct md_xml *p, const char *buf, size_t sz)
-{
 
-       p->pos += sz;
-       return(md_buf_puts(p->mbuf, buf, sz));
+       return((ssize_t)res);
 }
 
 
-static int
-mbuf_puts(struct md_xml *p, const char *buf)
+static ssize_t 
+xml_printtagname(struct md_mbuf *mbuf, enum md_ns ns, int tok)
 {
+       size_t           res;
 
-       return(mbuf_nputs(p, buf, strlen(buf)));
-}
-
-
-static int
-mbuf_indent(struct md_xml *p)
-{
-       size_t           i;
-
-       assert(p->pos == 0);
-
-       /* LINTED */
-       for (i = 0; i < MIN(p->indent, INDENT); i++)
-               if ( ! md_buf_putstring(p->mbuf, "    "))
-                       return(0);
+       res = 0;
+       switch (ns) {
+       case (MD_NS_BLOCK):
+               if ( ! ml_nputs(mbuf, "block:", 6, &res))
+                       return(-1);
+               break;
+       case (MD_NS_INLINE):
+               if ( ! ml_nputs(mbuf, "inline:", 7, &res))
+                       return(-1);
+               break;
+       case (MD_NS_BODY):
+               if ( ! ml_nputs(mbuf, "body:", 5, &res))
+                       return(-1);
+               break;
+       case (MD_NS_HEAD):
+               if ( ! ml_nputs(mbuf, "head:", 5, &res))
+                       return(-1);
+               break;
+       default:
+               break;
+       }
 
-       p->pos += i * INDENT;
-       return(1);
+       if ( ! ml_puts(mbuf, toknames[tok], &res))
+               return(-1);
+       return((ssize_t)res);
 }
 
 
-static int
-mbuf_newline(struct md_xml *p)
+/* ARGSUSED */
+static int 
+xml_begin(struct md_mbuf *mbuf, const struct md_args *args,
+               const struct tm *tm, const char *os, 
+               const char *title, enum roffmsec section, 
+               const char *vol)
 {
 
-       if ( ! md_buf_putchar(p->mbuf, '\n'))
+       if ( ! ml_puts(mbuf, "<?xml version=\"1.0\" "
+                               "encoding=\"UTF-8\"?>\n", NULL))
                return(0);
-
-       p->pos = 0;
-       return(1);
-}
-
-
-static int
-mbuf_data(struct md_xml *p, int space, char *buf)
-{
-       size_t           sz;
-       char            *bufp;
-
-       assert(p->mbuf);
-       assert(0 != p->indent);
-
-       if (MD_LITERAL & p->flags)
-               return(mbuf_putstring(p, buf));
-
-       while (*buf) {
-               while (*buf && isspace(*buf))
-                       buf++;
-
-               if (0 == *buf)
-                       break;
-
-               bufp = buf;
-               while (*buf && ! isspace(*buf))
-                       buf++;
-
-               if (0 != *buf)
-                       *buf++ = 0;
-
-               sz = strlen(bufp);
-
-               if (0 == p->pos) {
-                       if ( ! mbuf_indent(p))
-                               return(0);
-                       if ( ! mbuf_nputstring(p, bufp, sz))
-                               return(0);
-                       if (p->indent * INDENT + sz >= COLUMNS) {
-                               if ( ! mbuf_newline(p))
-                                       return(0);
-                               continue;
-                       }
-                       continue;
-               }
-
-               if (space && sz + p->pos >= COLUMNS) {
-                       if ( ! mbuf_newline(p))
-                               return(0);
-                       if ( ! mbuf_indent(p))
-                               return(0);
-               } else if (space) {
-                       if ( ! mbuf_nputs(p, " ", 1))
-                               return(0);
-               }
-
-               if ( ! mbuf_nputstring(p, bufp, sz))
-                       return(0);
-
-               if ( ! space && p->pos >= COLUMNS)
-                       if ( ! mbuf_newline(p))
-                               return(0);
-       }
-
-       return(1);
+       return(ml_puts(mbuf, "<mdoc xmlns:block=\"block\" "
+                               "xmlns:body=\"body\" "
+                               "xmlns:head=\"head\" "
+                               "xmlns:inline=\"inline\">", NULL));
 }
 
 
-int
-md_line_xml(void *arg, char *buf)
+/* ARGSUSED */
+static int 
+xml_end(struct md_mbuf *mbuf, const struct md_args *args)
 {
-       struct md_xml   *p;
 
-       p = (struct md_xml *)arg;
-       return(roff_engine(p->tree, buf));
+       return(ml_puts(mbuf, "</mdoc>", NULL));
 }
 
 
-int
-md_exit_xml(void *data, int flush)
+/* ARGSUSED */
+static ssize_t 
+xml_beginstring(struct md_mbuf *mbuf, 
+               const struct md_args *args, 
+               const char *buf, size_t sz)
 {
-       int              c;
-       struct md_xml   *p;
-
-       p = (struct md_xml *)data;
-       c = roff_free(p->tree, flush);
-       free(p);
 
-       return(c);
+       return(0);
 }
 
 
-void *
-md_init_xml(const struct md_args *args,
-               struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
+/* ARGSUSED */
+static ssize_t 
+xml_endstring(struct md_mbuf *mbuf, 
+               const struct md_args *args, 
+               const char *buf, size_t sz)
 {
-       struct roffcb    cb;
-       struct md_xml   *p;
-
-       cb.roffhead = roffhead;
-       cb.rofftail = rofftail;
-       cb.roffin = roffin;
-       cb.roffout = roffout;
-       cb.roffblkin = roffblkin;
-       cb.roffblkout = roffblkout;
-       cb.roffspecial = roffspecial;
-       cb.roffmsg = roffmsg;
-       cb.roffdata = roffdata;
-
-       if (NULL == (p = calloc(1, sizeof(struct md_xml))))
-               err(1, "malloc");
-
-       p->args = args;
-       p->mbuf = mbuf;
-       p->rbuf = rbuf;
-
-       assert(mbuf);
-
-       if (NULL == (p->tree = roff_alloc(&cb, p))) {
-               free(p);
-               return(NULL);
-       }
 
-       return(p);
+       return(0);
 }
 
 
 /* ARGSUSED */
-static int
-roffhead(void *arg)
+static ssize_t 
+xml_begintag(struct md_mbuf *mbuf, void *data,
+               const struct md_args *args, enum md_ns ns, 
+               int tok, const int *argc, const char **argv)
 {
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       if ( ! mbuf_puts(p, "<?xml version=\"1.0\" "
-                               "encoding=\"UTF-8\"?>\n"))
-               return(0);
-       if ( ! mbuf_puts(p, "<mdoc xmlns:block=\"block\" "
-                               "xmlns:special=\"special\" "
-                               "xmlns:inline=\"inline\">"))
-               return(0);
+       ssize_t          res, sz;
 
-       p->indent++;
-       p->last = MD_BLKIN;
-       return(mbuf_newline(p));
+       if (-1 == (res = xml_printtagname(mbuf, ns, tok)))
+               return(-1);
+       if (-1 == (sz = xml_printtagargs(mbuf, argc, argv)))
+               return(-1);
+       return(res + sz);
 }
 
 
-static int
-rofftail(void *arg)
+/* ARGSUSED */
+static ssize_t 
+xml_endtag(struct md_mbuf *mbuf, void *data,
+               const struct md_args *args, enum md_ns ns, int tok)
 {
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       if (0 != p->pos && ! mbuf_newline(p))
-               return(0);
-
-       if ( ! mbuf_puts(p, "</mdoc>"))
-               return(0);
 
-       p->last = MD_BLKOUT;
-       return(mbuf_newline(p));
+       return(xml_printtagname(mbuf, ns, tok));
 }
 
 
 /* ARGSUSED */
-static int
-roffspecial(void *arg, int tok)
+int
+xml_alloc(void **p)
 {
 
-       /* FIXME */
+       *p = NULL;
        return(1);
 }
 
 
-static int
-roffblkin(void *arg, int tok, int *argc, char **argv)
+/* ARGSUSED */
+void
+xml_free(void *p)
 {
-       struct md_xml   *p;
-       int              i;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       if (0 != p->pos) {
-               if ( ! mbuf_newline(p))
-                       return(0);
-               if ( ! mbuf_indent(p))
-                       return(0);
-       } else if ( ! mbuf_indent(p))
-               return(0);
-
-       if ( ! mbuf_nputs(p, "<", 1))
-               return(0);
-       if ( ! mbuf_nputs(p, "block:", 6))
-               return(0);
-       if ( ! mbuf_puts(p, toknames[tok]))
-               return(0);
 
-       /* FIXME: xml won't like standards args (e.g., p1003.1-90). */
-
-       for (i = 0; ROFF_ARGMAX != argc[i]; i++) {
-               if ( ! mbuf_nputs(p, " ", 1))
-                       return(0);
-               if ( ! mbuf_puts(p, tokargnames[argc[i]]))
-                       return(0);
-               if ( ! mbuf_nputs(p, "=\"", 2))
-                       return(0);
-               if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true"))
-                       return(0);
-               if ( ! mbuf_nputs(p, "\"", 1))
-                       return(0);
-       }
-
-       if ( ! mbuf_nputs(p, ">", 1))
-               return(0);
-
-       p->last = MD_BLKIN;
-       p->indent++;
-       return(mbuf_newline(p));
+       /* Do nothing. */
 }
 
 
-static int
-roffblkout(void *arg, int tok)
+int
+md_line_xml(void *data, char *buf)
 {
-       struct md_xml   *p;
 
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       p->indent--;
-
-       if (0 != p->pos) {
-               if ( ! mbuf_newline(p))
-                       return(0);
-               if ( ! mbuf_indent(p))
-                       return(0);
-       } else if ( ! mbuf_indent(p))
-               return(0);
-
-       if ( ! mbuf_nputs(p, "</", 2))
-               return(0);
-       if ( ! mbuf_nputs(p, "block:", 6))
-               return(0);
-       if ( ! mbuf_puts(p, toknames[tok]))
-               return(0);
-       if ( ! mbuf_nputs(p, ">", 1))
-               return(0);
-
-       p->last = MD_BLKOUT;
-       return(mbuf_newline(p));
+       return(mlg_line((struct md_mlg *)data, buf));
 }
 
 
-static int
-roffin(void *arg, int tok, int *argc, char **argv)
-{
-       struct md_xml   *p;
-       int              i;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       /* 
-        * FIXME: put all of this in a buffer, then check the buffer
-        * length versus the column width for nicer output.  This is a
-        * bit hacky.
-        */
-
-       if (p->pos + 11 > COLUMNS) 
-               if ( ! mbuf_newline(p))
-                       return(0);
-
-       if (0 != p->pos) {
-               switch (p->last) {
-               case (MD_TEXT):
-                       /* FALLTHROUGH */
-               case (MD_OUT):
-                       if ( ! mbuf_nputs(p, " ", 1))
-                               return(0);
-                       break;
-               default:
-                       break;
-               }
-       } else if ( ! mbuf_indent(p))
-               return(0);
-
-       p->last = MD_IN;
-
-       if ( ! mbuf_nputs(p, "<", 1))
-               return(0);
-       if ( ! mbuf_nputs(p, "inline:", 7))
-               return(0);
-       if ( ! mbuf_puts(p, toknames[tok]))
-               return(0);
-
-       for (i = 0; ROFF_ARGMAX != argc[i]; i++) {
-               if ( ! mbuf_nputs(p, " ", 1))
-                       return(0);
-               if ( ! mbuf_puts(p, tokargnames[argc[i]]))
-                       return(0);
-               if ( ! mbuf_nputs(p, "=\"", 2))
-                       return(0);
-               if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true"))
-                       return(0);
-               if ( ! mbuf_nputs(p, "\"", 1))
-                       return(0);
-       }
-       return(mbuf_nputs(p, ">", 1));
-}
-
-
-static int
-roffout(void *arg, int tok)
+int
+md_exit_xml(void *data, int flush)
 {
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
 
-       if (0 == p->pos && ! mbuf_indent(p))
-               return(0);
-
-       p->last = MD_OUT;
-
-       if ( ! mbuf_nputs(p, "</", 2))
-               return(0);
-       if ( ! mbuf_nputs(p, "inline:", 7))
-               return(0);
-       if ( ! mbuf_puts(p, toknames[tok]))
-               return(0);
-       return(mbuf_nputs(p, ">", 1));
+       return(mlg_exit((struct md_mlg *)data, flush));
 }
 
 
-static void
-roffmsg(void *arg, enum roffmsg lvl, 
-               const char *buf, const char *pos, char *msg)
+void *
+md_init_xml(const struct md_args *args,
+               struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
 {
-       char            *level;
-       struct md_xml   *p;
+       struct ml_cbs    cbs;
 
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       switch (lvl) {
-       case (ROFF_WARN):
-               if ( ! (MD_WARN_ALL & p->args->warnings))
-                       return;
-               level = "warning";
-               break;
-       case (ROFF_ERROR):
-               level = "error";
-               break;
-       default:
-               abort();
-       }
-       
-       if (pos)
-               (void)fprintf(stderr, "%s:%zu: %s: %s (column %zu)\n", 
-                               p->rbuf->name, p->rbuf->line, level, 
-                               msg, pos - buf);
-       else
-               (void)fprintf(stderr, "%s: %s: %s\n", 
-                               p->rbuf->name, level, msg);
+       cbs.ml_alloc = xml_alloc;
+       cbs.ml_free = xml_free;
+       cbs.ml_begintag = xml_begintag;
+       cbs.ml_endtag = xml_endtag;
+       cbs.ml_begin = xml_begin;
+       cbs.ml_end = xml_end;
+       cbs.ml_beginstring = xml_beginstring;
+       cbs.ml_endstring = xml_endstring;
 
+       return(mlg_alloc(args, rbuf, mbuf, &cbs));
 }
 
-
-static int
-roffdata(void *arg, int space, char *buf)
-{
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-       if ( ! mbuf_data(p, space, buf))
-               return(0);
-
-       p->last = MD_TEXT;
-       return(1);
-}