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

Diff for /mandoc/roff.c between version 1.135 and 1.142

version 1.135, 2011/04/17 09:08:19 version 1.142, 2011/05/26 11:58:25
Line 20 
Line 20 
 #endif  #endif
   
 #include <assert.h>  #include <assert.h>
 #include <errno.h>  
 #include <ctype.h>  #include <ctype.h>
 #include <limits.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <stdio.h>  
   
 #include "mandoc.h"  #include "mandoc.h"
 #include "libroff.h"  #include "libroff.h"
 #include "libmandoc.h"  #include "libmandoc.h"
   
   /* Maximum number of nested if-else conditionals. */
 #define RSTACK_MAX      128  #define RSTACK_MAX      128
   
 enum    rofft {  enum    rofft {
Line 63  enum rofft {
Line 61  enum rofft {
         ROFF_EQ,          ROFF_EQ,
         ROFF_EN,          ROFF_EN,
         ROFF_cblock,          ROFF_cblock,
         ROFF_ccond, /* FIXME: remove this. */          ROFF_ccond,
         ROFF_USERDEF,          ROFF_USERDEF,
         ROFF_MAX          ROFF_MAX
 };  };
Line 127  struct roffmac {
Line 125  struct roffmac {
         struct roffmac  *next;          struct roffmac  *next;
 };  };
   
   struct  predef {
           const char      *name; /* predefined input name */
           const char      *str; /* replacement symbol */
   };
   
   #define PREDEF(__name, __str) \
           { (__name), (__str) },
   
 static  enum rofferr     roff_block(ROFF_ARGS);  static  enum rofferr     roff_block(ROFF_ARGS);
 static  enum rofferr     roff_block_text(ROFF_ARGS);  static  enum rofferr     roff_block_text(ROFF_ARGS);
 static  enum rofferr     roff_block_sub(ROFF_ARGS);  static  enum rofferr     roff_block_sub(ROFF_ARGS);
Line 144  static const char *roff_getstrn(const struct roff *, 
Line 150  static const char *roff_getstrn(const struct roff *, 
 static  enum rofferr     roff_line_ignore(ROFF_ARGS);  static  enum rofferr     roff_line_ignore(ROFF_ARGS);
 static  enum rofferr     roff_nr(ROFF_ARGS);  static  enum rofferr     roff_nr(ROFF_ARGS);
 static  int              roff_res(struct roff *,  static  int              roff_res(struct roff *,
                                 char **, size_t *, int);                                  char **, size_t *, int, int);
 static  enum rofferr     roff_rm(ROFF_ARGS);  static  enum rofferr     roff_rm(ROFF_ARGS);
 static  void             roff_setstr(struct roff *,  static  void             roff_setstr(struct roff *,
                                 const char *, const char *, int);                                  const char *, const char *, int);
Line 198  static struct roffmac  roffs[ROFF_MAX] = {
Line 204  static struct roffmac  roffs[ROFF_MAX] = {
         { NULL, roff_userdef, NULL, NULL, 0, NULL },          { NULL, roff_userdef, NULL, NULL, 0, NULL },
 };  };
   
   /* Array of injected predefined strings. */
   #define PREDEFS_MAX      38
   static  const struct predef predefs[PREDEFS_MAX] = {
   #include "predefs.in"
   };
   
 static  void             roff_free1(struct roff *);  static  void             roff_free1(struct roff *);
 static  enum rofft       roff_hash_find(const char *, size_t);  static  enum rofft       roff_hash_find(const char *, size_t);
 static  void             roff_hash_init(void);  static  void             roff_hash_init(void);
Line 206  static void   roffnode_push(struct roff *, enum rofft,
Line 218  static void   roffnode_push(struct roff *, enum rofft,
                                 const char *, int, int);                                  const char *, int, int);
 static  void             roffnode_pop(struct roff *);  static  void             roffnode_pop(struct roff *);
 static  enum rofft       roff_parse(struct roff *, const char *, int *);  static  enum rofft       roff_parse(struct roff *, const char *, int *);
 static  int              roff_parse_nat(const char *, unsigned int *);  
   
 /* See roff_hash_find() */  /* See roff_hash_find() */
 #define ROFF_HASH(p)    (p[0] - ASCII_LO)  #define ROFF_HASH(p)    (p[0] - ASCII_LO)
Line 232  roff_hash_init(void)
Line 243  roff_hash_init(void)
         }          }
 }  }
   
   
 /*  /*
  * Look up a roff token by its name.  Returns ROFF_MAX if no macro by   * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
  * the nil-terminated string name could be found.   * the nil-terminated string name could be found.
Line 355  struct roff *
Line 365  struct roff *
 roff_alloc(struct regset *regs, struct mparse *parse)  roff_alloc(struct regset *regs, struct mparse *parse)
 {  {
         struct roff     *r;          struct roff     *r;
           int              i;
   
         r = mandoc_calloc(1, sizeof(struct roff));          r = mandoc_calloc(1, sizeof(struct roff));
         r->regs = regs;          r->regs = regs;
Line 362  roff_alloc(struct regset *regs, struct mparse *parse)
Line 373  roff_alloc(struct regset *regs, struct mparse *parse)
         r->rstackpos = -1;          r->rstackpos = -1;
   
         roff_hash_init();          roff_hash_init();
   
           for (i = 0; i < PREDEFS_MAX; i++)
                   roff_setstr(r, predefs[i].name, predefs[i].str, 0);
   
         return(r);          return(r);
 }  }
   
Line 372  roff_alloc(struct regset *regs, struct mparse *parse)
Line 387  roff_alloc(struct regset *regs, struct mparse *parse)
  * is processed.   * is processed.
  */   */
 static int  static int
 roff_res(struct roff *r, char **bufp, size_t *szp, int pos)  roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
 {  {
         const char      *stesc; /* start of an escape sequence ('\\') */          const char      *stesc; /* start of an escape sequence ('\\') */
         const char      *stnam; /* start of the name, after "[(*" */          const char      *stnam; /* start of the name, after "[(*" */
Line 439  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 454  roff_res(struct roff *r, char **bufp, size_t *szp, int
                 res = roff_getstrn(r, stnam, (size_t)i);                  res = roff_getstrn(r, stnam, (size_t)i);
   
                 if (NULL == res) {                  if (NULL == res) {
                         cp -= maxl ? 1 : 0;                          /* TODO: keep track of the correct position. */
                         continue;                          mandoc_msg(MANDOCERR_BADESCAPE, r->parse, ln, pos, NULL);
                           res = "";
                 }                  }
   
                 /* Replace the escape sequence by the string. */                  /* Replace the escape sequence by the string. */
Line 476  roff_parseln(struct roff *r, int ln, char **bufp, 
Line 492  roff_parseln(struct roff *r, int ln, char **bufp, 
          * words to fill in.           * words to fill in.
          */           */
   
         if (r->first_string && ! roff_res(r, bufp, szp, pos))          if (r->first_string && ! roff_res(r, bufp, szp, ln, pos))
                 return(ROFF_REPARSE);                  return(ROFF_REPARSE);
   
         ppos = pos;          ppos = pos;
Line 593  roff_parse(struct roff *r, const char *buf, int *pos)
Line 609  roff_parse(struct roff *r, const char *buf, int *pos)
         return(t);          return(t);
 }  }
   
   
 static int  
 roff_parse_nat(const char *buf, unsigned int *res)  
 {  
         char            *ep;  
         long             lval;  
   
         errno = 0;  
         lval = strtol(buf, &ep, 10);  
         if (buf[0] == '\0' || *ep != '\0')  
                 return(0);  
         if ((errno == ERANGE &&  
                         (lval == LONG_MAX || lval == LONG_MIN)) ||  
                         (lval > INT_MAX || lval < 0))  
                 return(0);  
   
         *res = (unsigned int)lval;  
         return(1);  
 }  
   
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_cblock(ROFF_ARGS)  roff_cblock(ROFF_ARGS)
Line 829  roff_block_sub(ROFF_ARGS)
Line 824  roff_block_sub(ROFF_ARGS)
          * pulling it out of the hashtable.           * pulling it out of the hashtable.
          */           */
   
         if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))          t = roff_parse(r, *bufp, &pos);
                 return(ROFF_IGN);  
   
         /*          /*
          * Macros other than block-end are only significant           * Macros other than block-end are only significant
Line 866  roff_cond_sub(ROFF_ARGS)
Line 860  roff_cond_sub(ROFF_ARGS)
 {  {
         enum rofft       t;          enum rofft       t;
         enum roffrule    rr;          enum roffrule    rr;
           char            *ep;
   
         rr = r->last->rule;          rr = r->last->rule;
           roffnode_cleanscope(r);
   
         /*          /*
          * Clean out scope.  If we've closed ourselves, then don't           * If the macro is unknown, first check if it contains a closing
          * continue.           * delimiter `\}'.  If it does, close out our scope and return
            * the currently-scoped rule (ignore or continue).  Else, drop
            * into the currently-scoped rule.
          */           */
   
         roffnode_cleanscope(r);  
   
         if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) {          if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) {
                 if ('\\' == (*bufp)[pos] && '}' == (*bufp)[pos + 1])                  ep = &(*bufp)[pos];
                         return(roff_ccond                  for ( ; NULL != (ep = strchr(ep, '\\')); ep++) {
                                 (r, ROFF_ccond, bufp, szp,                          ep++;
                                  ln, pos, pos + 2, offs));                          if ('}' != *ep)
                                   continue;
                           *ep = '&';
                           roff_ccond(r, ROFF_ccond, bufp, szp,
                                           ln, pos, pos + 2, offs);
                           break;
                   }
                 return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);                  return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
         }          }
   
Line 889  roff_cond_sub(ROFF_ARGS)
Line 891  roff_cond_sub(ROFF_ARGS)
          * if they're either structurally required (such as loops and           * if they're either structurally required (such as loops and
          * conditionals) or a closing macro.           * conditionals) or a closing macro.
          */           */
   
         if (ROFFRULE_DENY == rr)          if (ROFFRULE_DENY == rr)
                 if ( ! (ROFFMAC_STRUCT & roffs[t].flags))                  if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
                         if (ROFF_ccond != t)                          if (ROFF_ccond != t)
Line 899  roff_cond_sub(ROFF_ARGS)
Line 902  roff_cond_sub(ROFF_ARGS)
                                 ln, ppos, pos, offs));                                  ln, ppos, pos, offs));
 }  }
   
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_cond_text(ROFF_ARGS)  roff_cond_text(ROFF_ARGS)
 {  {
         char            *ep, *st;          char            *ep;
         enum roffrule    rr;          enum roffrule    rr;
   
         rr = r->last->rule;          rr = r->last->rule;
           roffnode_cleanscope(r);
   
         /*          ep = &(*bufp)[pos];
          * We display the value of the text if out current evaluation          for ( ; NULL != (ep = strchr(ep, '\\')); ep++) {
          * scope permits us to do so.                  ep++;
          */                  if ('}' != *ep)
                           continue;
         /* FIXME: use roff_ccond? */                  *ep = '&';
                   roff_ccond(r, ROFF_ccond, bufp, szp,
         st = &(*bufp)[pos];                                  ln, pos, pos + 2, offs);
         if (NULL == (ep = strstr(st, "\\}"))) {  
                 roffnode_cleanscope(r);  
                 return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);  
         }          }
   
         if (ep == st || (ep > st && '\\' != *(ep - 1)))  
                 roffnode_pop(r);  
   
         roffnode_cleanscope(r);  
         return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);          return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }  }
   
   
 static enum roffrule  static enum roffrule
 roff_evalcond(const char *v, int *pos)  roff_evalcond(const char *v, int *pos)
 {  {
Line 1091  roff_nr(ROFF_ARGS)
Line 1085  roff_nr(ROFF_ARGS)
 {  {
         const char      *key;          const char      *key;
         char            *val;          char            *val;
           int              iv;
         struct reg      *rg;          struct reg      *rg;
   
         val = *bufp + pos;          val = *bufp + pos;
Line 1099  roff_nr(ROFF_ARGS)
Line 1094  roff_nr(ROFF_ARGS)
   
         if (0 == strcmp(key, "nS")) {          if (0 == strcmp(key, "nS")) {
                 rg[(int)REG_nS].set = 1;                  rg[(int)REG_nS].set = 1;
                 if ( ! roff_parse_nat(val, &rg[(int)REG_nS].v.u))                  if ((iv = mandoc_strntou(val, strlen(val), 10)) >= 0)
                         rg[(int)REG_nS].v.u = 0;                          rg[REG_nS].v.u = (unsigned)iv;
                   else
                           rg[(int)REG_nS].v.u = 0u;
         }          }
   
         return(ROFF_IGN);          return(ROFF_IGN);
Line 1238  roff_userdef(ROFF_ARGS)
Line 1235  roff_userdef(ROFF_ARGS)
         cp = *bufp + pos;          cp = *bufp + pos;
         for (i = 0; i < 9; i++)          for (i = 0; i < 9; i++)
                 arg[i] = '\0' == *cp ? "" :                  arg[i] = '\0' == *cp ? "" :
                     mandoc_getarg(r->parse, &cp, ln, 1, &pos);                      mandoc_getarg(r->parse, &cp, ln, &pos);
   
         /*          /*
          * Expand macro arguments.           * Expand macro arguments.

Legend:
Removed from v.1.135  
changed lines
  Added in v.1.142

CVSweb