Annotation of mandoc/main.c, Revision 1.70
1.70 ! joerg 1: /* $Id: main.c,v 1.69 2010/05/15 16:18:23 joerg 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
1.68 joerg 271: resize_buf(struct buf *buf, size_t initial)
272: {
273: void *tmp;
274: size_t sz;
275:
276: if (buf->sz == 0)
277: sz = initial;
278: else
279: sz = 2 * buf->sz;
280: tmp = realloc(buf->buf, sz);
281: if (NULL == tmp) {
282: perror(NULL);
283: return(0);
284: }
285: buf->buf = tmp;
286: buf->sz = sz;
287: return(1);
288: }
289:
290:
291: static int
1.66 kristaps 292: read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
293: {
294: struct stat st;
1.68 joerg 295: size_t off;
1.66 kristaps 296: ssize_t ssz;
297:
298: if (-1 == fstat(curp->fd, &st)) {
299: perror(curp->file);
300: with_error = 1;
301: return(0);
302: }
303:
304: /*
305: * If we're a regular file, try just reading in the whole entry
306: * via mmap(). This is faster than reading it into blocks, and
307: * since each file is only a few bytes to begin with, I'm not
308: * concerned that this is going to tank any machines.
309: */
310:
311: if (S_ISREG(st.st_mode)) {
312: if (st.st_size >= (1U << 31)) {
313: fprintf(stderr, "%s: input too large\n",
314: curp->file);
315: with_error = 1;
316: return(0);
317: }
318: *with_mmap = 1;
319: fb->sz = st.st_size;
320: fb->buf = mmap(NULL, fb->sz, PROT_READ,
321: MAP_FILE, curp->fd, 0);
322: if (fb->buf != MAP_FAILED)
323: return(1);
324: }
325:
326: /*
327: * If this isn't a regular file (like, say, stdin), then we must
328: * go the old way and just read things in bit by bit.
329: */
330:
331: *with_mmap = 0;
332: off = 0;
333: fb->sz = 0;
334: fb->buf = NULL;
335: for (;;) {
336: if (off == fb->sz) {
337: if (fb->sz == (1U << 31)) {
338: fprintf(stderr, "%s: input too large\n",
339: curp->file);
340: break;
341: }
1.68 joerg 342: if (! resize_buf(fb, 65536))
1.66 kristaps 343: break;
344: }
345: ssz = read(curp->fd, fb->buf + off, fb->sz - off);
346: if (ssz == 0) {
347: fb->sz = off;
348: return(1);
349: }
350: if (ssz == -1) {
351: perror(curp->file);
352: break;
353: }
354: off += ssz;
355: }
356:
357: free(fb->buf);
358: fb->buf = NULL;
359: with_error = 1;
360: return(0);
361: }
362:
363:
1.64 kristaps 364: static void
1.66 kristaps 365: fdesc(struct curparse *curp)
1.1 kristaps 366: {
1.66 kristaps 367: struct buf ln, blk;
1.70 ! joerg 368: int i, pos, lnn, lnn_start, with_mmap;
1.19 kristaps 369: struct man *man;
370: struct mdoc *mdoc;
1.10 kristaps 371:
1.19 kristaps 372: man = NULL;
373: mdoc = NULL;
1.66 kristaps 374: memset(&ln, 0, sizeof(struct buf));
1.1 kristaps 375:
376: /*
1.70 ! joerg 377: * Two buffers: ln and buf. buf is the input file and may be
! 378: * memory mapped. ln is a line buffer and grows on-demand.
1.1 kristaps 379: */
380:
1.66 kristaps 381: if (!read_whole_file(curp, &blk, &with_mmap))
1.64 kristaps 382: return;
1.1 kristaps 383:
1.70 ! joerg 384: for (i = 0, lnn = 1; i < (int)blk.sz;) {
! 385: pos = 0;
! 386: lnn_start = lnn;
! 387: while (i < (int)blk.sz) {
! 388: if ('\n' == blk.buf[i]) {
! 389: ++i;
! 390: ++lnn;
! 391: break;
! 392: }
! 393: /* Trailing backslash is like a plain character. */
! 394: if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
! 395: if (pos >= (int)ln.sz)
! 396: if (! resize_buf(&ln, 256))
! 397: goto bailout;
! 398: ln.buf[pos++] = blk.buf[i++];
1.67 joerg 399: continue;
1.70 ! joerg 400: }
! 401: /* Found an escape and at least one other character. */
! 402: if ('\n' == blk.buf[i + 1]) {
! 403: /* Escaped newlines are skipped over */
! 404: i += 2;
! 405: ++lnn;
1.67 joerg 406: continue;
407: }
1.70 ! joerg 408: if ('"' == blk.buf[i + 1]) {
! 409: i += 2;
! 410: /* Comment, skip to end of line */
! 411: for (; i < (int)blk.sz; ++i) {
! 412: if ('\n' == blk.buf[i]) {
! 413: ++i;
! 414: ++lnn;
! 415: break;
! 416: }
! 417: }
! 418: /* Backout trailing whitespaces */
! 419: for (; pos > 0; --pos) {
! 420: if (ln.buf[pos - 1] != ' ')
! 421: break;
! 422: if (pos > 2 && ln.buf[pos - 2] == '\\')
! 423: break;
! 424: }
! 425: break;
! 426: }
! 427: /* Some other escape sequence, copy and continue. */
! 428: if (pos + 1 >= (int)ln.sz)
! 429: if (! resize_buf(&ln, 256))
! 430: goto bailout;
1.1 kristaps 431:
1.70 ! joerg 432: ln.buf[pos++] = blk.buf[i++];
! 433: ln.buf[pos++] = blk.buf[i++];
1.67 joerg 434: }
1.1 kristaps 435:
1.70 ! joerg 436: if (pos >= (int)ln.sz)
! 437: if (! resize_buf(&ln, 256))
! 438: goto bailout;
1.67 joerg 439: ln.buf[pos] = 0;
1.29 kristaps 440:
1.67 joerg 441: /* If unset, assign parser in pset(). */
1.19 kristaps 442:
1.67 joerg 443: if ( ! (man || mdoc) && ! pset(ln.buf, pos, curp, &man, &mdoc))
444: goto bailout;
1.19 kristaps 445:
1.67 joerg 446: /* Pass down into parsers. */
1.30 kristaps 447:
1.67 joerg 448: if (man && ! man_parseln(man, lnn, ln.buf))
449: goto bailout;
450: if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf))
451: goto bailout;
1.1 kristaps 452: }
453:
1.29 kristaps 454: /* NOTE a parser may not have been assigned, yet. */
1.19 kristaps 455:
1.22 kristaps 456: if ( ! (man || mdoc)) {
1.53 kristaps 457: fprintf(stderr, "%s: Not a manual\n", curp->file);
1.64 kristaps 458: goto bailout;
1.22 kristaps 459: }
460:
461: if (mdoc && ! mdoc_endparse(mdoc))
1.64 kristaps 462: goto bailout;
1.22 kristaps 463: if (man && ! man_endparse(man))
1.64 kristaps 464: goto bailout;
1.19 kristaps 465:
1.29 kristaps 466: /* If unset, allocate output dev now (if applicable). */
1.22 kristaps 467:
468: if ( ! (curp->outman && curp->outmdoc)) {
469: switch (curp->outtype) {
1.59 kristaps 470: case (OUTT_XHTML):
471: curp->outdata = xhtml_alloc(curp->outopts);
472: curp->outman = html_man;
473: curp->outmdoc = html_mdoc;
474: curp->outfree = html_free;
475: break;
1.43 kristaps 476: case (OUTT_HTML):
1.44 kristaps 477: curp->outdata = html_alloc(curp->outopts);
1.43 kristaps 478: curp->outman = html_man;
479: curp->outmdoc = html_mdoc;
480: curp->outfree = html_free;
481: break;
1.22 kristaps 482: case (OUTT_TREE):
483: curp->outman = tree_man;
484: curp->outmdoc = tree_mdoc;
485: break;
486: case (OUTT_LINT):
487: break;
488: default:
1.69 joerg 489: curp->outdata = ascii_alloc(80);
1.22 kristaps 490: curp->outman = terminal_man;
491: curp->outmdoc = terminal_mdoc;
492: curp->outfree = terminal_free;
493: break;
494: }
495: }
496:
497: /* Execute the out device, if it exists. */
498:
499: if (man && curp->outman)
1.42 kristaps 500: (*curp->outman)(curp->outdata, man);
1.22 kristaps 501: if (mdoc && curp->outmdoc)
1.42 kristaps 502: (*curp->outmdoc)(curp->outdata, mdoc);
1.22 kristaps 503:
1.64 kristaps 504: cleanup:
505: if (curp->mdoc) {
506: mdoc_free(curp->mdoc);
507: curp->mdoc = NULL;
508: }
509: if (curp->man) {
510: man_free(curp->man);
511: curp->man = NULL;
512: }
1.66 kristaps 513: if (ln.buf)
514: free(ln.buf);
515: if (with_mmap)
516: munmap(blk.buf, blk.sz);
517: else
518: free(blk.buf);
1.64 kristaps 519: return;
520:
521: bailout:
522: with_error = 1;
523: goto cleanup;
1.19 kristaps 524: }
525:
526:
527: static int
1.22 kristaps 528: pset(const char *buf, int pos, struct curparse *curp,
1.19 kristaps 529: struct man **man, struct mdoc **mdoc)
530: {
1.29 kristaps 531: int i;
1.19 kristaps 532:
533: /*
534: * Try to intuit which kind of manual parser should be used. If
535: * passed in by command-line (-man, -mdoc), then use that
536: * explicitly. If passed as -mandoc, then try to guess from the
1.30 kristaps 537: * line: either skip dot-lines, use -mdoc when finding `.Dt', or
1.19 kristaps 538: * default to -man, which is more lenient.
539: */
540:
1.29 kristaps 541: if (buf[0] == '.') {
542: for (i = 1; buf[i]; i++)
543: if (' ' != buf[i] && '\t' != buf[i])
544: break;
545: if (0 == buf[i])
546: return(1);
547: }
1.10 kristaps 548:
1.19 kristaps 549: switch (curp->inttype) {
550: case (INTT_MDOC):
551: if (NULL == curp->mdoc)
552: curp->mdoc = mdoc_init(curp);
553: if (NULL == (*mdoc = curp->mdoc))
554: return(0);
555: return(1);
556: case (INTT_MAN):
557: if (NULL == curp->man)
558: curp->man = man_init(curp);
559: if (NULL == (*man = curp->man))
560: return(0);
561: return(1);
562: default:
563: break;
564: }
565:
566: if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
567: if (NULL == curp->mdoc)
568: curp->mdoc = mdoc_init(curp);
569: if (NULL == (*mdoc = curp->mdoc))
570: return(0);
571: return(1);
572: }
573:
574: if (NULL == curp->man)
575: curp->man = man_init(curp);
576: if (NULL == (*man = curp->man))
577: return(0);
578: return(1);
1.10 kristaps 579: }
580:
581:
582: static int
583: moptions(enum intt *tflags, char *arg)
584: {
585:
1.17 kristaps 586: if (0 == strcmp(arg, "doc"))
1.10 kristaps 587: *tflags = INTT_MDOC;
1.19 kristaps 588: else if (0 == strcmp(arg, "andoc"))
589: *tflags = INTT_AUTO;
1.17 kristaps 590: else if (0 == strcmp(arg, "an"))
1.10 kristaps 591: *tflags = INTT_MAN;
592: else {
1.57 kristaps 593: fprintf(stderr, "%s: Bad argument\n", arg);
1.10 kristaps 594: return(0);
595: }
596:
597: return(1);
1.1 kristaps 598: }
599:
600:
601: static int
1.60 kristaps 602: toptions(struct curparse *curp, char *arg)
1.1 kristaps 603: {
604:
605: if (0 == strcmp(arg, "ascii"))
1.60 kristaps 606: curp->outtype = OUTT_ASCII;
607: else if (0 == strcmp(arg, "lint")) {
608: curp->outtype = OUTT_LINT;
609: curp->wflags |= WARN_WALL;
610: curp->fflags |= FL_STRICT;
611: }
1.1 kristaps 612: else if (0 == strcmp(arg, "tree"))
1.60 kristaps 613: curp->outtype = OUTT_TREE;
1.43 kristaps 614: else if (0 == strcmp(arg, "html"))
1.60 kristaps 615: curp->outtype = OUTT_HTML;
1.59 kristaps 616: else if (0 == strcmp(arg, "xhtml"))
1.60 kristaps 617: curp->outtype = OUTT_XHTML;
1.1 kristaps 618: else {
1.57 kristaps 619: fprintf(stderr, "%s: Bad argument\n", arg);
1.1 kristaps 620: return(0);
621: }
622:
623: return(1);
624: }
625:
626:
627: static int
628: foptions(int *fflags, char *arg)
629: {
1.34 kristaps 630: char *v, *o;
1.50 kristaps 631: const char *toks[8];
1.1 kristaps 632:
633: toks[0] = "ign-scope";
1.24 kristaps 634: toks[1] = "no-ign-escape";
635: toks[2] = "no-ign-macro";
1.62 kristaps 636: toks[3] = "ign-errors";
637: toks[4] = "strict";
638: toks[5] = "ign-escape";
639: toks[6] = NULL;
1.1 kristaps 640:
1.34 kristaps 641: while (*arg) {
642: o = arg;
1.45 kristaps 643: switch (getsubopt(&arg, UNCONST(toks), &v)) {
1.1 kristaps 644: case (0):
1.60 kristaps 645: *fflags |= FL_IGN_SCOPE;
1.1 kristaps 646: break;
647: case (1):
1.60 kristaps 648: *fflags |= FL_NIGN_ESCAPE;
1.1 kristaps 649: break;
650: case (2):
1.60 kristaps 651: *fflags |= FL_NIGN_MACRO;
1.1 kristaps 652: break;
1.20 kristaps 653: case (3):
1.62 kristaps 654: *fflags |= FL_IGN_ERRORS;
1.24 kristaps 655: break;
656: case (4):
1.62 kristaps 657: *fflags |= FL_STRICT;
1.39 kristaps 658: break;
659: case (5):
1.60 kristaps 660: *fflags &= ~FL_NIGN_ESCAPE;
1.50 kristaps 661: break;
1.1 kristaps 662: default:
1.57 kristaps 663: fprintf(stderr, "%s: Bad argument\n", o);
1.1 kristaps 664: return(0);
665: }
1.34 kristaps 666: }
1.1 kristaps 667:
668: return(1);
669: }
670:
671:
672: static int
673: woptions(int *wflags, char *arg)
674: {
1.34 kristaps 675: char *v, *o;
1.45 kristaps 676: const char *toks[3];
1.1 kristaps 677:
678: toks[0] = "all";
1.36 kristaps 679: toks[1] = "error";
680: toks[2] = NULL;
1.1 kristaps 681:
1.34 kristaps 682: while (*arg) {
683: o = arg;
1.45 kristaps 684: switch (getsubopt(&arg, UNCONST(toks), &v)) {
1.1 kristaps 685: case (0):
686: *wflags |= WARN_WALL;
687: break;
688: case (1):
689: *wflags |= WARN_WERR;
690: break;
691: default:
1.57 kristaps 692: fprintf(stderr, "%s: Bad argument\n", o);
1.1 kristaps 693: return(0);
694: }
1.34 kristaps 695: }
1.1 kristaps 696:
697: return(1);
698: }
699:
700:
1.2 kristaps 701: /* ARGSUSED */
1.1 kristaps 702: static int
703: merr(void *arg, int line, int col, const char *msg)
704: {
1.5 kristaps 705: struct curparse *curp;
706:
707: curp = (struct curparse *)arg;
1.36 kristaps 708:
1.40 kristaps 709: (void)fprintf(stderr, "%s:%d:%d: error: %s\n",
710: curp->file, line, col + 1, msg);
1.27 kristaps 711:
1.64 kristaps 712: with_error = 1;
713:
1.1 kristaps 714: return(0);
715: }
716:
717:
718: static int
1.37 kristaps 719: mwarn(void *arg, int line, int col, const char *msg)
1.1 kristaps 720: {
1.5 kristaps 721: struct curparse *curp;
1.1 kristaps 722:
1.5 kristaps 723: curp = (struct curparse *)arg;
1.1 kristaps 724:
1.36 kristaps 725: if ( ! (curp->wflags & WARN_WALL))
726: return(1);
727:
1.40 kristaps 728: (void)fprintf(stderr, "%s:%d:%d: warning: %s\n",
729: curp->file, line, col + 1, msg);
1.1 kristaps 730:
1.64 kristaps 731: with_warning = 1;
732: if (curp->wflags & WARN_WERR) {
733: with_error = 1;
734: return(0);
735: }
736:
737: return(1);
1.1 kristaps 738: }
739:
CVSweb