mandoc(1): Update to 1.9.20.
[dragonfly.git] / usr.bin / mandoc / mdoc_argv.c
1 /*      $Id: mdoc_argv.c,v 1.34 2010/03/29 19:28:04 kristaps Exp $ */
2 /*
3  * Copyright (c) 2008, 2009 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 above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <sys/types.h>
18
19 #include <assert.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "libmdoc.h"
26 #include "libmandoc.h"
27
28 /*
29  * Routines to parse arguments of macros.  Arguments follow the syntax
30  * of `-arg [val [valN...]]'.  Arguments come in all types:  quoted
31  * arguments, multiple arguments per value, no-value arguments, etc.
32  *
33  * There's no limit to the number or arguments that may be allocated.
34  */
35
36 #define ARGV_NONE       (1 << 0)
37 #define ARGV_SINGLE     (1 << 1)
38 #define ARGV_MULTI      (1 << 2)
39 #define ARGV_OPT_SINGLE (1 << 3)
40
41 #define MULTI_STEP       5
42
43 static  int              argv_a2arg(int, const char *);
44 static  int              args(struct mdoc *, int, int *,
45                                 char *, int, char **);
46 static  int              argv(struct mdoc *, int,
47                                 struct mdoc_argv *, int *, char *);
48 static  int              argv_single(struct mdoc *, int,
49                                 struct mdoc_argv *, int *, char *);
50 static  int              argv_opt_single(struct mdoc *, int,
51                                 struct mdoc_argv *, int *, char *);
52 static  int              argv_multi(struct mdoc *, int,
53                                 struct mdoc_argv *, int *, char *);
54
55 /* Per-argument flags. */
56
57 static  int mdoc_argvflags[MDOC_ARG_MAX] = {
58         ARGV_NONE,      /* MDOC_Split */
59         ARGV_NONE,      /* MDOC_Nosplit */
60         ARGV_NONE,      /* MDOC_Ragged */
61         ARGV_NONE,      /* MDOC_Unfilled */
62         ARGV_NONE,      /* MDOC_Literal */
63         ARGV_SINGLE,    /* MDOC_File */
64         ARGV_OPT_SINGLE, /* MDOC_Offset */
65         ARGV_NONE,      /* MDOC_Bullet */
66         ARGV_NONE,      /* MDOC_Dash */
67         ARGV_NONE,      /* MDOC_Hyphen */
68         ARGV_NONE,      /* MDOC_Item */
69         ARGV_NONE,      /* MDOC_Enum */
70         ARGV_NONE,      /* MDOC_Tag */
71         ARGV_NONE,      /* MDOC_Diag */
72         ARGV_NONE,      /* MDOC_Hang */
73         ARGV_NONE,      /* MDOC_Ohang */
74         ARGV_NONE,      /* MDOC_Inset */
75         ARGV_MULTI,     /* MDOC_Column */
76         ARGV_SINGLE,    /* MDOC_Width */
77         ARGV_NONE,      /* MDOC_Compact */
78         ARGV_NONE,      /* MDOC_Std */
79         ARGV_NONE,      /* MDOC_Filled */
80         ARGV_NONE,      /* MDOC_Words */
81         ARGV_NONE,      /* MDOC_Emphasis */
82         ARGV_NONE,      /* MDOC_Symbolic */
83         ARGV_NONE       /* MDOC_Symbolic */
84 };
85
86 static  int mdoc_argflags[MDOC_MAX] = {
87         0, /* Ap */
88         0, /* Dd */
89         0, /* Dt */
90         0, /* Os */
91         0, /* Sh */
92         0, /* Ss */
93         ARGS_DELIM, /* Pp */
94         ARGS_DELIM, /* D1 */
95         ARGS_DELIM, /* Dl */
96         0, /* Bd */
97         0, /* Ed */
98         0, /* Bl */
99         0, /* El */
100         0, /* It */
101         ARGS_DELIM, /* Ad */
102         ARGS_DELIM, /* An */
103         ARGS_DELIM, /* Ar */
104         0, /* Cd */
105         ARGS_DELIM, /* Cm */
106         ARGS_DELIM, /* Dv */
107         ARGS_DELIM, /* Er */
108         ARGS_DELIM, /* Ev */
109         0, /* Ex */
110         ARGS_DELIM, /* Fa */
111         0, /* Fd */
112         ARGS_DELIM, /* Fl */
113         ARGS_DELIM, /* Fn */
114         ARGS_DELIM, /* Ft */
115         ARGS_DELIM, /* Ic */
116         0, /* In */
117         ARGS_DELIM, /* Li */
118         0, /* Nd */
119         ARGS_DELIM, /* Nm */
120         ARGS_DELIM, /* Op */
121         0, /* Ot */
122         ARGS_DELIM, /* Pa */
123         0, /* Rv */
124         ARGS_DELIM, /* St */
125         ARGS_DELIM, /* Va */
126         ARGS_DELIM, /* Vt */
127         ARGS_DELIM, /* Xr */
128         0, /* %A */
129         0, /* %B */
130         0, /* %D */
131         0, /* %I */
132         0, /* %J */
133         0, /* %N */
134         0, /* %O */
135         0, /* %P */
136         0, /* %R */
137         0, /* %T */
138         0, /* %V */
139         ARGS_DELIM, /* Ac */
140         0, /* Ao */
141         ARGS_DELIM, /* Aq */
142         ARGS_DELIM, /* At */
143         ARGS_DELIM, /* Bc */
144         0, /* Bf */
145         0, /* Bo */
146         ARGS_DELIM, /* Bq */
147         ARGS_DELIM, /* Bsx */
148         ARGS_DELIM, /* Bx */
149         0, /* Db */
150         ARGS_DELIM, /* Dc */
151         0, /* Do */
152         ARGS_DELIM, /* Dq */
153         ARGS_DELIM, /* Ec */
154         0, /* Ef */
155         ARGS_DELIM, /* Em */
156         0, /* Eo */
157         ARGS_DELIM, /* Fx */
158         ARGS_DELIM, /* Ms */
159         ARGS_DELIM, /* No */
160         ARGS_DELIM, /* Ns */
161         ARGS_DELIM, /* Nx */
162         ARGS_DELIM, /* Ox */
163         ARGS_DELIM, /* Pc */
164         ARGS_DELIM, /* Pf */
165         0, /* Po */
166         ARGS_DELIM, /* Pq */
167         ARGS_DELIM, /* Qc */
168         ARGS_DELIM, /* Ql */
169         0, /* Qo */
170         ARGS_DELIM, /* Qq */
171         0, /* Re */
172         0, /* Rs */
173         ARGS_DELIM, /* Sc */
174         0, /* So */
175         ARGS_DELIM, /* Sq */
176         0, /* Sm */
177         ARGS_DELIM, /* Sx */
178         ARGS_DELIM, /* Sy */
179         ARGS_DELIM, /* Tn */
180         ARGS_DELIM, /* Ux */
181         ARGS_DELIM, /* Xc */
182         0, /* Xo */
183         0, /* Fo */
184         0, /* Fc */
185         0, /* Oo */
186         ARGS_DELIM, /* Oc */
187         0, /* Bk */
188         0, /* Ek */
189         0, /* Bt */
190         0, /* Hf */
191         0, /* Fr */
192         0, /* Ud */
193         0, /* Lb */
194         ARGS_DELIM, /* Lp */
195         ARGS_DELIM, /* Lk */
196         ARGS_DELIM, /* Mt */
197         ARGS_DELIM, /* Brq */
198         0, /* Bro */
199         ARGS_DELIM, /* Brc */
200         0, /* %C */
201         0, /* Es */
202         0, /* En */
203         0, /* Dx */
204         0, /* %Q */
205         0, /* br */
206         0, /* sp */
207         0, /* %U */
208 };
209
210
211 /*
212  * Parse an argument from line text.  This comes in the form of -key
213  * [value0...], which may either have a single mandatory value, at least
214  * one mandatory value, an optional single value, or no value.
215  */
216 int
217 mdoc_argv(struct mdoc *m, int line, int tok,
218                 struct mdoc_arg **v, int *pos, char *buf)
219 {
220         char             *p, sv;
221         struct mdoc_argv tmp;
222         struct mdoc_arg  *arg;
223
224         if (0 == buf[*pos])
225                 return(ARGV_EOLN);
226
227         assert(' ' != buf[*pos]);
228
229         /* Parse through to the first unescaped space. */
230
231         p = &buf[++(*pos)];
232
233         assert(*pos > 0);
234
235         /* LINTED */
236         while (buf[*pos]) {
237                 if (' ' == buf[*pos])
238                         if ('\\' != buf[*pos - 1])
239                                 break;
240                 (*pos)++;
241         }
242
243         /* XXX - save zeroed byte, if not an argument. */
244
245         sv = 0;
246         if (buf[*pos]) {
247                 sv = buf[*pos];
248                 buf[(*pos)++] = 0;
249         }
250
251         (void)memset(&tmp, 0, sizeof(struct mdoc_argv));
252         tmp.line = line;
253         tmp.pos = *pos;
254
255         /* See if our token accepts the argument. */
256
257         if (MDOC_ARG_MAX == (tmp.arg = argv_a2arg(tok, p))) {
258                 /* XXX - restore saved zeroed byte. */
259                 if (sv)
260                         buf[*pos - 1] = sv;
261                 return(ARGV_WORD);
262         }
263
264         while (buf[*pos] && ' ' == buf[*pos])
265                 (*pos)++;
266
267         if ( ! argv(m, line, &tmp, pos, buf))
268                 return(ARGV_ERROR);
269
270         if (NULL == (arg = *v))
271                 arg = *v = mandoc_calloc(1, sizeof(struct mdoc_arg));
272
273         arg->argc++;
274         arg->argv = mandoc_realloc
275                 (arg->argv, arg->argc * sizeof(struct mdoc_argv));
276
277         (void)memcpy(&arg->argv[(int)arg->argc - 1],
278                         &tmp, sizeof(struct mdoc_argv));
279
280         return(ARGV_ARG);
281 }
282
283
284 void
285 mdoc_argv_free(struct mdoc_arg *p)
286 {
287         int              i, j;
288
289         if (NULL == p)
290                 return;
291
292         if (p->refcnt) {
293                 --(p->refcnt);
294                 if (p->refcnt)
295                         return;
296         }
297         assert(p->argc);
298
299         /* LINTED */
300         for (i = 0; i < (int)p->argc; i++) {
301                 if (0 == p->argv[i].sz)
302                         continue;
303                 if (NULL == p->argv[i].value)
304                         continue;
305
306                 /* LINTED */
307                 for (j = 0; j < (int)p->argv[i].sz; j++)
308                         if (p->argv[i].value[j])
309                                 free(p->argv[i].value[j]);
310
311                 free(p->argv[i].value);
312         }
313
314         free(p->argv);
315         free(p);
316 }
317
318
319 int
320 mdoc_zargs(struct mdoc *m, int line, int *pos,
321                 char *buf, int flags, char **v)
322 {
323
324         return(args(m, line, pos, buf, flags, v));
325 }
326
327
328 int
329 mdoc_args(struct mdoc *m, int line,
330                 int *pos, char *buf, int tok, char **v)
331 {
332         int               fl, c, i;
333         struct mdoc_node *n;
334
335         fl = (0 == tok) ? 0 : mdoc_argflags[tok];
336
337         if (MDOC_It != tok)
338                 return(args(m, line, pos, buf, fl, v));
339
340         /*
341          * The `It' macro is a special case, as it acquires parameters from its
342          * parent `Bl' context, specifically, we're concerned with -column.
343          */
344
345         for (n = m->last; n; n = n->parent)
346                 if (MDOC_BLOCK == n->type && MDOC_Bl == n->tok)
347                         break;
348
349         assert(n);
350         c = (int)(n->args ? n->args->argc : 0);
351         assert(c > 0);
352
353         /* LINTED */
354         for (i = 0; i < c; i++) {
355                 if (MDOC_Column != n->args->argv[i].arg)
356                         continue;
357                 fl |= ARGS_TABSEP;
358                 fl &= ~ARGS_DELIM;
359                 break;
360         }
361
362         return(args(m, line, pos, buf, fl, v));
363 }
364
365
366 static int
367 args(struct mdoc *m, int line, int *pos,
368                 char *buf, int fl, char **v)
369 {
370         int               i;
371         char             *p, *pp;
372
373         /*
374          * Parse out the terms (like `val' in `.Xx -arg val' or simply
375          * `.Xx val'), which can have all sorts of properties:
376          *
377          *   ARGS_DELIM: use special handling if encountering trailing
378          *   delimiters in the form of [[::delim::][ ]+]+.
379          *
380          *   ARGS_NOWARN: don't post warnings.  This is only used when
381          *   re-parsing delimiters, as the warnings have already been
382          *   posted.
383          *
384          *   ARGS_TABSEP: use special handling for tab/`Ta' separated
385          *   phrases like in `Bl -column'.
386          */
387
388         assert(*pos);
389         assert(' ' != buf[*pos]);
390
391         if (0 == buf[*pos])
392                 return(ARGS_EOLN);
393
394         /*
395          * If the first character is a delimiter and we're to look for
396          * delimited strings, then pass down the buffer seeing if it
397          * follows the pattern of [[::delim::][ ]+]+.
398          */
399
400         if ((fl & ARGS_DELIM) && mdoc_iscdelim(buf[*pos]) > 1) {
401                 for (i = *pos; buf[i]; ) {
402                         if ( mdoc_iscdelim(buf[i]) < 2)
403                                 break;
404                         i++;
405                         if (0 == buf[i] || ' ' != buf[i])
406                                 break;
407                         i++;
408                         while (buf[i] && ' ' == buf[i])
409                                 i++;
410                 }
411
412                 if (0 == buf[i]) {
413                         *v = &buf[*pos];
414                         if (' ' != buf[i - 1])
415                                 return(ARGS_PUNCT);
416                         if (ARGS_NOWARN & fl)
417                                 return(ARGS_PUNCT);
418                         if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
419                                 return(ARGS_ERROR);
420                         return(ARGS_PUNCT);
421                 }
422         }
423
424         *v = &buf[*pos];
425
426         /*
427          * First handle TABSEP items, restricted to `Bl -column'.  This
428          * ignores conventional token parsing and instead uses tabs or
429          * `Ta' macros to separate phrases.  Phrases are parsed again
430          * for arguments at a later phase.
431          */
432
433         if (ARGS_TABSEP & fl) {
434                 /* Scan ahead to tab (can't be escaped). */
435                 p = strchr(*v, '\t');
436
437                 /* Scan ahead to unescaped `Ta'. */
438                 for (pp = *v; ; pp++) {
439                         if (NULL == (pp = strstr(pp, "Ta")))
440                                 break;
441                         if (pp > *v && ' ' != *(pp - 1))
442                                 continue;
443                         if (' ' == *(pp + 2) || 0 == *(pp + 2))
444                                 break;
445                 }
446
447                 /*
448                  * Adjust new-buffer position to be beyond delimiter
449                  * mark (e.g., Ta -> end + 2).
450                  */
451                 if (p && pp) {
452                         *pos += pp < p ? 2 : 1;
453                         p = pp < p ? pp : p;
454                 } else if (p && ! pp) {
455                         *pos += 1;
456                 } else if (pp && ! p) {
457                         p = pp;
458                         *pos += 2;
459                 } else
460                         p = strchr(*v, 0);
461
462                 /* Whitespace check for eoln case... */
463                 if (0 == *p && ' ' == *(p - 1) && ! (ARGS_NOWARN & fl))
464                         if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
465                                 return(ARGS_ERROR);
466
467                 *pos += (int)(p - *v);
468
469                 /* Strip delimiter's preceding whitespace. */
470                 pp = p - 1;
471                 while (pp > *v && ' ' == *pp) {
472                         if (pp > *v && '\\' == *(pp - 1))
473                                 break;
474                         pp--;
475                 }
476                 *(pp + 1) = 0;
477
478                 /* Strip delimiter's proceeding whitespace. */
479                 for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++)
480                         /* Skip ahead. */ ;
481
482                 return(ARGS_PHRASE);
483         }
484
485         /*
486          * Process a quoted literal.  A quote begins with a double-quote
487          * and ends with a double-quote NOT preceded by a double-quote.
488          * Whitespace is NOT involved in literal termination.
489          */
490
491         if ('\"' == buf[*pos]) {
492                 *v = &buf[++(*pos)];
493
494                 for ( ; buf[*pos]; (*pos)++) {
495                         if ('\"' != buf[*pos])
496                                 continue;
497                         if ('\"' != buf[*pos + 1])
498                                 break;
499                         (*pos)++;
500                 }
501
502                 if (0 == buf[*pos]) {
503                         if (ARGS_NOWARN & fl)
504                                 return(ARGS_QWORD);
505                         if ( ! mdoc_pwarn(m, line, *pos, EQUOTTERM))
506                                 return(ARGS_ERROR);
507                         return(ARGS_QWORD);
508                 }
509
510                 buf[(*pos)++] = 0;
511
512                 if (0 == buf[*pos])
513                         return(ARGS_QWORD);
514
515                 while (' ' == buf[*pos])
516                         (*pos)++;
517
518                 if (0 == buf[*pos] && ! (ARGS_NOWARN & fl))
519                         if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
520                                 return(ARGS_ERROR);
521
522                 return(ARGS_QWORD);
523         }
524
525         /*
526          * A non-quoted term progresses until either the end of line or
527          * a non-escaped whitespace.
528          */
529
530         for ( ; buf[*pos]; (*pos)++)
531                 if (' ' == buf[*pos] && '\\' != buf[*pos - 1])
532                         break;
533
534         if (0 == buf[*pos])
535                 return(ARGS_WORD);
536
537         buf[(*pos)++] = 0;
538
539         while (' ' == buf[*pos])
540                 (*pos)++;
541
542         if (0 == buf[*pos] && ! (ARGS_NOWARN & fl))
543                 if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
544                         return(ARGS_ERROR);
545
546         return(ARGS_WORD);
547 }
548
549
550 static int
551 argv_a2arg(int tok, const char *p)
552 {
553
554         /*
555          * Parse an argument identifier from its text.  XXX - this
556          * should really be table-driven to clarify the code.
557          *
558          * If you add an argument to the list, make sure that you
559          * register it here with its one or more macros!
560          */
561
562         switch (tok) {
563         case (MDOC_An):
564                 if (0 == strcmp(p, "split"))
565                         return(MDOC_Split);
566                 else if (0 == strcmp(p, "nosplit"))
567                         return(MDOC_Nosplit);
568                 break;
569
570         case (MDOC_Bd):
571                 if (0 == strcmp(p, "ragged"))
572                         return(MDOC_Ragged);
573                 else if (0 == strcmp(p, "unfilled"))
574                         return(MDOC_Unfilled);
575                 else if (0 == strcmp(p, "filled"))
576                         return(MDOC_Filled);
577                 else if (0 == strcmp(p, "literal"))
578                         return(MDOC_Literal);
579                 else if (0 == strcmp(p, "file"))
580                         return(MDOC_File);
581                 else if (0 == strcmp(p, "offset"))
582                         return(MDOC_Offset);
583                 else if (0 == strcmp(p, "compact"))
584                         return(MDOC_Compact);
585                 else if (0 == strcmp(p, "centered"))
586                         return(MDOC_Centred);
587                 break;
588
589         case (MDOC_Bf):
590                 if (0 == strcmp(p, "emphasis"))
591                         return(MDOC_Emphasis);
592                 else if (0 == strcmp(p, "literal"))
593                         return(MDOC_Literal);
594                 else if (0 == strcmp(p, "symbolic"))
595                         return(MDOC_Symbolic);
596                 break;
597
598         case (MDOC_Bk):
599                 if (0 == strcmp(p, "words"))
600                         return(MDOC_Words);
601                 break;
602
603         case (MDOC_Bl):
604                 if (0 == strcmp(p, "bullet"))
605                         return(MDOC_Bullet);
606                 else if (0 == strcmp(p, "dash"))
607                         return(MDOC_Dash);
608                 else if (0 == strcmp(p, "hyphen"))
609                         return(MDOC_Hyphen);
610                 else if (0 == strcmp(p, "item"))
611                         return(MDOC_Item);
612                 else if (0 == strcmp(p, "enum"))
613                         return(MDOC_Enum);
614                 else if (0 == strcmp(p, "tag"))
615                         return(MDOC_Tag);
616                 else if (0 == strcmp(p, "diag"))
617                         return(MDOC_Diag);
618                 else if (0 == strcmp(p, "hang"))
619                         return(MDOC_Hang);
620                 else if (0 == strcmp(p, "ohang"))
621                         return(MDOC_Ohang);
622                 else if (0 == strcmp(p, "inset"))
623                         return(MDOC_Inset);
624                 else if (0 == strcmp(p, "column"))
625                         return(MDOC_Column);
626                 else if (0 == strcmp(p, "width"))
627                         return(MDOC_Width);
628                 else if (0 == strcmp(p, "offset"))
629                         return(MDOC_Offset);
630                 else if (0 == strcmp(p, "compact"))
631                         return(MDOC_Compact);
632                 else if (0 == strcmp(p, "nested"))
633                         return(MDOC_Nested);
634                 break;
635
636         case (MDOC_Rv):
637                 /* FALLTHROUGH */
638         case (MDOC_Ex):
639                 if (0 == strcmp(p, "std"))
640                         return(MDOC_Std);
641                 break;
642         default:
643                 break;
644         }
645
646         return(MDOC_ARG_MAX);
647 }
648
649
650 static int
651 argv_multi(struct mdoc *m, int line,
652                 struct mdoc_argv *v, int *pos, char *buf)
653 {
654         int              c;
655         char            *p;
656
657         for (v->sz = 0; ; v->sz++) {
658                 if ('-' == buf[*pos])
659                         break;
660                 c = args(m, line, pos, buf, 0, &p);
661                 if (ARGS_ERROR == c)
662                         return(0);
663                 else if (ARGS_EOLN == c)
664                         break;
665
666                 if (0 == v->sz % MULTI_STEP)
667                         v->value = mandoc_realloc(v->value,
668                                 (v->sz + MULTI_STEP) * sizeof(char *));
669
670                 v->value[(int)v->sz] = mandoc_strdup(p);
671         }
672
673         return(1);
674 }
675
676
677 static int
678 argv_opt_single(struct mdoc *m, int line,
679                 struct mdoc_argv *v, int *pos, char *buf)
680 {
681         int              c;
682         char            *p;
683
684         if ('-' == buf[*pos])
685                 return(1);
686
687         c = args(m, line, pos, buf, 0, &p);
688         if (ARGS_ERROR == c)
689                 return(0);
690         if (ARGS_EOLN == c)
691                 return(1);
692
693         v->sz = 1;
694         v->value = mandoc_malloc(sizeof(char *));
695         v->value[0] = mandoc_strdup(p);
696
697         return(1);
698 }
699
700
701 /*
702  * Parse a single, mandatory value from the stream.
703  */
704 static int
705 argv_single(struct mdoc *m, int line,
706                 struct mdoc_argv *v, int *pos, char *buf)
707 {
708         int              c, ppos;
709         char            *p;
710
711         ppos = *pos;
712
713         c = args(m, line, pos, buf, 0, &p);
714         if (ARGS_ERROR == c)
715                 return(0);
716         if (ARGS_EOLN == c)
717                 return(mdoc_perr(m, line, ppos, EARGVAL));
718
719         v->sz = 1;
720         v->value = mandoc_malloc(sizeof(char *));
721         v->value[0] = mandoc_strdup(p);
722
723         return(1);
724 }
725
726
727 /*
728  * Determine rules for parsing arguments.  Arguments can either accept
729  * no parameters, an optional single parameter, one parameter, or
730  * multiple parameters.
731  */
732 static int
733 argv(struct mdoc *mdoc, int line,
734                 struct mdoc_argv *v, int *pos, char *buf)
735 {
736
737         v->sz = 0;
738         v->value = NULL;
739
740         switch (mdoc_argvflags[v->arg]) {
741         case (ARGV_SINGLE):
742                 return(argv_single(mdoc, line, v, pos, buf));
743         case (ARGV_MULTI):
744                 return(argv_multi(mdoc, line, v, pos, buf));
745         case (ARGV_OPT_SINGLE):
746                 return(argv_opt_single(mdoc, line, v, pos, buf));
747         default:
748                 /* ARGV_NONE */
749                 break;
750         }
751
752         return(1);
753 }