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