[BACK]Return to xml.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/Attic/xml.c between version 1.6 and 1.20

version 1.6, 2008/12/02 00:10:37 version 1.20, 2008/12/08 12:46:28
Line 16 
Line 16 
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.   * PERFORMANCE OF THIS SOFTWARE.
  */   */
 #include <sys/param.h>  
   
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  
 #include <err.h>  
 #include <stdio.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   
 #include "libmdocml.h"  #include "libmdocml.h"
 #include "private.h"  #include "private.h"
   #include "ml.h"
   
 #define MAXINDENT        8  
 #define COLUMNS          72  
   
 #ifdef  __linux__ /* FIXME */  static  int             xml_alloc(void **);
 #define strlcat          strncat  static  void            xml_free(void *);
 #endif  static  ssize_t         xml_endtag(struct md_mbuf *, void *,
                                   const struct md_args *,
 enum    md_ns {                                  enum md_ns, int);
         MD_NS_BLOCK,  static  ssize_t         xml_begintag(struct md_mbuf *, void *,
         MD_NS_INLINE,                                  const struct md_args *,
         MD_NS_DEFAULT                                  enum md_ns, int,
 };                                  const int *, const char **);
   static  ssize_t         xml_beginstring(struct md_mbuf *,
 enum    md_tok {                                  const struct md_args *,
         MD_BLKIN,  
         MD_BLKOUT,  
         MD_IN,  
         MD_OUT,  
         MD_TEXT,  
         MD_OVERRIDE  
 };  
   
 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 *,  
                                 const char *, size_t);                                  const char *, size_t);
 static  int              mbuf_puts(struct md_xml *, const char *);  static  ssize_t         xml_endstring(struct md_mbuf *,
 static  int              mbuf_nputs(struct md_xml *,                                  const struct md_args *,
                                 const char *, size_t);                                  const char *, size_t);
 static  int              mbuf_begintag(struct md_xml *, const char *,  static  int             xml_begin(struct md_mbuf *,
                                 enum md_ns, int *, char **);                                  const struct md_args *,
 static  int              mbuf_endtag(struct md_xml *,                                  const struct tm *,
                                 const char *, enum md_ns);                                  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  static ssize_t
 mbuf_begintag(struct md_xml *p, const char *name, enum md_ns ns,  xml_printtagargs(struct md_mbuf *mbuf, const int *argc,
                 int *argc, char **argv)                  const char **argv)
 {  {
         int              i;          int              i, c;
           size_t           res;
   
         if ( ! mbuf_nputs(p, "<", 1))          if (NULL == argc || NULL == argv)
                 return(0);                  return(0);
           assert(argc && argv);
   
         switch (ns) {          /* LINTED */
                 case (MD_NS_BLOCK):          for (res = 0, i = 0; ROFF_ARGMAX != (c = argc[i]); i++) {
                         if ( ! mbuf_nputs(p, "block:", 6))                  if ( ! ml_nputs(mbuf, " ", 1, &res))
                                 return(0);                          return(-1);
                         break;  
                 case (MD_NS_INLINE):  
                         if ( ! mbuf_nputs(p, "inline:", 7))  
                                 return(0);  
                         break;  
                 default:  
                         break;  
         }  
   
         if ( ! mbuf_puts(p, name))                  if ( ! ml_puts(mbuf, tokargnames[c], &res))
                 return(0);                          return(-1);
                   if ( ! ml_nputs(mbuf, "=\"", 2, &res))
         for (i = 0; ROFF_ARGMAX != argc[i]; i++) {                          return(-1);
                 if ( ! mbuf_nputs(p, " ", 1))                  if (argv[i]) {
                         return(0);                          if ( ! ml_putstring(mbuf, argv[i], &res))
                 if ( ! mbuf_puts(p, tokargnames[argc[i]]))                                  return(-1);
                         return(0);                  } else if ( ! ml_nputs(mbuf, "true", 4, &res))
                 if ( ! mbuf_nputs(p, "=\"", 2))                          return(-1);
                         return(0);                  if ( ! ml_nputs(mbuf, "\"", 1, &res))
                 if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true"))                          return(-1);
                         return(0);  
                 if ( ! mbuf_nputs(p, "\"", 1))  
                         return(0);  
         }          }
         return(mbuf_nputs(p, ">", 1));  
           return((ssize_t)res);
 }  }
   
   
 static int  static ssize_t
 mbuf_endtag(struct md_xml *p, const char *tag, enum md_ns ns)  xml_printtagname(struct md_mbuf *mbuf, enum md_ns ns, int tok)
 {  {
         if ( ! mbuf_nputs(p, "</", 2))          size_t           res;
                 return(0);  
   
           res = 0;
         switch (ns) {          switch (ns) {
                 case (MD_NS_BLOCK):          case (MD_NS_BLOCK):
                         if ( ! mbuf_nputs(p, "block:", 6))                  if ( ! ml_nputs(mbuf, "block:", 6, &res))
                                 return(0);                          return(-1);
                         break;                  break;
                 case (MD_NS_INLINE):          case (MD_NS_INLINE):
                         if ( ! mbuf_nputs(p, "inline:", 7))                  if ( ! ml_nputs(mbuf, "inline:", 7, &res))
                                 return(0);                          return(-1);
                         break;                  break;
                 default:          case (MD_NS_BODY):
                         break;                  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;
         }          }
   
         if ( ! mbuf_puts(p, tag))          if ( ! ml_puts(mbuf, toknames[tok], &res))
                 return(0);                  return(-1);
         return(mbuf_nputs(p, ">", 1));          return((ssize_t)res);
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_putstring(struct md_xml *p, const char *buf)  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)
 {  {
   
         return(mbuf_nputstring(p, buf, strlen(buf)));          if ( ! ml_puts(mbuf, "<?xml version=\"1.0\" "
                                   "encoding=\"UTF-8\"?>\n", NULL))
                   return(0);
           return(ml_puts(mbuf, "<mdoc xmlns:block=\"block\" "
                                   "xmlns:body=\"body\" "
                                   "xmlns:head=\"head\" "
                                   "xmlns:inline=\"inline\">", NULL));
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_nputstring(struct md_xml *p, const char *buf, size_t sz)  static int
   xml_end(struct md_mbuf *mbuf, const struct md_args *args)
 {  {
         size_t           i;  
   
         for (i = 0; i < sz; i++) {          return(ml_puts(mbuf, "</mdoc>", NULL));
                 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;  
                 case ('<'):  
                         if ( ! md_buf_puts(p->mbuf, "&lt;", 4))  
                                 return(0);  
                         p->pos += 4;  
                         break;  
                 case ('>'):  
                         if ( ! md_buf_puts(p->mbuf, "&gt;", 4))  
                                 return(0);  
                         p->pos += 4;  
                         break;  
                 default:  
                         if ( ! md_buf_putchar(p->mbuf, buf[i]))  
                                 return(0);  
                         p->pos++;  
                         break;  
                 }  
         }  
         return(1);  
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_nputs(struct md_xml *p, const char *buf, size_t sz)  static ssize_t
   xml_beginstring(struct md_mbuf *mbuf,
                   const struct md_args *args,
                   const char *buf, size_t sz)
 {  {
   
         p->pos += sz;          return(0);
         return(md_buf_puts(p->mbuf, buf, sz));  
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_puts(struct md_xml *p, const char *buf)  static ssize_t
   xml_endstring(struct md_mbuf *mbuf,
                   const struct md_args *args,
                   const char *buf, size_t sz)
 {  {
   
         return(mbuf_nputs(p, buf, strlen(buf)));          return(0);
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_indent(struct md_xml *p)  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)
 {  {
         size_t           i;          ssize_t          res, sz;
   
         assert(p->pos == 0);          if (-1 == (res = xml_printtagname(mbuf, ns, tok)))
                   return(-1);
           if (-1 == (sz = xml_printtagargs(mbuf, argc, argv)))
                   return(-1);
           return(res + sz);
   }
   
         /* LINTED */  
         for (i = 0; i < MIN(p->indent, MAXINDENT); i++)  
                 if ( ! md_buf_putstring(p->mbuf, "    "))  
                         return(0);  
   
         p->pos += i * 4;  /* ARGSUSED */
         return(1);  static ssize_t
   xml_endtag(struct md_mbuf *mbuf, void *data,
                   const struct md_args *args, enum md_ns ns, int tok)
   {
   
           return(xml_printtagname(mbuf, ns, tok));
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_newline(struct md_xml *p)  int
   xml_alloc(void **p)
 {  {
   
         if ( ! md_buf_putchar(p->mbuf, '\n'))          *p = NULL;
                 return(0);  
   
         p->pos = 0;  
         return(1);          return(1);
 }  }
   
   
 static int  /* ARGSUSED */
 mbuf_data(struct md_xml *p, int space, char *buf)  void
   xml_free(void *p)
 {  {
         size_t           sz;  
         char            *bufp;  
   
         assert(p->mbuf);          /* Do nothing. */
         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 * MAXINDENT + 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);  
 }  }
   
   
 int  int
 md_line_xml(void *arg, char *buf)  md_line_xml(void *data, char *buf)
 {  {
         struct md_xml   *p;  
   
         p = (struct md_xml *)arg;          return(mlg_line((struct md_mlg *)data, buf));
         return(roff_engine(p->tree, buf));  
 }  }
   
   
 int  int
 md_exit_xml(void *data, int flush)  md_exit_xml(void *data, int flush)
 {  {
         int              c;  
         struct md_xml   *p;  
   
         p = (struct md_xml *)data;          return(mlg_exit((struct md_mlg *)data, flush));
         c = roff_free(p->tree, flush);  
         free(p);  
   
         return(c);  
 }  }
   
   
Line 339  void *
Line 233  void *
 md_init_xml(const struct md_args *args,  md_init_xml(const struct md_args *args,
                 struct md_mbuf *mbuf, const struct md_rbuf *rbuf)                  struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
 {  {
         struct roffcb    cb;          struct ml_cbs    cbs;
         struct md_xml   *p;  
   
         cb.roffhead = roffhead;          cbs.ml_alloc = xml_alloc;
         cb.rofftail = rofftail;          cbs.ml_free = xml_free;
         cb.roffin = roffin;          cbs.ml_begintag = xml_begintag;
         cb.roffout = roffout;          cbs.ml_endtag = xml_endtag;
         cb.roffblkin = roffblkin;          cbs.ml_begin = xml_begin;
         cb.roffblkout = roffblkout;          cbs.ml_end = xml_end;
         cb.roffspecial = roffspecial;          cbs.ml_beginstring = xml_beginstring;
         cb.roffmsg = roffmsg;          cbs.ml_endstring = xml_endstring;
         cb.roffdata = roffdata;  
   
         if (NULL == (p = calloc(1, sizeof(struct md_xml))))          return(mlg_alloc(args, rbuf, mbuf, &cbs));
                 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);  
 }  
   
   
 /* ARGSUSED */  
 static int  
 roffhead(void *arg)  
 {  
         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);  
   
         p->indent++;  
         p->last = MD_BLKIN;  
         return(mbuf_newline(p));  
 }  
   
   
 static int  
 rofftail(void *arg)  
 {  
         struct md_xml   *p;  
   
         assert(arg);  
         p = (struct md_xml *)arg;  
   
         if (0 != p->pos && ! mbuf_newline(p))  
                 return(0);  
   
         p->last = MD_BLKOUT;  
         if ( ! mbuf_endtag(p, "mdoc", MD_NS_DEFAULT))  
                 return(0);  
   
         return(mbuf_newline(p));  
 }  
   
   
 static int  
 roffspecial(void *arg, int tok)  
 {  
         struct md_xml   *p;  
   
         assert(arg);  
         p = (struct md_xml *)arg;  
   
         /* FIXME: this is completely ad hoc. */  
   
         switch (tok) {  
         case (ROFF_Ns):  
                 p->last = MD_OVERRIDE;  
                 break;  
         default:  
                 break;  
         }  
   
         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 ( ! mbuf_indent(p))  
                         return(0);  
         } else if ( ! mbuf_indent(p))  
                 return(0);  
   
         /* FIXME: xml won't like standards args (e.g., p1003.1-90). */  
   
         p->last = MD_BLKIN;  
         p->indent++;  
   
         if ( ! mbuf_begintag(p, toknames[tok], MD_NS_BLOCK,  
                                 argc, argv))  
                 return(0);  
         return(mbuf_newline(p));  
 }  
   
   
 static int  
 roffblkout(void *arg, int tok)  
 {  
         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);  
   
         p->last = MD_BLKOUT;  
   
         if ( ! mbuf_endtag(p, toknames[tok], MD_NS_BLOCK))  
                 return(0);  
         return(mbuf_newline(p));  
 }  
   
   
 static int  
 roffin(void *arg, int tok, int *argc, char **argv)  
 {  
         struct md_xml   *p;  
   
         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;  
         return(mbuf_begintag(p, toknames[tok],  
                                 MD_NS_INLINE, argc, argv));  
 }  
   
   
 static int  
 roffout(void *arg, int tok)  
 {  
         struct md_xml   *p;  
   
         assert(arg);  
         p = (struct md_xml *)arg;  
   
         if (0 == p->pos && ! mbuf_indent(p))  
                 return(0);  
   
         p->last = MD_OUT;  
         return(mbuf_endtag(p, toknames[tok], MD_NS_INLINE));  
 }  
   
   
 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)  
 {  
         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);  
 }  }
   

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.20

CVSweb