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

Diff for /mandoc/Attic/html4_strict.c between version 1.2 and 1.9

version 1.2, 2008/11/23 19:10:03 version 1.9, 2008/11/29 14:14:21
Line 17 
Line 17 
  * PERFORMANCE OF THIS SOFTWARE.   * PERFORMANCE OF THIS SOFTWARE.
  */   */
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  
 #include <err.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <stdio.h>  
 #include <string.h>  
 #include <time.h>  
   
 #include "libmdocml.h"  #include "libmdocml.h"
 #include "private.h"  #include "private.h"
   
 enum    roffd {  
         ROFF_ENTER = 0,  
         ROFF_EXIT  
 };  
   
 enum    rofftype {  /* ARGSUSED */
         ROFF_NONE = 0,  
         ROFF_LAYOUT  
 };  
   
 struct rofftree;  
   
 #define ROFFCALL_ARGS     const struct md_args *arg,            \  
                           struct md_mbuf *out,                  \  
                           const struct md_rbuf *in,             \  
                           const char *buf, size_t sz,           \  
                           size_t pos, enum roffd type,          \  
                           struct rofftree *tree  
 typedef int             (*roffcall)(ROFFCALL_ARGS);  
   
 static  int               roff_Dd(ROFFCALL_ARGS);  
 static  int               roff_Dt(ROFFCALL_ARGS);  
 static  int               roff_Os(ROFFCALL_ARGS);  
 static  int               roff_Sh(ROFFCALL_ARGS);  
   
 struct  rofftok {  
         char              id;  
 #define ROFF___           0  
 #define ROFF_Dd           1  
 #define ROFF_Dt           2  
 #define ROFF_Os           3  
 #define ROFF_Sh           4  
 #define ROFF_Max          5  
         char              name[2];  
         roffcall          cb;  
         enum rofftype     type;  
         int               flags;  
 #define ROFF_NESTED      (1 << 0)  
 };  
   
 static const struct rofftok tokens[ROFF_Max] = {  
         { ROFF___,    "\\\"",      NULL, ROFF_NONE,     0 },  
         { ROFF_Dd,      "Dd",   roff_Dd, ROFF_NONE,     0 },  
         { ROFF_Dt,      "Dt",   roff_Dt, ROFF_NONE,     0 },  
         { ROFF_Os,      "Os",   roff_Os, ROFF_LAYOUT,   0 },  
         { ROFF_Sh,      "Sh",   roff_Sh, ROFF_LAYOUT,   0 },  
 };  
   
 struct  roffnode {  
         int               tok;  
         struct roffnode  *parent;  
         /* TODO: line number at acquisition. */  
 };  
   
 struct rofftree {  
         struct roffnode  *last;  
         time_t            date;  
         char              title[256];  
         char              section[256];  
         char              volume[256];  
         int               state;  
 #define ROFF_PRELUDE_Os  (1 << 1)  
 #define ROFF_PRELUDE_Dt  (1 << 2)  
 #define ROFF_PRELUDE_Dd  (1 << 3)  
 };  
   
 static  int               rofffind(const char *);  
 static  int               roffparse(const struct md_args *,  
                                 struct md_mbuf *,  
                                 const struct md_rbuf *,  
                                 const char *, size_t,  
                                 struct rofftree *);  
 static  int               textparse(struct md_mbuf *,  
                                 const struct md_rbuf *,  
                                 const char *, size_t,  
                                 const struct rofftree *);  
   
 static  void              dbg_enter(const struct md_args *, int);  
 static  void              dbg_leave(const struct md_args *, int);  
   
   
 int  int
 md_exit_html4_strict(const struct md_args *args, struct md_mbuf *out,  md_line_html4_strict(void *data, char *buf)
                 const struct md_rbuf *in, void *data)  
 {  {
         struct rofftree *tree;  
         int              error;  
   
         assert(args);  
         assert(data);  
         tree = (struct rofftree *)data;  
         error = 0;  
   
         while (tree->last)  
                 if ( ! (*tokens[tree->last->tok].cb)  
                                 (args, error ? NULL : out, in, NULL,  
                                  0, 0, ROFF_EXIT, tree))  
                         error = 1;  
   
         free(tree);  
         return(error ? 0 : 1);  
 }  
   
   
 int  
 md_init_html4_strict(const struct md_args *args, struct md_mbuf *out,  
                 const struct md_rbuf *in, void **data)  
 {  
         struct rofftree *tree;  
   
         assert(args);  
         assert(in);  
         assert(out);  
         assert(data);  
   
         /* TODO: write HTML-DTD header. */  
   
         if (NULL == (tree = calloc(1, sizeof(struct rofftree)))) {  
                 warn("malloc");  
                 return(0);  
         }  
   
         *data = tree;  
         return(1);          return(1);
 }  }
   
   
   /* ARGSUSED */
 int  int
 md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,  md_exit_html4_strict(void *data, int flush)
                 const struct md_rbuf *in, const char *buf,  
                 size_t sz, void *data)  
 {  {
         struct rofftree *tree;  
   
         assert(args);  
         assert(in);  
         assert(data);  
   
         tree = (struct rofftree *)data;  
   
         if (0 == sz) {  
                 warnx("%s: blank line (line %zu)", in->name, in->line);  
                 return(0);  
         } else if ('.' != *buf)  
                 return(textparse(out, in, buf, sz, tree));  
   
         return(roffparse(args, out, in, buf, sz, tree));  
 }  
   
   
 static int  
 textparse(struct md_mbuf *out, const struct md_rbuf *in,  
                 const char *buf, size_t sz,  
                 const struct rofftree *tree)  
 {  
   
         assert(tree);  
         assert(out);  
         assert(in);  
         assert(buf);  
         assert(sz > 0);  
   
         if (NULL == tree->last) {  
                 warnx("%s: unexpected text (line %zu)",  
                                 in->name, in->line);  
                 return(0);  
         } else if (NULL == tree->last->parent) {  
                 warnx("%s: disallowed text (line %zu)",  
                                 in->name, in->line);  
                 return(0);  
         }  
   
         if ( ! md_buf_puts(out, buf, sz))  
                 return(0);  
         return(md_buf_putstring(out, " "));  
 }  
   
   
 static int  
 roffparse(const struct md_args *args, struct md_mbuf *out,  
                 const struct md_rbuf *in, const char *buf,  
                 size_t sz, struct rofftree *tree)  
 {  
         int              tokid, t;  
         size_t           pos;  
         struct roffnode *node;  
   
         assert(args);  
         assert(out);  
         assert(in);  
         assert(buf);  
         assert(sz > 0);  
         assert(tree);  
   
         /*  
          * Extract the token identifier from the buffer.  If there's no  
          * callback for the token (comment, etc.) then exit immediately.  
          * We don't do any error handling (yet), so if the token doesn't  
          * exist, die.  
          */  
   
         if (3 > sz) {  
                 warnx("%s: malformed input (line %zu, col 1)",  
                                 in->name, in->line);  
                 return(0);  
         } else if (ROFF_Max == (tokid = rofffind(buf + 1))) {  
                 warnx("%s: unknown token `%c%c' (line %zu, col 1)",  
                                 in->name, *(buf + 1),  
                                 *(buf + 2), in->line);  
                 return(0);  
         } else if (NULL == tokens[tokid].cb)  
                 return(1); /* Skip token. */  
   
         pos = 3;  
   
         /*  
          * If this is a non-nestable layout token and we're below a  
          * token of the same type, then recurse upward to the token,  
          * closing out the interim scopes.  
          *  
          * If there's a nested token on the chain, then raise an error  
          * as nested tokens have corresponding "ending" tokens and we're  
          * breaking their scope.  
          */  
   
         node = NULL;  
   
         if (ROFF_LAYOUT == tokens[tokid].type &&  
                         ! (ROFF_NESTED & tokens[tokid].flags)) {  
                 for (node = tree->last; node; node = node->parent) {  
                         if (node->tok == tokid)  
                                 break;  
   
                         /* Don't break nested scope. */  
   
                         if ( ! (ROFF_NESTED & tokens[node->tok].flags))  
                                 continue;  
                         warnx("%s: scope of %s broken by %s "  
                                         "(line %zu, col %zu)",  
                                         in->name, tokens[tokid].name,  
                                         tokens[node->tok].name,  
                                         in->line, pos);  
                         return(0);  
                 }  
         }  
         if (node) {  
                 assert(ROFF_LAYOUT == tokens[tokid].type);  
                 assert( ! (ROFF_NESTED & tokens[tokid].flags));  
                 assert(node->tok == tokid);  
   
                 /* Clear up to last scoped token. */  
   
                 do {  
                         t = tree->last->tok;  
                         if ( ! (*tokens[tree->last->tok].cb)  
                                         (args, out, in, NULL,  
                                          0, 0, ROFF_EXIT, tree))  
                                 return(0);  
                 } while (t != tokid);  
         }  
   
         /* Proceed with actual token processing. */  
   
         return((*tokens[tokid].cb)(args, out, in, buf, sz,  
                                 pos, ROFF_ENTER, tree));  
 }  
   
   
 static int  
 rofffind(const char *name)  
 {  
         size_t           i;  
   
         assert(name);  
         /* FIXME: use a table, this is slow but ok for now. */  
         for (i = 0; i < ROFF_Max; i++)  
                 if (0 == strncmp(name, tokens[i].name, 2))  
                         return(i);  
   
         return(ROFF_Max);  
 }  
   
   
 /* ARGUSED */  
 static  int  
 roff_Dd(ROFFCALL_ARGS)  
 {  
   
         assert(in);  
         assert(tree);  
         assert(arg);  
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
         assert(type == ROFF_ENTER);  
   
         if (tree->last) {  
                 warnx("%s: superfluous prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(0);  
         }  
   
         if (0 != tree->state) {  
                 warnx("%s: bad manual prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(1);  
         }  
   
         /* TODO: parse date from buffer. */  
   
         tree->date = time(NULL);  
         tree->state |= ROFF_PRELUDE_Dd;  
   
         (void)printf("Dd\n");  
   
         return(1);          return(1);
 }  }
   
   
 static  int  /* ARGSUSED */
 roff_Dt(ROFFCALL_ARGS)  void *
   md_init_html4_strict(const struct md_args *args,
                   struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
 {  {
   
         assert(in);          return(NULL);
         assert(tree);  
         assert(arg);  
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
         assert(type == ROFF_ENTER);  
   
         if (tree->last) {  
                 warnx("%s: superfluous prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(0);  
         }  
   
         if ( ! (ROFF_PRELUDE_Dd & tree->state) ||  
                         (ROFF_PRELUDE_Os & tree->state) ||  
                         (ROFF_PRELUDE_Dt & tree->state)) {  
                 warnx("%s: bad manual prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(1);  
         }  
   
         /* TODO: parse titles from buffer. */  
   
         tree->state |= ROFF_PRELUDE_Dt;  
   
         (void)printf("Dt\n");  
   
         return(1);  
 }  }
   
   
 static  int  
 roff_Os(ROFFCALL_ARGS)  
 {  
         struct roffnode *node;  
   
         assert(arg);  
         assert(tree);  
         assert(in);  
   
         if (ROFF_EXIT == type) {  
                 assert(tree->last);  
                 assert(tree->last->tok == ROFF_Os);  
   
                 /* TODO: flush out ML footer. */  
   
                 node = tree->last;  
                 tree->last = node->parent;  
                 free(node);  
   
                 dbg_leave(arg, ROFF_Os);  
   
                 return(1);  
         }  
   
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
   
         if (tree->last) {  
                 warnx("%s: superfluous prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(0);  
         }  
   
         if ((ROFF_PRELUDE_Os & tree->state) ||  
                         ! (ROFF_PRELUDE_Dt & tree->state) ||  
                         ! (ROFF_PRELUDE_Dd & tree->state)) {  
                 warnx("%s: bad manual prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(1);  
         }  
   
         node = malloc(sizeof(struct roffnode));  
         if (NULL == node) {  
                 warn("malloc");  
                 return(0);  
         }  
         node->tok = ROFF_Os;  
         node->parent = NULL;  
   
         tree->state |= ROFF_PRELUDE_Os;  
         tree->last = node;  
   
         dbg_enter(arg, ROFF_Os);  
   
         return(1);  
 }  
   
   
 static  int  
 roff_Sh(ROFFCALL_ARGS)  
 {  
         struct roffnode *node;  
   
         assert(arg);  
         assert(tree);  
         assert(tree->last);  
         assert(in);  
   
         if (ROFF_EXIT == type) {  
                 assert(tree->last->tok == ROFF_Sh);  
   
                 node = tree->last;  
                 tree->last = node->parent;  
                 free(node);  
   
                 dbg_leave(arg, ROFF_Sh);  
   
                 return(1);  
         }  
   
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
   
         node = malloc(sizeof(struct roffnode));  
         if (NULL == node) {  
                 warn("malloc");  
                 return(0);  
         }  
         node->tok = ROFF_Sh;  
         node->parent = tree->last;  
   
         tree->last = node;  
   
         dbg_enter(arg, ROFF_Sh);  
   
         return(1);  
 }  
   
   
 static int dbg_lvl = 0; /* FIXME: de-globalise. */  
   
   
 static void  
 dbg_enter(const struct md_args *args, int tokid)  
 {  
         int              i;  
   
         assert(args);  
         if ( ! (args->dbg & MD_DBG_TREE))  
                 return;  
   
         assert(tokid >= 0 && tokid <= ROFF_Max);  
   
         for (i = 0; i < dbg_lvl; i++)  
                 (void)printf(" ");  
   
         (void)printf("%s\n", tokens[tokid].name);  
   
         if (ROFF_LAYOUT == tokens[tokid].type)  
                 dbg_lvl++;  
 }  
   
   
 static void  
 dbg_leave(const struct md_args *args, int tokid)  
 {  
         int              i;  
   
         assert(args);  
         if ( ! (args->dbg & MD_DBG_TREE))  
                 return;  
   
         assert(tokid >= 0 && tokid <= ROFF_Max);  
         assert(dbg_lvl > 0);  
   
         dbg_lvl--;  
         for (i = 0; i < dbg_lvl; i++)  
                 (void)printf(" ");  
   
         (void)printf("%s\n", tokens[tokid].name);  
 }  
   

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.9

CVSweb