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

Diff for /mandoc/roff.c between version 1.3 and 1.4

version 1.3, 2008/11/24 18:34:50 version 1.4, 2008/11/25 12:14:02
Line 37  enum roffd { 
Line 37  enum roffd { 
 /* FIXME: prolog roffs can be text roffs, too. */  /* FIXME: prolog roffs can be text roffs, too. */
   
 enum    rofftype {  enum    rofftype {
         ROFF_TITLE,  
         ROFF_COMMENT,          ROFF_COMMENT,
         ROFF_TEXT,          ROFF_TEXT,
         ROFF_LAYOUT          ROFF_LAYOUT
Line 50  enum rofftype { 
Line 49  enum rofftype { 
 struct  rofftree;  struct  rofftree;
   
 struct  rofftok {  struct  rofftok {
         char             *name;  
         int             (*cb)(ROFFCALL_ARGS);          int             (*cb)(ROFFCALL_ARGS);
         enum rofftype     type;          enum rofftype     type;
         int               flags;          int               flags;
Line 61  struct rofftok {
Line 59  struct rofftok {
 };  };
   
 struct  roffarg {  struct  roffarg {
         char             *name;          int               tok;
         int               flags;          int               flags;
 #define ROFF_VALUE       (1 << 0)  #define ROFF_VALUE       (1 << 0)
 };  };
Line 75  struct roffnode {
Line 73  struct roffnode {
 struct  rofftree {  struct  rofftree {
         struct roffnode  *last;          struct roffnode  *last;
         time_t            date;          time_t            date;
         char              title[256];          char              os[64];
         char              section[256];          char              title[64];
         char              volume[256];          char              section[64];
           char              volume[64];
         int               state;          int               state;
 #define ROFF_PRELUDE     (1 << 1)  #define ROFF_PRELUDE     (1 << 1)
 #define ROFF_PRELUDE_Os  (1 << 2)  #define ROFF_PRELUDE_Os  (1 << 2)
 #define ROFF_PRELUDE_Dt  (1 << 3)  #define ROFF_PRELUDE_Dt  (1 << 3)
 #define ROFF_PRELUDE_Dd  (1 << 4)  #define ROFF_PRELUDE_Dd  (1 << 4)
 #define ROFF_BODY        (1 << 5)  #define ROFF_BODY        (1 << 5)
         struct md_mbuf  *mbuf; /* NULL if ROFF_EXIT and error. */  
   
           roffin           roffin;
           roffblkin        roffblkin;
           roffout          roffout;
           roffblkout       roffblkout;
   
           struct md_mbuf          *mbuf; /* NULL if !flush. */
         const struct md_args    *args;          const struct md_args    *args;
         const struct md_rbuf    *rbuf;          const struct md_rbuf    *rbuf;
         const roffin            *roffin;  
         const roffblkin         *roffblkin;  
         const roffout           *roffout;  
         const roffblkout        *roffblkout;  
 };  };
   
 static  int               roff_Dd(ROFFCALL_ARGS);  static  int               roff_Dd(ROFFCALL_ARGS);
Line 101  static int    roff_Os(ROFFCALL_ARGS);
Line 101  static int    roff_Os(ROFFCALL_ARGS);
 static  int               roff_layout(ROFFCALL_ARGS);  static  int               roff_layout(ROFFCALL_ARGS);
 static  int               roff_text(ROFFCALL_ARGS);  static  int               roff_text(ROFFCALL_ARGS);
   
 static  struct roffnode  *roffnode_new(int, size_t,  static  struct roffnode  *roffnode_new(int, struct rofftree *);
                                 struct rofftree *);  
 static  void              roffnode_free(int, struct rofftree *);  static  void              roffnode_free(int, struct rofftree *);
   
 static  int               rofffindtok(const char *);  static  int               rofffindtok(const char *);
Line 114  static int    textparse(const struct rofftree *,
Line 113  static int    textparse(const struct rofftree *,
                                 const char *, size_t);                                  const char *, size_t);
   
   
 static const struct rofftok tokens[ROFF_MAX] = {  static  const struct rofftok tokens[ROFF_MAX] = {
         { "\\\"",    NULL, ROFF_COMMENT, 0 },          {        NULL, ROFF_COMMENT, 0 },
         {   "Dd", roff_Dd, ROFF_TITLE, 0 },          {     roff_Dd, ROFF_TEXT, 0 },                  /* Dd */
         {   "Dt", roff_Dt, ROFF_TITLE, 0 },          {     roff_Dt, ROFF_TEXT, 0 },                  /* Dt */
         {   "Os", roff_Os, ROFF_TITLE, 0 },          {     roff_Os, ROFF_TEXT, 0 },                  /* Os */
         {   "Sh", roff_layout, ROFF_LAYOUT, ROFF_PARSED },          { roff_layout, ROFF_LAYOUT, ROFF_PARSED },      /* Sh */
         {   "An", roff_text, ROFF_TEXT, ROFF_PARSED },          { roff_layout, ROFF_LAYOUT, ROFF_PARSED },      /* Ss XXX */
         {   "Li", roff_text, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE },          { roff_layout, ROFF_LAYOUT, 0 },                /* Pp */
           { roff_layout, ROFF_LAYOUT, 0 },                /* D1 */
           { roff_layout, ROFF_LAYOUT, 0 },                /* Dl */
           { roff_layout, ROFF_LAYOUT, 0 },                /* Bd */
           { roff_layout, ROFF_LAYOUT, 0 },                /* Ed */
           { roff_layout, ROFF_LAYOUT, 0 },                /* Bl */
           { roff_layout, ROFF_LAYOUT, 0 },                /* El */
           { roff_layout, ROFF_LAYOUT, 0 },                /* It */
           {   roff_text, ROFF_TEXT, ROFF_PARSED },        /* An */
           {   roff_text, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Li */
 };  };
   
 static const struct roffarg tokenargs[ROFF_ARGMAX] = {  /* FIXME: multiple owners? */
         {  "split",     0 },  
         {  "nosplit",   0 },  static  const struct roffarg tokenargs[ROFF_ARGMAX] = {
           { ROFF_An, 0 },                         /* split */
           { ROFF_An, 0 },                         /* nosplit */
           { ROFF_Bd, 0 },                         /* ragged */
           { ROFF_Bd, 0 },                         /* unfilled */
           { ROFF_Bd, 0 },                         /* literal */
           { ROFF_Bd, ROFF_VALUE },                /* file */
           { ROFF_Bd, ROFF_VALUE },                /* offset */
           { ROFF_Bl, 0 },                         /* bullet */
           { ROFF_Bl, 0 },                         /* dash */
           { ROFF_Bl, 0 },                         /* hyphen */
           { ROFF_Bl, 0 },                         /* item */
           { ROFF_Bl, 0 },                         /* enum */
           { ROFF_Bl, 0 },                         /* tag */
           { ROFF_Bl, 0 },                         /* diag */
           { ROFF_Bl, 0 },                         /* hang */
           { ROFF_Bl, 0 },                         /* ohang */
           { ROFF_Bl, 0 },                         /* inset */
           { ROFF_Bl, 0 },                         /* column */
 };  };
   
   static  const char *const toknames[ROFF_MAX] = ROFF_NAMES;
   static  const char *const tokargnames[ROFF_ARGMAX] = ROFF_ARGNAMES;
   
   
 int  int
 roff_free(struct rofftree *tree, int flush)  roff_free(struct rofftree *tree, int flush)
 {  {
Line 161  roff_free(struct rofftree *tree, int flush)
Line 190  roff_free(struct rofftree *tree, int flush)
   
 struct rofftree *  struct rofftree *
 roff_alloc(const struct md_args *args, struct md_mbuf *out,  roff_alloc(const struct md_args *args, struct md_mbuf *out,
                 const struct md_rbuf *in,                  const struct md_rbuf *in, roffin textin,
                 const roffin *roffin, const roffout *roffout,                  roffout textout, roffblkin blkin, roffblkout blkout)
                 const roffblkin *roffblkin,  
                 const roffblkout *roffblkout)  
 {  {
         struct rofftree *tree;          struct rofftree *tree;
   
Line 177  roff_alloc(const struct md_args *args, struct md_mbuf 
Line 204  roff_alloc(const struct md_args *args, struct md_mbuf 
         tree->args = args;          tree->args = args;
         tree->mbuf = out;          tree->mbuf = out;
         tree->rbuf = in;          tree->rbuf = in;
         tree->roffin = roffin;          tree->roffin = textin;
         tree->roffout = roffout;          tree->roffout = textout;
         tree->roffblkin = roffblkin;          tree->roffblkin = blkin;
         tree->roffblkout = roffblkout;          tree->roffblkout = blkout;
   
         return(tree);          return(tree);
 }  }
Line 289  roffparse(struct rofftree *tree, char *buf, size_t sz)
Line 316  roffparse(struct rofftree *tree, char *buf, size_t sz)
   
         if ( ! roffargs(tok, buf, argv)) {          if ( ! roffargs(tok, buf, argv)) {
                 warnx("%s: too many arguments to `%s' (line %zu)",                  warnx("%s: too many arguments to `%s' (line %zu)",
                                 tree->rbuf->name, tokens[tok].name,                                  tree->rbuf->name, toknames[tok],
                                 tree->rbuf->line);                                  tree->rbuf->line);
                 return(0);                  return(0);
         }          }
   
         /* Domain cross-contamination (and sanity) checks. */  
   
         switch (tokens[tok].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)",  
                                 tree->rbuf->name, tokens[tok].name,  
                                 tree->rbuf->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)",  
                                 tree->rbuf->name, tokens[tok].name,  
                                 tree->rbuf->line);  
                 return(0);  
         case (ROFF_COMMENT):  
                 return(1);  
         default:  
                 abort();  
         }  
   
         /*          /*
          * 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,
Line 350  roffparse(struct rofftree *tree, char *buf, size_t sz)
Line 346  roffparse(struct rofftree *tree, char *buf, size_t sz)
                         warnx("%s: scope of %s (line %zu) broken by "                          warnx("%s: scope of %s (line %zu) broken by "
                                         "%s (line %zu)",                                          "%s (line %zu)",
                                         tree->rbuf->name,                                          tree->rbuf->name,
                                         tokens[tok].name,                                          toknames[tok], node->line,
                                         node->line,                                          toknames[node->tok],
                                         tokens[node->tok].name,  
                                         tree->rbuf->line);                                          tree->rbuf->line);
                         return(0);                          return(0);
                 }                  }
Line 391  rofffindarg(const char *name)
Line 386  rofffindarg(const char *name)
         /* LINTED */          /* LINTED */
         for (i = 0; i < ROFF_ARGMAX; i++)          for (i = 0; i < ROFF_ARGMAX; i++)
                 /* LINTED */                  /* LINTED */
                 if (0 == strcmp(name, tokenargs[i].name))                  if (0 == strcmp(name, tokargnames[i]))
                         return((int)i);                          return((int)i);
   
         return(ROFF_ARGMAX);          return(ROFF_ARGMAX);
Line 408  rofffindtok(const char *name)
Line 403  rofffindtok(const char *name)
         /* LINTED */          /* LINTED */
         for (i = 0; i < ROFF_MAX; i++)          for (i = 0; i < ROFF_MAX; i++)
                 /* LINTED */                  /* LINTED */
                 if (0 == strncmp(name, tokens[i].name, 2))                  if (0 == strncmp(name, toknames[i], 2))
                         return((int)i);                          return((int)i);
   
         return(ROFF_MAX);          return(ROFF_MAX);
Line 426  rofffindcallable(const char *name)
Line 421  rofffindcallable(const char *name)
 }  }
   
   
 /* FIXME: accept only struct rofftree *. */  
 static struct roffnode *  static struct roffnode *
 roffnode_new(int tokid, size_t line, struct rofftree *tree)  roffnode_new(int tokid, struct rofftree *tree)
 {  {
         struct roffnode *p;          struct roffnode *p;
   
Line 437  roffnode_new(int tokid, size_t line, struct rofftree *
Line 431  roffnode_new(int tokid, size_t line, struct rofftree *
                 return(NULL);                  return(NULL);
         }          }
   
         p->line = line;          p->line = tree->rbuf->line;
         p->tok = tokid;          p->tok = tokid;
         p->parent = tree->last;          p->parent = tree->last;
         tree->last = p;          tree->last = p;
Line 459  roffnode_free(int tokid, struct rofftree *tree)
Line 453  roffnode_free(int tokid, struct rofftree *tree)
 }  }
   
   
 /* FIXME: accept only struct rofftree *. */  
 /* ARGSUSED */  /* ARGSUSED */
 static  int  static  int
 roff_Dd(ROFFCALL_ARGS)  roff_Dd(ROFFCALL_ARGS)
 {  {
   
           if (ROFF_BODY & tree->state) {
                   assert( ! (ROFF_PRELUDE & tree->state));
                   assert(ROFF_PRELUDE_Dd & tree->state);
                   return(roff_text(tok, tree, argv, type));
           }
   
         assert(ROFF_PRELUDE & tree->state);          assert(ROFF_PRELUDE & tree->state);
         if (ROFF_PRELUDE_Dt & tree->state ||          assert( ! (ROFF_BODY & tree->state));
                         ROFF_PRELUDE_Dd & tree->state) {  
           if (ROFF_PRELUDE_Dd & tree->state ||
                           ROFF_PRELUDE_Dt & tree->state) {
                 warnx("%s: prelude `Dd' out-of-order (line %zu)",                  warnx("%s: prelude `Dd' out-of-order (line %zu)",
                                 tree->rbuf->name, tree->rbuf->line);                                  tree->rbuf->name, tree->rbuf->line);
                 return(0);                  return(0);
         }          }
   
           /* TODO: parse date. */
   
         assert(NULL == tree->last);          assert(NULL == tree->last);
         tree->state |= ROFF_PRELUDE_Dd;          tree->state |= ROFF_PRELUDE_Dd;
   
Line 485  static int
Line 488  static int
 roff_Dt(ROFFCALL_ARGS)  roff_Dt(ROFFCALL_ARGS)
 {  {
   
           if (ROFF_BODY & tree->state) {
                   assert( ! (ROFF_PRELUDE & tree->state));
                   assert(ROFF_PRELUDE_Dt & tree->state);
                   return(roff_text(tok, tree, argv, type));
           }
   
         assert(ROFF_PRELUDE & tree->state);          assert(ROFF_PRELUDE & tree->state);
           assert( ! (ROFF_BODY & tree->state));
   
         if ( ! (ROFF_PRELUDE_Dd & tree->state) ||          if ( ! (ROFF_PRELUDE_Dd & tree->state) ||
                         (ROFF_PRELUDE_Dt & tree->state)) {                          (ROFF_PRELUDE_Dt & tree->state)) {
                 warnx("%s: prelude `Dt' out-of-order (line %zu)",                  warnx("%s: prelude `Dt' out-of-order (line %zu)",
Line 493  roff_Dt(ROFFCALL_ARGS)
Line 504  roff_Dt(ROFFCALL_ARGS)
                 return(0);                  return(0);
         }          }
   
           /* TODO: parse date. */
   
         assert(NULL == tree->last);          assert(NULL == tree->last);
         tree->state |= ROFF_PRELUDE_Dt;          tree->state |= ROFF_PRELUDE_Dt;
   
Line 506  roff_Os(ROFFCALL_ARGS)
Line 519  roff_Os(ROFFCALL_ARGS)
 {  {
   
         if (ROFF_EXIT == type) {          if (ROFF_EXIT == type) {
                 roffnode_free(ROFF_Os, tree);                  assert(ROFF_PRELUDE_Os & tree->state);
                 return(1);                  return(roff_layout(tok, tree, argv, type));
         }          } else if (ROFF_BODY & tree->state) {
                   assert( ! (ROFF_PRELUDE & tree->state));
                   assert(ROFF_PRELUDE_Os & tree->state);
                   return(roff_text(tok, tree, argv, type));
           }
   
         assert(ROFF_PRELUDE & tree->state);          assert(ROFF_PRELUDE & tree->state);
         if ( ! (ROFF_PRELUDE_Dt & tree->state) ||          if ( ! (ROFF_PRELUDE_Dt & tree->state) ||
Line 518  roff_Os(ROFFCALL_ARGS)
Line 535  roff_Os(ROFFCALL_ARGS)
                 return(0);                  return(0);
         }          }
   
         assert(NULL == tree->last);          /* TODO: extract OS. */
         if (NULL == roffnode_new(ROFF_Os, tree->rbuf->line, tree))  
                 return(0);  
   
         tree->state |= ROFF_PRELUDE_Os;          tree->state |= ROFF_PRELUDE_Os;
         tree->state &= ~ROFF_PRELUDE;          tree->state &= ~ROFF_PRELUDE;
         tree->state |= ROFF_BODY;          tree->state |= ROFF_BODY;
   
         return(1);          assert(NULL == tree->last);
   
           return(roff_layout(tok, tree, argv, type));
 }  }
   
   
Line 565  roff_layout(ROFFCALL_ARGS) 
Line 582  roff_layout(ROFFCALL_ARGS) 
         int              i, c, argcp[ROFF_MAXARG];          int              i, c, argcp[ROFF_MAXARG];
         char            *v, *argvp[ROFF_MAXARG];          char            *v, *argvp[ROFF_MAXARG];
   
           if (ROFF_PRELUDE & tree->state) {
                   warnx("%s: macro `%s' called in prelude (line %zu)",
                                   tree->rbuf->name, toknames[tok],
                                   tree->rbuf->line);
                   return(0);
           }
   
         if (ROFF_EXIT == type) {          if (ROFF_EXIT == type) {
                 roffnode_free(tok, tree);                  roffnode_free(tok, tree);
                 return((*tree->roffblkout[tok])(tok));                  return((*tree->roffblkout)(tok));
         }          }
   
         i = 0;          i = 0;
Line 575  roff_layout(ROFFCALL_ARGS) 
Line 599  roff_layout(ROFFCALL_ARGS) 
                 if (ROFF_ARGMAX == c) {                  if (ROFF_ARGMAX == c) {
                         warnx("%s: error parsing `%s' args (line %zu)",                          warnx("%s: error parsing `%s' args (line %zu)",
                                         tree->rbuf->name,                                          tree->rbuf->name,
                                         tokens[tok].name,                                          toknames[tok],
                                         tree->rbuf->line);                                          tree->rbuf->line);
                         return(0);                          return(0);
                 }                  }
Line 584  roff_layout(ROFFCALL_ARGS) 
Line 608  roff_layout(ROFFCALL_ARGS) 
                 argv++;                  argv++;
         }          }
   
         if (NULL == roffnode_new(tok, tree->rbuf->line, tree))          if (NULL == roffnode_new(tok, tree))
                 return(0);                  return(0);
   
         if ( ! (*tree->roffin[tok])(tok, argcp, argvp))          if ( ! (*tree->roffin)(tok, argcp, argvp))
                 return(0);                  return(0);
   
         if ( ! (ROFF_PARSED & tokens[tok].flags)) {          if ( ! (ROFF_PARSED & tokens[tok].flags)) {
                 /* TODO: print all tokens. */                  /* TODO: print all tokens. */
   
                 if ( ! ((*tree->roffout[tok])(tok)))                  if ( ! ((*tree->roffout)(tok)))
                         return(0);                          return(0);
                 return((*tree->roffblkin[tok])(tok));                  return((*tree->roffblkin)(tok));
         }          }
   
         while (*argv) {          while (*argv) {
Line 609  roff_layout(ROFFCALL_ARGS) 
Line 633  roff_layout(ROFFCALL_ARGS) 
                 argv++;                  argv++;
         }          }
   
         if ( ! ((*tree->roffout[tok])(tok)))          if ( ! ((*tree->roffout)(tok)))
                 return(0);                  return(0);
   
         return((*tree->roffblkin[tok])(tok));          return((*tree->roffblkin)(tok));
 }  }
   
   
Line 623  roff_text(ROFFCALL_ARGS) 
Line 647  roff_text(ROFFCALL_ARGS) 
         int              i, c, argcp[ROFF_MAXARG];          int              i, c, argcp[ROFF_MAXARG];
         char            *v, *argvp[ROFF_MAXARG];          char            *v, *argvp[ROFF_MAXARG];
   
           if (ROFF_PRELUDE & tree->state) {
                   warnx("%s: macro `%s' called in prelude (line %zu)",
                                   tree->rbuf->name, toknames[tok],
                                   tree->rbuf->line);
                   return(0);
           }
   
         i = 0;          i = 0;
         while (-1 != (c = roffnextopt(&argv, &v))) {          while (-1 != (c = roffnextopt(&argv, &v))) {
                 if (ROFF_ARGMAX == c) {                  if (ROFF_ARGMAX == c) {
                         warnx("%s: error parsing `%s' args (line %zu)",                          warnx("%s: error parsing `%s' args (line %zu)",
                                         tree->rbuf->name,                                          tree->rbuf->name,
                                         tokens[tok].name,                                          toknames[tok],
                                         tree->rbuf->line);                                          tree->rbuf->line);
                         return(0);                          return(0);
                 }                  }
Line 637  roff_text(ROFFCALL_ARGS) 
Line 668  roff_text(ROFFCALL_ARGS) 
                 argv++;                  argv++;
         }          }
   
         if ( ! (*tree->roffin[tok])(tok, argcp, argvp))          if ( ! (*tree->roffin)(tok, argcp, argvp))
                 return(0);                  return(0);
   
         if ( ! (ROFF_PARSED & tokens[tok].flags)) {          if ( ! (ROFF_PARSED & tokens[tok].flags)) {
                 /* TODO: print all tokens. */                  /* TODO: print all tokens. */
                 return((*tree->roffout[tok])(tok));                  return((*tree->roffout)(tok));
         }          }
   
         while (*argv) {          while (*argv) {
Line 656  roff_text(ROFFCALL_ARGS) 
Line 687  roff_text(ROFFCALL_ARGS) 
                 argv++;                  argv++;
         }          }
   
         return((*tree->roffout[tok])(tok));          return((*tree->roffout)(tok));
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

CVSweb