]> 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 c28e450503539165e1e6658d233fbcb56b964f74..6d7da207e231043522481021aebb157b79937e5c 100644 (file)
--- a/xml.c
+++ b/xml.c
@@ -1,4 +1,4 @@
-/* $Id: xml.c,v 1.9 2008/12/02 18:26: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        COLUMNS          72
-
-enum   md_ns {
-       MD_NS_BLOCK,
-       MD_NS_INLINE,
-       MD_NS_DEFAULT
-};
-
-enum   md_tok {
-       MD_BLKIN,               /* Controls spacing. */
-       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) /* TODO */
-#define        MD_OVERRIDE_ONE (1 << 1)
-#define        MD_OVERRIDE_ALL (1 << 2)
-};
-
-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, int *, char **, char **);
-
-static void             mbuf_mode(struct md_xml *, enum md_ns);
-static int              mbuf_newline(struct md_xml *);
-static int              xml_indent(struct md_xml *);
-static int              mbuf_data(struct md_xml *, int, char *);
-static int              xml_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              xml_puts(struct md_xml *, const char *);
-static int              xml_nputs(struct md_xml *, 
+static ssize_t         xml_endstring(struct md_mbuf *, 
+                               const struct md_args *, 
                                const char *, size_t);
-static int              xml_begintag(struct md_xml *, const char *, 
-                               enum md_ns, int *, char **);
-static int              xml_endtag(struct md_xml *, 
-                               const char *, enum md_ns);
-
-#ifdef __linux__ /* FIXME: remove */
-static size_t            strlcat(char *, const char *, size_t);
-static size_t            strlcpy(char *, const char *, size_t);
-#endif
-
-
-static void
-mbuf_mode(struct md_xml *p, enum md_ns ns)
-{
-       p->flags &= ~MD_OVERRIDE_ONE;
-       p->last = ns;
-}
-
-
-static int
-xml_begintag(struct md_xml *p, const char *name, enum md_ns ns, 
-               int *argc, char **argv)
-{
-       char             buf[64];
-       ssize_t          sz;
+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 ssize_t 
+xml_printtagargs(struct md_mbuf *mbuf, const int *argc,
+               const char **argv)
+{
+       int              i, c;
        size_t           res;
 
-       switch (ns) {
-       case (MD_NS_BLOCK):
-               res = strlcpy(buf, "block:", sizeof(buf));
-               assert(res < sizeof(buf));
-               break;
-       case (MD_NS_INLINE):
-               res = strlcpy(buf, "inline:", sizeof(buf));
-               assert(res < sizeof(buf));
-               break;
-       default:
-               *buf = 0;
-               break;
+       if (NULL == argc || NULL == argv)
+               return(0);
+       assert(argc && argv);
+
+       /* 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);
        }
 
-       res = strlcat(buf, name, sizeof(buf));
-       assert(res < sizeof(buf));
-
-       if (-1 == (sz = ml_begintag(p->mbuf, buf, argc, argv)))
-               return(0);
-
-       p->pos += sz;
-       return(1);
+       return((ssize_t)res);
 }
 
 
-static int
-xml_endtag(struct md_xml *p, const char *name, enum md_ns ns)
+static ssize_t 
+xml_printtagname(struct md_mbuf *mbuf, enum md_ns ns, int tok)
 {
-       char             buf[64];
-       ssize_t          sz;
        size_t           res;
 
+       res = 0;
        switch (ns) {
        case (MD_NS_BLOCK):
-               res = strlcpy(buf, "block:", sizeof(buf));
-               assert(res < sizeof(buf));
+               if ( ! ml_nputs(mbuf, "block:", 6, &res))
+                       return(-1);
                break;
        case (MD_NS_INLINE):
-               res = strlcpy(buf, "inline:", sizeof(buf));
-               assert(res < sizeof(buf));
+               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:
-               *buf = 0;
                break;
        }
 
-       res = strlcat(buf, name, sizeof(buf));
-       assert(res < sizeof(buf));
-
-       if (-1 == (sz = ml_endtag(p->mbuf, buf)))
-               return(0);
-
-       p->pos += sz;
-       return(1);
+       if ( ! ml_puts(mbuf, toknames[tok], &res))
+               return(-1);
+       return((ssize_t)res);
 }
 
 
-static int
-xml_nputstring(struct md_xml *p, const char *buf, size_t sz)
-{
-       ssize_t          res;
-
-       if (-1 == (res = ml_nputstring(p->mbuf, buf, sz)))
-               return(0);
-       p->pos += res;
-       return(1);
-}
-
-
-static int
-xml_nputs(struct md_xml *p, const char *buf, size_t sz)
-{
-       ssize_t          res;
-
-       if (-1 == (res = ml_nputs(p->mbuf, buf, sz)))
-               return(0);
-       p->pos += res;
-       return(1);
-}
-
-
-static int
-xml_puts(struct md_xml *p, const char *buf)
-{
-
-       return(xml_nputs(p, buf, strlen(buf)));
-}
-
-
-static int
-xml_indent(struct md_xml *p)
-{
-       ssize_t          res;
-
-       if (-1 == (res = ml_indent(p->mbuf, p->indent)))
-               return(0);
-       p->pos += res;
-       return(1);
-}
-
-
-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_OVERRIDE_ONE & p->flags || MD_OVERRIDE_ALL & p->flags)
-               space = 0;
-
-       if (MD_LITERAL & p->flags)
-               return(xml_nputstring(p, buf, sizeof(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 ( ! xml_indent(p))
-                               return(0);
-                       if ( ! xml_nputstring(p, bufp, sz))
-                               return(0);
-                       if (p->indent * MAXINDENT + sz >= COLUMNS)
-                               if ( ! mbuf_newline(p))
-                                       return(0);
-                       if ( ! (MD_OVERRIDE_ALL & p->flags))
-                               space = 1;
-                       continue;
-               }
-
-               if (space && sz + p->pos >= COLUMNS) {
-                       if ( ! mbuf_newline(p))
-                               return(0);
-                       if ( ! xml_indent(p))
-                               return(0);
-               } else if (space) {
-                       if ( ! xml_nputs(p, " ", 1))
-                               return(0);
-               }
-
-               if ( ! xml_nputstring(p, bufp, sz))
-                       return(0);
-
-               if ( ! (MD_OVERRIDE_ALL & p->flags))
-                       space = 1;
-       }
-
-       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 (-1 == xml_puts(p, "<?xml version=\"1.0\" "
-                               "encoding=\"UTF-8\"?>\n"))
-               return(0);
-       if (-1 == xml_puts(p, "<mdoc xmlns:block=\"block\" "
-                               "xmlns:special=\"special\" "
-                               "xmlns:inline=\"inline\">"))
-               return(0);
+       ssize_t          res, sz;
 
-       p->indent++;
-       mbuf_mode(p, 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);
-
-       mbuf_mode(p, MD_BLKOUT);
-       if ( ! xml_endtag(p, "mdoc", MD_NS_DEFAULT))
-               return(0);
-       return(mbuf_newline(p));
+       return(xml_printtagname(mbuf, ns, tok));
 }
 
 
 /* ARGSUSED */
-static int
-roffspecial(void *arg, int tok, int *argc, char **argv, char **more)
+int
+xml_alloc(void **p)
 {
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       /* FIXME: this is completely ad hoc. */
-
-       switch (tok) {
-       case (ROFF_Ns):
-               p->flags |= MD_OVERRIDE_ONE;
-               break;
-       case (ROFF_Sm):
-               assert(*more);
-               if (0 == strcmp(*more, "on"))
-                       p->flags |= MD_OVERRIDE_ALL;
-               else
-                       p->flags &= ~MD_OVERRIDE_ALL;
-               break;
-       default:
-               break;
-       }
 
+       *p = NULL;
        return(1);
 }
 
 
-static int
-roffblkin(void *arg, int tok, int *argc, char **argv)
-{
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       if (0 != p->pos) {
-               if ( ! mbuf_newline(p))
-                       return(0);
-               if ( ! xml_indent(p))
-                       return(0);
-       } else if ( ! xml_indent(p))
-               return(0);
-
-       /* FIXME: xml won't like standards args (e.g., p1003.1-90). */
-
-       p->indent++;
-       mbuf_mode(p, MD_BLKIN);
-
-       if ( ! xml_begintag(p, toknames[tok], MD_NS_BLOCK,
-                               argc, argv))
-               return(0);
-       return(mbuf_newline(p));
-}
-
-
-static int
-roffblkout(void *arg, int tok)
+/* ARGSUSED */
+void
+xml_free(void *p)
 {
-       struct md_xml   *p;
 
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       p->indent--;
-
-       if (0 != p->pos) {
-               if ( ! mbuf_newline(p))
-                       return(0);
-               if ( ! xml_indent(p))
-                       return(0);
-       } else if ( ! xml_indent(p))
-               return(0);
-
-       mbuf_mode(p, MD_BLKOUT);
-       if ( ! xml_endtag(p, toknames[tok], MD_NS_BLOCK))
-               return(0);
-       return(mbuf_newline(p));
+       /* Do nothing. */
 }
 
 
-static int
-roffin(void *arg, int tok, int *argc, char **argv)
+int
+md_line_xml(void *data, char *buf)
 {
-       struct md_xml   *p;
-
-       assert(arg);
-       p = (struct md_xml *)arg;
-
-       if ( ! (MD_OVERRIDE_ONE & p->flags) && 
-                       ! (MD_OVERRIDE_ALL & p->flags) && 
-                       p->pos + 11 > COLUMNS) 
-               if ( ! mbuf_newline(p))
-                       return(0);
-
-       if (0 != p->pos && (MD_TEXT == p->last || MD_OUT == p->last)
-                       && ! (MD_OVERRIDE_ONE & p->flags)
-                       && ! (MD_OVERRIDE_ALL & p->flags))
-               if ( ! xml_nputs(p, " ", 1))
-                       return(0);
-
-       if (0 == p->pos && ! xml_indent(p))
-               return(0);
 
-       mbuf_mode(p, MD_IN);
-       return(xml_begintag(p, toknames[tok], 
-                               MD_NS_INLINE, argc, argv));
+       return(mlg_line((struct md_mlg *)data, buf));
 }
 
 
-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 && ! xml_indent(p))
-               return(0);
 
-       mbuf_mode(p, MD_OUT);
-       return(xml_endtag(p, toknames[tok], MD_NS_INLINE));
+       return(mlg_exit((struct md_mlg *)data, flush));
 }
 
 
-static void
-roffmsg(void *arg, enum roffmsg lvl, 
-               const char *buf, const char *pos, char *msg)
-{
-       char            *level;
-       struct md_xml   *p;
-
-       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);
-
-}
-
-
-static int
-roffdata(void *arg, int space, char *buf)
+void *
+md_init_xml(const struct md_args *args,
+               struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
 {
-       struct md_xml   *p;
+       struct ml_cbs    cbs;
 
-       assert(arg);
-       p = (struct md_xml *)arg;
-       if ( ! mbuf_data(p, space, buf))
-               return(0);
+       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;
 
-       mbuf_mode(p, MD_TEXT);
-       return(1);
+       return(mlg_alloc(args, rbuf, mbuf, &cbs));
 }
 
-
-#ifdef __linux /* FIXME: remove. */
-/*     $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $      */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-static size_t
-strlcat(char *dst, const char *src, size_t siz)
-{
-       char *d = dst;
-       const char *s = src;
-       size_t n = siz;
-       size_t dlen;
-
-       /* Find the end of dst and adjust bytes left but don't go past
-        * end */
-       while (n-- != 0 && *d != '\0')
-               d++;
-       dlen = d - dst;
-       n = siz - dlen;
-
-       if (n == 0)
-               return(dlen + strlen(s));
-       while (*s != '\0') {
-               if (n != 1) {
-                       *d++ = *s;
-                       n--;
-               }
-               s++;
-       }
-       *d = '\0';
-
-       return(dlen + (s - src));       /* count does not include NUL */
-}
-
-
-static size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
-       char *d = dst;
-       const char *s = src;
-       size_t n = siz;
-
-       /* Copy as many bytes as will fit */
-       if (n != 0) {
-               while (--n != 0) {
-                       if ((*d++ = *s++) == '\0')
-                               break;
-               }
-       }
-
-       /* Not enough room in dst, add NUL and traverse rest of src */
-       if (n == 0) {
-               if (siz != 0)
-                       *d = '\0';              /* NUL-terminate dst */
-               while (*s++)
-                       ;
-       }
-
-       return(s - src - 1);    /* count does not include NUL */
-}
-#endif /*__linux__*/