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

Diff for /mandoc/main.c between version 1.134 and 1.150

version 1.134, 2011/01/04 12:06:21 version 1.150, 2011/03/15 16:23:51
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010, 2011 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
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 42 
Line 42 
 #endif  #endif
   
 #define REPARSE_LIMIT   1000  #define REPARSE_LIMIT   1000
 #define UNCONST(a)      ((void *)(uintptr_t)(const void *)(a))  
   
 /* FIXME: Intel's compiler?  LLVM?  pcc?  */  /* FIXME: Intel's compiler?  LLVM?  pcc?  */
   
Line 78  enum outt {
Line 77  enum outt {
 };  };
   
 struct  curparse {  struct  curparse {
         const char       *file;         /* Current parse. */          const char       *file;         /* current file-name */
         int               fd;           /* Current parse. */          enum mandoclevel  file_status;  /* error status of current parse */
         int               line;         /* Line number in the file. */          int               fd;           /* current file-descriptor */
         enum mandoclevel  wlevel;       /* Ignore messages below this. */          int               line;         /* line number in the file */
         int               wstop;        /* Stop after a file with a warning. */          enum mandoclevel  wlevel;       /* ignore messages below this */
           int               wstop;        /* stop after a file with a warning */
         enum intt         inttype;      /* which parser to use */          enum intt         inttype;      /* which parser to use */
         struct man       *pman;         /* persistent man parser */          struct man       *pman;         /* persistent man parser */
         struct mdoc      *pmdoc;        /* persistent mdoc parser */          struct mdoc      *pmdoc;        /* persistent mdoc parser */
Line 128  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 128  static const char * const mandocerrs[MANDOCERR_MAX] = 
         "no title in document",          "no title in document",
         "document title should be all caps",          "document title should be all caps",
         "unknown manual section",          "unknown manual section",
         "cannot parse date argument",          "date missing, using today's date",
           "cannot parse date, using it verbatim",
         "prologue macros out of order",          "prologue macros out of order",
         "duplicate prologue macro",          "duplicate prologue macro",
         "macro not allowed in prologue",          "macro not allowed in prologue",
Line 146  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 147  static const char * const mandocerrs[MANDOCERR_MAX] = 
         /* related to macros and nesting */          /* related to macros and nesting */
         "skipping obsolete macro",          "skipping obsolete macro",
         "skipping paragraph macro",          "skipping paragraph macro",
           "skipping no-space macro",
         "blocks badly nested",          "blocks badly nested",
         "child violates parent syntax",          "child violates parent syntax",
         "nested displays are not portable",          "nested displays are not portable",
Line 158  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 160  static const char * const mandocerrs[MANDOCERR_MAX] = 
         "list type must come first",          "list type must come first",
         "tag lists require a width argument",          "tag lists require a width argument",
         "missing font type",          "missing font type",
           "skipping end of block that is not open",
   
         /* related to bad macro arguments */          /* related to bad macro arguments */
         "skipping argument",          "skipping argument",
Line 178  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 181  static const char * const mandocerrs[MANDOCERR_MAX] = 
         "unknown escape sequence",          "unknown escape sequence",
         "unterminated quoted string",          "unterminated quoted string",
   
         /* related to tables */  
         "extra data cells",  
   
         "generic error",          "generic error",
   
         /* related to tables */          /* related to tables */
Line 190  static const char * const mandocerrs[MANDOCERR_MAX] = 
Line 190  static const char * const mandocerrs[MANDOCERR_MAX] = 
         "no table layout cells specified",          "no table layout cells specified",
         "no table data cells specified",          "no table data cells specified",
         "ignore data in cell",          "ignore data in cell",
           "data block still open",
           "ignoring extra data cells",
   
         "input stack limit exceeded, infinite loop?",          "input stack limit exceeded, infinite loop?",
         "skipping bad character",          "skipping bad character",
           "escaped character not allowed in a name",
         "skipping text before the first section header",          "skipping text before the first section header",
         "skipping unknown macro",          "skipping unknown macro",
         "NOT IMPLEMENTED: skipping request",          "NOT IMPLEMENTED, please use groff: skipping request",
         "line scope broken",          "line scope broken",
         "argument count wrong",          "argument count wrong",
         "skipping end of block that is not open",          "skipping end of block that is not open",
Line 238  static void    version(void) __attribute__((noreturn))
Line 241  static void    version(void) __attribute__((noreturn))
 static  int               woptions(struct curparse *, char *);  static  int               woptions(struct curparse *, char *);
   
 static  const char       *progname;  static  const char       *progname;
 static  enum mandoclevel  file_status = MANDOCLEVEL_OK;  
 static  enum mandoclevel  exit_status = MANDOCLEVEL_OK;  static  enum mandoclevel  exit_status = MANDOCLEVEL_OK;
   
 int  int
Line 375  pfile(const char *file, struct curparse *curp)
Line 377  pfile(const char *file, struct curparse *curp)
   
         if (-1 == (fd = open(file, O_RDONLY, 0))) {          if (-1 == (fd = open(file, O_RDONLY, 0))) {
                 perror(file);                  perror(file);
                 file_status = MANDOCLEVEL_SYSERR;                  curp->file_status = MANDOCLEVEL_SYSERR;
                 return(0);                  return(0);
         }          }
   
Line 393  pfile(const char *file, struct curparse *curp)
Line 395  pfile(const char *file, struct curparse *curp)
         if (-1 == close(fd))          if (-1 == close(fd))
                 perror(file);                  perror(file);
   
         return(MANDOCLEVEL_FATAL > file_status ? 1 : 0);          return(MANDOCLEVEL_FATAL > curp->file_status ? 1 : 0);
 }  }
   
   
Line 497  fdesc(struct curparse *curp)
Line 499  fdesc(struct curparse *curp)
   
         curp->mdoc = NULL;          curp->mdoc = NULL;
         curp->man = NULL;          curp->man = NULL;
         file_status = MANDOCLEVEL_OK;          curp->file_status = MANDOCLEVEL_OK;
   
         /* Make sure the mandotory roff parser is initialised. */          /* Make sure the mandotory roff parser is initialised. */
   
Line 510  fdesc(struct curparse *curp)
Line 512  fdesc(struct curparse *curp)
   
         pdesc(curp);          pdesc(curp);
   
         if (MANDOCLEVEL_FATAL <= file_status)          if (MANDOCLEVEL_FATAL <= curp->file_status)
                 goto cleanup;                  goto cleanup;
   
         /* NOTE a parser may not have been assigned, yet. */          /* NOTE a parser may not have been assigned, yet. */
   
         if ( ! (curp->man || curp->mdoc)) {          if ( ! (curp->man || curp->mdoc)) {
                 fprintf(stderr, "%s: Not a manual\n", curp->file);                  fprintf(stderr, "%s: Not a manual\n", curp->file);
                 file_status = MANDOCLEVEL_FATAL;                  curp->file_status = MANDOCLEVEL_FATAL;
                 goto cleanup;                  goto cleanup;
         }          }
   
         /* Clean up the parse routine ASTs. */          /* Clean up the parse routine ASTs. */
   
         if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {          if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
                 assert(MANDOCLEVEL_FATAL <= file_status);                  assert(MANDOCLEVEL_FATAL <= curp->file_status);
                 goto cleanup;                  goto cleanup;
         }          }
   
         if (curp->man && ! man_endparse(curp->man)) {          if (curp->man && ! man_endparse(curp->man)) {
                 assert(MANDOCLEVEL_FATAL <= file_status);                  assert(MANDOCLEVEL_FATAL <= curp->file_status);
                 goto cleanup;                  goto cleanup;
         }          }
   
Line 541  fdesc(struct curparse *curp)
Line 543  fdesc(struct curparse *curp)
          * the requested level, do not produce output.           * the requested level, do not produce output.
          */           */
   
         if (MANDOCLEVEL_OK != file_status && curp->wstop)          if (MANDOCLEVEL_OK != curp->file_status && curp->wstop)
                 goto cleanup;                  goto cleanup;
   
         /* If unset, allocate output dev now (if applicable). */          /* If unset, allocate output dev now (if applicable). */
Line 616  fdesc(struct curparse *curp)
Line 618  fdesc(struct curparse *curp)
         assert(curp->roff);          assert(curp->roff);
         roff_reset(curp->roff);          roff_reset(curp->roff);
   
         if (exit_status < file_status)          if (exit_status < curp->file_status)
                 exit_status = file_status;                  exit_status = curp->file_status;
   
         return;          return;
 }  }
Line 636  pdesc(struct curparse *curp)
Line 638  pdesc(struct curparse *curp)
          */           */
   
         if ( ! read_whole_file(curp, &blk, &with_mmap)) {          if ( ! read_whole_file(curp, &blk, &with_mmap)) {
                 file_status = MANDOCLEVEL_SYSERR;                  curp->file_status = MANDOCLEVEL_SYSERR;
                 return;                  return;
         }          }
   
Line 652  pdesc(struct curparse *curp)
Line 654  pdesc(struct curparse *curp)
                 free(blk.buf);                  free(blk.buf);
 }  }
   
   /*
    * Main parse routine for an opened file.  This is called for each
    * opened file and simply loops around the full input file, possibly
    * nesting (i.e., with `so').
    */
 static void  static void
 parsebuf(struct curparse *curp, struct buf blk, int start)  parsebuf(struct curparse *curp, struct buf blk, int start)
 {  {
           const struct tbl_span   *span;
         struct buf       ln;          struct buf       ln;
         enum rofferr     rr;          enum rofferr     rr;
         int              i, of, rc;          int              i, of, rc;
Line 662  parsebuf(struct curparse *curp, struct buf blk, int st
Line 670  parsebuf(struct curparse *curp, struct buf blk, int st
         int              lnn; /* line number in the real file */          int              lnn; /* line number in the real file */
         unsigned char    c;          unsigned char    c;
   
         /*  
          * Main parse routine for an opened file.  This is called for  
          * each opened file and simply loops around the full input file,  
          * possibly nesting (i.e., with `so').  
          */  
   
         memset(&ln, 0, sizeof(struct buf));          memset(&ln, 0, sizeof(struct buf));
   
         lnn = curp->line;          lnn = curp->line;
Line 683  parsebuf(struct curparse *curp, struct buf blk, int st
Line 685  parsebuf(struct curparse *curp, struct buf blk, int st
                 }                  }
   
                 while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {                  while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
   
                           /*
                            * When finding an unescaped newline character,
                            * leave the character loop to process the line.
                            * Skip a preceding carriage return, if any.
                            */
   
                           if ('\r' == blk.buf[i] && i + 1 < (int)blk.sz &&
                               '\n' == blk.buf[i + 1])
                                   ++i;
                         if ('\n' == blk.buf[i]) {                          if ('\n' == blk.buf[i]) {
                                 ++i;                                  ++i;
                                 ++lnn;                                  ++lnn;
Line 717  parsebuf(struct curparse *curp, struct buf blk, int st
Line 729  parsebuf(struct curparse *curp, struct buf blk, int st
                                 continue;                                  continue;
                         }                          }
   
                         /* Found escape & at least one other char. */                          /*
                            * Found escape and at least one other character.
                            * When it's a newline character, skip it.
                            * When there is a carriage return in between,
                            * skip that one as well.
                            */
   
                           if ('\r' == blk.buf[i + 1] && i + 2 < (int)blk.sz &&
                               '\n' == blk.buf[i + 2])
                                   ++i;
                         if ('\n' == blk.buf[i + 1]) {                          if ('\n' == blk.buf[i + 1]) {
                                 i += 2;                                  i += 2;
                                 /* Escaped newlines are skipped over */  
                                 ++lnn;                                  ++lnn;
                                 continue;                                  continue;
                         }                          }
Line 787  rerun:
Line 806  rerun:
                         pos = 0;                          pos = 0;
                         continue;                          continue;
                 case (ROFF_APPEND):                  case (ROFF_APPEND):
                         pos = strlen(ln.buf);                          pos = (int)strlen(ln.buf);
                         continue;                          continue;
                 case (ROFF_RERUN):                  case (ROFF_RERUN):
                         goto rerun;                          goto rerun;
Line 795  rerun:
Line 814  rerun:
                         pos = 0;                          pos = 0;
                         continue;                          continue;
                 case (ROFF_ERR):                  case (ROFF_ERR):
                         assert(MANDOCLEVEL_FATAL <= file_status);                          assert(MANDOCLEVEL_FATAL <= curp->file_status);
                         break;                          break;
                 case (ROFF_SO):                  case (ROFF_SO):
                         if (pfile(ln.buf + of, curp)) {                          if (pfile(ln.buf + of, curp)) {
Line 812  rerun:
Line 831  rerun:
                  * call, make sure we don't continue parsing.                   * call, make sure we don't continue parsing.
                  */                   */
   
                 if (MANDOCLEVEL_FATAL <= file_status)                  if (MANDOCLEVEL_FATAL <= curp->file_status)
                         break;                          break;
   
                 /*                  /*
Line 833  rerun:
Line 852  rerun:
                  * currently open parse.  Since we only get here if                   * currently open parse.  Since we only get here if
                  * there does exist data (see tbl_data.c), we're                   * there does exist data (see tbl_data.c), we're
                  * guaranteed that something's been allocated.                   * guaranteed that something's been allocated.
                    * Do the same for ROFF_EQN.
                  */                   */
   
                 if (ROFF_TBL == rr) {                  rc = -1;
                         assert(curp->man || curp->mdoc);  
                         if (curp->man)  
                                 man_addspan(curp->man, roff_span(curp->roff));  
                         else  
                                 mdoc_addspan(curp->mdoc, roff_span(curp->roff));  
   
                 } else if (curp->man || curp->mdoc) {                  if (ROFF_TBL == rr)
                           while (NULL != (span = roff_span(curp->roff))) {
                                   rc = curp->man ?
                                           man_addspan(curp->man, span) :
                                           mdoc_addspan(curp->mdoc, span);
                                   if (0 == rc)
                                           break;
                           }
                   else if (ROFF_EQN == rr)
                           rc = curp->mdoc ?
                                   mdoc_addeqn(curp->mdoc,
                                           roff_eqn(curp->roff)) :
                                   man_addeqn(curp->man,
                                           roff_eqn(curp->roff));
                   else if (curp->man || curp->mdoc)
                         rc = curp->man ?                          rc = curp->man ?
                                 man_parseln(curp->man,                                  man_parseln(curp->man,
                                         curp->line, ln.buf, of) :                                          curp->line, ln.buf, of) :
                                 mdoc_parseln(curp->mdoc,                                  mdoc_parseln(curp->mdoc,
                                         curp->line, ln.buf, of);                                          curp->line, ln.buf, of);
   
                         if ( ! rc) {                  if (0 == rc) {
                                 assert(MANDOCLEVEL_FATAL <= file_status);                          assert(MANDOCLEVEL_FATAL <= curp->file_status);
                                 break;                          break;
                         }  
                 }                  }
   
                 /* Temporary buffers typically are not full. */                  /* Temporary buffers typically are not full. */
Line 1032  mmsg(enum mandocerr t, void *arg, int ln, int col, con
Line 1060  mmsg(enum mandocerr t, void *arg, int ln, int col, con
                 fprintf(stderr, ": %s", msg);                  fprintf(stderr, ": %s", msg);
         fputc('\n', stderr);          fputc('\n', stderr);
   
         if (file_status < level)          if (cp->file_status < level)
                 file_status = level;                  cp->file_status = level;
   
         return(level < MANDOCLEVEL_FATAL);          return(level < MANDOCLEVEL_FATAL);
 }  }

Legend:
Removed from v.1.134  
changed lines
  Added in v.1.150

CVSweb