]> git.cameronkatri.com Git - mandoc.git/blob - argv.c
Broken build (changing err/warn/msg function prototypes for clarity).
[mandoc.git] / argv.c
1 /* $Id: argv.c,v 1.13 2009/01/15 15:46:45 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
4 *
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
8 * copies.
9 *
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.
18 */
19 #include <assert.h>
20 #include <ctype.h>
21 #include <err.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "private.h"
27
28
29 static int lookup(int, const char *);
30 static int parse(struct mdoc *, int, int,
31 struct mdoc_arg *, int *, char *);
32 static int parse_single(struct mdoc *, int,
33 struct mdoc_arg *, int *, char *);
34 static int parse_multi(struct mdoc *, int,
35 struct mdoc_arg *, int *, char *);
36 static int postparse(struct mdoc *, int,
37 const struct mdoc_arg *, int);
38
39
40 int
41 mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
42 {
43 int i;
44
45 if (0 == buf[*pos])
46 return(ARGS_EOLN);
47
48 if ('\"' == buf[*pos] && ! (fl & ARGS_QUOTED))
49 if ( ! mdoc_pwarn(mdoc, line, *pos, WARN_SYNTAX_QUOTED))
50 return(ARGS_ERROR);
51
52 if ('-' == buf[*pos])
53 if ( ! mdoc_pwarn(mdoc, line, *pos, WARN_SYNTAX_ARGLIKE))
54 return(ARGS_ERROR);
55
56 if ((fl & ARGS_DELIM) && mdoc_iscdelim(buf[*pos])) {
57 /*
58 * If ARGS_DELIM, return ARGS_PUNCT if only space-separated
59 * punctuation remains.
60 */
61 for (i = *pos; buf[i]; ) {
62 if ( ! mdoc_iscdelim(buf[i]))
63 break;
64 i++;
65 if (0 == buf[i] || ! isspace(buf[i]))
66 break;
67 i++;
68 while (buf[i] && isspace(buf[i]))
69 i++;
70 }
71 if (0 == buf[i]) {
72 *v = &buf[*pos];
73 return(ARGS_PUNCT);
74 }
75 }
76
77 /* Parse routine for non-quoted string. */
78
79 if ('\"' != buf[*pos]) {
80 *v = &buf[*pos];
81
82 /* FIXME: UGLY tab-sep processing. */
83
84 if (ARGS_TABSEP & fl)
85 while (buf[*pos]) {
86 if ('\t' == buf[*pos])
87 break;
88 if ('T' == buf[*pos]) {
89 (*pos)++;
90 if (0 == buf[*pos])
91 break;
92 if ('a' == buf[*pos]) {
93 buf[*pos - 1] = 0;
94 break;
95 }
96 }
97 (*pos)++;
98 }
99 else
100 while (buf[*pos] && ! isspace(buf[*pos]))
101 (*pos)++;
102
103 if (0 == buf[*pos])
104 return(ARGS_WORD);
105
106 buf[(*pos)++] = 0;
107
108 if (0 == buf[*pos])
109 return(ARGS_WORD);
110
111 if ( ! (ARGS_TABSEP & fl))
112 while (buf[*pos] && isspace(buf[*pos]))
113 (*pos)++;
114
115 if (buf[*pos])
116 return(ARGS_WORD);
117
118 if ( ! mdoc_pwarn(mdoc, line, *pos, WARN_SYNTAX_WS_EOLN))
119 return(ARGS_ERROR);
120
121 return(ARGS_WORD);
122 }
123
124 /*
125 * If we're a quoted string (and quoted strings are allowed),
126 * then parse ahead to the next quote. If none's found, it's an
127 * error. After, parse to the next word.
128 */
129
130 assert( ! (ARGS_TABSEP & fl));
131
132 *v = &buf[++(*pos)];
133
134 while (buf[*pos] && '\"' != buf[*pos])
135 (*pos)++;
136
137 if (0 == buf[*pos]) {
138 (void)mdoc_perr(mdoc, line, *pos, ERR_SYNTAX_UNQUOTE);
139 return(ARGS_ERROR);
140 }
141
142 buf[(*pos)++] = 0;
143 if (0 == buf[*pos])
144 return(ARGS_WORD);
145
146 while (buf[*pos] && isspace(buf[*pos]))
147 (*pos)++;
148
149 if (buf[*pos])
150 return(ARGS_WORD);
151
152 if ( ! mdoc_pwarn(mdoc, line, *pos, WARN_SYNTAX_WS_EOLN))
153 return(ARGS_ERROR);
154
155 return(ARGS_WORD);
156 }
157
158
159 static int
160 lookup(int tok, const char *argv)
161 {
162
163 switch (tok) {
164 case (MDOC_An):
165 if (xstrcmp(argv, "split"))
166 return(MDOC_Split);
167 else if (xstrcmp(argv, "nosplit"))
168 return(MDOC_Nosplit);
169 break;
170
171 case (MDOC_Bd):
172 if (xstrcmp(argv, "ragged"))
173 return(MDOC_Ragged);
174 else if (xstrcmp(argv, "unfilled"))
175 return(MDOC_Unfilled);
176 else if (xstrcmp(argv, "filled"))
177 return(MDOC_Filled);
178 else if (xstrcmp(argv, "literal"))
179 return(MDOC_Literal);
180 else if (xstrcmp(argv, "file"))
181 return(MDOC_File);
182 else if (xstrcmp(argv, "offset"))
183 return(MDOC_Offset);
184 break;
185
186 case (MDOC_Bf):
187 if (xstrcmp(argv, "emphasis"))
188 return(MDOC_Emphasis);
189 else if (xstrcmp(argv, "literal"))
190 return(MDOC_Literal);
191 else if (xstrcmp(argv, "symbolic"))
192 return(MDOC_Symbolic);
193 break;
194
195 case (MDOC_Bk):
196 if (xstrcmp(argv, "words"))
197 return(MDOC_Words);
198 break;
199
200 case (MDOC_Bl):
201 if (xstrcmp(argv, "bullet"))
202 return(MDOC_Bullet);
203 else if (xstrcmp(argv, "dash"))
204 return(MDOC_Dash);
205 else if (xstrcmp(argv, "hyphen"))
206 return(MDOC_Hyphen);
207 else if (xstrcmp(argv, "item"))
208 return(MDOC_Item);
209 else if (xstrcmp(argv, "enum"))
210 return(MDOC_Enum);
211 else if (xstrcmp(argv, "tag"))
212 return(MDOC_Tag);
213 else if (xstrcmp(argv, "diag"))
214 return(MDOC_Diag);
215 else if (xstrcmp(argv, "hang"))
216 return(MDOC_Hang);
217 else if (xstrcmp(argv, "ohang"))
218 return(MDOC_Ohang);
219 else if (xstrcmp(argv, "inset"))
220 return(MDOC_Inset);
221 else if (xstrcmp(argv, "column"))
222 return(MDOC_Column);
223 else if (xstrcmp(argv, "width"))
224 return(MDOC_Width);
225 else if (xstrcmp(argv, "offset"))
226 return(MDOC_Offset);
227 else if (xstrcmp(argv, "compact"))
228 return(MDOC_Compact);
229 break;
230
231 case (MDOC_Rv):
232 /* FALLTHROUGH */
233 case (MDOC_Ex):
234 if (xstrcmp(argv, "std"))
235 return(MDOC_Std);
236 break;
237
238 case (MDOC_St):
239 if (xstrcmp(argv, "p1003.1-88"))
240 return(MDOC_p1003_1_88);
241 else if (xstrcmp(argv, "p1003.1-90"))
242 return(MDOC_p1003_1_90);
243 else if (xstrcmp(argv, "p1003.1-96"))
244 return(MDOC_p1003_1_96);
245 else if (xstrcmp(argv, "p1003.1-2001"))
246 return(MDOC_p1003_1_2001);
247 else if (xstrcmp(argv, "p1003.1-2004"))
248 return(MDOC_p1003_1_2004);
249 else if (xstrcmp(argv, "p1003.1"))
250 return(MDOC_p1003_1);
251 else if (xstrcmp(argv, "p1003.1b"))
252 return(MDOC_p1003_1b);
253 else if (xstrcmp(argv, "p1003.1b-93"))
254 return(MDOC_p1003_1b_93);
255 else if (xstrcmp(argv, "p1003.1c-95"))
256 return(MDOC_p1003_1c_95);
257 else if (xstrcmp(argv, "p1003.1g-2000"))
258 return(MDOC_p1003_1g_2000);
259 else if (xstrcmp(argv, "p1003.2-92"))
260 return(MDOC_p1003_2_92);
261 else if (xstrcmp(argv, "p1003.2-95"))
262 return(MDOC_p1387_2_95);
263 else if (xstrcmp(argv, "p1003.2"))
264 return(MDOC_p1003_2);
265 else if (xstrcmp(argv, "p1387.2-95"))
266 return(MDOC_p1387_2);
267 else if (xstrcmp(argv, "isoC-90"))
268 return(MDOC_isoC_90);
269 else if (xstrcmp(argv, "isoC-amd1"))
270 return(MDOC_isoC_amd1);
271 else if (xstrcmp(argv, "isoC-tcor1"))
272 return(MDOC_isoC_tcor1);
273 else if (xstrcmp(argv, "isoC-tcor2"))
274 return(MDOC_isoC_tcor2);
275 else if (xstrcmp(argv, "isoC-99"))
276 return(MDOC_isoC_99);
277 else if (xstrcmp(argv, "ansiC"))
278 return(MDOC_ansiC);
279 else if (xstrcmp(argv, "ansiC-89"))
280 return(MDOC_ansiC_89);
281 else if (xstrcmp(argv, "ansiC-99"))
282 return(MDOC_ansiC_99);
283 else if (xstrcmp(argv, "ieee754"))
284 return(MDOC_ieee754);
285 else if (xstrcmp(argv, "iso8802-3"))
286 return(MDOC_iso8802_3);
287 else if (xstrcmp(argv, "xpg3"))
288 return(MDOC_xpg3);
289 else if (xstrcmp(argv, "xpg4"))
290 return(MDOC_xpg4);
291 else if (xstrcmp(argv, "xpg4.2"))
292 return(MDOC_xpg4_2);
293 else if (xstrcmp(argv, "xpg4.3"))
294 return(MDOC_xpg4_3);
295 else if (xstrcmp(argv, "xbd5"))
296 return(MDOC_xbd5);
297 else if (xstrcmp(argv, "xcu5"))
298 return(MDOC_xcu5);
299 else if (xstrcmp(argv, "xsh5"))
300 return(MDOC_xsh5);
301 else if (xstrcmp(argv, "xns5"))
302 return(MDOC_xns5);
303 else if (xstrcmp(argv, "xns5.2d2.0"))
304 return(MDOC_xns5_2d2_0);
305 else if (xstrcmp(argv, "xcurses4.2"))
306 return(MDOC_xcurses4_2);
307 else if (xstrcmp(argv, "susv2"))
308 return(MDOC_susv2);
309 else if (xstrcmp(argv, "susv3"))
310 return(MDOC_susv3);
311 else if (xstrcmp(argv, "svid4"))
312 return(MDOC_svid4);
313 break;
314
315 default:
316 break;
317 }
318
319 return(MDOC_ARG_MAX);
320 }
321
322
323 static int
324 postparse(struct mdoc *mdoc, int line, const struct mdoc_arg *v, int pos)
325 {
326
327 switch (v->arg) {
328 case (MDOC_Offset):
329 assert(v->value);
330 assert(v->value[0]);
331 if (xstrcmp(v->value[0], "left"))
332 break;
333 if (xstrcmp(v->value[0], "right"))
334 break;
335 if (xstrcmp(v->value[0], "center"))
336 break;
337 if (xstrcmp(v->value[0], "indent"))
338 break;
339 if (xstrcmp(v->value[0], "indent-two"))
340 break;
341 return(mdoc_perr(mdoc, line, pos, ERR_SYNTAX_ARGBAD));
342 default:
343 break;
344 }
345
346 return(1);
347 }
348
349
350 static int
351 parse_multi(struct mdoc *mdoc, int line,
352 struct mdoc_arg *v, int *pos, char *buf)
353 {
354 int c, ppos;
355 char *p;
356
357 v->sz = 0;
358 v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *));
359
360 ppos = *pos;
361
362 for (v->sz = 0; v->sz < MDOC_LINEARG_MAX; v->sz++) {
363 if ('-' == buf[*pos])
364 break;
365 c = mdoc_args(mdoc, line, pos, buf, ARGS_QUOTED, &p);
366 if (ARGS_ERROR == c) {
367 free(v->value);
368 return(0);
369 } else if (ARGS_EOLN == c)
370 break;
371 v->value[v->sz] = p;
372 }
373
374 if (0 < v->sz && v->sz < MDOC_LINEARG_MAX)
375 return(1);
376
377 c = 0 == v->sz ? ERR_SYNTAX_ARGVAL : ERR_SYNTAX_ARGMANY;
378 free(v->value);
379 return(mdoc_perr(mdoc, line, ppos, c));
380 }
381
382
383 static int
384 parse_single(struct mdoc *mdoc, int line,
385 struct mdoc_arg *v, int *pos, char *buf)
386 {
387 int c, ppos;
388 char *p;
389
390 ppos = *pos;
391
392 c = mdoc_args(mdoc, line, pos, buf, ARGS_QUOTED, &p);
393 if (ARGS_ERROR == c)
394 return(0);
395 if (ARGS_EOLN == c)
396 return(mdoc_perr(mdoc, line, ppos, ERR_SYNTAX_ARGVAL));
397
398 v->sz = 1;
399 v->value = xcalloc(1, sizeof(char *));
400 v->value[0] = p;
401 return(1);
402 }
403
404
405 static int
406 parse(struct mdoc *mdoc, int line, int tok,
407 struct mdoc_arg *v, int *pos, char *buf)
408 {
409
410 v->sz = 0;
411 v->value = NULL;
412
413 switch (v->arg) {
414 case(MDOC_Std):
415 /* FALLTHROUGH */
416 case(MDOC_Width):
417 /* FALLTHROUGH */
418 case(MDOC_Offset):
419 return(parse_single(mdoc, line, v, pos, buf));
420 case(MDOC_Column):
421 return(parse_multi(mdoc, line, v, pos, buf));
422 default:
423 break;
424 }
425
426 return(1);
427 }
428
429
430 int
431 mdoc_argv(struct mdoc *mdoc, int line, int tok,
432 struct mdoc_arg *v, int *pos, char *buf)
433 {
434 int i, ppos;
435 char *argv;
436
437 (void)memset(v, 0, sizeof(struct mdoc_arg));
438
439 if (0 == buf[*pos])
440 return(ARGV_EOLN);
441
442 assert( ! isspace(buf[*pos]));
443
444 if ('-' != buf[*pos])
445 return(ARGV_WORD);
446
447 i = *pos;
448 argv = &buf[++(*pos)];
449
450 v->line = line;
451 v->pos = *pos;
452
453 while (buf[*pos] && ! isspace(buf[*pos]))
454 (*pos)++;
455
456 if (buf[*pos])
457 buf[(*pos)++] = 0;
458
459 if (MDOC_ARG_MAX == (v->arg = lookup(tok, argv))) {
460 (void)mdoc_pwarn(mdoc, line, i, WARN_SYNTAX_ARGLIKE);
461 return(ARGV_WORD);
462 }
463
464 while (buf[*pos] && isspace(buf[*pos]))
465 (*pos)++;
466
467 /* FIXME: whitespace if no value. */
468
469 ppos = *pos;
470 if ( ! parse(mdoc, line, tok, v, pos, buf))
471 return(ARGV_ERROR);
472 if ( ! postparse(mdoc, line, v, ppos))
473 return(ARGV_ERROR);
474
475 return(ARGV_ARG);
476 }
477
478
479 void
480 mdoc_argv_free(int sz, struct mdoc_arg *arg)
481 {
482 int i;
483
484 for (i = 0; i < sz; i++) {
485 if (0 == arg[i].sz) {
486 assert(NULL == arg[i].value);
487 continue;
488 }
489 assert(arg[i].value);
490 free(arg[i].value);
491 }
492 }
493