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

Diff for /mandoc/main.c between version 1.2 and 1.182

version 1.2, 2009/03/19 16:18:36 version 1.182, 2014/08/21 00:32:15
Line 1 
Line 1 
 /* $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
    * Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
    * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.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   * purpose with or without fee is hereby granted, provided that the above
  * above copyright notice and this permission notice appear in all   * copyright notice and this permission notice appear in all copies.
  * copies.  
  *   *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  * PERFORMANCE OF THIS SOFTWARE.  
  */   */
 #include <sys/stat.h>  #include "config.h"
   
   #include <sys/types.h>
   
 #include <assert.h>  #include <assert.h>
 #include <err.h>  
 #include <fcntl.h>  
 #include <stdio.h>  #include <stdio.h>
   #include <stdint.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   
   #include "mandoc.h"
   #include "mandoc_aux.h"
   #include "main.h"
 #include "mdoc.h"  #include "mdoc.h"
   #include "man.h"
   #include "manpath.h"
   #include "mansearch.h"
   
 #define WARN_WALL         0x03          /* All-warnings mask. */  #if !defined(__GNUC__) || (__GNUC__ < 2)
 #define WARN_WCOMPAT     (1 << 0)       /* Compatibility warnings. */  # if !defined(lint)
 #define WARN_WSYNTAX     (1 << 1)       /* Syntax warnings. */  #  define __attribute__(x)
 #define WARN_WERR        (1 << 2)       /* Warnings->errors. */  # endif
   #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
   
 enum outt {  enum    outmode {
         OUTT_ASCII,          OUTMODE_DEF = 0,
         OUTT_LATIN1,          OUTMODE_FLN,
         OUTT_UTF8,          OUTMODE_LST,
         OUTT_TREE,          OUTMODE_ALL,
         OUTT_LINT          OUTMODE_INT,
           OUTMODE_ONE
 };  };
   
 typedef int             (*out_run)(void *, const struct mdoc *);  typedef void            (*out_mdoc)(void *, const struct mdoc *);
   typedef void            (*out_man)(void *, const struct man *);
 typedef void            (*out_free)(void *);  typedef void            (*out_free)(void *);
   
 extern  char             *__progname;  enum    outt {
           OUTT_ASCII = 0, /* -Tascii */
           OUTT_LOCALE,    /* -Tlocale */
           OUTT_UTF8,      /* -Tutf8 */
           OUTT_TREE,      /* -Ttree */
           OUTT_MAN,       /* -Tman */
           OUTT_HTML,      /* -Thtml */
           OUTT_XHTML,     /* -Txhtml */
           OUTT_LINT,      /* -Tlint */
           OUTT_PS,        /* -Tps */
           OUTT_PDF        /* -Tpdf */
   };
   
 extern  void             *ascii_alloc(void);  struct  curparse {
 extern  void             *latin1_alloc(void);          struct mparse    *mp;
 extern  void             *utf8_alloc(void);          enum mandoclevel  wlevel;       /* ignore messages below this */
 extern  int               terminal_run(void *, const struct mdoc *);          int               wstop;        /* stop after a file with a warning */
 extern  int               tree_run(void *, const struct mdoc *);          enum outt         outtype;      /* which output to use */
 extern  void              terminal_free(void *);          out_mdoc          outmdoc;      /* mdoc output ptr */
           out_man           outman;       /* man output ptr */
           out_free          outfree;      /* free output ptr */
           void             *outdata;      /* data for output */
           char              outopts[BUFSIZ]; /* buf of output opts */
   };
   
 __dead  static void       version(void);  static  int               moptions(int *, char *);
 __dead  static void       usage(void);  static  void              mmsg(enum mandocerr, enum mandoclevel,
 static  int               foptions(int *, char *);                                  const char *, int, int, const char *);
 static  int               toptions(enum outt *, char *);  static  void              parse(struct curparse *, int,
 static  int               woptions(int *, char *);                                  const char *, enum mandoclevel *);
 static  int               merr(void *, int, int, const char *);  static  int               toptions(struct curparse *, char *);
 static  int               mwarn(void *, int, int,  static  void              usage(enum argmode) __attribute__((noreturn));
                                 enum mdoc_warn, const char *);  static  void              version(void) __attribute__((noreturn));
 static  int               file(char **, size_t *, char **, size_t *,  static  int               woptions(struct curparse *, char *);
                                 const char *, struct mdoc *);  
 static  int               fdesc(char **, size_t *, char **, size_t *,  
                                 const char *, int, struct mdoc *);  
   
   static  const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
   static  const char       *progname;
   
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
         int              c, rc, fflags, wflags;          struct curparse  curp;
         struct mdoc_cb   cb;          struct mansearch search;
         struct mdoc     *mdoc;          struct manpaths  paths;
         char            *buf, *line;          char            *conf_file, *defpaths, *auxpaths;
         size_t           bufsz, linesz;          char            *defos;
         void            *outdata;  #if HAVE_SQLITE3
         enum outt        outtype;          struct manpage  *res;
         out_run          outrun;          char            **auxargv;
         out_free         outfree;          size_t           isec, i, sz;
           int              prio, best_prio;
           char             sec;
   #endif
           enum mandoclevel rc;
           enum outmode     outmode;
           int              show_usage;
           int              options;
           int              c;
   
         fflags = wflags = 0;          progname = strrchr(argv[0], '/');
         outtype = OUTT_ASCII;          if (progname == NULL)
                   progname = argv[0];
           else
                   ++progname;
   
         /* LINTED */          /* Search options. */
         while (-1 != (c = getopt(argc, argv, "f:VW:T:")))  
           memset(&paths, 0, sizeof(struct manpaths));
           conf_file = defpaths = auxpaths = NULL;
   
           memset(&search, 0, sizeof(struct mansearch));
           search.outkey = "Nd";
   
           if (strcmp(progname, "man") == 0)
                   search.argmode = ARG_NAME;
           else if (strncmp(progname, "apropos", 7) == 0)
                   search.argmode = ARG_EXPR;
           else if (strncmp(progname, "whatis", 6) == 0)
                   search.argmode = ARG_WORD;
           else
                   search.argmode = ARG_FILE;
   
           /* Parser and formatter options. */
   
           memset(&curp, 0, sizeof(struct curparse));
           curp.outtype = OUTT_ASCII;
           curp.wlevel  = MANDOCLEVEL_FATAL;
           options = MPARSE_SO;
           defos = NULL;
   
           show_usage = 0;
           outmode = OUTMODE_DEF;
           while (-1 != (c = getopt(argc, argv, "aC:fI:ikM:m:O:S:s:T:VW:w"))) {
                 switch (c) {                  switch (c) {
                 case ('f'):                  case 'a':
                         if ( ! foptions(&fflags, optarg))                          outmode = OUTMODE_ALL;
                                 return(0);  
                         break;                          break;
                 case ('T'):                  case 'C':
                         if ( ! toptions(&outtype, optarg))                          conf_file = optarg;
                                 return(0);  
                         break;                          break;
                 case ('W'):                  case 'f':
                         if ( ! woptions(&wflags, optarg))                          search.argmode = ARG_WORD;
                                 return(0);  
                         break;                          break;
                 case ('V'):                  case 'I':
                           if (strncmp(optarg, "os=", 3)) {
                                   fprintf(stderr,
                                       "%s: -I%s: Bad argument\n",
                                       progname, optarg);
                                   return((int)MANDOCLEVEL_BADARG);
                           }
                           if (defos) {
                                   fprintf(stderr,
                                       "%s: -I%s: Duplicate argument\n",
                                       progname, optarg);
                                   return((int)MANDOCLEVEL_BADARG);
                           }
                           defos = mandoc_strdup(optarg + 3);
                           break;
                   case 'i':
                           outmode = OUTMODE_INT;
                           break;
                   case 'k':
                           search.argmode = ARG_EXPR;
                           break;
                   case 'M':
                           defpaths = optarg;
                           break;
                   case 'm':
                           auxpaths = optarg;
                           break;
                   case 'O':
                           search.outkey = optarg;
                           (void)strlcat(curp.outopts, optarg, BUFSIZ);
                           (void)strlcat(curp.outopts, ",", BUFSIZ);
                           break;
                   case 'S':
                           search.arch = optarg;
                           break;
                   case 's':
                           search.sec = optarg;
                           break;
                   case 'T':
                           if ( ! toptions(&curp, optarg))
                                   return((int)MANDOCLEVEL_BADARG);
                           break;
                   case 'W':
                           if ( ! woptions(&curp, optarg))
                                   return((int)MANDOCLEVEL_BADARG);
                           break;
                   case 'w':
                           outmode = OUTMODE_FLN;
                           break;
                   case 'V':
                         version();                          version();
                         /* NOTREACHED */                          /* NOTREACHED */
                 default:                  default:
                         usage();                          show_usage = 1;
                         /* NOTREACHED */                          break;
                 }                  }
           }
   
           if (show_usage)
                   usage(search.argmode);
   
           if (outmode == OUTMODE_DEF) {
                   switch (search.argmode) {
                   case ARG_FILE:
                           outmode = OUTMODE_ALL;
                           break;
                   case ARG_NAME:
                           outmode = OUTMODE_ONE;
                           break;
                   default:
                           outmode = OUTMODE_LST;
                           break;
                   }
           }
   
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   #if HAVE_SQLITE3
           auxargv = NULL;
   #endif
   
         /*          rc = MANDOCLEVEL_OK;
          * Allocate the appropriate front-end.  Note that utf8, ascii  
          * and latin1 all resolve to the terminal front-end with  
          * different encodings (see terminal.c).  Not all frontends have  
          * cleanup or alloc routines.  
          */  
   
         switch (outtype) {          /* man(1), whatis(1), apropos(1) */
         case (OUTT_LATIN1):  
                 outdata = latin1_alloc();          if (search.argmode != ARG_FILE) {
                 outrun = terminal_run;  #if HAVE_SQLITE3
                 outfree = terminal_free;                  if (argc == 0)
                 break;                          usage(search.argmode);
         case (OUTT_UTF8):  
                 outdata = utf8_alloc();                  /* Access the mandoc database. */
                 outrun = terminal_run;  
                 outfree = terminal_free;                  manpath_parse(&paths, conf_file, defpaths, auxpaths);
                 break;                  mansearch_setup(1);
         case (OUTT_TREE):                  if( ! mansearch(&search, &paths, argc, argv, &res, &sz))
                 outdata = NULL;                          usage(search.argmode);
                 outrun = tree_run;                  manpath_free(&paths);
                 outfree = NULL;  
                 break;                  /*
         case (OUTT_LINT):                   * For standard man(1) and -a output mode,
                 outdata = NULL;                   * prepare for copying filename pointers
                 outrun = NULL;                   * into the program parameter array.
                 outfree = NULL;                   */
                 break;  
         default:                  if (outmode == OUTMODE_ONE) {
                 outdata = ascii_alloc();                          argc = 1;
                 outrun = terminal_run;                          argv[0] = res[0].file;
                 outfree = terminal_free;                          argv[1] = NULL;
                 break;                          best_prio = 10;
                   } else if (outmode == OUTMODE_ALL) {
                           argc = (int)sz;
                           argv = auxargv = mandoc_reallocarray(
                               NULL, sz + 1, sizeof(char *));
                           argv[argc] = NULL;
                   }
   
                   /* Iterate all matching manuals. */
   
                   for (i = 0; i < sz; i++) {
                           if (outmode == OUTMODE_FLN)
                                   puts(res[i].file);
                           else if (outmode == OUTMODE_LST)
                                   printf("%s - %s\n", res[i].names,
                                       res[i].output == NULL ? "" :
                                       res[i].output);
                           else if (outmode == OUTMODE_ALL)
                                   argv[i] = res[i].file;
                           else {
                                   /* Search for the best section. */
                                   isec = strcspn(res[i].file, "123456789");
                                   sec = res[i].file[isec];
                                   if ('\0' == sec)
                                           continue;
                                   prio = sec_prios[sec - '1'];
                                   if (prio >= best_prio)
                                           continue;
                                   best_prio = prio;
                                   argv[0] = res[i].file;
                           }
                   }
   
                   /*
                    * For man(1), -a and -i output mode, fall through
                    * to the main mandoc(1) code iterating files
                    * and running the parsers on each of them.
                    */
   
                   if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST)
                           goto out;
   #else
                   fputs("mandoc: database support not compiled in\n",
                       stderr);
                   return((int)MANDOCLEVEL_BADARG);
   #endif
         }          }
   
         /*          /* mandoc(1) */
          * All callbacks route into here, where we print them onto the  
          * screen.  XXX - for now, no path for debugging messages.  
          */  
   
         cb.mdoc_msg = NULL;          if ( ! moptions(&options, auxpaths))
         cb.mdoc_err = merr;                  return((int)MANDOCLEVEL_BADARG);
         cb.mdoc_warn = mwarn;  
   
         buf = line = NULL;          curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos);
         bufsz = linesz = 0;  
   
         mdoc = mdoc_alloc(&wflags, fflags, &cb);          /*
            * Conditionally start up the lookaside buffer before parsing.
            */
           if (OUTT_MAN == curp.outtype)
                   mparse_keep(curp.mp);
   
           if (NULL == *argv)
                   parse(&curp, STDIN_FILENO, "<stdin>", &rc);
   
         while (*argv) {          while (*argv) {
                 if ( ! file(&line, &linesz, &buf, &bufsz, *argv, mdoc))                  parse(&curp, -1, *argv, &rc);
                   if (MANDOCLEVEL_OK != rc && curp.wstop)
                         break;                          break;
                 if (outrun && ! (*outrun)(outdata, mdoc))                  ++argv;
                         break;  
   
                 /* Reset the parser for another file. */  
                 mdoc_reset(mdoc);  
                 argv++;  
         }          }
   
         rc = NULL == *argv;          if (curp.outfree)
                   (*curp.outfree)(curp.outdata);
           if (curp.mp)
                   mparse_free(curp.mp);
   
         if (buf)  #if HAVE_SQLITE3
                 free(buf);  out:
         if (line)          if (search.argmode != ARG_FILE) {
                 free(line);                  mansearch_free(res, sz);
         if (outfree)                  mansearch_setup(0);
                 (*outfree)(outdata);                  free(auxargv);
           }
   #endif
   
         mdoc_free(mdoc);          free(defos);
   
         return(rc ? EXIT_SUCCESS : EXIT_FAILURE);          return((int)rc);
 }  }
   
   static void
 __dead static void  
 version(void)  version(void)
 {  {
   
         (void)printf("%s %s\n", __progname, VERSION);          printf("mandoc %s\n", VERSION);
         exit(0);          exit((int)MANDOCLEVEL_OK);
         /* NOTREACHED */  
 }  }
   
   static void
 __dead static void  usage(enum argmode argmode)
 usage(void)  
 {  {
   
         (void)fprintf(stderr, "usage: %s\n", __progname);          switch (argmode) {
         exit(1);          case ARG_FILE:
         /* NOTREACHED */                  fputs("usage: mandoc [-V] [-Ios=name] [-mformat]"
                       " [-Ooption] [-Toutput] [-Wlevel]\n"
                       "\t      [file ...]\n", stderr);
                   break;
           case ARG_NAME:
                   fputs("usage: man [-acfhkVw] [-C file] "
                       "[-M path] [-m path] [-S arch] [-s section]\n"
                       "\t   [section] name ...\n", stderr);
                   break;
           case ARG_WORD:
                   fputs("usage: whatis [-V] [-C file] [-M path] [-m path] "
                       "[-S arch] [-s section] name ...\n", stderr);
                   break;
           case ARG_EXPR:
                   fputs("usage: apropos [-V] [-C file] [-M path] [-m path] "
                       "[-O outkey] [-S arch]\n"
                       "\t       [-s section] expression ...\n", stderr);
                   break;
           }
           exit((int)MANDOCLEVEL_BADARG);
 }  }
   
   static void
 static int  parse(struct curparse *curp, int fd, const char *file,
 file(char **ln, size_t *lnsz, char **buf, size_t *bufsz,          enum mandoclevel *level)
                 const char *file, struct mdoc *mdoc)  
 {  {
         int              fd, c;          enum mandoclevel  rc;
           struct mdoc      *mdoc;
           struct man       *man;
   
         if (-1 == (fd = open(file, O_RDONLY, 0))) {          /* Begin by parsing the file itself. */
                 warn("%s", file);  
                 return(0);  
         }  
   
         c = fdesc(ln, lnsz, buf, bufsz, file, fd, mdoc);          assert(file);
           assert(fd >= -1);
   
         if (-1 == close(fd))          rc = mparse_readfd(curp->mp, fd, file);
                 warn("%s", file);  
   
         return(c);          /* Stop immediately if the parse has failed. */
 }  
   
           if (MANDOCLEVEL_FATAL <= rc)
                   goto cleanup;
   
 static int  
 fdesc(char **lnp, size_t *lnsz, char **bufp, size_t *bufsz,  
                 const char *f, int fd, struct mdoc *mdoc)  
 {  
         size_t           sz;  
         ssize_t          ssz;  
         struct stat      st;  
         int              j, i, pos, lnn;  
         char            *ln, *buf;  
   
         buf = *bufp;  
         ln = *lnp;  
   
         /*          /*
          * Two buffers: ln and buf.  buf is the input buffer, optimised           * With -Wstop and warnings or errors of at least the requested
          * for each file's block size.  ln is a line buffer.  Both           * level, do not produce output.
          * growable, hence passed in by ptr-ptr.  
          */           */
   
         if (-1 == fstat(fd, &st)) {          if (MANDOCLEVEL_OK != rc && curp->wstop)
                 warnx("%s", f);                  goto cleanup;
                 sz = BUFSIZ;  
         } else  
                 sz = (unsigned)BUFSIZ > st.st_blksize ?  
                         (size_t)BUFSIZ : st.st_blksize;  
   
         if (sz > *bufsz) {          /* If unset, allocate output dev now (if applicable). */
                 if (NULL == (buf = realloc(buf, sz)))  
                         err(1, "realloc");  
                 *bufp = buf;  
                 *bufsz = sz;  
         }  
   
         /*          if ( ! (curp->outman && curp->outmdoc)) {
          * Fill buf with file blocksize and parse newlines into ln.                  switch (curp->outtype) {
          */                  case OUTT_XHTML:
                           curp->outdata = xhtml_alloc(curp->outopts);
                           curp->outfree = html_free;
                           break;
                   case OUTT_HTML:
                           curp->outdata = html_alloc(curp->outopts);
                           curp->outfree = html_free;
                           break;
                   case OUTT_UTF8:
                           curp->outdata = utf8_alloc(curp->outopts);
                           curp->outfree = ascii_free;
                           break;
                   case OUTT_LOCALE:
                           curp->outdata = locale_alloc(curp->outopts);
                           curp->outfree = ascii_free;
                           break;
                   case OUTT_ASCII:
                           curp->outdata = ascii_alloc(curp->outopts);
                           curp->outfree = ascii_free;
                           break;
                   case OUTT_PDF:
                           curp->outdata = pdf_alloc(curp->outopts);
                           curp->outfree = pspdf_free;
                           break;
                   case OUTT_PS:
                           curp->outdata = ps_alloc(curp->outopts);
                           curp->outfree = pspdf_free;
                           break;
                   default:
                           break;
                   }
   
         for (lnn = 1, pos = 0; ; ) {                  switch (curp->outtype) {
                 if (-1 == (ssz = read(fd, buf, sz))) {                  case OUTT_HTML:
                         warn("%s", f);                          /* FALLTHROUGH */
                         return(0);                  case OUTT_XHTML:
                 } else if (0 == ssz)                          curp->outman = html_man;
                           curp->outmdoc = html_mdoc;
                         break;                          break;
                   case OUTT_TREE:
                           curp->outman = tree_man;
                           curp->outmdoc = tree_mdoc;
                           break;
                   case OUTT_MAN:
                           curp->outmdoc = man_mdoc;
                           curp->outman = man_man;
                           break;
                   case OUTT_PDF:
                           /* FALLTHROUGH */
                   case OUTT_ASCII:
                           /* FALLTHROUGH */
                   case OUTT_UTF8:
                           /* FALLTHROUGH */
                   case OUTT_LOCALE:
                           /* FALLTHROUGH */
                   case OUTT_PS:
                           curp->outman = terminal_man;
                           curp->outmdoc = terminal_mdoc;
                           break;
                   default:
                           break;
                   }
           }
   
                 for (i = 0; i < (int)ssz; i++) {          mparse_result(curp->mp, &mdoc, &man, NULL);
                         if (pos >= (int)*lnsz) {  
                                 *lnsz += 256; /* Step-size. */  
                                 ln = realloc(ln, *lnsz);  
                                 if (NULL == ln)  
                                         err(1, "realloc");  
                                 *lnp = ln;  
                         }  
   
                         if ('\n' != buf[i]) {          /* Execute the out device, if it exists. */
                                 ln[pos++] = buf[i];  
                                 continue;  
                         }  
   
                         /* Check for CPP-escaped newline.  */          if (man && curp->outman)
                   (*curp->outman)(curp->outdata, man);
           if (mdoc && curp->outmdoc)
                   (*curp->outmdoc)(curp->outdata, mdoc);
   
                         if (pos > 0 && '\\' == ln[pos - 1]) {   cleanup:
                                 for (j = pos - 1; j >= 0; j--)  
                                         if ('\\' != ln[j])  
                                                 break;  
   
                                 if ( ! ((pos - j) % 2)) {          mparse_reset(curp->mp);
                                         pos--;  
                                         lnn++;  
                                         continue;  
                                 }  
                         }  
   
                         ln[pos] = 0;          if (*level < rc)
                         if ( ! mdoc_parseln(mdoc, lnn, ln))                  *level = rc;
                                 return(0);  
                         lnn++;  
                         pos = 0;  
                 }  
         }  
   
         return(mdoc_endparse(mdoc));  
 }  }
   
   
 static int  static int
 toptions(enum outt *tflags, char *arg)  moptions(int *options, char *arg)
 {  {
   
         if (0 == strcmp(arg, "ascii"))          if (arg == NULL)
                 *tflags = OUTT_ASCII;                  /* nothing to do */;
         else if (0 == strcmp(arg, "latin1"))          else if (0 == strcmp(arg, "doc"))
                 *tflags = OUTT_LATIN1;                  *options |= MPARSE_MDOC;
         else if (0 == strcmp(arg, "utf8"))          else if (0 == strcmp(arg, "andoc"))
                 *tflags = OUTT_UTF8;                  /* nothing to do */;
         else if (0 == strcmp(arg, "lint"))          else if (0 == strcmp(arg, "an"))
                 *tflags = OUTT_LINT;                  *options |= MPARSE_MAN;
         else if (0 == strcmp(arg, "tree"))  
                 *tflags = OUTT_TREE;  
         else {          else {
                 warnx("bad argument: -T%s", arg);                  fprintf(stderr, "%s: -m%s: Bad argument\n",
                       progname, arg);
                 return(0);                  return(0);
         }          }
   
         return(1);          return(1);
 }  }
   
   
 /*  
  * Parse out the options for [-fopt...] setting compiler options.  These  
  * can be comma-delimited or called again.  
  */  
 static int  static int
 foptions(int *fflags, char *arg)  toptions(struct curparse *curp, char *arg)
 {  {
         char            *v;  
         char            *toks[4];  
   
         toks[0] = "ign-scope";          if (0 == strcmp(arg, "ascii"))
         toks[1] = "ign-escape";                  curp->outtype = OUTT_ASCII;
         toks[2] = "ign-macro";          else if (0 == strcmp(arg, "lint")) {
         toks[3] = NULL;                  curp->outtype = OUTT_LINT;
                   curp->wlevel  = MANDOCLEVEL_WARNING;
           } else if (0 == strcmp(arg, "tree"))
                   curp->outtype = OUTT_TREE;
           else if (0 == strcmp(arg, "man"))
                   curp->outtype = OUTT_MAN;
           else if (0 == strcmp(arg, "html"))
                   curp->outtype = OUTT_HTML;
           else if (0 == strcmp(arg, "utf8"))
                   curp->outtype = OUTT_UTF8;
           else if (0 == strcmp(arg, "locale"))
                   curp->outtype = OUTT_LOCALE;
           else if (0 == strcmp(arg, "xhtml"))
                   curp->outtype = OUTT_XHTML;
           else if (0 == strcmp(arg, "ps"))
                   curp->outtype = OUTT_PS;
           else if (0 == strcmp(arg, "pdf"))
                   curp->outtype = OUTT_PDF;
           else {
                   fprintf(stderr, "%s: -T%s: Bad argument\n",
                       progname, arg);
                   return(0);
           }
   
         while (*arg)  
                 switch (getsubopt(&arg, toks, &v)) {  
                 case (0):  
                         *fflags |= MDOC_IGN_SCOPE;  
                         break;  
                 case (1):  
                         *fflags |= MDOC_IGN_ESCAPE;  
                         break;  
                 case (2):  
                         *fflags |= MDOC_IGN_MACRO;  
                         break;  
                 default:  
                         warnx("bad argument: -f%s", arg);  
                         return(0);  
                 }  
   
         return(1);          return(1);
 }  }
   
   
 /*  
  * Parse out the options for [-Werr...], which sets warning modes.  
  * These can be comma-delimited or called again.  
  */  
 static int  static int
 woptions(int *wflags, char *arg)  woptions(struct curparse *curp, char *arg)
 {  {
         char            *v;          char            *v, *o;
         char            *toks[5];          const char      *toks[6];
   
         toks[0] = "all";          toks[0] = "stop";
         toks[1] = "compat";          toks[1] = "all";
         toks[2] = "syntax";          toks[2] = "warning";
         toks[3] = "error";          toks[3] = "error";
         toks[4] = NULL;          toks[4] = "fatal";
           toks[5] = NULL;
   
         while (*arg)          while (*arg) {
                 switch (getsubopt(&arg, toks, &v)) {                  o = arg;
                 case (0):                  switch (getsubopt(&arg, UNCONST(toks), &v)) {
                         *wflags |= WARN_WALL;                  case 0:
                           curp->wstop = 1;
                         break;                          break;
                 case (1):                  case 1:
                         *wflags |= WARN_WCOMPAT;                          /* FALLTHROUGH */
                   case 2:
                           curp->wlevel = MANDOCLEVEL_WARNING;
                         break;                          break;
                 case (2):                  case 3:
                         *wflags |= WARN_WSYNTAX;                          curp->wlevel = MANDOCLEVEL_ERROR;
                         break;                          break;
                 case (3):                  case 4:
                         *wflags |= WARN_WERR;                          curp->wlevel = MANDOCLEVEL_FATAL;
                         break;                          break;
                 default:                  default:
                         warnx("bad argument: -W%s", arg);                          fprintf(stderr, "%s: -W%s: Bad argument\n",
                               progname, o);
                         return(0);                          return(0);
                 }                  }
           }
   
         return(1);          return(1);
 }  }
   
   static void
 /* ARGSUSED */  mmsg(enum mandocerr t, enum mandoclevel lvl,
 static int                  const char *file, int line, int col, const char *msg)
 merr(void *arg, int line, int col, const char *msg)  
 {  {
           const char      *mparse_msg;
   
         warnx("error: %s (line %d, column %d)", msg, line, col);          fprintf(stderr, "%s: %s:", progname, file);
         return(0);  
 }  
   
           if (line)
                   fprintf(stderr, "%d:%d:", line, col + 1);
   
 static int          fprintf(stderr, " %s", mparse_strlevel(lvl));
 mwarn(void *arg, int line, int col,  
                 enum mdoc_warn type, const char *msg)  
 {  
         int              flags;  
         char            *wtype;  
   
         flags = *(int *)arg;          if (NULL != (mparse_msg = mparse_strerror(t)))
         wtype = NULL;                  fprintf(stderr, ": %s", mparse_msg);
   
         switch (type) {          if (msg)
         case (WARN_COMPAT):                  fprintf(stderr, ": %s", msg);
                 wtype = "compat";  
                 if (flags & WARN_WCOMPAT)  
                         break;  
                 return(1);  
         case (WARN_SYNTAX):  
                 wtype = "syntax";  
                 if (flags & WARN_WSYNTAX)  
                         break;  
                 return(1);  
         }  
   
         assert(wtype);          fputc('\n', stderr);
         warnx("%s warning: %s (line %d, column %d)",  
                         wtype, msg, line, col);  
   
         if ( ! (flags & WARN_WERR))  
                 return(1);  
   
         warnx("%s: considering warnings as errors",  
                         __progname);  
         return(0);  
 }  }
   
   

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

CVSweb