Print this page
Update to 1.12.3.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mandoc/main.c
+++ new/usr/src/cmd/mandoc/main.c
1 -/* $Id: main.c,v 1.165 2011/10/06 22:29:12 kristaps Exp $ */
1 +/* $Id: main.c,v 1.167 2012/11/19 17:22:26 schwarze Exp $ */
2 2 /*
3 3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 - * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
4 + * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
5 5 *
6 6 * Permission to use, copy, modify, and distribute this software for any
7 7 * purpose with or without fee is hereby granted, provided that the above
8 8 * copyright notice and this permission notice appear in all copies.
9 9 *
10 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 17 */
18 18 #ifdef HAVE_CONFIG_H
19 19 #include "config.h"
20 20 #endif
21 21
22 22 #include <assert.h>
23 23 #include <stdio.h>
24 24 #include <stdint.h>
25 25 #include <stdlib.h>
26 26 #include <string.h>
27 27 #include <unistd.h>
28 28
29 29 #include "mandoc.h"
30 30 #include "main.h"
31 31 #include "mdoc.h"
32 32 #include "man.h"
33 33
34 34 #if !defined(__GNUC__) || (__GNUC__ < 2)
35 35 # if !defined(lint)
36 36 # define __attribute__(x)
37 37 # endif
38 38 #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
39 39
40 40 typedef void (*out_mdoc)(void *, const struct mdoc *);
41 41 typedef void (*out_man)(void *, const struct man *);
42 42 typedef void (*out_free)(void *);
43 43
44 44 enum outt {
45 45 OUTT_ASCII = 0, /* -Tascii */
46 46 OUTT_LOCALE, /* -Tlocale */
47 47 OUTT_UTF8, /* -Tutf8 */
48 48 OUTT_TREE, /* -Ttree */
49 49 OUTT_MAN, /* -Tman */
50 50 OUTT_HTML, /* -Thtml */
51 51 OUTT_XHTML, /* -Txhtml */
52 52 OUTT_LINT, /* -Tlint */
53 53 OUTT_PS, /* -Tps */
54 54 OUTT_PDF /* -Tpdf */
55 55 };
56 56
57 57 struct curparse {
58 58 struct mparse *mp;
59 59 enum mandoclevel wlevel; /* ignore messages below this */
60 60 int wstop; /* stop after a file with a warning */
61 61 enum outt outtype; /* which output to use */
62 62 out_mdoc outmdoc; /* mdoc output ptr */
63 63 out_man outman; /* man output ptr */
64 64 out_free outfree; /* free output ptr */
65 65 void *outdata; /* data for output */
66 66 char outopts[BUFSIZ]; /* buf of output opts */
67 67 };
68 68
69 69 static int moptions(enum mparset *, char *);
70 70 static void mmsg(enum mandocerr, enum mandoclevel,
71 71 const char *, int, int, const char *);
72 72 static void parse(struct curparse *, int,
73 73 const char *, enum mandoclevel *);
74 74 static int toptions(struct curparse *, char *);
75 75 static void usage(void) __attribute__((noreturn));
76 76 static void version(void) __attribute__((noreturn));
77 77 static int woptions(struct curparse *, char *);
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
78 78
79 79 static const char *progname;
80 80
81 81 int
82 82 main(int argc, char *argv[])
83 83 {
84 84 int c;
85 85 struct curparse curp;
86 86 enum mparset type;
87 87 enum mandoclevel rc;
88 + char *defos;
88 89
89 90 progname = strrchr(argv[0], '/');
90 91 if (progname == NULL)
91 92 progname = argv[0];
92 93 else
93 94 ++progname;
94 95
95 96 memset(&curp, 0, sizeof(struct curparse));
96 97
97 98 type = MPARSE_AUTO;
98 99 curp.outtype = OUTT_ASCII;
99 100 curp.wlevel = MANDOCLEVEL_FATAL;
101 + defos = NULL;
100 102
101 103 /* LINTED */
102 - while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
104 + while (-1 != (c = getopt(argc, argv, "I:m:O:T:VW:")))
103 105 switch (c) {
106 + case ('I'):
107 + if (strncmp(optarg, "os=", 3)) {
108 + fprintf(stderr, "-I%s: Bad argument\n",
109 + optarg);
110 + return((int)MANDOCLEVEL_BADARG);
111 + }
112 + if (defos) {
113 + fprintf(stderr, "-I%s: Duplicate argument\n",
114 + optarg);
115 + return((int)MANDOCLEVEL_BADARG);
116 + }
117 + defos = mandoc_strdup(optarg + 3);
118 + break;
104 119 case ('m'):
105 120 if ( ! moptions(&type, optarg))
106 121 return((int)MANDOCLEVEL_BADARG);
107 122 break;
108 123 case ('O'):
109 124 (void)strlcat(curp.outopts, optarg, BUFSIZ);
110 125 (void)strlcat(curp.outopts, ",", BUFSIZ);
111 126 break;
112 127 case ('T'):
113 128 if ( ! toptions(&curp, optarg))
114 129 return((int)MANDOCLEVEL_BADARG);
115 130 break;
116 131 case ('W'):
117 132 if ( ! woptions(&curp, optarg))
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
118 133 return((int)MANDOCLEVEL_BADARG);
119 134 break;
120 135 case ('V'):
121 136 version();
122 137 /* NOTREACHED */
123 138 default:
124 139 usage();
125 140 /* NOTREACHED */
126 141 }
127 142
128 - curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
143 + curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp, defos);
129 144
130 145 /*
131 146 * Conditionally start up the lookaside buffer before parsing.
132 147 */
133 148 if (OUTT_MAN == curp.outtype)
134 149 mparse_keep(curp.mp);
135 150
136 151 argc -= optind;
137 152 argv += optind;
138 153
139 154 rc = MANDOCLEVEL_OK;
140 155
141 156 if (NULL == *argv)
142 157 parse(&curp, STDIN_FILENO, "<stdin>", &rc);
143 158
144 159 while (*argv) {
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
145 160 parse(&curp, -1, *argv, &rc);
146 161 if (MANDOCLEVEL_OK != rc && curp.wstop)
147 162 break;
148 163 ++argv;
149 164 }
150 165
151 166 if (curp.outfree)
152 167 (*curp.outfree)(curp.outdata);
153 168 if (curp.mp)
154 169 mparse_free(curp.mp);
170 + free(defos);
155 171
156 172 return((int)rc);
157 173 }
158 174
159 175 static void
160 176 version(void)
161 177 {
162 178
163 179 printf("%s %s\n", progname, VERSION);
164 180 exit((int)MANDOCLEVEL_OK);
165 181 }
166 182
167 183 static void
168 184 usage(void)
169 185 {
170 186
171 187 fprintf(stderr, "usage: %s "
172 188 "[-V] "
173 - "[-foption] "
189 + "[-Ios=name] "
174 190 "[-mformat] "
175 191 "[-Ooption] "
176 192 "[-Toutput] "
177 - "[-Wlevel] "
178 - "[file...]\n",
193 + "[-Wlevel]\n"
194 + "\t [file ...]\n",
179 195 progname);
180 196
181 197 exit((int)MANDOCLEVEL_BADARG);
182 198 }
183 199
184 200 static void
185 201 parse(struct curparse *curp, int fd,
186 202 const char *file, enum mandoclevel *level)
187 203 {
188 204 enum mandoclevel rc;
189 205 struct mdoc *mdoc;
190 206 struct man *man;
191 207
192 208 /* Begin by parsing the file itself. */
193 209
194 210 assert(file);
195 211 assert(fd >= -1);
196 212
197 213 rc = mparse_readfd(curp->mp, fd, file);
198 214
199 215 /* Stop immediately if the parse has failed. */
200 216
201 217 if (MANDOCLEVEL_FATAL <= rc)
202 218 goto cleanup;
203 219
204 220 /*
205 221 * With -Wstop and warnings or errors of at least the requested
206 222 * level, do not produce output.
207 223 */
208 224
209 225 if (MANDOCLEVEL_OK != rc && curp->wstop)
210 226 goto cleanup;
211 227
212 228 /* If unset, allocate output dev now (if applicable). */
213 229
214 230 if ( ! (curp->outman && curp->outmdoc)) {
215 231 switch (curp->outtype) {
216 232 case (OUTT_XHTML):
217 233 curp->outdata = xhtml_alloc(curp->outopts);
218 234 curp->outfree = html_free;
219 235 break;
220 236 case (OUTT_HTML):
221 237 curp->outdata = html_alloc(curp->outopts);
222 238 curp->outfree = html_free;
223 239 break;
224 240 case (OUTT_UTF8):
225 241 curp->outdata = utf8_alloc(curp->outopts);
226 242 curp->outfree = ascii_free;
227 243 break;
228 244 case (OUTT_LOCALE):
229 245 curp->outdata = locale_alloc(curp->outopts);
230 246 curp->outfree = ascii_free;
231 247 break;
232 248 case (OUTT_ASCII):
233 249 curp->outdata = ascii_alloc(curp->outopts);
234 250 curp->outfree = ascii_free;
235 251 break;
236 252 case (OUTT_PDF):
237 253 curp->outdata = pdf_alloc(curp->outopts);
238 254 curp->outfree = pspdf_free;
239 255 break;
240 256 case (OUTT_PS):
241 257 curp->outdata = ps_alloc(curp->outopts);
242 258 curp->outfree = pspdf_free;
243 259 break;
244 260 default:
245 261 break;
246 262 }
247 263
248 264 switch (curp->outtype) {
249 265 case (OUTT_HTML):
250 266 /* FALLTHROUGH */
251 267 case (OUTT_XHTML):
252 268 curp->outman = html_man;
253 269 curp->outmdoc = html_mdoc;
254 270 break;
255 271 case (OUTT_TREE):
256 272 curp->outman = tree_man;
257 273 curp->outmdoc = tree_mdoc;
258 274 break;
259 275 case (OUTT_MAN):
260 276 curp->outmdoc = man_mdoc;
261 277 curp->outman = man_man;
262 278 break;
263 279 case (OUTT_PDF):
264 280 /* FALLTHROUGH */
265 281 case (OUTT_ASCII):
266 282 /* FALLTHROUGH */
267 283 case (OUTT_UTF8):
268 284 /* FALLTHROUGH */
269 285 case (OUTT_LOCALE):
270 286 /* FALLTHROUGH */
271 287 case (OUTT_PS):
272 288 curp->outman = terminal_man;
273 289 curp->outmdoc = terminal_mdoc;
274 290 break;
275 291 default:
276 292 break;
277 293 }
278 294 }
279 295
280 296 mparse_result(curp->mp, &mdoc, &man);
281 297
282 298 /* Execute the out device, if it exists. */
283 299
284 300 if (man && curp->outman)
285 301 (*curp->outman)(curp->outdata, man);
286 302 if (mdoc && curp->outmdoc)
287 303 (*curp->outmdoc)(curp->outdata, mdoc);
288 304
289 305 cleanup:
290 306
291 307 mparse_reset(curp->mp);
292 308
293 309 if (*level < rc)
294 310 *level = rc;
295 311 }
296 312
297 313 static int
298 314 moptions(enum mparset *tflags, char *arg)
299 315 {
300 316
301 317 if (0 == strcmp(arg, "doc"))
302 318 *tflags = MPARSE_MDOC;
303 319 else if (0 == strcmp(arg, "andoc"))
304 320 *tflags = MPARSE_AUTO;
305 321 else if (0 == strcmp(arg, "an"))
306 322 *tflags = MPARSE_MAN;
307 323 else {
308 324 fprintf(stderr, "%s: Bad argument\n", arg);
309 325 return(0);
310 326 }
311 327
312 328 return(1);
313 329 }
314 330
315 331 static int
316 332 toptions(struct curparse *curp, char *arg)
317 333 {
318 334
319 335 if (0 == strcmp(arg, "ascii"))
320 336 curp->outtype = OUTT_ASCII;
321 337 else if (0 == strcmp(arg, "lint")) {
322 338 curp->outtype = OUTT_LINT;
323 339 curp->wlevel = MANDOCLEVEL_WARNING;
324 340 } else if (0 == strcmp(arg, "tree"))
325 341 curp->outtype = OUTT_TREE;
326 342 else if (0 == strcmp(arg, "man"))
327 343 curp->outtype = OUTT_MAN;
328 344 else if (0 == strcmp(arg, "html"))
329 345 curp->outtype = OUTT_HTML;
330 346 else if (0 == strcmp(arg, "utf8"))
331 347 curp->outtype = OUTT_UTF8;
332 348 else if (0 == strcmp(arg, "locale"))
333 349 curp->outtype = OUTT_LOCALE;
334 350 else if (0 == strcmp(arg, "xhtml"))
335 351 curp->outtype = OUTT_XHTML;
336 352 else if (0 == strcmp(arg, "ps"))
337 353 curp->outtype = OUTT_PS;
338 354 else if (0 == strcmp(arg, "pdf"))
339 355 curp->outtype = OUTT_PDF;
340 356 else {
341 357 fprintf(stderr, "%s: Bad argument\n", arg);
342 358 return(0);
343 359 }
344 360
345 361 return(1);
346 362 }
347 363
348 364 static int
349 365 woptions(struct curparse *curp, char *arg)
350 366 {
351 367 char *v, *o;
352 368 const char *toks[6];
353 369
354 370 toks[0] = "stop";
355 371 toks[1] = "all";
356 372 toks[2] = "warning";
357 373 toks[3] = "error";
358 374 toks[4] = "fatal";
359 375 toks[5] = NULL;
360 376
361 377 while (*arg) {
362 378 o = arg;
363 379 switch (getsubopt(&arg, UNCONST(toks), &v)) {
364 380 case (0):
365 381 curp->wstop = 1;
366 382 break;
367 383 case (1):
368 384 /* FALLTHROUGH */
369 385 case (2):
370 386 curp->wlevel = MANDOCLEVEL_WARNING;
371 387 break;
372 388 case (3):
373 389 curp->wlevel = MANDOCLEVEL_ERROR;
374 390 break;
375 391 case (4):
376 392 curp->wlevel = MANDOCLEVEL_FATAL;
377 393 break;
378 394 default:
379 395 fprintf(stderr, "-W%s: Bad argument\n", o);
380 396 return(0);
381 397 }
382 398 }
383 399
384 400 return(1);
385 401 }
386 402
387 403 static void
388 404 mmsg(enum mandocerr t, enum mandoclevel lvl,
389 405 const char *file, int line, int col, const char *msg)
390 406 {
391 407
392 408 fprintf(stderr, "%s:%d:%d: %s: %s",
393 409 file, line, col + 1,
394 410 mparse_strlevel(lvl),
395 411 mparse_strerror(t));
396 412
397 413 if (msg)
398 414 fprintf(stderr, ": %s", msg);
399 415
400 416 fputc('\n', stderr);
401 417 }
↓ open down ↓ |
213 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX