]>
git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
60bf8943773beb4d4c8372af3341e2bc00dbfc9d
1 /* $Id: mdocml.c,v 1.22 2008/12/15 02:23:12 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)
37 #define MD_WARN_ALL (1 << 0)
38 #define MD_WARN_ERR (1 << 1)
49 static void usage(void);
51 static int parse_begin(struct md_parse
*);
52 static int parse_leave(struct md_parse
*, int);
53 static int io_begin(struct md_parse
*);
54 static int io_leave(struct md_parse
*, int);
55 static int buf_begin(struct md_parse
*);
56 static int buf_leave(struct md_parse
*, int);
58 static int msg_err(void *, int, int, enum mdoc_err
);
59 static int msg_warn(void *, int, int, enum mdoc_warn
);
60 static void msg_msg(void *, int, const char *);
63 extern int getsubopt(char **, char *const *, char **);
67 main(int argc
, char *argv
[])
70 struct md_parse parser
;
74 char *toks
[] = { "all", "error", NULL
};
79 (void)memset(&parser
, 0, sizeof(struct md_parse
));
81 while (-1 != (c
= getopt(argc
, argv
, "vW:")))
89 switch (getsubopt(&opts
, toks
, &v
)) {
91 parser
.warn
|= MD_WARN_ALL
;
94 parser
.warn
|= MD_WARN_ERR
;
111 parser
.name
= *argv
++;
113 if ( ! io_begin(&parser
))
114 return(EXIT_FAILURE
);
116 return(EXIT_SUCCESS
);
121 io_leave(struct md_parse
*p
, int code
)
124 if (-1 == p
->fd
|| STDIN_FILENO
== p
->fd
)
127 if (-1 == close(p
->fd
)) {
136 io_begin(struct md_parse
*p
)
139 p
->fd
= STDIN_FILENO
;
140 if (0 != strncmp(p
->name
, "-", 1))
141 if (-1 == (p
->fd
= open(p
->name
, O_RDONLY
, 0))) {
143 return(io_leave(p
, 0));
146 return(io_leave(p
, buf_begin(p
)));
151 buf_leave(struct md_parse
*p
, int code
)
161 buf_begin(struct md_parse
*p
)
165 if (-1 == fstat(p
->fd
, &st
)) {
170 p
->bufsz
= MAX(st
.st_blksize
, BUFSIZ
);
172 if (NULL
== (p
->buf
= malloc(p
->bufsz
))) {
174 return(buf_leave(p
, 0));
177 return(buf_leave(p
, parse_begin(p
)));
182 print_node(const struct mdoc_node
*n
, int indent
)
189 assert(NULL
== n
->child
);
194 p
= mdoc_macronames
[n
->data
.body
.tok
];
198 p
= mdoc_macronames
[n
->data
.head
.tok
];
202 assert(NULL
== n
->child
);
203 p
= mdoc_macronames
[n
->data
.elem
.tok
];
207 p
= mdoc_macronames
[n
->data
.block
.tok
];
215 for (i
= 0; i
< indent
; i
++)
217 (void)printf("%s (%s)\n", p
, t
);
220 print_node(n
->child
, indent
+ 1);
222 print_node(n
->next
, indent
);
227 parse_leave(struct md_parse
*p
, int code
)
229 const struct mdoc_node
*n
;
232 if ((n
= mdoc_result(p
->mdoc
)))
241 parse_begin(struct md_parse
*p
)
245 char line
[256], sv
[256];
248 cb
.mdoc_err
= msg_err
;
249 cb
.mdoc_warn
= msg_warn
;
250 cb
.mdoc_msg
= msg_msg
;
252 if (NULL
== (p
->mdoc
= mdoc_alloc(p
, &cb
)))
253 return(parse_leave(p
, 0));
259 if (-1 == (sz
= read(p
->fd
, p
->buf
, p
->bufsz
))) {
261 return(parse_leave(p
, 0));
265 for (i
= 0; i
< sz
; i
++) {
266 if ('\n' != p
->buf
[i
]) {
267 if (pos
< sizeof(line
)) {
270 line
[pos
++] = p
->buf
[i
];
273 warnx("%s: line %d too long",
275 return(parse_leave(p
, 0));
278 line
[(int)pos
] = sv
[(int)pos
] = 0;
279 if ( ! mdoc_parseln(p
->mdoc
, line
))
280 return(parse_leave(p
, 0));
287 return(parse_leave(p
, 1));
292 msg_err(void *arg
, int tok
, int col
, enum mdoc_err type
)
298 p
= (struct md_parse
*)arg
;
303 case (ERR_SYNTAX_QUOTE
):
304 lit
= "syntax: unterminated quotation";
306 case (ERR_SYNTAX_WS
):
307 lit
= "syntax: whitespace in argument";
309 case (ERR_SCOPE_BREAK
):
310 /* Which scope is broken? */
311 fmt
= "macro `%s' breaks prior explicit scope";
313 case (ERR_MACRO_NOTSUP
):
314 fmt
= "macro `%s' not supported";
316 case (ERR_MACRO_NOTCALL
):
317 fmt
= "macro `%s' not callable";
320 fmt
= "macro `%s' expects one or more arguments";
328 (void)fprintf(stderr
, "%s:%d: error: ",
330 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
332 (void)fprintf(stderr
, "%s:%d: error: %s",
333 p
->name
, p
->lnn
, lit
);
336 (void)fprintf(stderr
, " (column %d)\n", col
);
340 (void)fprintf(stderr
, "\nFrom: %s\n ", p
->line
);
341 for (i
= 0; i
< col
; i
++)
342 (void)fprintf(stderr
, " ");
343 (void)fprintf(stderr
, "^\n");
350 msg_msg(void *arg
, int col
, const char *msg
)
355 p
= (struct md_parse
*)arg
;
360 (void)printf("%s:%d: %s", p
->name
, p
->lnn
, msg
);
363 (void)printf(" (column %d)\n", col
);
367 (void)printf("\nFrom: %s\n ", p
->line
);
368 for (i
= 0; i
< col
; i
++)
375 msg_warn(void *arg
, int tok
, int col
, enum mdoc_warn type
)
380 extern char *__progname
;
382 p
= (struct md_parse
*)arg
;
384 if ( ! (p
->warn
& MD_WARN_ALL
))
390 case (WARN_SYNTAX_WS_EOLN
):
391 lit
= "syntax: whitespace at end-of-line";
393 case (WARN_SYNTAX_MACLIKE
):
394 lit
= "syntax: macro-like argument";
396 case (WARN_ARGS_GE1
):
397 fmt
= "macro `%s' suggests one or more arguments";
405 (void)fprintf(stderr
, "%s:%d: warning: ",
407 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
409 (void)fprintf(stderr
, "%s:%d: warning: %s",
410 p
->name
, p
->lnn
, lit
);
413 (void)fprintf(stderr
, "\nFrom: %s\n ", p
->line
);
414 for (i
= 0; i
< col
; i
++)
415 (void)fprintf(stderr
, " ");
416 (void)fprintf(stderr
, "^\n");
418 (void)fprintf(stderr
, " (column %d)\n", col
);
420 if (p
->warn
& MD_WARN_ERR
) {
421 (void)fprintf(stderr
, "%s: considering warnings as "
422 "errors\n", __progname
);
433 extern char *__progname
;
435 (void)fprintf(stderr
, "usage: %s [-v] [-Wwarn...] [infile]\n",