[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.5

version 1.2, 2008/11/23 19:10:03 version 1.5, 2008/11/23 23:35:25
Line 27 
Line 27 
 #include "libmdocml.h"  #include "libmdocml.h"
 #include "private.h"  #include "private.h"
   
 enum    roffd {  enum    roffd {
         ROFF_ENTER = 0,          ROFF_ENTER = 0,
         ROFF_EXIT          ROFF_EXIT
 };  };
   
 enum    rofftype {  enum    rofftype {
         ROFF_NONE = 0,          ROFF_TITLE,
         ROFF_LAYOUT          ROFF_COMMENT,
           ROFF_TEXT,
           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
   
 #define ROFFCALL_ARGS     const struct md_args *arg,            \  struct  rofftree;
                           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 {  struct  rofftok {
         char              id;          int               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];          char              name[2];
         roffcall          cb;          int             (*cb)(ROFFCALL_ARGS);
         enum rofftype     type;          enum rofftype     type;
         int               flags;          int               flags;
 #define ROFF_NESTED      (1 << 0)  #define ROFF_NESTED      (1 << 0)
   #define ROFF_PARSED      (1 << 1)
   #define ROFF_CALLABLE    (1 << 2)
 };  };
   
 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 {  struct  roffnode {
         int               tok;          int               tok;
         struct roffnode  *parent;          struct roffnode  *parent;
         /* TODO: line number at acquisition. */          size_t            line;
 };  };
   
 struct rofftree {  struct  rofftree {
         struct roffnode  *last;          struct roffnode  *last;
         time_t            date;          time_t            date;
         char              title[256];          char              title[256];
         char              section[256];          char              section[256];
         char              volume[256];          char              volume[256];
         int               state;          int               state;
 #define ROFF_PRELUDE_Os  (1 << 1)  #define ROFF_PRELUDE     (1 << 1)
 #define ROFF_PRELUDE_Dt  (1 << 2)  #define ROFF_PRELUDE_Os  (1 << 2)
 #define ROFF_PRELUDE_Dd  (1 << 3)  #define ROFF_PRELUDE_Dt  (1 << 3)
   #define ROFF_PRELUDE_Dd  (1 << 4)
   #define ROFF_BODY        (1 << 5)
 };  };
   
   #define ROFF___           0
   #define ROFF_Dd           1
   #define ROFF_Dt           2
   #define ROFF_Os           3
   #define ROFF_Sh           4
   #define ROFF_An           5
   #define ROFF_Li           6
   #define ROFF_Max          7
   
   static  int               roff_Dd(ROFFCALL_ARGS);
   static  int               roff_Dt(ROFFCALL_ARGS);
   static  int               roff_Os(ROFFCALL_ARGS);
   static  int               roff_Sh(ROFFCALL_ARGS);
   static  int               roff_An(ROFFCALL_ARGS);
   static  int               roff_Li(ROFFCALL_ARGS);
   
   static  struct roffnode  *roffnode_new(int, size_t,
                                   struct rofftree *);
   static  void              roffnode_free(int, struct rofftree *);
   
 static  int               rofffind(const char *);  static  int               rofffind(const char *);
 static  int               roffparse(const struct md_args *,  static  int               roffparse(const struct md_args *,
                                 struct md_mbuf *,                                  struct md_mbuf *,
Line 108  static void    dbg_enter(const struct md_args *, int);
Line 112  static void    dbg_enter(const struct md_args *, int);
 static  void              dbg_leave(const struct md_args *, int);  static  void              dbg_leave(const struct md_args *, int);
   
   
   static const struct rofftok tokens[ROFF_Max] =
   {
   { ROFF___, "\\\"",     NULL, ROFF_COMMENT,                        0 },
   { ROFF_Dd,   "Dd",  roff_Dd, ROFF_TITLE,                          0 },
   { ROFF_Dt,   "Dt",  roff_Dt, ROFF_TITLE,                          0 },
   { ROFF_Os,   "Os",  roff_Os, ROFF_TITLE,                          0 },
   { ROFF_Sh,   "Sh",  roff_Sh, ROFF_LAYOUT,                         0 },
   { ROFF_An,   "An",  roff_An, ROFF_TEXT, ROFF_PARSED                 },
   { ROFF_Li,   "Li",  roff_Li, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE },
   };
   
   
 int  int
 md_exit_html4_strict(const struct md_args *args, struct md_mbuf *out,  md_exit_html4_strict(const struct md_args *args, struct md_mbuf *out,
                 const struct md_rbuf *in, void *data)                  const struct md_rbuf *in, int error, void *data)
 {  {
         struct rofftree *tree;          struct rofftree *tree;
         int              error;  
   
         assert(args);          assert(args);
         assert(data);          assert(data);
         tree = (struct rofftree *)data;          tree = (struct rofftree *)data;
         error = 0;  
   
           if (-1 == error)
                   out = NULL;
   
           /* LINTED */
         while (tree->last)          while (tree->last)
                 if ( ! (*tokens[tree->last->tok].cb)                  if ( ! (*tokens[tree->last->tok].cb)(args, out, in,
                                 (args, error ? NULL : out, in, NULL,                                          NULL, 0, 0, ROFF_EXIT, tree))
                                  0, 0, ROFF_EXIT, tree))                          out = NULL;
                         error = 1;  
   
           if (out && (ROFF_PRELUDE & tree->state)) {
                   warnx("%s: prelude never finished", in->name);
                   error = 1;
           }
   
         free(tree);          free(tree);
   
         return(error ? 0 : 1);          return(error ? 0 : 1);
 }  }
   
Line 149  md_init_html4_strict(const struct md_args *args, struc
Line 172  md_init_html4_strict(const struct md_args *args, struc
                 return(0);                  return(0);
         }          }
   
           tree->state = ROFF_PRELUDE;
   
         *data = tree;          *data = tree;
         return(1);          return(1);
 }  }
Line 229  roffparse(const struct md_args *args, struct md_mbuf *
Line 254  roffparse(const struct md_args *args, struct md_mbuf *
          */           */
   
         if (3 > sz) {          if (3 > sz) {
                 warnx("%s: malformed input (line %zu, col 1)",                  warnx("%s: malformed line (line %zu)",
                                 in->name, in->line);                                  in->name, in->line);
                 return(0);                  return(0);
         } else if (ROFF_Max == (tokid = rofffind(buf + 1))) {          } else if (ROFF_Max == (tokid = rofffind(buf + 1))) {
                 warnx("%s: unknown token `%c%c' (line %zu, col 1)",                  warnx("%s: unknown line token `%c%c' (line %zu)",
                                 in->name, *(buf + 1),                                  in->name, *(buf + 1),
                                 *(buf + 2), in->line);                                  *(buf + 2), in->line);
                 return(0);                  return(0);
         } else if (NULL == tokens[tokid].cb)          }
                 return(1); /* Skip token. */  
   
         pos = 3;          /* Domain cross-contamination (and sanity) checks. */
   
           switch (tokens[tokid].type) {
           case (ROFF_TITLE):
                   if (ROFF_PRELUDE & tree->state) {
                           assert( ! (ROFF_BODY & tree->state));
                           break;
                   }
                   assert(ROFF_BODY & tree->state);
                   warnx("%s: prelude token `%s' in body (line %zu)",
                                   in->name, tokens[tokid].name, in->line);
                   return(0);
           case (ROFF_LAYOUT):
                   /* FALLTHROUGH */
           case (ROFF_TEXT):
                   if (ROFF_BODY & tree->state) {
                           assert( ! (ROFF_PRELUDE & tree->state));
                           break;
                   }
                   assert(ROFF_PRELUDE & tree->state);
                   warnx("%s: body token `%s' in prelude (line %zu)",
                                   in->name, tokens[tokid].name, in->line);
                   return(0);
           case (ROFF_COMMENT):
                   return(1);
           default:
                   abort();
           }
   
         /*          /*
            * Text-domain checks.
            */
   
           if (ROFF_TEXT == tokens[tokid].type &&
                           ! (ROFF_PARSED & tokens[tokid].flags)) {
                   warnx("%s: text token `%s' not callable (line %zu)",
                                   in->name, tokens[tokid].name, in->line);
                   return(0);
           }
   
           /*
          * If this is a non-nestable layout token and we're below a           * If this is a non-nestable layout token and we're below a
          * token of the same type, then recurse upward to the token,           * token of the same type, then recurse upward to the token,
          * closing out the interim scopes.           * closing out the interim scopes.
Line 253  roffparse(const struct md_args *args, struct md_mbuf *
Line 315  roffparse(const struct md_args *args, struct md_mbuf *
          */           */
   
         node = NULL;          node = NULL;
           pos = 3;
   
         if (ROFF_LAYOUT == tokens[tokid].type &&          if (ROFF_LAYOUT == tokens[tokid].type &&
                         ! (ROFF_NESTED & tokens[tokid].flags)) {                          ! (ROFF_NESTED & tokens[tokid].flags)) {
Line 264  roffparse(const struct md_args *args, struct md_mbuf *
Line 327  roffparse(const struct md_args *args, struct md_mbuf *
   
                         if ( ! (ROFF_NESTED & tokens[node->tok].flags))                          if ( ! (ROFF_NESTED & tokens[node->tok].flags))
                                 continue;                                  continue;
                         warnx("%s: scope of %s broken by %s "                          warnx("%s: scope of %s (line %zu) broken by "
                                         "(line %zu, col %zu)",                                          "%s (line %zu)", in->name,
                                         in->name, tokens[tokid].name,                                          tokens[tokid].name,
                                           node->line,
                                         tokens[node->tok].name,                                          tokens[node->tok].name,
                                         in->line, pos);                                          in->line);
                         return(0);                          return(0);
                 }                  }
         }          }
   
         if (node) {          if (node) {
                 assert(ROFF_LAYOUT == tokens[tokid].type);                  assert(ROFF_LAYOUT == tokens[tokid].type);
                 assert( ! (ROFF_NESTED & tokens[tokid].flags));                  assert( ! (ROFF_NESTED & tokens[tokid].flags));
Line 279  roffparse(const struct md_args *args, struct md_mbuf *
Line 344  roffparse(const struct md_args *args, struct md_mbuf *
   
                 /* Clear up to last scoped token. */                  /* Clear up to last scoped token. */
   
                   /* LINTED */
                 do {                  do {
                         t = tree->last->tok;                          t = tree->last->tok;
                         if ( ! (*tokens[tree->last->tok].cb)                          if ( ! (*tokens[tree->last->tok].cb)
Line 302  rofffind(const char *name)
Line 368  rofffind(const char *name)
   
         assert(name);          assert(name);
         /* FIXME: use a table, this is slow but ok for now. */          /* FIXME: use a table, this is slow but ok for now. */
   
           /* LINTED */
         for (i = 0; i < ROFF_Max; i++)          for (i = 0; i < ROFF_Max; i++)
                   /* LINTED */
                 if (0 == strncmp(name, tokens[i].name, 2))                  if (0 == strncmp(name, tokens[i].name, 2))
                         return(i);                          return((int)i);
   
         return(ROFF_Max);          return(ROFF_Max);
 }  }
   
   
 /* ARGUSED */  static struct roffnode *
   roffnode_new(int tokid, size_t line, struct rofftree *tree)
   {
           struct roffnode *p;
   
           if (NULL == (p = malloc(sizeof(struct roffnode)))) {
                   warn("malloc");
                   return(NULL);
           }
   
           p->line = line;
           p->tok = tokid;
           p->parent = tree->last;
           tree->last = p;
           return(p);
   }
   
   
   static void
   roffnode_free(int tokid, struct rofftree *tree)
   {
           struct roffnode *p;
   
           assert(tree->last);
           assert(tree->last->tok == tokid);
   
           p = tree->last;
           tree->last = tree->last->parent;
           free(p);
   }
   
   
   static int dbg_lvl = 0;
   
   
   static void
   dbg_enter(const struct md_args *args, int tokid)
   {
           int              i;
           static char      buf[72];
   
           assert(args);
           if ( ! (args->dbg & MD_DBG_TREE))
                   return;
           assert(tokid >= 0 && tokid <= ROFF_Max);
   
           buf[0] = 0;
   
           switch (tokens[tokid].type) {
           case (ROFF_LAYOUT):
                   /* FALLTHROUGH */
           case (ROFF_TEXT):
                   (void)strlcat(buf, "body: ", sizeof(buf));
                   break;
           case (ROFF_TITLE):
                   (void)strlcat(buf, "prelude: ", sizeof(buf));
                   break;
           default:
                   abort();
           }
   
           /* LINTED */
           for (i = 0; i < dbg_lvl; i++)
                   (void)strlcat(buf, "  ", sizeof(buf));
   
           (void)strlcat(buf, tokens[tokid].name, sizeof(buf));
   
           (void)printf("%s\n", buf);
   
           if (ROFF_LAYOUT == tokens[tokid].type)
                   dbg_lvl++;
   }
   
   
   static void
   dbg_leave(const struct md_args *args, int tokid)
   {
           assert(args);
           if ( ! (args->dbg & MD_DBG_TREE))
                   return;
           if (ROFF_LAYOUT != tokens[tokid].type)
                   return;
   
           assert(tokid >= 0 && tokid <= ROFF_Max);
           assert(dbg_lvl > 0);
           dbg_lvl--;
   }
   
   
 static  int  static  int
 roff_Dd(ROFFCALL_ARGS)  roff_Dd(ROFFCALL_ARGS)
 {  {
   
         assert(in);          dbg_enter(arg, ROFF_Dd);
         assert(tree);  
         assert(arg);  
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
         assert(type == ROFF_ENTER);  
   
         if (tree->last) {          assert(ROFF_PRELUDE & tree->state);
                 warnx("%s: superfluous prelude (line %zu, col %zu)",          if (ROFF_PRELUDE_Dt & tree->state ||
                                 in->name, in->line, pos);                          ROFF_PRELUDE_Dd & tree->state) {
                   warnx("%s: prelude `Dd' out-of-order (line %zu)",
                                   in->name, in->line);
                 return(0);                  return(0);
         }          }
   
         if (0 != tree->state) {          assert(NULL == tree->last);
                 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;          tree->state |= ROFF_PRELUDE_Dd;
   
         (void)printf("Dd\n");          dbg_leave(arg, ROFF_Dd);
   
         return(1);          return(1);
 }  }
Line 351  static int
Line 495  static int
 roff_Dt(ROFFCALL_ARGS)  roff_Dt(ROFFCALL_ARGS)
 {  {
   
         assert(in);          dbg_enter(arg, ROFF_Dt);
         assert(tree);  
         assert(arg);  
         assert(out);  
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
         assert(type == ROFF_ENTER);  
   
         if (tree->last) {          assert(ROFF_PRELUDE & tree->state);
                 warnx("%s: superfluous prelude (line %zu, col %zu)",  
                                 in->name, in->line, pos);  
                 return(0);  
         }  
   
         if ( ! (ROFF_PRELUDE_Dd & tree->state) ||          if ( ! (ROFF_PRELUDE_Dd & tree->state) ||
                         (ROFF_PRELUDE_Os & tree->state) ||  
                         (ROFF_PRELUDE_Dt & tree->state)) {                          (ROFF_PRELUDE_Dt & tree->state)) {
                 warnx("%s: bad manual prelude (line %zu, col %zu)",                  warnx("%s: prelude `Dt' out-of-order (line %zu)",
                                 in->name, in->line, pos);                                  in->name, in->line);
                 return(1);                  return(0);
         }          }
   
         /* TODO: parse titles from buffer. */          assert(NULL == tree->last);
   
         tree->state |= ROFF_PRELUDE_Dt;          tree->state |= ROFF_PRELUDE_Dt;
   
         (void)printf("Dt\n");          dbg_leave(arg, ROFF_Dt);
   
         return(1);          return(1);
 }  }
Line 387  roff_Dt(ROFFCALL_ARGS)
Line 517  roff_Dt(ROFFCALL_ARGS)
 static  int  static  int
 roff_Os(ROFFCALL_ARGS)  roff_Os(ROFFCALL_ARGS)
 {  {
         struct roffnode *node;  
   
         assert(arg);  
         assert(tree);  
         assert(in);  
   
         if (ROFF_EXIT == type) {          if (ROFF_EXIT == type) {
                 assert(tree->last);                  roffnode_free(ROFF_Os, tree);
                 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);                  dbg_leave(arg, ROFF_Os);
   
                 return(1);                  return(1);
         }          }
   
         assert(out);          dbg_enter(arg, ROFF_Os);
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
   
         if (tree->last) {          assert(ROFF_PRELUDE & tree->state);
                 warnx("%s: superfluous prelude (line %zu, col %zu)",          if ( ! (ROFF_PRELUDE_Dt & tree->state) ||
                                 in->name, in->line, pos);                          ! (ROFF_PRELUDE_Dd & tree->state)) {
                   warnx("%s: prelude `Os' out-of-order (line %zu)",
                                   in->name, in->line);
                 return(0);                  return(0);
         }          }
   
         if ((ROFF_PRELUDE_Os & tree->state) ||          assert(NULL == tree->last);
                         ! (ROFF_PRELUDE_Dt & tree->state) ||          if (NULL == roffnode_new(ROFF_Os, in->line, tree))
                         ! (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);                  return(0);
         }  
         node->tok = ROFF_Os;  
         node->parent = NULL;  
   
         tree->state |= ROFF_PRELUDE_Os;          tree->state |= ROFF_PRELUDE_Os;
         tree->last = node;          tree->state &= ~ROFF_PRELUDE;
           tree->state |= ROFF_BODY;
   
         dbg_enter(arg, ROFF_Os);  
   
         return(1);          return(1);
 }  }
   
   
 static  int  static int
 roff_Sh(ROFFCALL_ARGS)  roff_Sh(ROFFCALL_ARGS)
 {  {
         struct roffnode *node;  
   
         assert(arg);  
         assert(tree);  
         assert(tree->last);  
         assert(in);  
   
         if (ROFF_EXIT == type) {          if (ROFF_EXIT == type) {
                 assert(tree->last->tok == ROFF_Sh);                  roffnode_free(ROFF_Sh, tree);
   
                 node = tree->last;  
                 tree->last = node->parent;  
                 free(node);  
   
                 dbg_leave(arg, ROFF_Sh);                  dbg_leave(arg, ROFF_Sh);
   
                 return(1);                  return(1);
         }          }
   
         assert(out);          dbg_enter(arg, ROFF_Sh);
         assert(buf);  
         assert(sz > 0);  
         assert(pos > 0);  
   
         node = malloc(sizeof(struct roffnode));          if (NULL == roffnode_new(ROFF_Sh, in->line, tree))
         if (NULL == node) {  
                 warn("malloc");  
                 return(0);                  return(0);
         }  
         node->tok = ROFF_Sh;  
         node->parent = tree->last;  
   
         tree->last = node;          dbg_leave(arg, ROFF_Li);
   
         dbg_enter(arg, ROFF_Sh);  
   
         return(1);          return(1);
 }  }
   
   
 static int dbg_lvl = 0; /* FIXME: de-globalise. */  static int
   roff_Li(ROFFCALL_ARGS)
   {
   
           dbg_enter(arg, ROFF_Li);
           dbg_leave(arg, ROFF_Li);
   
 static void          return(1);
 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);  #if 0
   static int
   parse_args(void)
   {
           skip_whitespace();
   
         for (i = 0; i < dbg_lvl; i++)          while (pos < sz) {
                 (void)printf(" ");  
   
         (void)printf("%s\n", tokens[tokid].name);                  if (is_arg) {
                   } else if (parsable) {
                           if (is_callable_token()) {
                           }
                   }
   
         if (ROFF_LAYOUT == tokens[tokid].type)                  skip_whitespace();
                 dbg_lvl++;          }
 }  }
   #endif
   
   
 static void  static int
 dbg_leave(const struct md_args *args, int tokid)  roff_An(ROFFCALL_ARGS)
 {  {
         int              i;  
   
         assert(args);          dbg_enter(arg, ROFF_An);
         if ( ! (args->dbg & MD_DBG_TREE))  
                 return;  
   
         assert(tokid >= 0 && tokid <= ROFF_Max);          /* Do our ML stuff. */
         assert(dbg_lvl > 0);  
   
         dbg_lvl--;          /*parse_args();*/
         for (i = 0; i < dbg_lvl; i++)  
                 (void)printf(" ");  
   
         (void)printf("%s\n", tokens[tokid].name);          /* Do our trailing whitespace stuff. */
 }  
   
           dbg_leave(arg, ROFF_An);
   
           return(1);
   }

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

CVSweb