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