]>
git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
1 /* $Id: mdocml.c,v 1.26 2008/12/28 21:25:09 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
];
208 params
= n
->data
.head
.args
;
209 sz
= n
->data
.head
.sz
;
212 assert(NULL
== n
->child
);
213 p
= mdoc_macronames
[n
->data
.elem
.tok
];
215 argv
= n
->data
.elem
.argv
;
216 argc
= n
->data
.elem
.argc
;
217 params
= n
->data
.elem
.args
;
218 sz
= n
->data
.elem
.sz
;
221 p
= mdoc_macronames
[n
->data
.block
.tok
];
223 argv
= n
->data
.block
.argv
;
224 argc
= n
->data
.block
.argc
;
231 for (i
= 0; i
< indent
; i
++)
233 (void)printf("%s (%s)", p
, t
);
235 for (i
= 0; i
< (int)argc
; i
++) {
236 (void)printf(" -%s", mdoc_argnames
[argv
[i
].arg
]);
237 for (j
= 0; j
< (int)argv
[i
].sz
; j
++)
238 (void)printf(" \"%s\"", argv
[i
].value
[j
]);
241 for (i
= 0; i
< (int)sz
; i
++)
242 (void)printf(" \"%s\"", params
[i
]);
247 print_node(n
->child
, indent
+ 1);
249 print_node(n
->next
, indent
);
254 parse_leave(struct md_parse
*p
, int code
)
256 const struct mdoc_node
*n
;
259 if ((n
= mdoc_result(p
->mdoc
)))
268 parse_begin(struct md_parse
*p
)
272 char line
[256], sv
[256];
275 cb
.mdoc_err
= msg_err
;
276 cb
.mdoc_warn
= msg_warn
;
277 cb
.mdoc_msg
= msg_msg
;
279 if (NULL
== (p
->mdoc
= mdoc_alloc(p
, &cb
)))
280 return(parse_leave(p
, 0));
286 if (-1 == (sz
= read(p
->fd
, p
->buf
, p
->bufsz
))) {
288 return(parse_leave(p
, 0));
292 for (i
= 0; i
< sz
; i
++) {
293 if ('\n' != p
->buf
[i
]) {
294 if (pos
< sizeof(line
)) {
295 sv
[(int)pos
] = p
->buf
[(int)i
];
300 warnx("%s: line %d too long",
302 return(parse_leave(p
, 0));
305 line
[(int)pos
] = sv
[(int)pos
] = 0;
306 if ( ! mdoc_parseln(p
->mdoc
, line
))
307 return(parse_leave(p
, 0));
314 return(parse_leave(p
, 1));
319 msg_err(void *arg
, int tok
, int col
, enum mdoc_err type
)
325 p
= (struct md_parse
*)arg
;
330 case (ERR_SYNTAX_QUOTE
):
331 lit
= "syntax: disallowed argument quotation";
333 case (ERR_SYNTAX_UNQUOTE
):
334 lit
= "syntax: unterminated quotation";
336 case (ERR_SYNTAX_WS
):
337 lit
= "syntax: whitespace in argument";
339 case (ERR_SYNTAX_ARGFORM
):
340 fmt
= "syntax: macro `%s' arguments malformed";
342 case (ERR_SYNTAX_ARG
):
343 fmt
= "syntax: unknown argument for macro `%s'";
345 case (ERR_SCOPE_BREAK
):
346 /* Which scope is broken? */
347 fmt
= "scope: macro `%s' breaks prior explicit scope";
349 case (ERR_SCOPE_NOCTX
):
350 fmt
= "scope: closure macro `%s' has no context";
352 case (ERR_SCOPE_NONEST
):
353 fmt
= "scope: macro `%s' may not be nested in the current context";
355 case (ERR_MACRO_NOTSUP
):
356 fmt
= "macro `%s' not supported";
358 case (ERR_MACRO_NOTCALL
):
359 fmt
= "macro `%s' not callable";
361 case (ERR_SEC_PROLOGUE
):
362 fmt
= "macro `%s' cannot be called in the prologue";
364 case (ERR_SEC_NPROLOGUE
):
365 fmt
= "macro `%s' called outside of prologue";
368 fmt
= "macro `%s' expects one or more arguments";
370 case (ERR_ARGS_MANY
):
371 fmt
= "macro `%s' has too many arguments";
373 case (ERR_SEC_PROLOGUE_OO
):
374 fmt
= "prologue macro `%s' is out-of-order";
376 case (ERR_SEC_PROLOGUE_REP
):
377 fmt
= "prologue macro `%s' repeated";
380 lit
= "`NAME' section must be first";
382 case (ERR_SYNTAX_ARGVAL
):
383 lit
= "syntax: expected value for macro argument";
385 case (ERR_SYNTAX_ARGBAD
):
386 lit
= "syntax: invalid value for macro argument";
388 case (ERR_SYNTAX_ARGMANY
):
389 lit
= "syntax: too many values for macro argument";
397 (void)fprintf(stderr
, "%s:%d: error: ",
399 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
401 (void)fprintf(stderr
, "%s:%d: error: %s",
402 p
->name
, p
->lnn
, lit
);
406 (void)fprintf(stderr
, " (column %d)\n", col
);
408 } else if (-1 == col
) {
409 (void)fprintf(stderr
, "\nFrom: %s", p
->line
);
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");
423 msg_msg(void *arg
, int col
, const char *msg
)
428 p
= (struct md_parse
*)arg
;
433 (void)printf("%s:%d: %s", p
->name
, p
->lnn
, msg
);
437 (void)printf(" (column %d)\n", col
);
439 } else if (-1 == col
) {
440 (void)printf("\nFrom %s\n", p
->line
);
444 (void)printf("\nFrom: %s\n ", p
->line
);
445 for (i
= 0; i
< col
; i
++)
452 msg_warn(void *arg
, int tok
, int col
, enum mdoc_warn type
)
457 extern char *__progname
;
459 p
= (struct md_parse
*)arg
;
461 if ( ! (p
->warn
& MD_WARN_ALL
))
467 case (WARN_SYNTAX_WS_EOLN
):
468 lit
= "syntax: whitespace at end-of-line";
470 case (WARN_SYNTAX_QUOTED
):
471 lit
= "syntax: quotation mark starting string";
473 case (WARN_SYNTAX_MACLIKE
):
474 lit
= "syntax: macro-like argument";
476 case (WARN_SYNTAX_ARGLIKE
):
477 lit
= "syntax: argument-like value";
480 lit
= "section is out of conventional order";
482 case (WARN_ARGS_GE1
):
483 fmt
= "macro `%s' suggests one or more arguments";
485 case (WARN_ARGS_EQ0
):
486 fmt
= "macro `%s' suggests zero arguments";
488 case (WARN_IGN_AFTER_BLK
):
489 fmt
= "ignore: macro `%s' ignored after block macro";
491 case (WARN_IGN_BEFORE_BLK
):
492 fmt
= "ignore: macro before block macro `%s' ignored";
500 (void)fprintf(stderr
, "%s:%d: warning: ",
502 (void)fprintf(stderr
, fmt
, mdoc_macronames
[tok
]);
504 (void)fprintf(stderr
, "%s:%d: warning: %s",
505 p
->name
, p
->lnn
, lit
);
508 (void)fprintf(stderr
, "\nFrom: %s\n ", p
->line
);
509 for (i
= 0; i
< col
; i
++)
510 (void)fprintf(stderr
, " ");
511 (void)fprintf(stderr
, "^\n");
513 (void)fprintf(stderr
, " (column %d)\n", col
);
515 if (p
->warn
& MD_WARN_ERR
) {
516 (void)fprintf(stderr
, "%s: considering warnings as "
517 "errors\n", __progname
);
528 extern char *__progname
;
530 (void)fprintf(stderr
, "usage: %s [-v] [-Wwarn...] [infile]\n",