]>
git.cameronkatri.com Git - mandoc.git/blob - argv.c
1 /* $Id: argv.c,v 1.22 2009/01/20 20:56:21 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.
29 * Parse arguments and parameters of macros. Arguments follow the
30 * syntax of `-arg [val [valN...]]', while parameters are free-form text
31 * following arguments (if any). This file must correctly handle the
32 * strange punctuation rules dictated by groff.
35 /* FIXME: .It called with -column and quoted arguments. */
37 static int lookup(int, const char *);
38 static int parse(struct mdoc
*, int,
39 struct mdoc_arg
*, int *, char *);
40 static int parse_single(struct mdoc
*, int,
41 struct mdoc_arg
*, int *, char *);
42 static int parse_multi(struct mdoc
*, int,
43 struct mdoc_arg
*, int *, char *);
44 static int postparse(struct mdoc
*, int,
45 const struct mdoc_arg
*, int);
47 #define ARGS_QUOTED (1 << 0)
48 #define ARGS_DELIM (1 << 1)
49 #define ARGS_TABSEP (1 << 2)
51 static int mdoc_argflags
[MDOC_MAX
] = {
75 ARGS_DELIM
| ARGS_QUOTED
, /* Fa */
78 ARGS_DELIM
| ARGS_QUOTED
, /* Fn */
79 ARGS_DELIM
| ARGS_QUOTED
, /* Ft */
100 ARGS_QUOTED
, /* %P */
101 ARGS_QUOTED
, /* %R */
102 ARGS_QUOTED
, /* %T */
103 ARGS_QUOTED
, /* %V */
112 ARGS_DELIM
, /* Bsx */
162 mdoc_args(struct mdoc
*mdoc
, int line
,
163 int *pos
, char *buf
, int tok
, char **v
)
168 fl
= 0 == tok
? 0 : mdoc_argflags
[tok
];
169 if (MDOC_It
== tok
) {
170 n
= mdoc
->last
->parent
;
171 /* FIXME: scan for ARGS_TABSEP. */
178 if ('\"' == buf
[*pos
] && ! (fl
& ARGS_QUOTED
))
179 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_SYNTAX
, "unexpected quoted parameter"))
182 if ('-' == buf
[*pos
])
183 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_SYNTAX
, "argument-like parameter"))
186 if ((fl
& ARGS_DELIM
) && mdoc_iscdelim(buf
[*pos
])) {
188 * If ARGS_DELIM, return ARGS_PUNCT if only space-separated
189 * punctuation remains.
191 for (i
= *pos
; buf
[i
]; ) {
192 if ( ! mdoc_iscdelim(buf
[i
]))
195 if (0 == buf
[i
] || ! isspace((int)buf
[i
]))
198 while (buf
[i
] && isspace((int)buf
[i
]))
207 /* Parse routine for non-quoted string. */
210 if ('\"' != buf
[*pos
] || ! (ARGS_QUOTED
& fl
)) {
213 /* FIXME: UGLY tab-sep processing. */
215 if (ARGS_TABSEP
& fl
)
217 if ('\t' == buf
[*pos
])
219 if ('T' == buf
[*pos
]) {
223 if ('a' == buf
[*pos
]) {
232 if (isspace((int)buf
[*pos
]))
233 if ('\\' != buf
[*pos
- 1])
247 if ( ! (ARGS_TABSEP
& fl
))
248 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
254 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_COMPAT
, "whitespace at end-of-line"))
261 * If we're a quoted string (and quoted strings are allowed),
262 * then parse ahead to the next quote. If none's found, it's an
263 * error. After, parse to the next word.
268 while (buf
[*pos
] && '\"' != buf
[*pos
])
271 if (0 == buf
[*pos
]) {
272 (void)mdoc_perr(mdoc
, line
, *pos
, "unterminated quoted parameter");
280 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
286 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_COMPAT
, "whitespace at end-of-line"))
294 lookup(int tok
, const char *argv
)
299 if (xstrcmp(argv
, "split"))
301 else if (xstrcmp(argv
, "nosplit"))
302 return(MDOC_Nosplit
);
306 if (xstrcmp(argv
, "ragged"))
308 else if (xstrcmp(argv
, "unfilled"))
309 return(MDOC_Unfilled
);
310 else if (xstrcmp(argv
, "filled"))
312 else if (xstrcmp(argv
, "literal"))
313 return(MDOC_Literal
);
314 else if (xstrcmp(argv
, "file"))
316 else if (xstrcmp(argv
, "offset"))
321 if (xstrcmp(argv
, "emphasis"))
322 return(MDOC_Emphasis
);
323 else if (xstrcmp(argv
, "literal"))
324 return(MDOC_Literal
);
325 else if (xstrcmp(argv
, "symbolic"))
326 return(MDOC_Symbolic
);
330 if (xstrcmp(argv
, "words"))
335 if (xstrcmp(argv
, "bullet"))
337 else if (xstrcmp(argv
, "dash"))
339 else if (xstrcmp(argv
, "hyphen"))
341 else if (xstrcmp(argv
, "item"))
343 else if (xstrcmp(argv
, "enum"))
345 else if (xstrcmp(argv
, "tag"))
347 else if (xstrcmp(argv
, "diag"))
349 else if (xstrcmp(argv
, "hang"))
351 else if (xstrcmp(argv
, "ohang"))
353 else if (xstrcmp(argv
, "inset"))
355 else if (xstrcmp(argv
, "column"))
357 else if (xstrcmp(argv
, "width"))
359 else if (xstrcmp(argv
, "offset"))
361 else if (xstrcmp(argv
, "compact"))
362 return(MDOC_Compact
);
368 if (xstrcmp(argv
, "std"))
373 if (xstrcmp(argv
, "p1003.1-88"))
374 return(MDOC_p1003_1_88
);
375 else if (xstrcmp(argv
, "p1003.1-90"))
376 return(MDOC_p1003_1_90
);
377 else if (xstrcmp(argv
, "p1003.1-96"))
378 return(MDOC_p1003_1_96
);
379 else if (xstrcmp(argv
, "p1003.1-2001"))
380 return(MDOC_p1003_1_2001
);
381 else if (xstrcmp(argv
, "p1003.1-2004"))
382 return(MDOC_p1003_1_2004
);
383 else if (xstrcmp(argv
, "p1003.1"))
384 return(MDOC_p1003_1
);
385 else if (xstrcmp(argv
, "p1003.1b"))
386 return(MDOC_p1003_1b
);
387 else if (xstrcmp(argv
, "p1003.1b-93"))
388 return(MDOC_p1003_1b_93
);
389 else if (xstrcmp(argv
, "p1003.1c-95"))
390 return(MDOC_p1003_1c_95
);
391 else if (xstrcmp(argv
, "p1003.1g-2000"))
392 return(MDOC_p1003_1g_2000
);
393 else if (xstrcmp(argv
, "p1003.2-92"))
394 return(MDOC_p1003_2_92
);
395 else if (xstrcmp(argv
, "p1003.2-95"))
396 return(MDOC_p1387_2_95
);
397 else if (xstrcmp(argv
, "p1003.2"))
398 return(MDOC_p1003_2
);
399 else if (xstrcmp(argv
, "p1387.2-95"))
400 return(MDOC_p1387_2
);
401 else if (xstrcmp(argv
, "isoC-90"))
402 return(MDOC_isoC_90
);
403 else if (xstrcmp(argv
, "isoC-amd1"))
404 return(MDOC_isoC_amd1
);
405 else if (xstrcmp(argv
, "isoC-tcor1"))
406 return(MDOC_isoC_tcor1
);
407 else if (xstrcmp(argv
, "isoC-tcor2"))
408 return(MDOC_isoC_tcor2
);
409 else if (xstrcmp(argv
, "isoC-99"))
410 return(MDOC_isoC_99
);
411 else if (xstrcmp(argv
, "ansiC"))
413 else if (xstrcmp(argv
, "ansiC-89"))
414 return(MDOC_ansiC_89
);
415 else if (xstrcmp(argv
, "ansiC-99"))
416 return(MDOC_ansiC_99
);
417 else if (xstrcmp(argv
, "ieee754"))
418 return(MDOC_ieee754
);
419 else if (xstrcmp(argv
, "iso8802-3"))
420 return(MDOC_iso8802_3
);
421 else if (xstrcmp(argv
, "xpg3"))
423 else if (xstrcmp(argv
, "xpg4"))
425 else if (xstrcmp(argv
, "xpg4.2"))
427 else if (xstrcmp(argv
, "xpg4.3"))
429 else if (xstrcmp(argv
, "xbd5"))
431 else if (xstrcmp(argv
, "xcu5"))
433 else if (xstrcmp(argv
, "xsh5"))
435 else if (xstrcmp(argv
, "xns5"))
437 else if (xstrcmp(argv
, "xns5.2d2.0"))
438 return(MDOC_xns5_2d2_0
);
439 else if (xstrcmp(argv
, "xcurses4.2"))
440 return(MDOC_xcurses4_2
);
441 else if (xstrcmp(argv
, "susv2"))
443 else if (xstrcmp(argv
, "susv3"))
445 else if (xstrcmp(argv
, "svid4"))
453 return(MDOC_ARG_MAX
);
458 postparse(struct mdoc
*mdoc
, int line
, const struct mdoc_arg
*v
, int pos
)
465 if (xstrcmp(v
->value
[0], "left"))
467 if (xstrcmp(v
->value
[0], "right"))
469 if (xstrcmp(v
->value
[0], "center"))
471 if (xstrcmp(v
->value
[0], "indent"))
473 if (xstrcmp(v
->value
[0], "indent-two"))
475 return(mdoc_perr(mdoc
, line
, pos
, "invalid offset value"));
485 parse_multi(struct mdoc
*mdoc
, int line
,
486 struct mdoc_arg
*v
, int *pos
, char *buf
)
492 v
->value
= xcalloc(MDOC_LINEARG_MAX
, sizeof(char *));
496 for (v
->sz
= 0; v
->sz
< MDOC_LINEARG_MAX
; v
->sz
++) {
497 if ('-' == buf
[*pos
])
499 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
500 if (ARGS_ERROR
== c
) {
503 } else if (ARGS_EOLN
== c
)
508 if (0 < v
->sz
&& v
->sz
< MDOC_LINEARG_MAX
)
512 return(mdoc_perr(mdoc
, line
, ppos
, 0 == v
->sz
?
513 "argument requires a value" :
514 "too many values to argument"));
519 parse_single(struct mdoc
*mdoc
, int line
,
520 struct mdoc_arg
*v
, int *pos
, char *buf
)
527 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
531 return(mdoc_perr(mdoc
, line
, ppos
, "argument requires a value"));
534 v
->value
= xcalloc(1, sizeof(char *));
541 parse(struct mdoc
*mdoc
, int line
,
542 struct mdoc_arg
*v
, int *pos
, char *buf
)
554 return(parse_single(mdoc
, line
, v
, pos
, buf
));
556 return(parse_multi(mdoc
, line
, v
, pos
, buf
));
566 mdoc_argv(struct mdoc
*mdoc
, int line
, int tok
,
567 struct mdoc_arg
*v
, int *pos
, char *buf
)
572 (void)memset(v
, 0, sizeof(struct mdoc_arg
));
577 assert( ! isspace((int)buf
[*pos
]));
579 if ('-' != buf
[*pos
])
583 argv
= &buf
[++(*pos
)];
590 if (isspace((int)buf
[*pos
]))
591 if ('\\' != buf
[*pos
- 1])
599 if (MDOC_ARG_MAX
== (v
->arg
= lookup(tok
, argv
))) {
600 if ( ! mdoc_pwarn(mdoc
, line
, i
, WARN_SYNTAX
, "argument-like parameter"))
605 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
608 /* FIXME: whitespace if no value. */
611 if ( ! parse(mdoc
, line
, v
, pos
, buf
))
613 if ( ! postparse(mdoc
, line
, v
, ppos
))
621 mdoc_argv_free(int sz
, struct mdoc_arg
*arg
)
625 for (i
= 0; i
< sz
; i
++) {
626 if (0 == arg
[i
].sz
) {
627 assert(NULL
== arg
[i
].value
);
630 assert(arg
[i
].value
);