]>
git.cameronkatri.com Git - mandoc.git/blob - mdoc_argv.c
1 /* $Id: mdoc_argv.c,v 1.9 2009/07/06 09:21:24 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 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 above
7 * copyright notice and this permission notice appear in all copies.
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.
17 #include <sys/types.h>
28 * Routines to parse arguments of macros. Arguments follow the syntax
29 * of `-arg [val [valN...]]'. Arguments come in all types: quoted
30 * arguments, multiple arguments per value, no-value arguments, etc.
32 * There's no limit to the number or arguments that may be allocated.
35 /* FIXME .Bf Li raises "macro-like parameter". */
36 /* FIXME .Bl -column should deprecate old-groff syntax. */
38 #define ARGS_QUOTED (1 << 0)
39 #define ARGS_DELIM (1 << 1)
40 #define ARGS_TABSEP (1 << 2)
41 #define ARGS_ARGVLIKE (1 << 3)
43 #define ARGV_NONE (1 << 0)
44 #define ARGV_SINGLE (1 << 1)
45 #define ARGV_MULTI (1 << 2)
46 #define ARGV_OPT_SINGLE (1 << 3)
63 static int argv_a2arg(int, const char *);
64 static int args(struct mdoc
*, int, int *,
65 char *, int, char **);
66 static int argv(struct mdoc
*, int,
67 struct mdoc_argv
*, int *, char *);
68 static int argv_single(struct mdoc
*, int,
69 struct mdoc_argv
*, int *, char *);
70 static int argv_opt_single(struct mdoc
*, int,
71 struct mdoc_argv
*, int *, char *);
72 static int argv_multi(struct mdoc
*, int,
73 struct mdoc_argv
*, int *, char *);
74 static int pwarn(struct mdoc
*, int, int, enum mwarn
);
75 static int perr(struct mdoc
*, int, int, enum merr
);
77 #define verr(m, t) perr((m), (m)->last->line, (m)->last->pos, (t))
79 /* Per-argument flags. */
81 static int mdoc_argvflags
[MDOC_ARG_MAX
] = {
82 ARGV_NONE
, /* MDOC_Split */
83 ARGV_NONE
, /* MDOC_Nosplit */
84 ARGV_NONE
, /* MDOC_Ragged */
85 ARGV_NONE
, /* MDOC_Unfilled */
86 ARGV_NONE
, /* MDOC_Literal */
87 ARGV_NONE
, /* MDOC_File */
88 ARGV_SINGLE
, /* MDOC_Offset */
89 ARGV_NONE
, /* MDOC_Bullet */
90 ARGV_NONE
, /* MDOC_Dash */
91 ARGV_NONE
, /* MDOC_Hyphen */
92 ARGV_NONE
, /* MDOC_Item */
93 ARGV_NONE
, /* MDOC_Enum */
94 ARGV_NONE
, /* MDOC_Tag */
95 ARGV_NONE
, /* MDOC_Diag */
96 ARGV_NONE
, /* MDOC_Hang */
97 ARGV_NONE
, /* MDOC_Ohang */
98 ARGV_NONE
, /* MDOC_Inset */
99 ARGV_MULTI
, /* MDOC_Column */
100 ARGV_SINGLE
, /* MDOC_Width */
101 ARGV_NONE
, /* MDOC_Compact */
102 ARGV_OPT_SINGLE
, /* MDOC_Std */
103 ARGV_NONE
, /* MDOC_Filled */
104 ARGV_NONE
, /* MDOC_Words */
105 ARGV_NONE
, /* MDOC_Emphasis */
106 ARGV_NONE
, /* MDOC_Symbolic */
107 ARGV_NONE
/* MDOC_Symbolic */
110 static int mdoc_argflags
[MDOC_MAX
] = {
115 ARGS_QUOTED
, /* Sh */
116 ARGS_QUOTED
, /* Ss */
119 ARGS_DELIM
| ARGS_QUOTED
, /* Dl */
122 ARGS_QUOTED
, /* Bl */
127 ARGS_DELIM
| ARGS_QUOTED
, /* Ar */
128 ARGS_QUOTED
, /* Cd */
134 ARGS_DELIM
| ARGS_QUOTED
, /* Fa */
137 ARGS_DELIM
| ARGS_QUOTED
, /* Fn */
138 ARGS_DELIM
| ARGS_QUOTED
, /* Ft */
141 ARGS_DELIM
| ARGS_QUOTED
, /* Li */
142 ARGS_QUOTED
, /* Nd */
148 ARGS_DELIM
| ARGS_ARGVLIKE
, /* St */
152 ARGS_QUOTED
, /* %A */
153 ARGS_QUOTED
, /* %B */
154 ARGS_QUOTED
, /* %D */
155 ARGS_QUOTED
, /* %I */
156 ARGS_QUOTED
, /* %J */
157 ARGS_QUOTED
, /* %N */
158 ARGS_QUOTED
, /* %O */
159 ARGS_QUOTED
, /* %P */
160 ARGS_QUOTED
, /* %R */
161 ARGS_QUOTED
, /* %T */
162 ARGS_QUOTED
, /* %V */
171 ARGS_DELIM
, /* Bsx */
202 ARGS_DELIM
| ARGS_QUOTED
, /* Sy */
207 ARGS_QUOTED
, /* Fo */
219 ARGS_DELIM
| ARGS_QUOTED
, /* Lk */
220 ARGS_DELIM
| ARGS_QUOTED
, /* Mt */
221 ARGS_DELIM
, /* Brq */
223 ARGS_DELIM
, /* Brc */
224 ARGS_QUOTED
, /* %C */
228 ARGS_QUOTED
, /* %Q */
233 * Parse an argument from line text. This comes in the form of -key
234 * [value0...], which may either have a single mandatory value, at least
235 * one mandatory value, an optional single value, or no value.
238 mdoc_argv(struct mdoc
*mdoc
, int line
, int tok
,
239 struct mdoc_arg
**v
, int *pos
, char *buf
)
243 struct mdoc_argv tmp
;
244 struct mdoc_arg
*arg
;
249 assert(' ' != buf
[*pos
]);
251 if ('-' != buf
[*pos
] || ARGS_ARGVLIKE
& mdoc_argflags
[tok
])
254 /* Parse through to the first unescaped space. */
263 if (' ' == buf
[*pos
])
264 if ('\\' != buf
[*pos
- 1])
269 /* XXX - save zeroed byte, if not an argument. */
277 (void)memset(&tmp
, 0, sizeof(struct mdoc_argv
));
281 /* See if our token accepts the argument. */
283 if (MDOC_ARG_MAX
== (tmp
.arg
= argv_a2arg(tok
, p
))) {
284 /* XXX - restore saved zeroed byte. */
287 if ( ! pwarn(mdoc
, line
, i
, WARGVPARM
))
292 while (buf
[*pos
] && ' ' == buf
[*pos
])
295 if ( ! argv(mdoc
, line
, &tmp
, pos
, buf
))
298 if (NULL
== (arg
= *v
)) {
299 *v
= calloc(1, sizeof(struct mdoc_arg
));
301 (void)verr(mdoc
, EMALLOC
);
308 arg
->argv
= realloc(arg
->argv
, arg
->argc
*
309 sizeof(struct mdoc_argv
));
311 if (NULL
== arg
->argv
) {
312 (void)verr(mdoc
, EMALLOC
);
316 (void)memcpy(&arg
->argv
[(int)arg
->argc
- 1],
317 &tmp
, sizeof(struct mdoc_argv
));
324 mdoc_argv_free(struct mdoc_arg
*p
)
339 for (i
= 0; i
< (int)p
->argc
; i
++) {
340 if (0 == p
->argv
[i
].sz
)
343 for (j
= 0; j
< (int)p
->argv
[i
].sz
; j
++)
344 free(p
->argv
[i
].value
[j
]);
346 free(p
->argv
[i
].value
);
356 perr(struct mdoc
*mdoc
, int line
, int pos
, enum merr code
)
363 p
= "memory exhausted";
366 p
= "unterminated quoted parameter";
369 p
= "argument requires a value";
374 return(mdoc_perr(mdoc
, line
, pos
, p
));
379 pwarn(struct mdoc
*mdoc
, int line
, int pos
, enum mwarn code
)
387 p
= "unexpected quoted parameter";
390 p
= "argument-like parameter";
393 p
= "last list column is empty";
396 p
= "trailing whitespace";
401 return(mdoc_pwarn(mdoc
, line
, pos
, p
));
406 mdoc_args(struct mdoc
*mdoc
, int line
,
407 int *pos
, char *buf
, int tok
, char **v
)
412 fl
= (0 == tok
) ? 0 : mdoc_argflags
[tok
];
415 * Override per-macro argument flags with context-specific ones.
416 * As of now, this is only valid for `It' depending on its list
422 for (n
= mdoc
->last
; n
; n
= n
->parent
)
423 if (MDOC_BLOCK
== n
->type
&& MDOC_Bl
== n
->tok
)
427 c
= (int)(n
->args
? n
->args
->argc
: 0);
431 * Using `Bl -column' adds ARGS_TABSEP to the arguments
432 * and invalidates ARGS_DELIM. Using `Bl -diag' allows
433 * for quoted arguments.
437 for (i
= 0; i
< c
; i
++) {
438 switch (n
->args
->argv
[i
].arg
) {
457 return(args(mdoc
, line
, pos
, buf
, fl
, v
));
462 args(struct mdoc
*mdoc
, int line
,
463 int *pos
, char *buf
, int fl
, char **v
)
473 if ('\"' == buf
[*pos
] && ! (fl
& ARGS_QUOTED
))
474 if ( ! pwarn(mdoc
, line
, *pos
, WQUOTPARM
))
477 if ( ! (fl
& ARGS_ARGVLIKE
) && '-' == buf
[*pos
])
478 if ( ! pwarn(mdoc
, line
, *pos
, WARGVPARM
))
482 * If the first character is a delimiter and we're to look for
483 * delimited strings, then pass down the buffer seeing if it
484 * follows the pattern of [[::delim::][ ]+]+.
487 if ((fl
& ARGS_DELIM
) && mdoc_iscdelim(buf
[*pos
])) {
488 for (i
= *pos
; buf
[i
]; ) {
489 if ( ! mdoc_iscdelim(buf
[i
]))
492 /* There must be at least one space... */
493 if (0 == buf
[i
] || ' ' != buf
[i
])
496 while (buf
[i
] && ' ' == buf
[i
])
505 /* First parse non-quoted strings. */
507 if ('\"' != buf
[*pos
] || ! (ARGS_QUOTED
& fl
)) {
511 * Thar be dragons here! If we're tab-separated, search
512 * ahead for either a tab or the `Ta' macro.
513 * If a `Ta' is detected, it must be space-buffered before and
514 * after. If either of these hold true, then prune out the
515 * extra spaces and call it an argument.
518 if (ARGS_TABSEP
& fl
) {
519 /* Scan ahead to unescaped tab. */
521 p
= strchr(*v
, '\t');
523 /* Scan ahead to unescaped `Ta'. */
525 for (pp
= *v
; ; pp
++) {
526 if (NULL
== (pp
= strstr(pp
, "Ta")))
528 if (pp
> *v
&& ' ' != *(pp
- 1))
530 if (' ' == *(pp
+ 2) || 0 == *(pp
+ 2))
534 /* Choose delimiter tab/Ta. */
537 p
= (p
< pp
? p
: pp
);
541 /* Strip delimiter's preceding whitespace. */
545 while (pp
> *v
&& ' ' == *pp
)
547 if (pp
== *v
&& ' ' == *pp
)
553 /* ...in- and proceding whitespace. */
555 if (p
&& ('\t' != *p
)) {
566 *pos
+= (int)(p
- *v
);
570 if ( ! pwarn(mdoc
, line
, *pos
, WCOLEMPTY
))
572 if (p
&& 0 == *p
&& p
> *v
&& ' ' == *(p
- 1))
573 if ( ! pwarn(mdoc
, line
, *pos
, WTAILWS
))
579 /* Configure the eoln case, too. */
584 if (p
> *v
&& ' ' == *(p
- 1))
585 if ( ! pwarn(mdoc
, line
, *pos
, WTAILWS
))
587 *pos
+= (int)(p
- *v
);
592 /* Do non-tabsep look-ahead here. */
594 if ( ! (ARGS_TABSEP
& fl
))
596 if (' ' == buf
[*pos
])
597 if ('\\' != buf
[*pos
- 1])
610 if ( ! (ARGS_TABSEP
& fl
))
611 while (buf
[*pos
] && ' ' == buf
[*pos
])
617 if ( ! pwarn(mdoc
, line
, *pos
, WTAILWS
))
624 * If we're a quoted string (and quoted strings are allowed),
625 * then parse ahead to the next quote. If none's found, it's an
626 * error. After, parse to the next word.
631 while (buf
[*pos
] && '\"' != buf
[*pos
])
634 if (0 == buf
[*pos
]) {
635 (void)perr(mdoc
, line
, *pos
, EQUOTTERM
);
643 while (buf
[*pos
] && ' ' == buf
[*pos
])
649 if ( ! pwarn(mdoc
, line
, *pos
, WTAILWS
))
657 argv_a2arg(int tok
, const char *argv
)
661 * Parse an argument identifier from its text. XXX - this
662 * should really be table-driven to clarify the code.
664 * If you add an argument to the list, make sure that you
665 * register it here with its one or more macros!
670 if (0 == strcmp(argv
, "split"))
672 else if (0 == strcmp(argv
, "nosplit"))
673 return(MDOC_Nosplit
);
677 if (0 == strcmp(argv
, "ragged"))
679 else if (0 == strcmp(argv
, "unfilled"))
680 return(MDOC_Unfilled
);
681 else if (0 == strcmp(argv
, "filled"))
683 else if (0 == strcmp(argv
, "literal"))
684 return(MDOC_Literal
);
685 else if (0 == strcmp(argv
, "file"))
687 else if (0 == strcmp(argv
, "offset"))
689 else if (0 == strcmp(argv
, "compact"))
690 return(MDOC_Compact
);
694 if (0 == strcmp(argv
, "emphasis"))
695 return(MDOC_Emphasis
);
696 else if (0 == strcmp(argv
, "literal"))
697 return(MDOC_Literal
);
698 else if (0 == strcmp(argv
, "symbolic"))
699 return(MDOC_Symbolic
);
703 if (0 == strcmp(argv
, "words"))
708 if (0 == strcmp(argv
, "bullet"))
710 else if (0 == strcmp(argv
, "dash"))
712 else if (0 == strcmp(argv
, "hyphen"))
714 else if (0 == strcmp(argv
, "item"))
716 else if (0 == strcmp(argv
, "enum"))
718 else if (0 == strcmp(argv
, "tag"))
720 else if (0 == strcmp(argv
, "diag"))
722 else if (0 == strcmp(argv
, "hang"))
724 else if (0 == strcmp(argv
, "ohang"))
726 else if (0 == strcmp(argv
, "inset"))
728 else if (0 == strcmp(argv
, "column"))
730 else if (0 == strcmp(argv
, "width"))
732 else if (0 == strcmp(argv
, "offset"))
734 else if (0 == strcmp(argv
, "compact"))
735 return(MDOC_Compact
);
736 else if (0 == strcmp(argv
, "nested"))
743 if (0 == strcmp(argv
, "std"))
750 return(MDOC_ARG_MAX
);
755 argv_multi(struct mdoc
*mdoc
, int line
,
756 struct mdoc_argv
*v
, int *pos
, char *buf
)
761 for (v
->sz
= 0; ; v
->sz
++) {
762 if ('-' == buf
[*pos
])
764 c
= args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
767 else if (ARGS_EOLN
== c
)
770 if (0 == v
->sz
% MULTI_STEP
) {
771 v
->value
= realloc(v
->value
,
772 (v
->sz
+ MULTI_STEP
) * sizeof(char *));
773 if (NULL
== v
->value
) {
774 (void)verr(mdoc
, EMALLOC
);
778 if (NULL
== (v
->value
[(int)v
->sz
] = strdup(p
)))
779 return(verr(mdoc
, EMALLOC
));
787 argv_opt_single(struct mdoc
*mdoc
, int line
,
788 struct mdoc_argv
*v
, int *pos
, char *buf
)
793 if ('-' == buf
[*pos
])
796 c
= args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
803 if (NULL
== (v
->value
= calloc(1, sizeof(char *))))
804 return(verr(mdoc
, EMALLOC
));
805 if (NULL
== (v
->value
[0] = strdup(p
)))
806 return(verr(mdoc
, EMALLOC
));
813 * Parse a single, mandatory value from the stream.
816 argv_single(struct mdoc
*mdoc
, int line
,
817 struct mdoc_argv
*v
, int *pos
, char *buf
)
824 c
= args(mdoc
, line
, pos
, buf
, ARGS_QUOTED
, &p
);
828 return(perr(mdoc
, line
, ppos
, EARGVAL
));
831 if (NULL
== (v
->value
= calloc(1, sizeof(char *))))
832 return(verr(mdoc
, EMALLOC
));
833 if (NULL
== (v
->value
[0] = strdup(p
)))
834 return(verr(mdoc
, EMALLOC
));
841 * Determine rules for parsing arguments. Arguments can either accept
842 * no parameters, an optional single parameter, one parameter, or
843 * multiple parameters.
846 argv(struct mdoc
*mdoc
, int line
,
847 struct mdoc_argv
*v
, int *pos
, char *buf
)
853 switch (mdoc_argvflags
[v
->arg
]) {
855 return(argv_single(mdoc
, line
, v
, pos
, buf
));
857 return(argv_multi(mdoc
, line
, v
, pos
, buf
));
858 case (ARGV_OPT_SINGLE
):
859 return(argv_opt_single(mdoc
, line
, v
, pos
, buf
));