]>
git.cameronkatri.com Git - mandoc.git/blob - main.c
3601b7af4bdae72c8129a9bccffcfedc1ebbc84d
1 /* $Id: main.c,v 1.12 2009/03/23 15:41:09 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
33 extern int getsubopt(char **, char * const *, char **);
35 # define __dead __attribute__((__noreturn__))
37 #elif defined(__FreeBSD__)
39 # define __dead __dead2
51 #define WARN_WALL 0x03 /* All-warnings mask. */
52 #define WARN_WCOMPAT (1 << 0) /* Compatibility warnings. */
53 #define WARN_WSYNTAX (1 << 1) /* Syntax warnings. */
54 #define WARN_WERR (1 << 2) /* Warnings->errors. */
70 typedef int (*out_run
)(void *, const struct man
*,
72 typedef void (*out_free
)(void *);
74 extern char *__progname
;
76 extern void *ascii_alloc(void);
77 extern void *latin1_alloc(void);
78 extern void *utf8_alloc(void);
79 extern int terminal_run(void *, const struct man
*,
81 extern int tree_run(void *, const struct man
*,
83 extern void terminal_free(void *);
85 static int foptions(int *, char *);
86 static int toptions(enum outt
*, char *);
87 static int moptions(enum intt
*, char *);
88 static int woptions(int *, char *);
89 static int merr(void *, int, int, const char *);
90 static int mwarn(void *, int, int,
91 enum mdoc_warn
, const char *);
92 static int file(struct buf
*, struct buf
*,
94 struct man
*, struct mdoc
*);
95 static int fdesc(struct buf
*, struct buf
*,
97 struct man
*, struct mdoc
*);
99 __dead
static void version(void);
100 __dead
static void usage(void);
104 main(int argc
, char *argv
[])
116 struct curparse curp
;
119 outtype
= OUTT_ASCII
;
122 bzero(&curp
, sizeof(struct curparse
));
125 while (-1 != (c
= getopt(argc
, argv
, "f:m:VW:T:")))
128 if ( ! foptions(&fflags
, optarg
))
132 if ( ! moptions(&inttype
, optarg
))
136 if ( ! toptions(&outtype
, optarg
))
140 if ( ! woptions(&curp
.wflags
, optarg
))
155 * Allocate the appropriate front-end. Note that utf8, ascii
156 * and latin1 all resolve to the terminal front-end with
157 * different encodings (see terminal.c). Not all frontends have
158 * cleanup or alloc routines.
163 outdata
= latin1_alloc();
164 outrun
= terminal_run
;
165 outfree
= terminal_free
;
168 outdata
= utf8_alloc();
169 outrun
= terminal_run
;
170 outfree
= terminal_free
;
183 outdata
= ascii_alloc();
184 outrun
= terminal_run
;
185 outfree
= terminal_free
;
190 * All callbacks route into here, where we print them onto the
191 * screen. XXX - for now, no path for debugging messages.
196 cb
.mdoc_warn
= mwarn
;
198 bzero(&ln
, sizeof(struct buf
));
199 bzero(&blk
, sizeof(struct buf
));
209 mdoc
= mdoc_alloc(&curp
, fflags
, &cb
);
214 * Loop around available files.
218 curp
.file
= "<stdin>";
220 c
= fdesc(&blk
, &ln
, "stdin",
221 STDIN_FILENO
, man
, mdoc
);
223 if (c
&& NULL
== outrun
)
225 else if (c
&& outrun
&& (*outrun
)(outdata
, man
, mdoc
))
230 c
= file(&blk
, &ln
, *argv
, man
, mdoc
);
233 if (outrun
&& ! (*outrun
)(outdata
, man
, mdoc
))
256 return(rc
? EXIT_SUCCESS
: EXIT_FAILURE
);
264 (void)printf("%s %s\n", __progname
, VERSION
);
274 (void)fprintf(stderr
, "usage: %s [-V] [-foption...] "
275 "[-mformat] [-Toutput] [-Werr...]\n",
283 file(struct buf
*blk
, struct buf
*ln
, const char *file
,
284 struct man
*man
, struct mdoc
*mdoc
)
288 if (-1 == (fd
= open(file
, O_RDONLY
, 0))) {
293 c
= fdesc(blk
, ln
, file
, fd
, man
, mdoc
);
303 fdesc(struct buf
*blk
, struct buf
*ln
,
304 const char *f
, int fd
,
305 struct man
*man
, struct mdoc
*mdoc
)
312 assert( ! (man
&& mdoc
));
315 * Two buffers: ln and buf. buf is the input buffer, optimised
316 * for each file's block size. ln is a line buffer. Both
317 * growable, hence passed in by ptr-ptr.
322 if (-1 == fstat(fd
, &st
))
324 else if ((size_t)st
.st_blksize
> sz
)
328 blk
->buf
= realloc(blk
->buf
, sz
);
329 if (NULL
== blk
->buf
)
335 * Fill buf with file blocksize and parse newlines into ln.
338 for (lnn
= 1, pos
= 0; ; ) {
339 if (-1 == (ssz
= read(fd
, blk
->buf
, sz
))) {
345 for (i
= 0; i
< (int)ssz
; i
++) {
346 if (pos
>= (int)ln
->sz
) {
347 ln
->sz
+= 256; /* Step-size. */
348 ln
->buf
= realloc(ln
->buf
, ln
->sz
);
353 if ('\n' != blk
->buf
[i
]) {
354 ln
->buf
[pos
++] = blk
->buf
[i
];
358 /* Check for CPP-escaped newline. */
360 if (pos
> 0 && '\\' == ln
->buf
[pos
- 1]) {
361 for (j
= pos
- 1; j
>= 0; j
--)
362 if ('\\' != ln
->buf
[j
])
365 if ( ! ((pos
- j
) % 2)) {
373 if (mdoc
&& ! mdoc_parseln(mdoc
, lnn
, ln
->buf
))
375 if (man
&& ! man_parseln(man
, lnn
, ln
->buf
))
383 return(mdoc_endparse(mdoc
));
385 return(man_endparse(man
));
390 moptions(enum intt
*tflags
, char *arg
)
393 if (0 == strcmp(arg
, "mdoc"))
395 else if (0 == strcmp(arg
, "man"))
398 warnx("bad argument: -m%s", arg
);
407 toptions(enum outt
*tflags
, char *arg
)
410 if (0 == strcmp(arg
, "ascii"))
411 *tflags
= OUTT_ASCII
;
412 else if (0 == strcmp(arg
, "latin1"))
413 *tflags
= OUTT_LATIN1
;
414 else if (0 == strcmp(arg
, "utf8"))
416 else if (0 == strcmp(arg
, "lint"))
418 else if (0 == strcmp(arg
, "tree"))
421 warnx("bad argument: -T%s", arg
);
430 * Parse out the options for [-fopt...] setting compiler options. These
431 * can be comma-delimited or called again.
434 foptions(int *fflags
, char *arg
)
439 toks
[0] = "ign-scope";
440 toks
[1] = "ign-escape";
441 toks
[2] = "ign-macro";
445 switch (getsubopt(&arg
, toks
, &v
)) {
447 *fflags
|= MDOC_IGN_SCOPE
;
450 *fflags
|= MDOC_IGN_ESCAPE
;
453 *fflags
|= MDOC_IGN_MACRO
;
456 warnx("bad argument: -f%s", arg
);
465 * Parse out the options for [-Werr...], which sets warning modes.
466 * These can be comma-delimited or called again.
469 woptions(int *wflags
, char *arg
)
481 switch (getsubopt(&arg
, toks
, &v
)) {
483 *wflags
|= WARN_WALL
;
486 *wflags
|= WARN_WCOMPAT
;
489 *wflags
|= WARN_WSYNTAX
;
492 *wflags
|= WARN_WERR
;
495 warnx("bad argument: -W%s", arg
);
505 merr(void *arg
, int line
, int col
, const char *msg
)
507 struct curparse
*curp
;
509 curp
= (struct curparse
*)arg
;
511 warnx("%s:%d: error: %s (column %d)",
512 curp
->file
, line
, msg
, col
);
518 mwarn(void *arg
, int line
, int col
,
519 enum mdoc_warn type
, const char *msg
)
521 struct curparse
*curp
;
524 curp
= (struct curparse
*)arg
;
530 if (curp
->wflags
& WARN_WCOMPAT
)
535 if (curp
->wflags
& WARN_WSYNTAX
)
541 warnx("%s:%d: %s warning: %s (column %d)",
542 curp
->file
, line
, wtype
, msg
, col
);
544 if ( ! (curp
->wflags
& WARN_WERR
))
547 warnx("%s: considering warnings as errors",