]>
git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
1 /* $Id: mdocml.c,v 1.34 2009/01/05 16:11:14 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
)
188 struct mdoc_arg
*argv
;
197 assert(NULL
== n
->child
);
198 p
= n
->data
.text
.string
;
202 p
= mdoc_macronames
[n
->data
.body
.tok
];
206 p
= mdoc_macronames
[n
->data
.head
.tok
];
210 p
= mdoc_macronames
[n
->data
.tail
.tok
];
214 p
= mdoc_macronames
[n
->data
.elem
.tok
];
216 argv
= n
->data
.elem
.argv
;
217 argc
= n
->data
.elem
.argc
;
218 params
= n
->data
.elem
.args
;
219 sz
= n
->data
.elem
.sz
;
222 p
= mdoc_macronames
[n
->data
.block
.tok
];
224 argv
= n
->data
.block
.argv
;
225 argc
= n
->data
.block
.argc
;
232 for (i
= 0; i
< indent
; i
++)
234 (void)printf("%s (%s)", p
, t
);
236 for (i
= 0; i
< (int)argc
; i
++) {
237 (void)printf(" -%s", mdoc_argnames
[argv
[i
].arg
]);
238 for (j
= 0; j
< (int)argv
[i
].sz
; j
++)
239 (void)printf(" \"%s\"", argv
[i
].value
[j
]);
242 for (i
= 0; i
< (int)sz
; i
++)
243 (void)printf(" \"%s\"", params
[i
]);
248 print_node(n
->child
, indent
+ 1);
250 print_node(n
->next
, indent
);
255 parse_leave(struct md_parse
*p
, int code
)
257 const struct mdoc_node
*n
;
260 if ((n
= mdoc_result(p
->mdoc
)))
269 parse_begin(struct md_parse
*p
)
273 char line
[256], sv
[256];
276 cb
.mdoc_err
= msg_err
;
277 cb
.mdoc_warn
= msg_warn
;
278 cb
.mdoc_msg
= msg_msg
;
280 if (NULL
== (p
->mdoc
= mdoc_alloc(p
, &cb
)))
281 return(parse_leave(p
, 0));
287 if (-1 == (sz
= read(p
->fd
, p
->buf
, p
->bufsz
))) {
289 return(parse_leave(p
, 0));
293 for (i
= 0; i
< sz
; i
++) {
294 if ('\n' != p
->buf
[i
]) {
295 if (pos
< sizeof(line
)) {
296 sv
[(int)pos
] = p
->buf
[(int)i
];
301 warnx("%s: line %d too long",
303 return(parse_leave(p
, 0));
306 line
[(int)pos
] = sv
[(int)pos
] = 0;
307 if ( ! mdoc_parseln(p
->mdoc
, line
))
308 return(parse_leave(p
, 0));
315 return(parse_leave(p
, 1));
320 msg_err(void *arg
, int tok
, int col
, enum mdoc_err type
)
326 p
= (struct md_parse
*)arg
;
331 case (ERR_SYNTAX_QUOTE
):
332 lit
= "syntax: disallowed argument quotation";
334 case (ERR_SYNTAX_UNQUOTE
):
335 lit
= "syntax: unterminated quotation";
337 case (ERR_SYNTAX_WS
):
338 lit
= "syntax: whitespace in argument";
340 case (ERR_SYNTAX_ARGFORM
):
341 fmt
= "syntax: macro `%s' arguments malformed";
343 case (ERR_SYNTAX_NOPUNCT
):
344 fmt
= "syntax: macro `%s' doesn't understand punctuation";
346 case (ERR_SYNTAX_ARG
):
347 fmt
= "syntax: unknown argument for macro `%s'";
349 case (ERR_SCOPE_BREAK
):
350 /* Which scope is broken? */
351 fmt
= "scope: macro `%s' breaks prior explicit scope";
353 case (ERR_SCOPE_NOCTX
):
354 fmt
= "scope: closure macro `%s' has no context";
356 case (ERR_SCOPE_NONEST
):
357 fmt
= "scope: macro `%s' may not be nested in the current context";
359 case (ERR_MACRO_NOTSUP
):
360 fmt
= "macro `%s' not supported";
362 case (ERR_MACRO_NOTCALL
):
363 fmt
= "macro `%s' not callable";
365 case (ERR_SEC_PROLOGUE
):
366 fmt
= "macro `%s' cannot be called in the prologue";
368 case (ERR_SEC_NPROLOGUE
):
369 fmt
= "macro `%s' called outside of prologue";
372 fmt
= "macro `%s' expects zero arguments";
375 fmt
= "macro `%s' expects one argument";
378 fmt
= "macro `%s' expects one or more arguments";
381 fmt
= "macro `%s' expects two or fewer arguments";
383 case (ERR_ARGS_MANY
):
384 fmt
= "macro `%s' has too many arguments";
386 case (ERR_SEC_PROLOGUE_OO
):
387 fmt
= "prologue macro `%s' is out-of-order";
389 case (ERR_SEC_PROLOGUE_REP
):
390 fmt
= "prologue macro `%s' repeated";
393 lit
= "`NAME' section must be first";
395 case (ERR_SYNTAX_ARGVAL
):
396 lit
= "syntax: expected value for macro argument";
398 case (ERR_SYNTAX_ARGBAD
):
399 lit
= "syntax: invalid value for macro argument";
401 case (ERR_SYNTAX_ARGMANY
):
402 lit
= "syntax: too many values for macro argument";
404 case (ERR_SYNTAX_CHILDHEAD
):
405 lit
= "syntax: expected only block-header section";
407 case (ERR_SYNTAX_CHILDBODY
):
408 lit
= "syntax: expected only a block-body section";
410 case (ERR_SYNTAX_EMPTYHEAD
):
411 lit
= "syntax: block-header section may not be empty";
413 case (ERR_SYNTAX_EMPTYBODY
):
414 lit
= "syntax: block-body section may not be empty";
422 (void)fprintf(stderr
, "%s:%d: error: ",
424 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
426 (void)fprintf(stderr
, "%s:%d: error: %s",
427 p
->name
, p
->lnn
, lit
);
431 (void)fprintf(stderr
, " (column %d)\n", col
);
433 } else if (-1 == col
) {
434 (void)fprintf(stderr
, "\nFrom: %s", p
->line
);
438 (void)fprintf(stderr
, "\nFrom: %s\n ", p
->line
);
439 for (i
= 0; i
< col
; i
++)
440 (void)fprintf(stderr
, " ");
441 (void)fprintf(stderr
, "^\n");
448 msg_msg(void *arg
, int col
, const char *msg
)
453 p
= (struct md_parse
*)arg
;
458 (void)printf("%s:%d: %s", p
->name
, p
->lnn
, msg
);
462 (void)printf(" (column %d)\n", col
);
464 } else if (-1 == col
) {
465 (void)printf("\nFrom %s\n", p
->line
);
469 (void)printf("\nFrom: %s\n ", p
->line
);
470 for (i
= 0; i
< col
; i
++)
477 msg_warn(void *arg
, int tok
, int col
, enum mdoc_warn type
)
482 extern char *__progname
;
484 p
= (struct md_parse
*)arg
;
486 if ( ! (p
->warn
& MD_WARN_ALL
))
492 case (WARN_SYNTAX_WS_EOLN
):
493 lit
= "syntax: whitespace at end-of-line";
495 case (WARN_SYNTAX_QUOTED
):
496 lit
= "syntax: quotation mark starting string";
498 case (WARN_SYNTAX_MACLIKE
):
499 lit
= "syntax: macro-like argument";
501 case (WARN_SYNTAX_ARGLIKE
):
502 lit
= "syntax: argument-like value";
504 case (WARN_SYNTAX_EMPTYBODY
):
505 lit
= "syntax: empty block-body section";
508 lit
= "section is out of conventional order";
510 case (WARN_ARGS_GE1
):
511 fmt
= "macro `%s' suggests one or more arguments";
513 case (WARN_ARGS_EQ0
):
514 fmt
= "macro `%s' suggests zero arguments";
516 case (WARN_IGN_AFTER_BLK
):
517 fmt
= "ignore: macro `%s' ignored after block macro";
519 case (WARN_IGN_OBSOLETE
):
520 fmt
= "ignore: macro `%s' is obsolete";
522 case (WARN_IGN_BEFORE_BLK
):
523 fmt
= "ignore: macro before block macro `%s' ignored";
525 case (WARN_COMPAT_TROFF
):
526 fmt
= "compat: macro `%s' behaves differently in troff and nroff";
534 (void)fprintf(stderr
, "%s:%d: warning: ",
536 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
538 (void)fprintf(stderr
, "%s:%d: warning: %s",
539 p
->name
, p
->lnn
, lit
);
542 (void)fprintf(stderr
, "\nFrom: %s\n ", p
->line
);
543 for (i
= 0; i
< col
; i
++)
544 (void)fprintf(stderr
, " ");
545 (void)fprintf(stderr
, "^\n");
547 (void)fprintf(stderr
, " (column %d)\n", col
);
549 if (p
->warn
& MD_WARN_ERR
) {
550 (void)fprintf(stderr
, "%s: considering warnings as "
551 "errors\n", __progname
);
562 extern char *__progname
;
564 (void)fprintf(stderr
, "usage: %s [-v] [-Wwarn...] [infile]\n",