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

Diff for /mandoc/roff.c between version 1.263 and 1.269

version 1.263, 2015/02/21 14:46:58 version 1.269, 2015/04/23 16:17:44
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 28 
Line 28 
   
 #include "mandoc.h"  #include "mandoc.h"
 #include "mandoc_aux.h"  #include "mandoc_aux.h"
   #include "roff.h"
 #include "libmandoc.h"  #include "libmandoc.h"
   #include "roff_int.h"
 #include "libroff.h"  #include "libroff.h"
   
 /* Maximum number of nested if-else conditionals. */  /* Maximum number of nested if-else conditionals. */
Line 37 
Line 39 
 /* Maximum number of string expansions per line, to break infinite loops. */  /* Maximum number of string expansions per line, to break infinite loops. */
 #define EXPAND_LIMIT    1000  #define EXPAND_LIMIT    1000
   
   /* --- data types --------------------------------------------------------- */
   
 enum    rofft {  enum    rofft {
         ROFF_ab,          ROFF_ab,
         ROFF_ad,          ROFF_ad,
Line 373  struct predef {
Line 377  struct predef {
 #define PREDEF(__name, __str) \  #define PREDEF(__name, __str) \
         { (__name), (__str) },          { (__name), (__str) },
   
   /* --- function prototypes ------------------------------------------------ */
   
 static  enum rofft       roffhash_find(const char *, size_t);  static  enum rofft       roffhash_find(const char *, size_t);
 static  void             roffhash_init(void);  static  void             roffhash_init(void);
 static  void             roffnode_cleanscope(struct roff *);  static  void             roffnode_cleanscope(struct roff *);
Line 412  static const char *roff_getstrn(const struct roff *,
Line 418  static const char *roff_getstrn(const struct roff *,
 static  enum rofferr     roff_insec(ROFF_ARGS);  static  enum rofferr     roff_insec(ROFF_ARGS);
 static  enum rofferr     roff_it(ROFF_ARGS);  static  enum rofferr     roff_it(ROFF_ARGS);
 static  enum rofferr     roff_line_ignore(ROFF_ARGS);  static  enum rofferr     roff_line_ignore(ROFF_ARGS);
   static  void             roff_man_alloc1(struct roff_man *);
   static  void             roff_man_free1(struct roff_man *);
 static  enum rofferr     roff_nr(ROFF_ARGS);  static  enum rofferr     roff_nr(ROFF_ARGS);
 static  enum rofft       roff_parse(struct roff *, char *, int *,  static  enum rofft       roff_parse(struct roff *, char *, int *,
                                 int, int);                                  int, int);
Line 435  static enum rofferr  roff_T_(ROFF_ARGS);
Line 443  static enum rofferr  roff_T_(ROFF_ARGS);
 static  enum rofferr     roff_unsupp(ROFF_ARGS);  static  enum rofferr     roff_unsupp(ROFF_ARGS);
 static  enum rofferr     roff_userdef(ROFF_ARGS);  static  enum rofferr     roff_userdef(ROFF_ARGS);
   
   /* --- constant data ------------------------------------------------------ */
   
 /* See roffhash_find() */  /* See roffhash_find() */
   
 #define ASCII_HI         126  #define ASCII_HI         126
Line 731  static int  roffit_lines;  /* number of lines to delay
Line 741  static int  roffit_lines;  /* number of lines to delay
 static  char    *roffit_macro;  /* nil-terminated macro line */  static  char    *roffit_macro;  /* nil-terminated macro line */
   
   
   /* --- request table ------------------------------------------------------ */
   
 static void  static void
 roffhash_init(void)  roffhash_init(void)
 {  {
Line 783  roffhash_find(const char *p, size_t s)
Line 795  roffhash_find(const char *p, size_t s)
         return(ROFF_MAX);          return(ROFF_MAX);
 }  }
   
   /* --- stack of request blocks -------------------------------------------- */
   
 /*  /*
  * Pop the current node off of the stack of roff instructions currently   * Pop the current node off of the stack of roff instructions currently
  * pending.   * pending.
Line 823  roffnode_push(struct roff *r, enum rofft tok, const ch
Line 837  roffnode_push(struct roff *r, enum rofft tok, const ch
         r->last = p;          r->last = p;
 }  }
   
   /* --- roff parser state data management ---------------------------------- */
   
 static void  static void
 roff_free1(struct roff *r)  roff_free1(struct roff *r)
 {  {
Line 898  roff_alloc(struct mparse *parse, const struct mchars *
Line 914  roff_alloc(struct mparse *parse, const struct mchars *
         return(r);          return(r);
 }  }
   
   /* --- syntax tree state data management ---------------------------------- */
   
   static void
   roff_man_free1(struct roff_man *man)
   {
   
           if (man->first != NULL)
                   roff_node_delete(man, man->first);
           free(man->meta.msec);
           free(man->meta.vol);
           free(man->meta.os);
           free(man->meta.arch);
           free(man->meta.title);
           free(man->meta.name);
           free(man->meta.date);
   }
   
   static void
   roff_man_alloc1(struct roff_man *man)
   {
   
           memset(&man->meta, 0, sizeof(man->meta));
           man->first = mandoc_calloc(1, sizeof(*man->first));
           man->first->type = ROFFT_ROOT;
           man->last = man->first;
           man->last_es = NULL;
           man->flags = 0;
           man->macroset = MACROSET_NONE;
           man->lastsec = man->lastnamed = SEC_NONE;
           man->next = ROFF_NEXT_CHILD;
   }
   
   void
   roff_man_reset(struct roff_man *man)
   {
   
           roff_man_free1(man);
           roff_man_alloc1(man);
   }
   
   void
   roff_man_free(struct roff_man *man)
   {
   
           roff_man_free1(man);
           free(man);
   }
   
   struct roff_man *
   roff_man_alloc(struct roff *roff, struct mparse *parse,
           const char *defos, int quick)
   {
           struct roff_man *man;
   
           man = mandoc_calloc(1, sizeof(*man));
           man->parse = parse;
           man->roff = roff;
           man->defos = defos;
           man->quick = quick;
           roff_man_alloc1(man);
           return(man);
   }
   
   /* --- syntax tree handling ----------------------------------------------- */
   
   struct roff_node *
   roff_node_alloc(struct roff_man *man, int line, int pos,
           enum roff_type type, int tok)
   {
           struct roff_node        *n;
   
           n = mandoc_calloc(1, sizeof(*n));
           n->line = line;
           n->pos = pos;
           n->tok = tok;
           n->type = type;
           n->sec = man->lastsec;
   
           if (man->flags & MDOC_SYNOPSIS)
                   n->flags |= MDOC_SYNPRETTY;
           else
                   n->flags &= ~MDOC_SYNPRETTY;
           if (man->flags & MDOC_NEWLINE)
                   n->flags |= MDOC_LINE;
           man->flags &= ~MDOC_NEWLINE;
   
           return(n);
   }
   
   void
   roff_node_append(struct roff_man *man, struct roff_node *n)
   {
   
           switch (man->next) {
           case ROFF_NEXT_SIBLING:
                   man->last->next = n;
                   n->prev = man->last;
                   n->parent = man->last->parent;
                   break;
           case ROFF_NEXT_CHILD:
                   man->last->child = n;
                   n->parent = man->last;
                   break;
           default:
                   abort();
                   /* NOTREACHED */
           }
           n->parent->nchild++;
   
           /*
            * Copy over the normalised-data pointer of our parent.  Not
            * everybody has one, but copying a null pointer is fine.
            */
   
           switch (n->type) {
           case ROFFT_BODY:
                   if (n->end != ENDBODY_NOT)
                           break;
                   /* FALLTHROUGH */
           case ROFFT_TAIL:
                   /* FALLTHROUGH */
           case ROFFT_HEAD:
                   n->norm = n->parent->norm;
                   break;
           default:
                   break;
           }
   
           if (man->macroset == MACROSET_MDOC)
                   mdoc_valid_pre(man, n);
   
           switch (n->type) {
           case ROFFT_HEAD:
                   assert(n->parent->type == ROFFT_BLOCK);
                   n->parent->head = n;
                   break;
           case ROFFT_BODY:
                   if (n->end)
                           break;
                   assert(n->parent->type == ROFFT_BLOCK);
                   n->parent->body = n;
                   break;
           case ROFFT_TAIL:
                   assert(n->parent->type == ROFFT_BLOCK);
                   n->parent->tail = n;
                   break;
           default:
                   break;
           }
           man->last = n;
   }
   
   void
   roff_word_alloc(struct roff_man *man, int line, int pos, const char *word)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, line, pos, ROFFT_TEXT, TOKEN_NONE);
           n->string = roff_strdup(man->roff, word);
           roff_node_append(man, n);
           if (man->macroset == MACROSET_MDOC)
                   mdoc_valid_post(man);
           else
                   man_valid_post(man);
           man->next = ROFF_NEXT_SIBLING;
   }
   
   void
   roff_word_append(struct roff_man *man, const char *word)
   {
           struct roff_node        *n;
           char                    *addstr, *newstr;
   
           n = man->last;
           addstr = roff_strdup(man->roff, word);
           mandoc_asprintf(&newstr, "%s %s", n->string, addstr);
           free(addstr);
           free(n->string);
           n->string = newstr;
           man->next = ROFF_NEXT_SIBLING;
   }
   
   void
   roff_elem_alloc(struct roff_man *man, int line, int pos, int tok)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, line, pos, ROFFT_ELEM, tok);
           roff_node_append(man, n);
           man->next = ROFF_NEXT_CHILD;
   }
   
   struct roff_node *
   roff_block_alloc(struct roff_man *man, int line, int pos, int tok)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, line, pos, ROFFT_BLOCK, tok);
           roff_node_append(man, n);
           man->next = ROFF_NEXT_CHILD;
           return(n);
   }
   
   struct roff_node *
   roff_head_alloc(struct roff_man *man, int line, int pos, int tok)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, line, pos, ROFFT_HEAD, tok);
           roff_node_append(man, n);
           man->next = ROFF_NEXT_CHILD;
           return(n);
   }
   
   struct roff_node *
   roff_body_alloc(struct roff_man *man, int line, int pos, int tok)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, line, pos, ROFFT_BODY, tok);
           roff_node_append(man, n);
           man->next = ROFF_NEXT_CHILD;
           return(n);
   }
   
   void
   roff_addeqn(struct roff_man *man, const struct eqn *eqn)
   {
           struct roff_node        *n;
   
           n = roff_node_alloc(man, eqn->ln, eqn->pos, ROFFT_EQN, TOKEN_NONE);
           n->eqn = eqn;
           if (eqn->ln > man->last->line)
                   n->flags |= MDOC_LINE;
           roff_node_append(man, n);
           man->next = ROFF_NEXT_SIBLING;
   }
   
   void
   roff_addtbl(struct roff_man *man, const struct tbl_span *tbl)
   {
           struct roff_node        *n;
   
           if (man->macroset == MACROSET_MAN)
                   man_breakscope(man, TOKEN_NONE);
           n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE);
           n->span = tbl;
           roff_node_append(man, n);
           if (man->macroset == MACROSET_MDOC)
                   mdoc_valid_post(man);
           else
                   man_valid_post(man);
           man->next = ROFF_NEXT_SIBLING;
   }
   
   void
   roff_node_unlink(struct roff_man *man, struct roff_node *n)
   {
   
           /* Adjust siblings. */
   
           if (n->prev)
                   n->prev->next = n->next;
           if (n->next)
                   n->next->prev = n->prev;
   
           /* Adjust parent. */
   
           if (n->parent != NULL) {
                   n->parent->nchild--;
                   if (n->parent->child == n)
                           n->parent->child = n->next;
                   if (n->parent->last == n)
                           n->parent->last = n->prev;
           }
   
           /* Adjust parse point. */
   
           if (man == NULL)
                   return;
           if (man->last == n) {
                   if (n->prev == NULL) {
                           man->last = n->parent;
                           man->next = ROFF_NEXT_CHILD;
                   } else {
                           man->last = n->prev;
                           man->next = ROFF_NEXT_SIBLING;
                   }
           }
           if (man->first == n)
                   man->first = NULL;
   }
   
   void
   roff_node_free(struct roff_node *n)
   {
   
           if (n->args != NULL)
                   mdoc_argv_free(n->args);
           if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM)
                   free(n->norm);
           free(n->string);
           free(n);
   }
   
   void
   roff_node_delete(struct roff_man *man, struct roff_node *n)
   {
   
           while (n->child != NULL)
                   roff_node_delete(man, n->child);
           assert(n->nchild == 0);
           roff_node_unlink(man, n);
           roff_node_free(n);
   }
   
   void
   deroff(char **dest, const struct roff_node *n)
   {
           char    *cp;
           size_t   sz;
   
           if (n->type != ROFFT_TEXT) {
                   for (n = n->child; n != NULL; n = n->next)
                           deroff(dest, n);
                   return;
           }
   
           /* Skip leading whitespace and escape sequences. */
   
           cp = n->string;
           while (*cp != '\0') {
                   if ('\\' == *cp) {
                           cp++;
                           mandoc_escape((const char **)&cp, NULL, NULL);
                   } else if (isspace((unsigned char)*cp))
                           cp++;
                   else
                           break;
           }
   
           /* Skip trailing whitespace. */
   
           for (sz = strlen(cp); sz; sz--)
                   if ( ! isspace((unsigned char)cp[sz-1]))
                           break;
   
           /* Skip empty strings. */
   
           if (sz == 0)
                   return;
   
           if (*dest == NULL) {
                   *dest = mandoc_strndup(cp, sz);
                   return;
           }
   
           mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp);
           free(*dest);
           *dest = cp;
   }
   
   /* --- main functions of the roff parser ---------------------------------- */
   
 /*  /*
  * In the current line, expand escape sequences that tend to get   * In the current line, expand escape sequences that tend to get
  * used in numerical expressions and conditional requests.   * used in numerical expressions and conditional requests.
Line 1128  roff_parsetext(struct buf *buf, int pos, int *offs)
Line 1508  roff_parsetext(struct buf *buf, int pos, int *offs)
                         esc = mandoc_escape((const char **)&p, NULL, NULL);                          esc = mandoc_escape((const char **)&p, NULL, NULL);
                         if (esc == ESCAPE_ERROR)                          if (esc == ESCAPE_ERROR)
                                 break;                                  break;
                           while (*p == '-')
                                   p++;
                         continue;                          continue;
                 } else if (p == start) {                  } else if (p == start) {
                         p++;                          p++;
Line 1315  roff_parse(struct roff *r, char *buf, int *pos, int ln
Line 1697  roff_parse(struct roff *r, char *buf, int *pos, int ln
         return(t);          return(t);
 }  }
   
   /* --- handling of request blocks ----------------------------------------- */
   
 static enum rofferr  static enum rofferr
 roff_cblock(ROFF_ARGS)  roff_cblock(ROFF_ARGS)
 {  {
Line 1625  roff_cond_text(ROFF_ARGS)
Line 2009  roff_cond_text(ROFF_ARGS)
         return(rr ? ROFF_CONT : ROFF_IGN);          return(rr ? ROFF_CONT : ROFF_IGN);
 }  }
   
   /* --- handling of numeric and conditional expressions -------------------- */
   
 /*  /*
  * Parse a single signed integer number.  Stop at the first non-digit.   * Parse a single signed integer number.  Stop at the first non-digit.
  * If there is at least one digit, return success and advance the   * If there is at least one digit, return success and advance the
Line 2142  roff_evalnum(struct roff *r, int ln, const char *v,
Line 2528  roff_evalnum(struct roff *r, int ln, const char *v,
         return(1);          return(1);
 }  }
   
   /* --- register management ------------------------------------------------ */
   
 void  void
 roff_setreg(struct roff *r, const char *name, int val, char sign)  roff_setreg(struct roff *r, const char *name, int val, char sign)
 {  {
Line 2306  roff_rr(ROFF_ARGS)
Line 2694  roff_rr(ROFF_ARGS)
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
   /* --- handler functions for roff requests -------------------------------- */
   
 static enum rofferr  static enum rofferr
 roff_rm(ROFF_ARGS)  roff_rm(ROFF_ARGS)
 {  {
Line 2650  roff_so(ROFF_ARGS)
Line 3040  roff_so(ROFF_ARGS)
         return(ROFF_SO);          return(ROFF_SO);
 }  }
   
   /* --- user defined strings and macros ------------------------------------ */
   
 static enum rofferr  static enum rofferr
 roff_userdef(ROFF_ARGS)  roff_userdef(ROFF_ARGS)
 {  {
Line 2917  roff_freestr(struct roffkv *r)
Line 3309  roff_freestr(struct roffkv *r)
                 free(n);                  free(n);
         }          }
 }  }
   
   /* --- accessors and utility functions ------------------------------------ */
   
 const struct tbl_span *  const struct tbl_span *
 roff_span(const struct roff *r)  roff_span(const struct roff *r)

Legend:
Removed from v.1.263  
changed lines
  Added in v.1.269

CVSweb