]>
git.cameronkatri.com Git - mandoc.git/blob - argv.c
1 /* $Id: argv.c,v 1.21 2009/01/20 13:49:36 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);
49 mdoc_args(struct mdoc
*mdoc
, int line
, int *pos
, char *buf
, int fl
, char **v
)
56 if ('\"' == buf
[*pos
] && ! (fl
& ARGS_QUOTED
))
57 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_SYNTAX
, "unexpected quoted parameter"))
61 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_SYNTAX
, "argument-like parameter"))
64 if ((fl
& ARGS_DELIM
) && mdoc_iscdelim(buf
[*pos
])) {
66 * If ARGS_DELIM, return ARGS_PUNCT if only space-separated
67 * punctuation remains.
69 for (i
= *pos
; buf
[i
]; ) {
70 if ( ! mdoc_iscdelim(buf
[i
]))
73 if (0 == buf
[i
] || ! isspace((int)buf
[i
]))
76 while (buf
[i
] && isspace((int)buf
[i
]))
85 /* Parse routine for non-quoted string. */
88 if ('\"' != buf
[*pos
] || ! (ARGS_QUOTED
& fl
)) {
91 /* FIXME: UGLY tab-sep processing. */
95 if ('\t' == buf
[*pos
])
97 if ('T' == buf
[*pos
]) {
101 if ('a' == buf
[*pos
]) {
110 if (isspace((int)buf
[*pos
]))
111 if ('\\' != buf
[*pos
- 1])
125 if ( ! (ARGS_TABSEP
& fl
))
126 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
132 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_COMPAT
, "whitespace at end-of-line"))
139 * If we're a quoted string (and quoted strings are allowed),
140 * then parse ahead to the next quote. If none's found, it's an
141 * error. After, parse to the next word.
146 while (buf
[*pos
] && '\"' != buf
[*pos
])
149 if (0 == buf
[*pos
]) {
150 (void)mdoc_perr(mdoc
, line
, *pos
, "unterminated quoted parameter");
158 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
164 if ( ! mdoc_pwarn(mdoc
, line
, *pos
, WARN_COMPAT
, "whitespace at end-of-line"))
172 lookup(int tok
, const char *argv
)
177 if (xstrcmp(argv
, "split"))
179 else if (xstrcmp(argv
, "nosplit"))
180 return(MDOC_Nosplit
);
184 if (xstrcmp(argv
, "ragged"))
186 else if (xstrcmp(argv
, "unfilled"))
187 return(MDOC_Unfilled
);
188 else if (xstrcmp(argv
, "filled"))
190 else if (xstrcmp(argv
, "literal"))
191 return(MDOC_Literal
);
192 else if (xstrcmp(argv
, "file"))
194 else if (xstrcmp(argv
, "offset"))
199 if (xstrcmp(argv
, "emphasis"))
200 return(MDOC_Emphasis
);
201 else if (xstrcmp(argv
, "literal"))
202 return(MDOC_Literal
);
203 else if (xstrcmp(argv
, "symbolic"))
204 return(MDOC_Symbolic
);
208 if (xstrcmp(argv
, "words"))
213 if (xstrcmp(argv
, "bullet"))
215 else if (xstrcmp(argv
, "dash"))
217 else if (xstrcmp(argv
, "hyphen"))
219 else if (xstrcmp(argv
, "item"))
221 else if (xstrcmp(argv
, "enum"))
223 else if (xstrcmp(argv
, "tag"))
225 else if (xstrcmp(argv
, "diag"))
227 else if (xstrcmp(argv
, "hang"))
229 else if (xstrcmp(argv
, "ohang"))
231 else if (xstrcmp(argv
, "inset"))
233 else if (xstrcmp(argv
, "column"))
235 else if (xstrcmp(argv
, "width"))
237 else if (xstrcmp(argv
, "offset"))
239 else if (xstrcmp(argv
, "compact"))
240 return(MDOC_Compact
);
246 if (xstrcmp(argv
, "std"))
251 if (xstrcmp(argv
, "p1003.1-88"))
252 return(MDOC_p1003_1_88
);
253 else if (xstrcmp(argv
, "p1003.1-90"))
254 return(MDOC_p1003_1_90
);
255 else if (xstrcmp(argv
, "p1003.1-96"))
256 return(MDOC_p1003_1_96
);
257 else if (xstrcmp(argv
, "p1003.1-2001"))
258 return(MDOC_p1003_1_2001
);
259 else if (xstrcmp(argv
, "p1003.1-2004"))
260 return(MDOC_p1003_1_2004
);
261 else if (xstrcmp(argv
, "p1003.1"))
262 return(MDOC_p1003_1
);
263 else if (xstrcmp(argv
, "p1003.1b"))
264 return(MDOC_p1003_1b
);
265 else if (xstrcmp(argv
, "p1003.1b-93"))
266 return(MDOC_p1003_1b_93
);
267 else if (xstrcmp(argv
, "p1003.1c-95"))
268 return(MDOC_p1003_1c_95
);
269 else if (xstrcmp(argv
, "p1003.1g-2000"))
270 return(MDOC_p1003_1g_2000
);
271 else if (xstrcmp(argv
, "p1003.2-92"))
272 return(MDOC_p1003_2_92
);
273 else if (xstrcmp(argv
, "p1003.2-95"))
274 return(MDOC_p1387_2_95
);
275 else if (xstrcmp(argv
, "p1003.2"))
276 return(MDOC_p1003_2
);
277 else if (xstrcmp(argv
, "p1387.2-95"))
278 return(MDOC_p1387_2
);
279 else if (xstrcmp(argv
, "isoC-90"))
280 return(MDOC_isoC_90
);
281 else if (xstrcmp(argv
, "isoC-amd1"))
282 return(MDOC_isoC_amd1
);
283 else if (xstrcmp(argv
, "isoC-tcor1"))
284 return(MDOC_isoC_tcor1
);
285 else if (xstrcmp(argv
, "isoC-tcor2"))
286 return(MDOC_isoC_tcor2
);
287 else if (xstrcmp(argv
, "isoC-99"))
288 return(MDOC_isoC_99
);
289 else if (xstrcmp(argv
, "ansiC"))
291 else if (xstrcmp(argv
, "ansiC-89"))
292 return(MDOC_ansiC_89
);
293 else if (xstrcmp(argv
, "ansiC-99"))
294 return(MDOC_ansiC_99
);
295 else if (xstrcmp(argv
, "ieee754"))
296 return(MDOC_ieee754
);
297 else if (xstrcmp(argv
, "iso8802-3"))
298 return(MDOC_iso8802_3
);
299 else if (xstrcmp(argv
, "xpg3"))
301 else if (xstrcmp(argv
, "xpg4"))
303 else if (xstrcmp(argv
, "xpg4.2"))
305 else if (xstrcmp(argv
, "xpg4.3"))
307 else if (xstrcmp(argv
, "xbd5"))
309 else if (xstrcmp(argv
, "xcu5"))
311 else if (xstrcmp(argv
, "xsh5"))
313 else if (xstrcmp(argv
, "xns5"))
315 else if (xstrcmp(argv
, "xns5.2d2.0"))
316 return(MDOC_xns5_2d2_0
);
317 else if (xstrcmp(argv
, "xcurses4.2"))
318 return(MDOC_xcurses4_2
);
319 else if (xstrcmp(argv
, "susv2"))
321 else if (xstrcmp(argv
, "susv3"))
323 else if (xstrcmp(argv
, "svid4"))
331 return(MDOC_ARG_MAX
);
336 postparse(struct mdoc
*mdoc
, int line
, const struct mdoc_arg
*v
, int pos
)
343 if (xstrcmp(v
->value
[0], "left"))
345 if (xstrcmp(v
->value
[0], "right"))
347 if (xstrcmp(v
->value
[0], "center"))
349 if (xstrcmp(v
->value
[0], "indent"))
351 if (xstrcmp(v
->value
[0], "indent-two"))
353 return(mdoc_perr(mdoc
, line
, pos
, "invalid offset value"));
363 parse_multi(struct mdoc
*mdoc
, int line
,
364 struct mdoc_arg
*v
, int *pos
, char *buf
)
370 v
->value
= xcalloc(MDOC_LINEARG_MAX
, sizeof(char *));
374 for (v
->sz
= 0; v
->sz
< MDOC_LINEARG_MAX
; v
->sz
++) {
375 if ('-' == buf
[*pos
])
377 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
378 if (ARGS_ERROR
== c
) {
381 } else if (ARGS_EOLN
== c
)
386 if (0 < v
->sz
&& v
->sz
< MDOC_LINEARG_MAX
)
390 return(mdoc_perr(mdoc
, line
, ppos
, 0 == v
->sz
?
391 "argument requires a value" :
392 "too many values to argument"));
397 parse_single(struct mdoc
*mdoc
, int line
,
398 struct mdoc_arg
*v
, int *pos
, char *buf
)
405 c
= mdoc_args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
409 return(mdoc_perr(mdoc
, line
, ppos
, "argument requires a value"));
412 v
->value
= xcalloc(1, sizeof(char *));
419 parse(struct mdoc
*mdoc
, int line
,
420 struct mdoc_arg
*v
, int *pos
, char *buf
)
432 return(parse_single(mdoc
, line
, v
, pos
, buf
));
434 return(parse_multi(mdoc
, line
, v
, pos
, buf
));
444 mdoc_argv(struct mdoc
*mdoc
, int line
, int tok
,
445 struct mdoc_arg
*v
, int *pos
, char *buf
)
450 (void)memset(v
, 0, sizeof(struct mdoc_arg
));
455 assert( ! isspace((int)buf
[*pos
]));
457 if ('-' != buf
[*pos
])
461 argv
= &buf
[++(*pos
)];
468 if (isspace((int)buf
[*pos
]))
469 if ('\\' != buf
[*pos
- 1])
477 if (MDOC_ARG_MAX
== (v
->arg
= lookup(tok
, argv
))) {
478 if ( ! mdoc_pwarn(mdoc
, line
, i
, WARN_SYNTAX
, "argument-like parameter"))
483 while (buf
[*pos
] && isspace((int)buf
[*pos
]))
486 /* FIXME: whitespace if no value. */
489 if ( ! parse(mdoc
, line
, v
, pos
, buf
))
491 if ( ! postparse(mdoc
, line
, v
, ppos
))
499 mdoc_argv_free(int sz
, struct mdoc_arg
*arg
)
503 for (i
= 0; i
< sz
; i
++) {
504 if (0 == arg
[i
].sz
) {
505 assert(NULL
== arg
[i
].value
);
508 assert(arg
[i
].value
);