]>
git.cameronkatri.com Git - mandoc.git/blob - mmain.c
1 /* $Id: mmain.c,v 1.11 2009/03/09 13:35:09 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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.
20 #include <sys/param.h>
33 #define MD_LINE_SZ (256) /* Input line step-size. */
36 int warn
; /* Warning flags. */
37 #define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */
38 #define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */
39 #define MD_WARN_ALL (0x03) /* Show all warnings. */
40 #define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */
41 int dbg
; /* Debug level. */
42 struct mdoc
*mdoc
; /* Active parser. */
43 char *buf
; /* Input buffer. */
44 size_t bufsz
; /* Input buffer size. */
45 char *in
; /* Input file name. */
46 int fdin
; /* Input file desc. */
47 int pflags
; /* Parse flags. */
50 extern char *__progname
;
52 static int optswarn(struct mmain
*, char *);
53 static int optsopt(struct mmain
*, char *);
54 static int parse(struct mmain
*);
55 static void msg_msg(void *, int, int, const char *);
56 static int msg_err(void *, int, int, const char *);
57 static int msg_warn(void *, int, int,
58 enum mdoc_warn
, const char *);
61 extern int getsubopt(char **, char *const *, char **);
62 extern size_t strlcpy(char *, const char *, size_t);
63 extern size_t strlcat(char *, const char *, size_t);
68 * Print our and our caller's usage message.
71 mmain_usage(const char *help
)
74 warnx("usage: %s %s%s[-v] [-foption...] [-Wwarn...] [infile]", __progname
,
75 help
? help
: "", help
? " " : "");
80 * Allocate the convenience library and initialise some values.
87 if (NULL
== (p
= calloc(1, sizeof(struct mmain
))))
91 p
->fdin
= STDIN_FILENO
;
98 * Parse command-line options. Accepts a small (<28 char) opstring "u"
99 * parameter (e.g. "ho:") or NULL, a corresponding "help" string (e.g.
100 * "[-h] [-o output]" or NULL, a callback function for parsed arguments
101 * and an opaque pointer argument for that function.
104 mmain_getopt(struct mmain
*p
, int argc
, char *argv
[],
105 const char *help
, const char *u
, void *arg
,
106 int (*getopt_cb
)(void *, int, const char *))
109 char opts
[32]; /* XXX */
114 sz
= strlcpy(opts
, "VvW:f:", 32);
118 sz
= strlcat(opts
, u
, 32);
125 while (-1 != (c
= getopt(argc
, argv
, opts
)))
128 if ( ! optsopt(p
, optarg
))
135 (void)printf("%s %s\n", __progname
, VERSION
);
138 if ( ! optswarn(p
, optarg
))
146 if ((*getopt_cb
)(arg
, c
, optarg
))
152 if ((argc
-= optind
) > 0)
160 mmain_exit(struct mmain
*p
, int code
)
171 mmain_mdoc(struct mmain
*p
)
177 cb
.mdoc_err
= msg_err
;
178 cb
.mdoc_warn
= msg_warn
;
179 cb
.mdoc_msg
= msg_msg
;
181 if (0 != strcmp(p
->in
, "-"))
182 if (-1 == (p
->fdin
= open(p
->in
, O_RDONLY
, 0))) {
187 /* Allocate a buffer to be BUFSIZ/block size. */
189 if (-1 == fstat(p
->fdin
, &st
)) {
193 p
->bufsz
= (size_t)MAX(st
.st_blksize
, BUFSIZ
);
195 p
->buf
= malloc(p
->bufsz
);
199 /* Allocate the parser. */
201 p
->mdoc
= mdoc_alloc(p
, p
->pflags
, &cb
);
203 /* Parse the input file. */
208 if (STDIN_FILENO
!= p
->fdin
)
209 if (-1 == close(p
->fdin
))
212 return(c
? p
->mdoc
: NULL
);
217 optsopt(struct mmain
*p
, char *arg
)
220 char *toks
[] = { "ign-scope", "ign-escape",
224 switch (getsubopt(&arg
, toks
, &v
)) {
226 p
->pflags
|= MDOC_IGN_SCOPE
;
229 p
->pflags
|= MDOC_IGN_ESCAPE
;
232 p
->pflags
|= MDOC_IGN_MACRO
;
235 warnx("unknown -f argument");
244 optswarn(struct mmain
*p
, char *arg
)
247 char *toks
[] = { "all", "compat",
248 "syntax", "error", NULL
};
251 switch (getsubopt(&arg
, toks
, &v
)) {
253 p
->warn
|= MD_WARN_ALL
;
256 p
->warn
|= MD_WARN_COMPAT
;
259 p
->warn
|= MD_WARN_SYNTAX
;
262 p
->warn
|= MD_WARN_ERR
;
265 warnx("unknown -W argument");
274 parse(struct mmain
*p
)
277 int j
, i
, pos
, len
, lnn
;
280 for (ln
= NULL
, lnn
= 1, len
= pos
= 0; ; ) {
281 if (-1 == (sz
= read(p
->fdin
, p
->buf
, p
->bufsz
))) {
287 for (i
= 0; i
< (int)sz
; i
++) {
290 ln
= realloc(ln
, (size_t)len
);
295 if ('\n' != p
->buf
[i
]) {
296 ln
[pos
++] = p
->buf
[i
];
300 /* Check for escaped newline. */
302 if (pos
> 0 && '\\' == ln
[pos
- 1]) {
303 for (j
= pos
- 1; j
>= 0; j
--)
307 if ( ! ((pos
- j
) % 2)) {
315 if ( ! mdoc_parseln(p
->mdoc
, lnn
, ln
)) {
327 warnx("%s: file not eof-terminated", p
->in
);
328 return(mdoc_endparse(p
->mdoc
));
333 msg_err(void *arg
, int line
, int col
, const char *msg
)
337 p
= (struct mmain
*)arg
;
339 warnx("%s:%d: error: %s (column %d)",
340 p
->in
, line
, msg
, col
);
346 msg_msg(void *arg
, int line
, int col
, const char *msg
)
350 p
= (struct mmain
*)arg
;
355 warnx("%s:%d: debug: %s (column %d)",
356 p
->in
, line
, msg
, col
);
361 msg_warn(void *arg
, int line
, int col
,
362 enum mdoc_warn type
, const char *msg
)
366 p
= (struct mmain
*)arg
;
370 if (p
->warn
& MD_WARN_COMPAT
)
374 if (p
->warn
& MD_WARN_SYNTAX
)
379 warnx("%s:%d: warning: %s (column %d)",
380 p
->in
, line
, msg
, col
);
382 if ( ! (p
->warn
& MD_WARN_ERR
))
385 warnx("%s: considering warnings as errors", __progname
);