Annotation of mandoc/main.c, Revision 1.67
1.67 ! joerg 1: /* $Id: main.c,v 1.66 2010/05/15 05:11:50 kristaps Exp $ */
1.1 kristaps 2: /*
1.26 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
1.25 kristaps 6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 8: *
1.25 kristaps 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 kristaps 16: */
1.58 kristaps 17: #ifdef HAVE_CONFIG_H
18: #include "config.h"
19: #endif
20:
1.66 kristaps 21: #include <sys/mman.h>
1.1 kristaps 22: #include <sys/stat.h>
23:
24: #include <assert.h>
25: #include <fcntl.h>
26: #include <stdio.h>
1.45 kristaps 27: #include <stdint.h>
1.1 kristaps 28: #include <stdlib.h>
29: #include <string.h>
30: #include <unistd.h>
31:
32: #include "mdoc.h"
1.10 kristaps 33: #include "man.h"
1.46 kristaps 34: #include "main.h"
1.1 kristaps 35:
1.45 kristaps 36: #define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
37:
1.55 kristaps 38: /* FIXME: Intel's compiler? LLVM? pcc? */
39:
40: #if !defined(__GNUC__) || (__GNUC__ < 2)
1.56 kristaps 41: # if !defined(lint)
42: # define __attribute__(x)
43: # endif
1.55 kristaps 44: #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
1.16 kristaps 45:
1.42 kristaps 46: typedef void (*out_mdoc)(void *, const struct mdoc *);
47: typedef void (*out_man)(void *, const struct man *);
1.22 kristaps 48: typedef void (*out_free)(void *);
49:
1.5 kristaps 50: struct buf {
51: char *buf;
52: size_t sz;
53: };
54:
1.19 kristaps 55: enum intt {
56: INTT_AUTO,
57: INTT_MDOC,
58: INTT_MAN
59: };
60:
61: enum outt {
62: OUTT_ASCII = 0,
63: OUTT_TREE,
1.43 kristaps 64: OUTT_HTML,
1.59 kristaps 65: OUTT_XHTML,
1.19 kristaps 66: OUTT_LINT
67: };
68:
1.5 kristaps 69: struct curparse {
1.22 kristaps 70: const char *file; /* Current parse. */
71: int fd; /* Current parse. */
1.5 kristaps 72: int wflags;
1.36 kristaps 73: #define WARN_WALL (1 << 0) /* All-warnings mask. */
1.1 kristaps 74: #define WARN_WERR (1 << 2) /* Warnings->errors. */
1.23 kristaps 75: int fflags;
1.60 kristaps 76: #define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */
77: #define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */
78: #define FL_NIGN_MACRO (1 << 2) /* Don't ignore bad macros. */
79: #define FL_IGN_ERRORS (1 << 4) /* Ignore failed parse. */
1.66 kristaps 80: #define FL_STRICT FL_NIGN_ESCAPE | \
81: FL_NIGN_MACRO
1.29 kristaps 82: enum intt inttype; /* Input parsers... */
1.19 kristaps 83: struct man *man;
84: struct mdoc *mdoc;
1.29 kristaps 85: enum outt outtype; /* Output devices... */
1.22 kristaps 86: out_mdoc outmdoc;
87: out_man outman;
88: out_free outfree;
89: void *outdata;
1.49 kristaps 90: char outopts[BUFSIZ];
1.5 kristaps 91: };
1.1 kristaps 92:
1.66 kristaps 93: static void fdesc(struct curparse *);
94: static void ffile(const char *, struct curparse *);
1.1 kristaps 95: static int foptions(int *, char *);
1.66 kristaps 96: static struct man *man_init(struct curparse *);
97: static struct mdoc *mdoc_init(struct curparse *);
98: static int merr(void *, int, int, const char *);
1.10 kristaps 99: static int moptions(enum intt *, char *);
1.37 kristaps 100: static int mwarn(void *, int, int, const char *);
1.22 kristaps 101: static int pset(const char *, int, struct curparse *,
1.19 kristaps 102: struct man **, struct mdoc **);
1.66 kristaps 103: static int toptions(struct curparse *, char *);
104: static void usage(void) __attribute__((noreturn));
1.55 kristaps 105: static void version(void) __attribute__((noreturn));
1.66 kristaps 106: static int woptions(int *, char *);
1.1 kristaps 107:
1.54 kristaps 108: static const char *progname;
1.66 kristaps 109: static int with_error;
110: static int with_warning;
1.1 kristaps 111:
112: int
113: main(int argc, char *argv[])
114: {
1.64 kristaps 115: int c;
1.5 kristaps 116: struct curparse curp;
1.1 kristaps 117:
1.54 kristaps 118: progname = strrchr(argv[0], '/');
119: if (progname == NULL)
120: progname = argv[0];
121: else
122: ++progname;
123:
1.51 kristaps 124: memset(&curp, 0, sizeof(struct curparse));
1.5 kristaps 125:
1.19 kristaps 126: curp.inttype = INTT_AUTO;
1.22 kristaps 127: curp.outtype = OUTT_ASCII;
1.19 kristaps 128:
1.1 kristaps 129: /* LINTED */
1.47 kristaps 130: while (-1 != (c = getopt(argc, argv, "f:m:O:T:VW:")))
1.1 kristaps 131: switch (c) {
132: case ('f'):
1.19 kristaps 133: if ( ! foptions(&curp.fflags, optarg))
1.32 kristaps 134: return(EXIT_FAILURE);
1.1 kristaps 135: break;
1.10 kristaps 136: case ('m'):
1.19 kristaps 137: if ( ! moptions(&curp.inttype, optarg))
1.32 kristaps 138: return(EXIT_FAILURE);
1.10 kristaps 139: break;
1.48 kristaps 140: case ('O'):
1.49 kristaps 141: (void)strlcat(curp.outopts, optarg, BUFSIZ);
142: (void)strlcat(curp.outopts, ",", BUFSIZ);
1.44 kristaps 143: break;
1.1 kristaps 144: case ('T'):
1.60 kristaps 145: if ( ! toptions(&curp, optarg))
1.32 kristaps 146: return(EXIT_FAILURE);
1.1 kristaps 147: break;
148: case ('W'):
1.5 kristaps 149: if ( ! woptions(&curp.wflags, optarg))
1.32 kristaps 150: return(EXIT_FAILURE);
1.1 kristaps 151: break;
152: case ('V'):
153: version();
154: /* NOTREACHED */
155: default:
156: usage();
157: /* NOTREACHED */
158: }
159:
160: argc -= optind;
161: argv += optind;
162:
1.30 kristaps 163: if (NULL == *argv) {
164: curp.file = "<stdin>";
165: curp.fd = STDIN_FILENO;
1.39 kristaps 166:
1.66 kristaps 167: fdesc(&curp);
1.64 kristaps 168: }
169:
170: while (*argv) {
1.66 kristaps 171: ffile(*argv, &curp);
1.64 kristaps 172:
173: if (with_error && !(curp.fflags & FL_IGN_ERRORS))
174: break;
175: ++argv;
1.1 kristaps 176: }
177:
1.22 kristaps 178: if (curp.outfree)
179: (*curp.outfree)(curp.outdata);
1.1 kristaps 180:
1.66 kristaps 181: return((with_warning || with_error) ?
182: EXIT_FAILURE : EXIT_SUCCESS);
1.1 kristaps 183: }
184:
185:
1.55 kristaps 186: static void
1.1 kristaps 187: version(void)
188: {
189:
1.54 kristaps 190: (void)printf("%s %s\n", progname, VERSION);
1.18 kristaps 191: exit(EXIT_SUCCESS);
1.1 kristaps 192: }
193:
194:
1.55 kristaps 195: static void
1.1 kristaps 196: usage(void)
197: {
198:
1.61 kristaps 199: (void)fprintf(stderr, "usage: %s [-V] [-foption] "
1.48 kristaps 200: "[-mformat] [-Ooption] [-Toutput] "
1.61 kristaps 201: "[-Werr] [file...]\n", progname);
1.18 kristaps 202: exit(EXIT_FAILURE);
1.1 kristaps 203: }
204:
205:
1.19 kristaps 206: static struct man *
207: man_init(struct curparse *curp)
208: {
209: int pflags;
210: struct man_cb mancb;
211:
212: mancb.man_err = merr;
1.37 kristaps 213: mancb.man_warn = mwarn;
1.19 kristaps 214:
1.30 kristaps 215: /* Defaults from mandoc.1. */
1.27 kristaps 216:
1.62 kristaps 217: pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE;
1.27 kristaps 218:
1.60 kristaps 219: if (curp->fflags & FL_NIGN_MACRO)
1.20 kristaps 220: pflags &= ~MAN_IGN_MACRO;
1.60 kristaps 221: if (curp->fflags & FL_NIGN_ESCAPE)
1.33 kristaps 222: pflags &= ~MAN_IGN_ESCAPE;
1.19 kristaps 223:
1.52 kristaps 224: return(man_alloc(curp, pflags, &mancb));
1.19 kristaps 225: }
226:
227:
228: static struct mdoc *
229: mdoc_init(struct curparse *curp)
230: {
231: int pflags;
232: struct mdoc_cb mdoccb;
233:
234: mdoccb.mdoc_err = merr;
1.37 kristaps 235: mdoccb.mdoc_warn = mwarn;
1.19 kristaps 236:
1.30 kristaps 237: /* Defaults from mandoc.1. */
1.27 kristaps 238:
1.62 kristaps 239: pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE;
1.19 kristaps 240:
1.60 kristaps 241: if (curp->fflags & FL_IGN_SCOPE)
1.19 kristaps 242: pflags |= MDOC_IGN_SCOPE;
1.60 kristaps 243: if (curp->fflags & FL_NIGN_ESCAPE)
1.24 kristaps 244: pflags &= ~MDOC_IGN_ESCAPE;
1.60 kristaps 245: if (curp->fflags & FL_NIGN_MACRO)
1.24 kristaps 246: pflags &= ~MDOC_IGN_MACRO;
1.19 kristaps 247:
1.52 kristaps 248: return(mdoc_alloc(curp, pflags, &mdoccb));
1.19 kristaps 249: }
250:
251:
1.64 kristaps 252: static void
1.66 kristaps 253: ffile(const char *file, struct curparse *curp)
1.1 kristaps 254: {
255:
1.19 kristaps 256: curp->file = file;
257: if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
1.53 kristaps 258: perror(curp->file);
1.64 kristaps 259: with_error = 1;
260: return;
1.1 kristaps 261: }
262:
1.66 kristaps 263: fdesc(curp);
1.1 kristaps 264:
1.19 kristaps 265: if (-1 == close(curp->fd))
1.53 kristaps 266: perror(curp->file);
1.1 kristaps 267: }
268:
269:
1.66 kristaps 270: static int
271: read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
272: {
273: struct stat st;
274: char *buf;
275: size_t sz, off;
276: ssize_t ssz;
277:
278: if (-1 == fstat(curp->fd, &st)) {
279: perror(curp->file);
280: with_error = 1;
281: return(0);
282: }
283:
284: /*
285: * If we're a regular file, try just reading in the whole entry
286: * via mmap(). This is faster than reading it into blocks, and
287: * since each file is only a few bytes to begin with, I'm not
288: * concerned that this is going to tank any machines.
289: */
290:
291: if (S_ISREG(st.st_mode)) {
292: if (st.st_size >= (1U << 31)) {
293: fprintf(stderr, "%s: input too large\n",
294: curp->file);
295: with_error = 1;
296: return(0);
297: }
298: *with_mmap = 1;
299: fb->sz = st.st_size;
300: fb->buf = mmap(NULL, fb->sz, PROT_READ,
301: MAP_FILE, curp->fd, 0);
302: if (fb->buf != MAP_FAILED)
303: return(1);
304: }
305:
306: /*
307: * If this isn't a regular file (like, say, stdin), then we must
308: * go the old way and just read things in bit by bit.
309: */
310:
311: *with_mmap = 0;
312: off = 0;
313: fb->sz = 0;
314: fb->buf = NULL;
315: for (;;) {
316: if (off == fb->sz) {
317: if (fb->sz == (1U << 31)) {
318: fprintf(stderr, "%s: input too large\n",
319: curp->file);
320: break;
321: }
322: if (fb->sz == 0)
323: sz = 65536;
324: else
325: sz = 2 * fb->sz;
326: buf = realloc(fb->buf, sz);
327: if (NULL == buf) {
328: perror(NULL);
329: break;
330: }
331: fb->buf = buf;
332: fb->sz = sz;
333: }
334: ssz = read(curp->fd, fb->buf + off, fb->sz - off);
335: if (ssz == 0) {
336: fb->sz = off;
337: return(1);
338: }
339: if (ssz == -1) {
340: perror(curp->file);
341: break;
342: }
343: off += ssz;
344: }
345:
346: free(fb->buf);
347: fb->buf = NULL;
348: with_error = 1;
349: return(0);
350: }
351:
352:
1.64 kristaps 353: static void
1.66 kristaps 354: fdesc(struct curparse *curp)
1.1 kristaps 355: {
356: size_t sz;
1.66 kristaps 357: struct buf ln, blk;
358: int j, i, pos, lnn, comment, with_mmap;
1.19 kristaps 359: struct man *man;
360: struct mdoc *mdoc;
1.10 kristaps 361:
1.19 kristaps 362: sz = BUFSIZ;
363: man = NULL;
364: mdoc = NULL;
1.66 kristaps 365: memset(&ln, 0, sizeof(struct buf));
1.1 kristaps 366:
367: /*
1.19 kristaps 368: * Two buffers: ln and buf. buf is the input buffer optimised
369: * here for each file's block size. ln is a line buffer. Both
1.1 kristaps 370: * growable, hence passed in by ptr-ptr.
371: */
372:
1.66 kristaps 373: if (!read_whole_file(curp, &blk, &with_mmap))
1.64 kristaps 374: return;
1.1 kristaps 375:
1.19 kristaps 376: /* Fill buf with file blocksize. */
1.1 kristaps 377:
1.66 kristaps 378: for (i = lnn = pos = comment = 0; i < (int)blk.sz; ++i) {
1.67 ! joerg 379: if (pos >= (int)ln.sz) {
! 380: ln.sz += 256; /* Step-size. */
! 381: ln.buf = realloc(ln.buf, ln.sz);
! 382: if (NULL == ln.buf) {
! 383: perror(NULL);
! 384: goto bailout;
1.1 kristaps 385: }
1.67 ! joerg 386: }
! 387:
! 388: if ('\n' != blk.buf[i]) {
! 389: if (comment)
! 390: continue;
! 391: ln.buf[pos++] = blk.buf[i];
! 392:
! 393: /* Handle in-line `\"' comments. */
! 394:
! 395: if (1 == pos || '\"' != ln.buf[pos - 1])
! 396: continue;
1.1 kristaps 397:
1.67 ! joerg 398: for (j = pos - 2; j >= 0; j--)
! 399: if ('\\' != ln.buf[j])
! 400: break;
! 401:
! 402: if ( ! ((pos - 2 - j) % 2))
1.1 kristaps 403: continue;
404:
1.67 ! joerg 405: comment = 1;
! 406: pos -= 2;
! 407: for (; pos > 0; --pos) {
! 408: if (ln.buf[pos - 1] != ' ')
! 409: break;
! 410: if (pos > 2 && ln.buf[pos - 2] == '\\')
! 411: break;
! 412: }
! 413: continue;
! 414: }
! 415:
! 416: /* Handle escaped `\\n' newlines. */
1.1 kristaps 417:
1.67 ! joerg 418: if (pos > 0 && 0 == comment && '\\' == ln.buf[pos - 1]) {
! 419: for (j = pos - 1; j >= 0; j--)
! 420: if ('\\' != ln.buf[j])
! 421: break;
! 422: if ( ! ((pos - j) % 2)) {
! 423: pos--;
! 424: lnn++;
! 425: continue;
1.1 kristaps 426: }
1.67 ! joerg 427: }
1.1 kristaps 428:
1.67 ! joerg 429: ln.buf[pos] = 0;
! 430: lnn++;
1.29 kristaps 431:
1.67 ! joerg 432: /* If unset, assign parser in pset(). */
1.19 kristaps 433:
1.67 ! joerg 434: if ( ! (man || mdoc) && ! pset(ln.buf, pos, curp, &man, &mdoc))
! 435: goto bailout;
1.19 kristaps 436:
1.67 ! joerg 437: pos = comment = 0;
1.19 kristaps 438:
1.67 ! joerg 439: /* Pass down into parsers. */
1.30 kristaps 440:
1.67 ! joerg 441: if (man && ! man_parseln(man, lnn, ln.buf))
! 442: goto bailout;
! 443: if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf))
! 444: goto bailout;
1.1 kristaps 445: }
446:
1.29 kristaps 447: /* NOTE a parser may not have been assigned, yet. */
1.19 kristaps 448:
1.22 kristaps 449: if ( ! (man || mdoc)) {
1.53 kristaps 450: fprintf(stderr, "%s: Not a manual\n", curp->file);
1.64 kristaps 451: goto bailout;
1.22 kristaps 452: }
453:
454: if (mdoc && ! mdoc_endparse(mdoc))
1.64 kristaps 455: goto bailout;
1.22 kristaps 456: if (man && ! man_endparse(man))
1.64 kristaps 457: goto bailout;
1.19 kristaps 458:
1.29 kristaps 459: /* If unset, allocate output dev now (if applicable). */
1.22 kristaps 460:
461: if ( ! (curp->outman && curp->outmdoc)) {
462: switch (curp->outtype) {
1.59 kristaps 463: case (OUTT_XHTML):
464: curp->outdata = xhtml_alloc(curp->outopts);
465: curp->outman = html_man;
466: curp->outmdoc = html_mdoc;
467: curp->outfree = html_free;
468: break;
1.43 kristaps 469: case (OUTT_HTML):
1.44 kristaps 470: curp->outdata = html_alloc(curp->outopts);
1.43 kristaps 471: curp->outman = html_man;
472: curp->outmdoc = html_mdoc;
473: curp->outfree = html_free;
474: break;
1.22 kristaps 475: case (OUTT_TREE):
476: curp->outman = tree_man;
477: curp->outmdoc = tree_mdoc;
478: break;
479: case (OUTT_LINT):
480: break;
481: default:
482: curp->outdata = ascii_alloc();
483: curp->outman = terminal_man;
484: curp->outmdoc = terminal_mdoc;
485: curp->outfree = terminal_free;
486: break;
487: }
488: }
489:
490: /* Execute the out device, if it exists. */
491:
492: if (man && curp->outman)
1.42 kristaps 493: (*curp->outman)(curp->outdata, man);
1.22 kristaps 494: if (mdoc && curp->outmdoc)
1.42 kristaps 495: (*curp->outmdoc)(curp->outdata, mdoc);
1.22 kristaps 496:
1.64 kristaps 497: cleanup:
498: if (curp->mdoc) {
499: mdoc_free(curp->mdoc);
500: curp->mdoc = NULL;
501: }
502: if (curp->man) {
503: man_free(curp->man);
504: curp->man = NULL;
505: }
1.66 kristaps 506: if (ln.buf)
507: free(ln.buf);
508: if (with_mmap)
509: munmap(blk.buf, blk.sz);
510: else
511: free(blk.buf);
1.64 kristaps 512: return;
513:
514: bailout:
515: with_error = 1;
516: goto cleanup;
1.19 kristaps 517: }
518:
519:
520: static int
1.22 kristaps 521: pset(const char *buf, int pos, struct curparse *curp,
1.19 kristaps 522: struct man **man, struct mdoc **mdoc)
523: {
1.29 kristaps 524: int i;
1.19 kristaps 525:
526: /*
527: * Try to intuit which kind of manual parser should be used. If
528: * passed in by command-line (-man, -mdoc), then use that
529: * explicitly. If passed as -mandoc, then try to guess from the
1.30 kristaps 530: * line: either skip dot-lines, use -mdoc when finding `.Dt', or
1.19 kristaps 531: * default to -man, which is more lenient.
532: */
533:
1.29 kristaps 534: if (buf[0] == '.') {
535: for (i = 1; buf[i]; i++)
536: if (' ' != buf[i] && '\t' != buf[i])
537: break;
538: if (0 == buf[i])
539: return(1);
540: }
1.10 kristaps 541:
1.19 kristaps 542: switch (curp->inttype) {
543: case (INTT_MDOC):
544: if (NULL == curp->mdoc)
545: curp->mdoc = mdoc_init(curp);
546: if (NULL == (*mdoc = curp->mdoc))
547: return(0);
548: return(1);
549: case (INTT_MAN):
550: if (NULL == curp->man)
551: curp->man = man_init(curp);
552: if (NULL == (*man = curp->man))
553: return(0);
554: return(1);
555: default:
556: break;
557: }
558:
559: if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
560: if (NULL == curp->mdoc)
561: curp->mdoc = mdoc_init(curp);
562: if (NULL == (*mdoc = curp->mdoc))
563: return(0);
564: return(1);
565: }
566:
567: if (NULL == curp->man)
568: curp->man = man_init(curp);
569: if (NULL == (*man = curp->man))
570: return(0);
571: return(1);
1.10 kristaps 572: }
573:
574:
575: static int
576: moptions(enum intt *tflags, char *arg)
577: {
578:
1.17 kristaps 579: if (0 == strcmp(arg, "doc"))
1.10 kristaps 580: *tflags = INTT_MDOC;
1.19 kristaps 581: else if (0 == strcmp(arg, "andoc"))
582: *tflags = INTT_AUTO;
1.17 kristaps 583: else if (0 == strcmp(arg, "an"))
1.10 kristaps 584: *tflags = INTT_MAN;
585: else {
1.57 kristaps 586: fprintf(stderr, "%s: Bad argument\n", arg);
1.10 kristaps 587: return(0);
588: }
589:
590: return(1);
1.1 kristaps 591: }
592:
593:
594: static int
1.60 kristaps 595: toptions(struct curparse *curp, char *arg)
1.1 kristaps 596: {
597:
598: if (0 == strcmp(arg, "ascii"))
1.60 kristaps 599: curp->outtype = OUTT_ASCII;
600: else if (0 == strcmp(arg, "lint")) {
601: curp->outtype = OUTT_LINT;
602: curp->wflags |= WARN_WALL;
603: curp->fflags |= FL_STRICT;
604: }
1.1 kristaps 605: else if (0 == strcmp(arg, "tree"))
1.60 kristaps 606: curp->outtype = OUTT_TREE;
1.43 kristaps 607: else if (0 == strcmp(arg, "html"))
1.60 kristaps 608: curp->outtype = OUTT_HTML;
1.59 kristaps 609: else if (0 == strcmp(arg, "xhtml"))
1.60 kristaps 610: curp->outtype = OUTT_XHTML;
1.1 kristaps 611: else {
1.57 kristaps 612: fprintf(stderr, "%s: Bad argument\n", arg);
1.1 kristaps 613: return(0);
614: }
615:
616: return(1);
617: }
618:
619:
620: static int
621: foptions(int *fflags, char *arg)
622: {
1.34 kristaps 623: char *v, *o;
1.50 kristaps 624: const char *toks[8];
1.1 kristaps 625:
626: toks[0] = "ign-scope";
1.24 kristaps 627: toks[1] = "no-ign-escape";
628: toks[2] = "no-ign-macro";
1.62 kristaps 629: toks[3] = "ign-errors";
630: toks[4] = "strict";
631: toks[5] = "ign-escape";
632: toks[6] = NULL;
1.1 kristaps 633:
1.34 kristaps 634: while (*arg) {
635: o = arg;
1.45 kristaps 636: switch (getsubopt(&arg, UNCONST(toks), &v)) {
1.1 kristaps 637: case (0):
1.60 kristaps 638: *fflags |= FL_IGN_SCOPE;
1.1 kristaps 639: break;
640: case (1):
1.60 kristaps 641: *fflags |= FL_NIGN_ESCAPE;
1.1 kristaps 642: break;
643: case (2):
1.60 kristaps 644: *fflags |= FL_NIGN_MACRO;
1.1 kristaps 645: break;
1.20 kristaps 646: case (3):
1.62 kristaps 647: *fflags |= FL_IGN_ERRORS;
1.24 kristaps 648: break;
649: case (4):
1.62 kristaps 650: *fflags |= FL_STRICT;
1.39 kristaps 651: break;
652: case (5):
1.60 kristaps 653: *fflags &= ~FL_NIGN_ESCAPE;
1.50 kristaps 654: break;
1.1 kristaps 655: default:
1.57 kristaps 656: fprintf(stderr, "%s: Bad argument\n", o);
1.1 kristaps 657: return(0);
658: }
1.34 kristaps 659: }
1.1 kristaps 660:
661: return(1);
662: }
663:
664:
665: static int
666: woptions(int *wflags, char *arg)
667: {
1.34 kristaps 668: char *v, *o;
1.45 kristaps 669: const char *toks[3];
1.1 kristaps 670:
671: toks[0] = "all";
1.36 kristaps 672: toks[1] = "error";
673: toks[2] = NULL;
1.1 kristaps 674:
1.34 kristaps 675: while (*arg) {
676: o = arg;
1.45 kristaps 677: switch (getsubopt(&arg, UNCONST(toks), &v)) {
1.1 kristaps 678: case (0):
679: *wflags |= WARN_WALL;
680: break;
681: case (1):
682: *wflags |= WARN_WERR;
683: break;
684: default:
1.57 kristaps 685: fprintf(stderr, "%s: Bad argument\n", o);
1.1 kristaps 686: return(0);
687: }
1.34 kristaps 688: }
1.1 kristaps 689:
690: return(1);
691: }
692:
693:
1.2 kristaps 694: /* ARGSUSED */
1.1 kristaps 695: static int
696: merr(void *arg, int line, int col, const char *msg)
697: {
1.5 kristaps 698: struct curparse *curp;
699:
700: curp = (struct curparse *)arg;
1.36 kristaps 701:
1.40 kristaps 702: (void)fprintf(stderr, "%s:%d:%d: error: %s\n",
703: curp->file, line, col + 1, msg);
1.27 kristaps 704:
1.64 kristaps 705: with_error = 1;
706:
1.1 kristaps 707: return(0);
708: }
709:
710:
711: static int
1.37 kristaps 712: mwarn(void *arg, int line, int col, const char *msg)
1.1 kristaps 713: {
1.5 kristaps 714: struct curparse *curp;
1.1 kristaps 715:
1.5 kristaps 716: curp = (struct curparse *)arg;
1.1 kristaps 717:
1.36 kristaps 718: if ( ! (curp->wflags & WARN_WALL))
719: return(1);
720:
1.40 kristaps 721: (void)fprintf(stderr, "%s:%d:%d: warning: %s\n",
722: curp->file, line, col + 1, msg);
1.1 kristaps 723:
1.64 kristaps 724: with_warning = 1;
725: if (curp->wflags & WARN_WERR) {
726: with_error = 1;
727: return(0);
728: }
729:
730: return(1);
1.1 kristaps 731: }
732:
CVSweb