]>
git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
1 /* $Id: mdocml.c,v 1.41 2009/01/12 16:39:57 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
;
195 /* FIXME: put parts of this in util.c. */
198 assert(NULL
== n
->child
);
199 p
= n
->data
.text
.string
;
203 p
= mdoc_macronames
[n
->tok
];
207 p
= mdoc_macronames
[n
->tok
];
211 p
= mdoc_macronames
[n
->tok
];
215 p
= mdoc_macronames
[n
->tok
];
217 argv
= n
->data
.elem
.argv
;
218 argc
= n
->data
.elem
.argc
;
221 p
= mdoc_macronames
[n
->tok
];
223 argv
= n
->data
.block
.argv
;
224 argc
= n
->data
.block
.argc
;
235 for (i
= 0; i
< indent
; i
++)
237 (void)printf("%s (%s)", p
, t
);
239 for (i
= 0; i
< (int)argc
; i
++) {
240 (void)printf(" -%s", mdoc_argnames
[argv
[i
].arg
]);
243 for (j
= 0; j
< (int)argv
[i
].sz
; j
++)
244 (void)printf(" [%s]", argv
[i
].value
[j
]);
249 for (i
= 0; i
< (int)sz
; i
++)
250 (void)printf(" [%s]", params
[i
]);
252 (void)printf(" %d:%d\n", n
->line
, n
->pos
);
255 print_node(n
->child
, indent
+ 1);
257 print_node(n
->next
, indent
);
262 parse_leave(struct md_parse
*p
, int code
)
264 const struct mdoc_node
*n
;
269 if ( ! mdoc_endparse(p
->mdoc
))
271 if ((n
= mdoc_result(p
->mdoc
)))
281 parse_begin(struct md_parse
*p
)
285 char line
[256], sv
[256];
288 cb
.mdoc_err
= msg_err
;
289 cb
.mdoc_warn
= msg_warn
;
290 cb
.mdoc_msg
= msg_msg
;
292 if (NULL
== (p
->mdoc
= mdoc_alloc(p
, &cb
)))
293 return(parse_leave(p
, 0));
299 if (-1 == (sz
= read(p
->fd
, p
->buf
, p
->bufsz
))) {
301 return(parse_leave(p
, 0));
305 for (i
= 0; i
< sz
; i
++) {
306 if ('\n' != p
->buf
[i
]) {
307 if (pos
< sizeof(line
)) {
308 sv
[(int)pos
] = p
->buf
[(int)i
];
313 warnx("%s: line %d too long",
315 return(parse_leave(p
, 0));
318 line
[(int)pos
] = sv
[(int)pos
] = 0;
319 if ( ! mdoc_parseln(p
->mdoc
, p
->lnn
, line
))
320 return(parse_leave(p
, 0));
327 return(parse_leave(p
, 1));
332 msg_err(void *arg
, int line
, int col
, enum mdoc_err type
)
337 p
= (struct md_parse
*)arg
;
342 case (ERR_SYNTAX_NOTEXT
):
343 lit
= "syntax: context-free text disallowed";
345 case (ERR_SYNTAX_QUOTE
):
346 lit
= "syntax: disallowed argument quotation";
348 case (ERR_SYNTAX_UNQUOTE
):
349 lit
= "syntax: unterminated quotation";
351 case (ERR_SYNTAX_WS
):
352 lit
= "syntax: whitespace in argument";
354 case (ERR_SYNTAX_ARGFORM
):
355 lit
= "syntax: macro arguments malformed";
357 case (ERR_SYNTAX_NOPUNCT
):
358 lit
= "syntax: macro doesn't understand punctuation";
360 case (ERR_SYNTAX_ARG
):
361 lit
= "syntax: unknown argument for macro";
363 case (ERR_SCOPE_BREAK
):
364 /* Which scope is broken? */
365 lit
= "scope: macro breaks prior explicit scope";
367 case (ERR_SCOPE_NOCTX
):
368 lit
= "scope: closure macro has no context";
370 case (ERR_SCOPE_NONEST
):
371 lit
= "scope: macro may not be nested in the current context";
373 case (ERR_MACRO_NOTSUP
):
374 lit
= "macro not supported";
376 case (ERR_MACRO_NOTCALL
):
377 lit
= "macro not callable";
379 case (ERR_SEC_PROLOGUE
):
380 lit
= "macro cannot be called in the prologue";
382 case (ERR_SEC_NPROLOGUE
):
383 lit
= "macro called outside of prologue";
386 lit
= "macro expects zero arguments";
389 lit
= "macro expects one argument";
392 lit
= "macro expects one or more arguments";
395 lit
= "macro expects two or fewer arguments";
398 lit
= "macro expects eight or fewer arguments";
400 case (ERR_ARGS_MANY
):
401 lit
= "macro has too many arguments";
403 case (ERR_SEC_PROLOGUE_OO
):
404 lit
= "prologue macro is out-of-order";
406 case (ERR_SEC_PROLOGUE_REP
):
407 lit
= "prologue macro repeated";
410 lit
= "`NAME' section must be first";
412 case (ERR_SYNTAX_ARGVAL
):
413 lit
= "syntax: expected value for macro argument";
415 case (ERR_SYNTAX_ARGBAD
):
416 lit
= "syntax: invalid value(s) for macro argument";
418 case (ERR_SYNTAX_ARGMISS
):
419 lit
= "syntax: missing required argument(s) for macro";
421 case (ERR_SYNTAX_ARGMANY
):
422 lit
= "syntax: too many values for macro argument";
424 case (ERR_SYNTAX_CHILDBAD
):
425 lit
= "syntax: invalid child for parent macro";
427 case (ERR_SYNTAX_PARENTBAD
):
428 lit
= "syntax: invalid parent for macro";
430 case (ERR_SYNTAX_CHILDHEAD
):
431 lit
= "syntax: expected only block-header section";
433 case (ERR_SYNTAX_CHILDBODY
):
434 lit
= "syntax: expected only a block-body section";
436 case (ERR_SYNTAX_EMPTYHEAD
):
437 lit
= "syntax: block-header section may not be empty";
439 case (ERR_SYNTAX_EMPTYBODY
):
440 lit
= "syntax: block-body section may not be empty";
447 (void)fprintf(stderr
, "%s:%d: error: %s (column %d)\n",
448 p
->name
, line
, lit
, col
);
454 msg_msg(void *arg
, int line
, int col
, const char *msg
)
458 p
= (struct md_parse
*)arg
;
463 (void)printf("%s:%d: %s (column %d)\n",
464 p
->name
, line
, msg
, col
);
469 msg_warn(void *arg
, int line
, int col
, enum mdoc_warn type
)
473 extern char *__progname
;
475 p
= (struct md_parse
*)arg
;
477 if ( ! (p
->warn
& MD_WARN_ALL
))
483 case (WARN_SYNTAX_WS_EOLN
):
484 lit
= "syntax: whitespace at end-of-line";
486 case (WARN_SYNTAX_QUOTED
):
487 lit
= "syntax: quotation mark starting string";
489 case (WARN_SYNTAX_MACLIKE
):
490 lit
= "syntax: macro-like argument";
492 case (WARN_SYNTAX_ARGLIKE
):
493 lit
= "syntax: argument-like value";
495 case (WARN_SYNTAX_EMPTYBODY
):
496 lit
= "syntax: macro suggests non-empty block-body section";
498 case (WARN_SYNTAX_EMPTYHEAD
):
499 lit
= "syntax: macro suggests non-empty block-head section";
501 case (WARN_SYNTAX_NOBODY
):
502 lit
= "syntax: macro suggests empty block-body section";
505 lit
= "section is out of conventional order";
508 lit
= "section repeated";
510 case (WARN_ARGS_GE1
):
511 lit
= "macro suggests one or more arguments";
513 case (WARN_ARGS_EQ0
):
514 lit
= "macro suggests zero arguments";
516 case (WARN_IGN_AFTER_BLK
):
517 lit
= "ignore: macro ignored after block macro";
519 case (WARN_IGN_OBSOLETE
):
520 lit
= "ignore: macro is obsolete";
522 case (WARN_IGN_BEFORE_BLK
):
523 lit
= "ignore: macro before block macro ignored";
525 case (WARN_COMPAT_TROFF
):
526 lit
= "compat: macro behaves differently in troff and nroff";
534 (void)fprintf(stderr
, "%s:%d: warning: %s (column %d)\n",
535 p
->name
, line
, lit
, col
);
537 if (p
->warn
& MD_WARN_ERR
) {
538 (void)fprintf(stderr
, "%s: considering warnings as "
539 "errors\n", __progname
);
550 extern char *__progname
;
552 (void)fprintf(stderr
, "usage: %s [-v] [-Wwarn...] [infile]\n",