]>
git.cameronkatri.com Git - mandoc.git/blob - mdocterm.c
1 /* $Id: mdocterm.c,v 1.1 2009/02/21 21:00:06 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>
34 #define MD_LINE_SZ (256) /* Max input line size. */
37 int warn
; /* Warning flags. */
38 #define MD_WARN_SYNTAX (1 << 0) /* Show syntax warnings. */
39 #define MD_WARN_COMPAT (1 << 1) /* Show compat warnings. */
40 #define MD_WARN_ALL (0x03) /* Show all warnings. */
41 #define MD_WARN_ERR (1 << 2) /* Make warnings->errors. */
42 int dbg
; /* Debug level. */
43 struct mdoc
*mdoc
; /* Active parser. */
44 char *buf
; /* Input buffer. */
45 u_long bufsz
; /* Input buffer size. */
46 char *in
; /* Input file name. */
47 int fdin
; /* Input file desc. */
50 extern char *__progname
;
52 static void usage(void);
53 static int getsopts(struct md_parse
*, char *);
54 static int parse(struct md_parse
*);
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 **);
65 main(int argc
, char *argv
[])
74 (void)memset(&p
, 0, sizeof(struct md_parse
));
76 while (-1 != (c
= getopt(argc
, argv
, "vW:")))
82 if ( ! getsopts(&p
, optarg
))
93 /* Initialise the input file. */
96 p
.fdin
= STDIN_FILENO
;
100 p
.fdin
= open(p
.in
, O_RDONLY
, 0);
105 /* Allocate a buffer to be BUFSIZ/block size. */
107 if (-1 == fstat(p
.fdin
, &st
)) {
111 p
.bufsz
= MAX(st
.st_blksize
, BUFSIZ
);
113 p
.buf
= malloc(p
.bufsz
);
117 /* Allocate the parser. */
119 cb
.mdoc_err
= msg_err
;
120 cb
.mdoc_warn
= msg_warn
;
121 cb
.mdoc_msg
= msg_msg
;
123 p
.mdoc
= mdoc_alloc(&p
, &cb
);
125 /* Parse the input file. */
130 if (STDIN_FILENO
!= p
.fdin
&& -1 == close(p
.fdin
))
135 return(EXIT_FAILURE
);
138 /* If the parse succeeded, print it out. */
140 termprint(mdoc_node(p
.mdoc
), mdoc_meta(p
.mdoc
));
143 return(EXIT_SUCCESS
);
148 getsopts(struct md_parse
*p
, char *arg
)
151 char *toks
[] = { "all", "compat",
152 "syntax", "error", NULL
};
155 switch (getsubopt(&arg
, toks
, &v
)) {
157 p
->warn
|= MD_WARN_ALL
;
160 p
->warn
|= MD_WARN_COMPAT
;
163 p
->warn
|= MD_WARN_SYNTAX
;
166 p
->warn
|= MD_WARN_ERR
;
178 parse(struct md_parse
*p
)
182 char line
[MD_LINE_SZ
];
186 * This is a little more complicated than fgets. TODO: have
187 * some benchmarks that show it's faster (note that I want to
188 * check many, many manuals simultaneously, so speed is
189 * important). Fill a buffer (sized to the block size) with a
190 * single read, then parse \n-terminated lines into a line
191 * buffer, which is passed to the parser. Hard-code the line
192 * buffer to a particular size -- a reasonable assumption.
195 for (lnn
= 1, pos
= 0; ; ) {
196 if (-1 == (sz
= read(p
->fdin
, p
->buf
, p
->bufsz
))) {
202 for (i
= 0; i
< sz
; i
++) {
203 if ('\n' != p
->buf
[i
]) {
204 if (pos
< sizeof(line
)) {
205 line
[(int)pos
++] = p
->buf
[(int)i
];
208 warnx("%s: line %d too long", p
->in
, lnn
);
213 if ( ! mdoc_parseln(p
->mdoc
, lnn
, line
))
221 return(mdoc_endparse(p
->mdoc
));
226 msg_err(void *arg
, int line
, int col
, const char *msg
)
230 p
= (struct md_parse
*)arg
;
232 warnx("%s:%d: error: %s (column %d)",
233 p
->in
, line
, msg
, col
);
239 msg_msg(void *arg
, int line
, int col
, const char *msg
)
243 p
= (struct md_parse
*)arg
;
248 warnx("%s:%d: debug: %s (column %d)",
249 p
->in
, line
, msg
, col
);
254 msg_warn(void *arg
, int line
, int col
,
255 enum mdoc_warn type
, const char *msg
)
259 p
= (struct md_parse
*)arg
;
263 if (p
->warn
& MD_WARN_COMPAT
)
267 if (p
->warn
& MD_WARN_SYNTAX
)
272 warnx("%s:%d: warning: %s (column %d)",
273 p
->in
, line
, msg
, col
);
275 if ( ! (p
->warn
& MD_WARN_ERR
))
278 warnx("%s: considering warnings as errors", __progname
);
287 warnx("usage: %s [-v] [-Wwarn...] [infile]", __progname
);