]>
git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
1f29809d381582027acbfdef583c51427568d8fa
1 /* $Id: mdocml.c,v 1.39 2009/01/12 10:31:53 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, 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
;
220 p
= mdoc_macronames
[n
->data
.block
.tok
];
222 argv
= n
->data
.block
.argv
;
223 argc
= n
->data
.block
.argc
;
234 for (i
= 0; i
< indent
; i
++)
236 (void)printf("%s (%s)", p
, t
);
238 for (i
= 0; i
< (int)argc
; i
++) {
239 (void)printf(" -%s", mdoc_argnames
[argv
[i
].arg
]);
240 for (j
= 0; j
< (int)argv
[i
].sz
; j
++)
241 (void)printf(" \"%s\"", argv
[i
].value
[j
]);
244 for (i
= 0; i
< (int)sz
; i
++)
245 (void)printf(" \"%s\"", params
[i
]);
247 (void)printf(" %d:%d\n", n
->line
, n
->pos
);
250 print_node(n
->child
, indent
+ 1);
252 print_node(n
->next
, indent
);
257 parse_leave(struct md_parse
*p
, int code
)
259 const struct mdoc_node
*n
;
264 if ( ! mdoc_endparse(p
->mdoc
))
266 if ((n
= mdoc_result(p
->mdoc
)))
276 parse_begin(struct md_parse
*p
)
280 char line
[256], sv
[256];
283 cb
.mdoc_err
= msg_err
;
284 cb
.mdoc_warn
= msg_warn
;
285 cb
.mdoc_msg
= msg_msg
;
287 if (NULL
== (p
->mdoc
= mdoc_alloc(p
, &cb
)))
288 return(parse_leave(p
, 0));
294 if (-1 == (sz
= read(p
->fd
, p
->buf
, p
->bufsz
))) {
296 return(parse_leave(p
, 0));
300 for (i
= 0; i
< sz
; i
++) {
301 if ('\n' != p
->buf
[i
]) {
302 if (pos
< sizeof(line
)) {
303 sv
[(int)pos
] = p
->buf
[(int)i
];
308 warnx("%s: line %d too long",
310 return(parse_leave(p
, 0));
313 line
[(int)pos
] = sv
[(int)pos
] = 0;
314 if ( ! mdoc_parseln(p
->mdoc
, p
->lnn
, line
))
315 return(parse_leave(p
, 0));
322 return(parse_leave(p
, 1));
327 msg_err(void *arg
, int line
, int col
, enum mdoc_err type
)
332 p
= (struct md_parse
*)arg
;
337 case (ERR_SYNTAX_NOTEXT
):
338 lit
= "syntax: context-free text disallowed";
340 case (ERR_SYNTAX_QUOTE
):
341 lit
= "syntax: disallowed argument quotation";
343 case (ERR_SYNTAX_UNQUOTE
):
344 lit
= "syntax: unterminated quotation";
346 case (ERR_SYNTAX_WS
):
347 lit
= "syntax: whitespace in argument";
349 case (ERR_SYNTAX_ARGFORM
):
350 lit
= "syntax: macro arguments malformed";
352 case (ERR_SYNTAX_NOPUNCT
):
353 lit
= "syntax: macro doesn't understand punctuation";
355 case (ERR_SYNTAX_ARG
):
356 lit
= "syntax: unknown argument for macro";
358 case (ERR_SCOPE_BREAK
):
359 /* Which scope is broken? */
360 lit
= "scope: macro breaks prior explicit scope";
362 case (ERR_SCOPE_NOCTX
):
363 lit
= "scope: closure macro has no context";
365 case (ERR_SCOPE_NONEST
):
366 lit
= "scope: macro may not be nested in the current context";
368 case (ERR_MACRO_NOTSUP
):
369 lit
= "macro not supported";
371 case (ERR_MACRO_NOTCALL
):
372 lit
= "macro not callable";
374 case (ERR_SEC_PROLOGUE
):
375 lit
= "macro cannot be called in the prologue";
377 case (ERR_SEC_NPROLOGUE
):
378 lit
= "macro called outside of prologue";
381 lit
= "macro expects zero arguments";
384 lit
= "macro expects one argument";
387 lit
= "macro expects one or more arguments";
390 lit
= "macro expects two or fewer arguments";
393 lit
= "macro expects eight or fewer arguments";
395 case (ERR_ARGS_MANY
):
396 lit
= "macro has too many arguments";
398 case (ERR_SEC_PROLOGUE_OO
):
399 lit
= "prologue macro is out-of-order";
401 case (ERR_SEC_PROLOGUE_REP
):
402 lit
= "prologue macro repeated";
405 lit
= "`NAME' section must be first";
407 case (ERR_SYNTAX_ARGVAL
):
408 lit
= "syntax: expected value for macro argument";
410 case (ERR_SYNTAX_ARGBAD
):
411 lit
= "syntax: invalid value(s) for macro argument";
413 case (ERR_SYNTAX_ARGMISS
):
414 lit
= "syntax: missing required argument(s) for macro";
416 case (ERR_SYNTAX_ARGMANY
):
417 lit
= "syntax: too many values for macro argument";
419 case (ERR_SYNTAX_CHILDBAD
):
420 lit
= "syntax: invalid child for parent macro";
422 case (ERR_SYNTAX_CHILDHEAD
):
423 lit
= "syntax: expected only block-header section";
425 case (ERR_SYNTAX_CHILDBODY
):
426 lit
= "syntax: expected only a block-body section";
428 case (ERR_SYNTAX_EMPTYHEAD
):
429 lit
= "syntax: block-header section may not be empty";
431 case (ERR_SYNTAX_EMPTYBODY
):
432 lit
= "syntax: block-body section may not be empty";
439 (void)fprintf(stderr
, "%s:%d: error: %s (column %d)\n",
440 p
->name
, line
, lit
, col
);
446 msg_msg(void *arg
, int line
, int col
, const char *msg
)
450 p
= (struct md_parse
*)arg
;
455 (void)printf("%s:%d: %s (column %d)\n",
456 p
->name
, line
, msg
, col
);
461 msg_warn(void *arg
, int line
, int col
, enum mdoc_warn type
)
465 extern char *__progname
;
467 p
= (struct md_parse
*)arg
;
469 if ( ! (p
->warn
& MD_WARN_ALL
))
475 case (WARN_SYNTAX_WS_EOLN
):
476 lit
= "syntax: whitespace at end-of-line";
478 case (WARN_SYNTAX_QUOTED
):
479 lit
= "syntax: quotation mark starting string";
481 case (WARN_SYNTAX_MACLIKE
):
482 lit
= "syntax: macro-like argument";
484 case (WARN_SYNTAX_ARGLIKE
):
485 lit
= "syntax: argument-like value";
487 case (WARN_SYNTAX_EMPTYBODY
):
488 lit
= "syntax: empty block-body section";
491 lit
= "section is out of conventional order";
494 lit
= "section repeated";
496 case (WARN_ARGS_GE1
):
497 lit
= "macro suggests one or more arguments";
499 case (WARN_ARGS_EQ0
):
500 lit
= "macro suggests zero arguments";
502 case (WARN_IGN_AFTER_BLK
):
503 lit
= "ignore: macro ignored after block macro";
505 case (WARN_IGN_OBSOLETE
):
506 lit
= "ignore: macro is obsolete";
508 case (WARN_IGN_BEFORE_BLK
):
509 lit
= "ignore: macro before block macro ignored";
511 case (WARN_COMPAT_TROFF
):
512 lit
= "compat: macro behaves differently in troff and nroff";
520 (void)fprintf(stderr
, "%s:%d: warning: %s (column %d)\n",
521 p
->name
, line
, lit
, col
);
523 if (p
->warn
& MD_WARN_ERR
) {
524 (void)fprintf(stderr
, "%s: considering warnings as "
525 "errors\n", __progname
);
536 extern char *__progname
;
538 (void)fprintf(stderr
, "usage: %s [-v] [-Wwarn...] [infile]\n",