xref: /titanic_53/usr/src/cmd/mandoc/mdoc_argv.c (revision 95c635efb7c3b86efc493e0447eaec7aecca3f0f)
1*95c635efSGarrett D'Amore /*	$Id: mdoc_argv.c,v 1.82 2012/03/23 05:50:24 kristaps Exp $ */
2*95c635efSGarrett D'Amore /*
3*95c635efSGarrett D'Amore  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*95c635efSGarrett D'Amore  *
5*95c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
6*95c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
7*95c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
8*95c635efSGarrett D'Amore  *
9*95c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*95c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*95c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*95c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*95c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*95c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*95c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*95c635efSGarrett D'Amore  */
17*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H
18*95c635efSGarrett D'Amore #include "config.h"
19*95c635efSGarrett D'Amore #endif
20*95c635efSGarrett D'Amore 
21*95c635efSGarrett D'Amore #include <sys/types.h>
22*95c635efSGarrett D'Amore 
23*95c635efSGarrett D'Amore #include <assert.h>
24*95c635efSGarrett D'Amore #include <stdlib.h>
25*95c635efSGarrett D'Amore #include <stdio.h>
26*95c635efSGarrett D'Amore #include <string.h>
27*95c635efSGarrett D'Amore 
28*95c635efSGarrett D'Amore #include "mdoc.h"
29*95c635efSGarrett D'Amore #include "mandoc.h"
30*95c635efSGarrett D'Amore #include "libmdoc.h"
31*95c635efSGarrett D'Amore #include "libmandoc.h"
32*95c635efSGarrett D'Amore 
33*95c635efSGarrett D'Amore #define	MULTI_STEP	 5 /* pre-allocate argument values */
34*95c635efSGarrett D'Amore #define	DELIMSZ	  	 6 /* max possible size of a delimiter */
35*95c635efSGarrett D'Amore 
36*95c635efSGarrett D'Amore enum	argsflag {
37*95c635efSGarrett D'Amore 	ARGSFL_NONE = 0,
38*95c635efSGarrett D'Amore 	ARGSFL_DELIM, /* handle delimiters of [[::delim::][ ]+]+ */
39*95c635efSGarrett D'Amore 	ARGSFL_TABSEP /* handle tab/`Ta' separated phrases */
40*95c635efSGarrett D'Amore };
41*95c635efSGarrett D'Amore 
42*95c635efSGarrett D'Amore enum	argvflag {
43*95c635efSGarrett D'Amore 	ARGV_NONE, /* no args to flag (e.g., -split) */
44*95c635efSGarrett D'Amore 	ARGV_SINGLE, /* one arg to flag (e.g., -file xxx)  */
45*95c635efSGarrett D'Amore 	ARGV_MULTI, /* multiple args (e.g., -column xxx yyy) */
46*95c635efSGarrett D'Amore 	ARGV_OPT_SINGLE /* optional arg (e.g., -offset [xxx]) */
47*95c635efSGarrett D'Amore };
48*95c635efSGarrett D'Amore 
49*95c635efSGarrett D'Amore struct	mdocarg {
50*95c635efSGarrett D'Amore 	enum argsflag	 flags;
51*95c635efSGarrett D'Amore 	const enum mdocargt *argvs;
52*95c635efSGarrett D'Amore };
53*95c635efSGarrett D'Amore 
54*95c635efSGarrett D'Amore static	void		 argn_free(struct mdoc_arg *, int);
55*95c635efSGarrett D'Amore static	enum margserr	 args(struct mdoc *, int, int *,
56*95c635efSGarrett D'Amore 				char *, enum argsflag, char **);
57*95c635efSGarrett D'Amore static	int		 args_checkpunct(const char *, int);
58*95c635efSGarrett D'Amore static	int		 argv_multi(struct mdoc *, int,
59*95c635efSGarrett D'Amore 				struct mdoc_argv *, int *, char *);
60*95c635efSGarrett D'Amore static	int		 argv_opt_single(struct mdoc *, int,
61*95c635efSGarrett D'Amore 				struct mdoc_argv *, int *, char *);
62*95c635efSGarrett D'Amore static	int		 argv_single(struct mdoc *, int,
63*95c635efSGarrett D'Amore 				struct mdoc_argv *, int *, char *);
64*95c635efSGarrett D'Amore 
65*95c635efSGarrett D'Amore static	const enum argvflag argvflags[MDOC_ARG_MAX] = {
66*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Split */
67*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Nosplit */
68*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Ragged */
69*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Unfilled */
70*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Literal */
71*95c635efSGarrett D'Amore 	ARGV_SINGLE,	/* MDOC_File */
72*95c635efSGarrett D'Amore 	ARGV_OPT_SINGLE, /* MDOC_Offset */
73*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Bullet */
74*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Dash */
75*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Hyphen */
76*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Item */
77*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Enum */
78*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Tag */
79*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Diag */
80*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Hang */
81*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Ohang */
82*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Inset */
83*95c635efSGarrett D'Amore 	ARGV_MULTI,	/* MDOC_Column */
84*95c635efSGarrett D'Amore 	ARGV_OPT_SINGLE, /* MDOC_Width */
85*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Compact */
86*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Std */
87*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Filled */
88*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Words */
89*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Emphasis */
90*95c635efSGarrett D'Amore 	ARGV_NONE,	/* MDOC_Symbolic */
91*95c635efSGarrett D'Amore 	ARGV_NONE	/* MDOC_Symbolic */
92*95c635efSGarrett D'Amore };
93*95c635efSGarrett D'Amore 
94*95c635efSGarrett D'Amore static	const enum mdocargt args_Ex[] = {
95*95c635efSGarrett D'Amore 	MDOC_Std,
96*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
97*95c635efSGarrett D'Amore };
98*95c635efSGarrett D'Amore 
99*95c635efSGarrett D'Amore static	const enum mdocargt args_An[] = {
100*95c635efSGarrett D'Amore 	MDOC_Split,
101*95c635efSGarrett D'Amore 	MDOC_Nosplit,
102*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
103*95c635efSGarrett D'Amore };
104*95c635efSGarrett D'Amore 
105*95c635efSGarrett D'Amore static	const enum mdocargt args_Bd[] = {
106*95c635efSGarrett D'Amore 	MDOC_Ragged,
107*95c635efSGarrett D'Amore 	MDOC_Unfilled,
108*95c635efSGarrett D'Amore 	MDOC_Filled,
109*95c635efSGarrett D'Amore 	MDOC_Literal,
110*95c635efSGarrett D'Amore 	MDOC_File,
111*95c635efSGarrett D'Amore 	MDOC_Offset,
112*95c635efSGarrett D'Amore 	MDOC_Compact,
113*95c635efSGarrett D'Amore 	MDOC_Centred,
114*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
115*95c635efSGarrett D'Amore };
116*95c635efSGarrett D'Amore 
117*95c635efSGarrett D'Amore static	const enum mdocargt args_Bf[] = {
118*95c635efSGarrett D'Amore 	MDOC_Emphasis,
119*95c635efSGarrett D'Amore 	MDOC_Literal,
120*95c635efSGarrett D'Amore 	MDOC_Symbolic,
121*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
122*95c635efSGarrett D'Amore };
123*95c635efSGarrett D'Amore 
124*95c635efSGarrett D'Amore static	const enum mdocargt args_Bk[] = {
125*95c635efSGarrett D'Amore 	MDOC_Words,
126*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
127*95c635efSGarrett D'Amore };
128*95c635efSGarrett D'Amore 
129*95c635efSGarrett D'Amore static	const enum mdocargt args_Bl[] = {
130*95c635efSGarrett D'Amore 	MDOC_Bullet,
131*95c635efSGarrett D'Amore 	MDOC_Dash,
132*95c635efSGarrett D'Amore 	MDOC_Hyphen,
133*95c635efSGarrett D'Amore 	MDOC_Item,
134*95c635efSGarrett D'Amore 	MDOC_Enum,
135*95c635efSGarrett D'Amore 	MDOC_Tag,
136*95c635efSGarrett D'Amore 	MDOC_Diag,
137*95c635efSGarrett D'Amore 	MDOC_Hang,
138*95c635efSGarrett D'Amore 	MDOC_Ohang,
139*95c635efSGarrett D'Amore 	MDOC_Inset,
140*95c635efSGarrett D'Amore 	MDOC_Column,
141*95c635efSGarrett D'Amore 	MDOC_Width,
142*95c635efSGarrett D'Amore 	MDOC_Offset,
143*95c635efSGarrett D'Amore 	MDOC_Compact,
144*95c635efSGarrett D'Amore 	MDOC_Nested,
145*95c635efSGarrett D'Amore 	MDOC_ARG_MAX
146*95c635efSGarrett D'Amore };
147*95c635efSGarrett D'Amore 
148*95c635efSGarrett D'Amore static	const struct mdocarg mdocargs[MDOC_MAX] = {
149*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ap */
150*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Dd */
151*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Dt */
152*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Os */
153*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Sh */
154*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ss */
155*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Pp */
156*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* D1 */
157*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Dl */
158*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Bd }, /* Bd */
159*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ed */
160*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Bl }, /* Bl */
161*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* El */
162*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* It */
163*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ad */
164*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, args_An }, /* An */
165*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ar */
166*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Cd */
167*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Cm */
168*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Dv */
169*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Er */
170*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ev */
171*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Ex }, /* Ex */
172*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Fa */
173*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Fd */
174*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Fl */
175*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Fn */
176*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ft */
177*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ic */
178*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* In */
179*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Li */
180*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Nd */
181*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Nm */
182*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Op */
183*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ot */
184*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Pa */
185*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Ex }, /* Rv */
186*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* St */
187*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Va */
188*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Vt */
189*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Xr */
190*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %A */
191*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %B */
192*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %D */
193*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %I */
194*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %J */
195*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %N */
196*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %O */
197*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %P */
198*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %R */
199*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %T */
200*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %V */
201*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ac */
202*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ao */
203*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Aq */
204*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* At */
205*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Bc */
206*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Bf }, /* Bf */
207*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Bo */
208*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Bq */
209*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Bsx */
210*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Bx */
211*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Db */
212*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Dc */
213*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Do */
214*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Dq */
215*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ec */
216*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ef */
217*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Em */
218*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Eo */
219*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Fx */
220*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ms */
221*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* No */
222*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ns */
223*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Nx */
224*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ox */
225*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Pc */
226*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Pf */
227*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Po */
228*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Pq */
229*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Qc */
230*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ql */
231*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Qo */
232*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Qq */
233*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Re */
234*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Rs */
235*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Sc */
236*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* So */
237*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Sq */
238*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Sm */
239*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Sx */
240*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Sy */
241*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Tn */
242*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Ux */
243*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Xc */
244*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Xo */
245*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Fo */
246*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Fc */
247*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Oo */
248*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Oc */
249*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, args_Bk }, /* Bk */
250*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ek */
251*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Bt */
252*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Hf */
253*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Fr */
254*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ud */
255*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Lb */
256*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Lp */
257*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Lk */
258*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Mt */
259*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Brq */
260*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Bro */
261*95c635efSGarrett D'Amore 	{ ARGSFL_DELIM, NULL }, /* Brc */
262*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %C */
263*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Es */
264*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* En */
265*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Dx */
266*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %Q */
267*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* br */
268*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* sp */
269*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* %U */
270*95c635efSGarrett D'Amore 	{ ARGSFL_NONE, NULL }, /* Ta */
271*95c635efSGarrett D'Amore };
272*95c635efSGarrett D'Amore 
273*95c635efSGarrett D'Amore 
274*95c635efSGarrett D'Amore /*
275*95c635efSGarrett D'Amore  * Parse an argument from line text.  This comes in the form of -key
276*95c635efSGarrett D'Amore  * [value0...], which may either have a single mandatory value, at least
277*95c635efSGarrett D'Amore  * one mandatory value, an optional single value, or no value.
278*95c635efSGarrett D'Amore  */
279*95c635efSGarrett D'Amore enum margverr
280*95c635efSGarrett D'Amore mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
281*95c635efSGarrett D'Amore 		struct mdoc_arg **v, int *pos, char *buf)
282*95c635efSGarrett D'Amore {
283*95c635efSGarrett D'Amore 	char		 *p, sv;
284*95c635efSGarrett D'Amore 	struct mdoc_argv tmp;
285*95c635efSGarrett D'Amore 	struct mdoc_arg	 *arg;
286*95c635efSGarrett D'Amore 	const enum mdocargt *ap;
287*95c635efSGarrett D'Amore 
288*95c635efSGarrett D'Amore 	if ('\0' == buf[*pos])
289*95c635efSGarrett D'Amore 		return(ARGV_EOLN);
290*95c635efSGarrett D'Amore 	else if (NULL == (ap = mdocargs[tok].argvs))
291*95c635efSGarrett D'Amore 		return(ARGV_WORD);
292*95c635efSGarrett D'Amore 	else if ('-' != buf[*pos])
293*95c635efSGarrett D'Amore 		return(ARGV_WORD);
294*95c635efSGarrett D'Amore 
295*95c635efSGarrett D'Amore 	/* Seek to the first unescaped space. */
296*95c635efSGarrett D'Amore 
297*95c635efSGarrett D'Amore 	p = &buf[++(*pos)];
298*95c635efSGarrett D'Amore 
299*95c635efSGarrett D'Amore 	assert(*pos > 0);
300*95c635efSGarrett D'Amore 
301*95c635efSGarrett D'Amore 	for ( ; buf[*pos] ; (*pos)++)
302*95c635efSGarrett D'Amore 		if (' ' == buf[*pos] && '\\' != buf[*pos - 1])
303*95c635efSGarrett D'Amore 			break;
304*95c635efSGarrett D'Amore 
305*95c635efSGarrett D'Amore 	/*
306*95c635efSGarrett D'Amore 	 * We want to nil-terminate the word to look it up (it's easier
307*95c635efSGarrett D'Amore 	 * that way).  But we may not have a flag, in which case we need
308*95c635efSGarrett D'Amore 	 * to restore the line as-is.  So keep around the stray byte,
309*95c635efSGarrett D'Amore 	 * which we'll reset upon exiting (if necessary).
310*95c635efSGarrett D'Amore 	 */
311*95c635efSGarrett D'Amore 
312*95c635efSGarrett D'Amore 	if ('\0' != (sv = buf[*pos]))
313*95c635efSGarrett D'Amore 		buf[(*pos)++] = '\0';
314*95c635efSGarrett D'Amore 
315*95c635efSGarrett D'Amore 	/*
316*95c635efSGarrett D'Amore 	 * Now look up the word as a flag.  Use temporary storage that
317*95c635efSGarrett D'Amore 	 * we'll copy into the node's flags, if necessary.
318*95c635efSGarrett D'Amore 	 */
319*95c635efSGarrett D'Amore 
320*95c635efSGarrett D'Amore 	memset(&tmp, 0, sizeof(struct mdoc_argv));
321*95c635efSGarrett D'Amore 
322*95c635efSGarrett D'Amore 	tmp.line = line;
323*95c635efSGarrett D'Amore 	tmp.pos = *pos;
324*95c635efSGarrett D'Amore 	tmp.arg = MDOC_ARG_MAX;
325*95c635efSGarrett D'Amore 
326*95c635efSGarrett D'Amore 	while (MDOC_ARG_MAX != (tmp.arg = *ap++))
327*95c635efSGarrett D'Amore 		if (0 == strcmp(p, mdoc_argnames[tmp.arg]))
328*95c635efSGarrett D'Amore 			break;
329*95c635efSGarrett D'Amore 
330*95c635efSGarrett D'Amore 	if (MDOC_ARG_MAX == tmp.arg) {
331*95c635efSGarrett D'Amore 		/*
332*95c635efSGarrett D'Amore 		 * The flag was not found.
333*95c635efSGarrett D'Amore 		 * Restore saved zeroed byte and return as a word.
334*95c635efSGarrett D'Amore 		 */
335*95c635efSGarrett D'Amore 		if (sv)
336*95c635efSGarrett D'Amore 			buf[*pos - 1] = sv;
337*95c635efSGarrett D'Amore 		return(ARGV_WORD);
338*95c635efSGarrett D'Amore 	}
339*95c635efSGarrett D'Amore 
340*95c635efSGarrett D'Amore 	/* Read to the next word (the argument). */
341*95c635efSGarrett D'Amore 
342*95c635efSGarrett D'Amore 	while (buf[*pos] && ' ' == buf[*pos])
343*95c635efSGarrett D'Amore 		(*pos)++;
344*95c635efSGarrett D'Amore 
345*95c635efSGarrett D'Amore 	switch (argvflags[tmp.arg]) {
346*95c635efSGarrett D'Amore 	case (ARGV_SINGLE):
347*95c635efSGarrett D'Amore 		if ( ! argv_single(m, line, &tmp, pos, buf))
348*95c635efSGarrett D'Amore 			return(ARGV_ERROR);
349*95c635efSGarrett D'Amore 		break;
350*95c635efSGarrett D'Amore 	case (ARGV_MULTI):
351*95c635efSGarrett D'Amore 		if ( ! argv_multi(m, line, &tmp, pos, buf))
352*95c635efSGarrett D'Amore 			return(ARGV_ERROR);
353*95c635efSGarrett D'Amore 		break;
354*95c635efSGarrett D'Amore 	case (ARGV_OPT_SINGLE):
355*95c635efSGarrett D'Amore 		if ( ! argv_opt_single(m, line, &tmp, pos, buf))
356*95c635efSGarrett D'Amore 			return(ARGV_ERROR);
357*95c635efSGarrett D'Amore 		break;
358*95c635efSGarrett D'Amore 	case (ARGV_NONE):
359*95c635efSGarrett D'Amore 		break;
360*95c635efSGarrett D'Amore 	}
361*95c635efSGarrett D'Amore 
362*95c635efSGarrett D'Amore 	if (NULL == (arg = *v))
363*95c635efSGarrett D'Amore 		arg = *v = mandoc_calloc(1, sizeof(struct mdoc_arg));
364*95c635efSGarrett D'Amore 
365*95c635efSGarrett D'Amore 	arg->argc++;
366*95c635efSGarrett D'Amore 	arg->argv = mandoc_realloc
367*95c635efSGarrett D'Amore 		(arg->argv, arg->argc * sizeof(struct mdoc_argv));
368*95c635efSGarrett D'Amore 
369*95c635efSGarrett D'Amore 	memcpy(&arg->argv[(int)arg->argc - 1],
370*95c635efSGarrett D'Amore 			&tmp, sizeof(struct mdoc_argv));
371*95c635efSGarrett D'Amore 
372*95c635efSGarrett D'Amore 	return(ARGV_ARG);
373*95c635efSGarrett D'Amore }
374*95c635efSGarrett D'Amore 
375*95c635efSGarrett D'Amore void
376*95c635efSGarrett D'Amore mdoc_argv_free(struct mdoc_arg *p)
377*95c635efSGarrett D'Amore {
378*95c635efSGarrett D'Amore 	int		 i;
379*95c635efSGarrett D'Amore 
380*95c635efSGarrett D'Amore 	if (NULL == p)
381*95c635efSGarrett D'Amore 		return;
382*95c635efSGarrett D'Amore 
383*95c635efSGarrett D'Amore 	if (p->refcnt) {
384*95c635efSGarrett D'Amore 		--(p->refcnt);
385*95c635efSGarrett D'Amore 		if (p->refcnt)
386*95c635efSGarrett D'Amore 			return;
387*95c635efSGarrett D'Amore 	}
388*95c635efSGarrett D'Amore 	assert(p->argc);
389*95c635efSGarrett D'Amore 
390*95c635efSGarrett D'Amore 	for (i = (int)p->argc - 1; i >= 0; i--)
391*95c635efSGarrett D'Amore 		argn_free(p, i);
392*95c635efSGarrett D'Amore 
393*95c635efSGarrett D'Amore 	free(p->argv);
394*95c635efSGarrett D'Amore 	free(p);
395*95c635efSGarrett D'Amore }
396*95c635efSGarrett D'Amore 
397*95c635efSGarrett D'Amore static void
398*95c635efSGarrett D'Amore argn_free(struct mdoc_arg *p, int iarg)
399*95c635efSGarrett D'Amore {
400*95c635efSGarrett D'Amore 	struct mdoc_argv *arg;
401*95c635efSGarrett D'Amore 	int		  j;
402*95c635efSGarrett D'Amore 
403*95c635efSGarrett D'Amore 	arg = &p->argv[iarg];
404*95c635efSGarrett D'Amore 
405*95c635efSGarrett D'Amore 	if (arg->sz && arg->value) {
406*95c635efSGarrett D'Amore 		for (j = (int)arg->sz - 1; j >= 0; j--)
407*95c635efSGarrett D'Amore 			free(arg->value[j]);
408*95c635efSGarrett D'Amore 		free(arg->value);
409*95c635efSGarrett D'Amore 	}
410*95c635efSGarrett D'Amore 
411*95c635efSGarrett D'Amore 	for (--p->argc; iarg < (int)p->argc; iarg++)
412*95c635efSGarrett D'Amore 		p->argv[iarg] = p->argv[iarg+1];
413*95c635efSGarrett D'Amore }
414*95c635efSGarrett D'Amore 
415*95c635efSGarrett D'Amore enum margserr
416*95c635efSGarrett D'Amore mdoc_zargs(struct mdoc *m, int line, int *pos, char *buf, char **v)
417*95c635efSGarrett D'Amore {
418*95c635efSGarrett D'Amore 
419*95c635efSGarrett D'Amore 	return(args(m, line, pos, buf, ARGSFL_NONE, v));
420*95c635efSGarrett D'Amore }
421*95c635efSGarrett D'Amore 
422*95c635efSGarrett D'Amore enum margserr
423*95c635efSGarrett D'Amore mdoc_args(struct mdoc *m, int line, int *pos,
424*95c635efSGarrett D'Amore 		char *buf, enum mdoct tok, char **v)
425*95c635efSGarrett D'Amore {
426*95c635efSGarrett D'Amore 	enum argsflag	  fl;
427*95c635efSGarrett D'Amore 	struct mdoc_node *n;
428*95c635efSGarrett D'Amore 
429*95c635efSGarrett D'Amore 	fl = mdocargs[tok].flags;
430*95c635efSGarrett D'Amore 
431*95c635efSGarrett D'Amore 	if (MDOC_It != tok)
432*95c635efSGarrett D'Amore 		return(args(m, line, pos, buf, fl, v));
433*95c635efSGarrett D'Amore 
434*95c635efSGarrett D'Amore 	/*
435*95c635efSGarrett D'Amore 	 * We know that we're in an `It', so it's reasonable to expect
436*95c635efSGarrett D'Amore 	 * us to be sitting in a `Bl'.  Someday this may not be the case
437*95c635efSGarrett D'Amore 	 * (if we allow random `It's sitting out there), so provide a
438*95c635efSGarrett D'Amore 	 * safe fall-back into the default behaviour.
439*95c635efSGarrett D'Amore 	 */
440*95c635efSGarrett D'Amore 
441*95c635efSGarrett D'Amore 	for (n = m->last; n; n = n->parent)
442*95c635efSGarrett D'Amore 		if (MDOC_Bl == n->tok)
443*95c635efSGarrett D'Amore 			if (LIST_column == n->norm->Bl.type) {
444*95c635efSGarrett D'Amore 				fl = ARGSFL_TABSEP;
445*95c635efSGarrett D'Amore 				break;
446*95c635efSGarrett D'Amore 			}
447*95c635efSGarrett D'Amore 
448*95c635efSGarrett D'Amore 	return(args(m, line, pos, buf, fl, v));
449*95c635efSGarrett D'Amore }
450*95c635efSGarrett D'Amore 
451*95c635efSGarrett D'Amore static enum margserr
452*95c635efSGarrett D'Amore args(struct mdoc *m, int line, int *pos,
453*95c635efSGarrett D'Amore 		char *buf, enum argsflag fl, char **v)
454*95c635efSGarrett D'Amore {
455*95c635efSGarrett D'Amore 	char		*p, *pp;
456*95c635efSGarrett D'Amore 	enum margserr	 rc;
457*95c635efSGarrett D'Amore 
458*95c635efSGarrett D'Amore 	if ('\0' == buf[*pos]) {
459*95c635efSGarrett D'Amore 		if (MDOC_PPHRASE & m->flags)
460*95c635efSGarrett D'Amore 			return(ARGS_EOLN);
461*95c635efSGarrett D'Amore 		/*
462*95c635efSGarrett D'Amore 		 * If we're not in a partial phrase and the flag for
463*95c635efSGarrett D'Amore 		 * being a phrase literal is still set, the punctuation
464*95c635efSGarrett D'Amore 		 * is unterminated.
465*95c635efSGarrett D'Amore 		 */
466*95c635efSGarrett D'Amore 		if (MDOC_PHRASELIT & m->flags)
467*95c635efSGarrett D'Amore 			mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
468*95c635efSGarrett D'Amore 
469*95c635efSGarrett D'Amore 		m->flags &= ~MDOC_PHRASELIT;
470*95c635efSGarrett D'Amore 		return(ARGS_EOLN);
471*95c635efSGarrett D'Amore 	}
472*95c635efSGarrett D'Amore 
473*95c635efSGarrett D'Amore 	*v = &buf[*pos];
474*95c635efSGarrett D'Amore 
475*95c635efSGarrett D'Amore 	if (ARGSFL_DELIM == fl)
476*95c635efSGarrett D'Amore 		if (args_checkpunct(buf, *pos))
477*95c635efSGarrett D'Amore 			return(ARGS_PUNCT);
478*95c635efSGarrett D'Amore 
479*95c635efSGarrett D'Amore 	/*
480*95c635efSGarrett D'Amore 	 * First handle TABSEP items, restricted to `Bl -column'.  This
481*95c635efSGarrett D'Amore 	 * ignores conventional token parsing and instead uses tabs or
482*95c635efSGarrett D'Amore 	 * `Ta' macros to separate phrases.  Phrases are parsed again
483*95c635efSGarrett D'Amore 	 * for arguments at a later phase.
484*95c635efSGarrett D'Amore 	 */
485*95c635efSGarrett D'Amore 
486*95c635efSGarrett D'Amore 	if (ARGSFL_TABSEP == fl) {
487*95c635efSGarrett D'Amore 		/* Scan ahead to tab (can't be escaped). */
488*95c635efSGarrett D'Amore 		p = strchr(*v, '\t');
489*95c635efSGarrett D'Amore 		pp = NULL;
490*95c635efSGarrett D'Amore 
491*95c635efSGarrett D'Amore 		/* Scan ahead to unescaped `Ta'. */
492*95c635efSGarrett D'Amore 		if ( ! (MDOC_PHRASELIT & m->flags))
493*95c635efSGarrett D'Amore 			for (pp = *v; ; pp++) {
494*95c635efSGarrett D'Amore 				if (NULL == (pp = strstr(pp, "Ta")))
495*95c635efSGarrett D'Amore 					break;
496*95c635efSGarrett D'Amore 				if (pp > *v && ' ' != *(pp - 1))
497*95c635efSGarrett D'Amore 					continue;
498*95c635efSGarrett D'Amore 				if (' ' == *(pp + 2) || '\0' == *(pp + 2))
499*95c635efSGarrett D'Amore 					break;
500*95c635efSGarrett D'Amore 			}
501*95c635efSGarrett D'Amore 
502*95c635efSGarrett D'Amore 		/* By default, assume a phrase. */
503*95c635efSGarrett D'Amore 		rc = ARGS_PHRASE;
504*95c635efSGarrett D'Amore 
505*95c635efSGarrett D'Amore 		/*
506*95c635efSGarrett D'Amore 		 * Adjust new-buffer position to be beyond delimiter
507*95c635efSGarrett D'Amore 		 * mark (e.g., Ta -> end + 2).
508*95c635efSGarrett D'Amore 		 */
509*95c635efSGarrett D'Amore 		if (p && pp) {
510*95c635efSGarrett D'Amore 			*pos += pp < p ? 2 : 1;
511*95c635efSGarrett D'Amore 			rc = pp < p ? ARGS_PHRASE : ARGS_PPHRASE;
512*95c635efSGarrett D'Amore 			p = pp < p ? pp : p;
513*95c635efSGarrett D'Amore 		} else if (p && ! pp) {
514*95c635efSGarrett D'Amore 			rc = ARGS_PPHRASE;
515*95c635efSGarrett D'Amore 			*pos += 1;
516*95c635efSGarrett D'Amore 		} else if (pp && ! p) {
517*95c635efSGarrett D'Amore 			p = pp;
518*95c635efSGarrett D'Amore 			*pos += 2;
519*95c635efSGarrett D'Amore 		} else {
520*95c635efSGarrett D'Amore 			rc = ARGS_PEND;
521*95c635efSGarrett D'Amore 			p = strchr(*v, 0);
522*95c635efSGarrett D'Amore 		}
523*95c635efSGarrett D'Amore 
524*95c635efSGarrett D'Amore 		/* Whitespace check for eoln case... */
525*95c635efSGarrett D'Amore 		if ('\0' == *p && ' ' == *(p - 1))
526*95c635efSGarrett D'Amore 			mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
527*95c635efSGarrett D'Amore 
528*95c635efSGarrett D'Amore 		*pos += (int)(p - *v);
529*95c635efSGarrett D'Amore 
530*95c635efSGarrett D'Amore 		/* Strip delimiter's preceding whitespace. */
531*95c635efSGarrett D'Amore 		pp = p - 1;
532*95c635efSGarrett D'Amore 		while (pp > *v && ' ' == *pp) {
533*95c635efSGarrett D'Amore 			if (pp > *v && '\\' == *(pp - 1))
534*95c635efSGarrett D'Amore 				break;
535*95c635efSGarrett D'Amore 			pp--;
536*95c635efSGarrett D'Amore 		}
537*95c635efSGarrett D'Amore 		*(pp + 1) = 0;
538*95c635efSGarrett D'Amore 
539*95c635efSGarrett D'Amore 		/* Strip delimiter's proceeding whitespace. */
540*95c635efSGarrett D'Amore 		for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++)
541*95c635efSGarrett D'Amore 			/* Skip ahead. */ ;
542*95c635efSGarrett D'Amore 
543*95c635efSGarrett D'Amore 		return(rc);
544*95c635efSGarrett D'Amore 	}
545*95c635efSGarrett D'Amore 
546*95c635efSGarrett D'Amore 	/*
547*95c635efSGarrett D'Amore 	 * Process a quoted literal.  A quote begins with a double-quote
548*95c635efSGarrett D'Amore 	 * and ends with a double-quote NOT preceded by a double-quote.
549*95c635efSGarrett D'Amore 	 * Whitespace is NOT involved in literal termination.
550*95c635efSGarrett D'Amore 	 */
551*95c635efSGarrett D'Amore 
552*95c635efSGarrett D'Amore 	if (MDOC_PHRASELIT & m->flags || '\"' == buf[*pos]) {
553*95c635efSGarrett D'Amore 		if ( ! (MDOC_PHRASELIT & m->flags))
554*95c635efSGarrett D'Amore 			*v = &buf[++(*pos)];
555*95c635efSGarrett D'Amore 
556*95c635efSGarrett D'Amore 		if (MDOC_PPHRASE & m->flags)
557*95c635efSGarrett D'Amore 			m->flags |= MDOC_PHRASELIT;
558*95c635efSGarrett D'Amore 
559*95c635efSGarrett D'Amore 		for ( ; buf[*pos]; (*pos)++) {
560*95c635efSGarrett D'Amore 			if ('\"' != buf[*pos])
561*95c635efSGarrett D'Amore 				continue;
562*95c635efSGarrett D'Amore 			if ('\"' != buf[*pos + 1])
563*95c635efSGarrett D'Amore 				break;
564*95c635efSGarrett D'Amore 			(*pos)++;
565*95c635efSGarrett D'Amore 		}
566*95c635efSGarrett D'Amore 
567*95c635efSGarrett D'Amore 		if ('\0' == buf[*pos]) {
568*95c635efSGarrett D'Amore 			if (MDOC_PPHRASE & m->flags)
569*95c635efSGarrett D'Amore 				return(ARGS_QWORD);
570*95c635efSGarrett D'Amore 			mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
571*95c635efSGarrett D'Amore 			return(ARGS_QWORD);
572*95c635efSGarrett D'Amore 		}
573*95c635efSGarrett D'Amore 
574*95c635efSGarrett D'Amore 		m->flags &= ~MDOC_PHRASELIT;
575*95c635efSGarrett D'Amore 		buf[(*pos)++] = '\0';
576*95c635efSGarrett D'Amore 
577*95c635efSGarrett D'Amore 		if ('\0' == buf[*pos])
578*95c635efSGarrett D'Amore 			return(ARGS_QWORD);
579*95c635efSGarrett D'Amore 
580*95c635efSGarrett D'Amore 		while (' ' == buf[*pos])
581*95c635efSGarrett D'Amore 			(*pos)++;
582*95c635efSGarrett D'Amore 
583*95c635efSGarrett D'Amore 		if ('\0' == buf[*pos])
584*95c635efSGarrett D'Amore 			mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
585*95c635efSGarrett D'Amore 
586*95c635efSGarrett D'Amore 		return(ARGS_QWORD);
587*95c635efSGarrett D'Amore 	}
588*95c635efSGarrett D'Amore 
589*95c635efSGarrett D'Amore 	p = &buf[*pos];
590*95c635efSGarrett D'Amore 	*v = mandoc_getarg(m->parse, &p, line, pos);
591*95c635efSGarrett D'Amore 
592*95c635efSGarrett D'Amore 	return(ARGS_WORD);
593*95c635efSGarrett D'Amore }
594*95c635efSGarrett D'Amore 
595*95c635efSGarrett D'Amore /*
596*95c635efSGarrett D'Amore  * Check if the string consists only of space-separated closing
597*95c635efSGarrett D'Amore  * delimiters.  This is a bit of a dance: the first must be a close
598*95c635efSGarrett D'Amore  * delimiter, but it may be followed by middle delimiters.  Arbitrary
599*95c635efSGarrett D'Amore  * whitespace may separate these tokens.
600*95c635efSGarrett D'Amore  */
601*95c635efSGarrett D'Amore static int
602*95c635efSGarrett D'Amore args_checkpunct(const char *buf, int i)
603*95c635efSGarrett D'Amore {
604*95c635efSGarrett D'Amore 	int		 j;
605*95c635efSGarrett D'Amore 	char		 dbuf[DELIMSZ];
606*95c635efSGarrett D'Amore 	enum mdelim	 d;
607*95c635efSGarrett D'Amore 
608*95c635efSGarrett D'Amore 	/* First token must be a close-delimiter. */
609*95c635efSGarrett D'Amore 
610*95c635efSGarrett D'Amore 	for (j = 0; buf[i] && ' ' != buf[i] && j < DELIMSZ; j++, i++)
611*95c635efSGarrett D'Amore 		dbuf[j] = buf[i];
612*95c635efSGarrett D'Amore 
613*95c635efSGarrett D'Amore 	if (DELIMSZ == j)
614*95c635efSGarrett D'Amore 		return(0);
615*95c635efSGarrett D'Amore 
616*95c635efSGarrett D'Amore 	dbuf[j] = '\0';
617*95c635efSGarrett D'Amore 	if (DELIM_CLOSE != mdoc_isdelim(dbuf))
618*95c635efSGarrett D'Amore 		return(0);
619*95c635efSGarrett D'Amore 
620*95c635efSGarrett D'Amore 	while (' ' == buf[i])
621*95c635efSGarrett D'Amore 		i++;
622*95c635efSGarrett D'Amore 
623*95c635efSGarrett D'Amore 	/* Remaining must NOT be open/none. */
624*95c635efSGarrett D'Amore 
625*95c635efSGarrett D'Amore 	while (buf[i]) {
626*95c635efSGarrett D'Amore 		j = 0;
627*95c635efSGarrett D'Amore 		while (buf[i] && ' ' != buf[i] && j < DELIMSZ)
628*95c635efSGarrett D'Amore 			dbuf[j++] = buf[i++];
629*95c635efSGarrett D'Amore 
630*95c635efSGarrett D'Amore 		if (DELIMSZ == j)
631*95c635efSGarrett D'Amore 			return(0);
632*95c635efSGarrett D'Amore 
633*95c635efSGarrett D'Amore 		dbuf[j] = '\0';
634*95c635efSGarrett D'Amore 		d = mdoc_isdelim(dbuf);
635*95c635efSGarrett D'Amore 		if (DELIM_NONE == d || DELIM_OPEN == d)
636*95c635efSGarrett D'Amore 			return(0);
637*95c635efSGarrett D'Amore 
638*95c635efSGarrett D'Amore 		while (' ' == buf[i])
639*95c635efSGarrett D'Amore 			i++;
640*95c635efSGarrett D'Amore 	}
641*95c635efSGarrett D'Amore 
642*95c635efSGarrett D'Amore 	return('\0' == buf[i]);
643*95c635efSGarrett D'Amore }
644*95c635efSGarrett D'Amore 
645*95c635efSGarrett D'Amore static int
646*95c635efSGarrett D'Amore argv_multi(struct mdoc *m, int line,
647*95c635efSGarrett D'Amore 		struct mdoc_argv *v, int *pos, char *buf)
648*95c635efSGarrett D'Amore {
649*95c635efSGarrett D'Amore 	enum margserr	 ac;
650*95c635efSGarrett D'Amore 	char		*p;
651*95c635efSGarrett D'Amore 
652*95c635efSGarrett D'Amore 	for (v->sz = 0; ; v->sz++) {
653*95c635efSGarrett D'Amore 		if ('-' == buf[*pos])
654*95c635efSGarrett D'Amore 			break;
655*95c635efSGarrett D'Amore 		ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
656*95c635efSGarrett D'Amore 		if (ARGS_ERROR == ac)
657*95c635efSGarrett D'Amore 			return(0);
658*95c635efSGarrett D'Amore 		else if (ARGS_EOLN == ac)
659*95c635efSGarrett D'Amore 			break;
660*95c635efSGarrett D'Amore 
661*95c635efSGarrett D'Amore 		if (0 == v->sz % MULTI_STEP)
662*95c635efSGarrett D'Amore 			v->value = mandoc_realloc(v->value,
663*95c635efSGarrett D'Amore 				(v->sz + MULTI_STEP) * sizeof(char *));
664*95c635efSGarrett D'Amore 
665*95c635efSGarrett D'Amore 		v->value[(int)v->sz] = mandoc_strdup(p);
666*95c635efSGarrett D'Amore 	}
667*95c635efSGarrett D'Amore 
668*95c635efSGarrett D'Amore 	return(1);
669*95c635efSGarrett D'Amore }
670*95c635efSGarrett D'Amore 
671*95c635efSGarrett D'Amore static int
672*95c635efSGarrett D'Amore argv_opt_single(struct mdoc *m, int line,
673*95c635efSGarrett D'Amore 		struct mdoc_argv *v, int *pos, char *buf)
674*95c635efSGarrett D'Amore {
675*95c635efSGarrett D'Amore 	enum margserr	 ac;
676*95c635efSGarrett D'Amore 	char		*p;
677*95c635efSGarrett D'Amore 
678*95c635efSGarrett D'Amore 	if ('-' == buf[*pos])
679*95c635efSGarrett D'Amore 		return(1);
680*95c635efSGarrett D'Amore 
681*95c635efSGarrett D'Amore 	ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
682*95c635efSGarrett D'Amore 	if (ARGS_ERROR == ac)
683*95c635efSGarrett D'Amore 		return(0);
684*95c635efSGarrett D'Amore 	if (ARGS_EOLN == ac)
685*95c635efSGarrett D'Amore 		return(1);
686*95c635efSGarrett D'Amore 
687*95c635efSGarrett D'Amore 	v->sz = 1;
688*95c635efSGarrett D'Amore 	v->value = mandoc_malloc(sizeof(char *));
689*95c635efSGarrett D'Amore 	v->value[0] = mandoc_strdup(p);
690*95c635efSGarrett D'Amore 
691*95c635efSGarrett D'Amore 	return(1);
692*95c635efSGarrett D'Amore }
693*95c635efSGarrett D'Amore 
694*95c635efSGarrett D'Amore static int
695*95c635efSGarrett D'Amore argv_single(struct mdoc *m, int line,
696*95c635efSGarrett D'Amore 		struct mdoc_argv *v, int *pos, char *buf)
697*95c635efSGarrett D'Amore {
698*95c635efSGarrett D'Amore 	int		 ppos;
699*95c635efSGarrett D'Amore 	enum margserr	 ac;
700*95c635efSGarrett D'Amore 	char		*p;
701*95c635efSGarrett D'Amore 
702*95c635efSGarrett D'Amore 	ppos = *pos;
703*95c635efSGarrett D'Amore 
704*95c635efSGarrett D'Amore 	ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
705*95c635efSGarrett D'Amore 	if (ARGS_EOLN == ac) {
706*95c635efSGarrett D'Amore 		mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTARGVCOUNT);
707*95c635efSGarrett D'Amore 		return(0);
708*95c635efSGarrett D'Amore 	} else if (ARGS_ERROR == ac)
709*95c635efSGarrett D'Amore 		return(0);
710*95c635efSGarrett D'Amore 
711*95c635efSGarrett D'Amore 	v->sz = 1;
712*95c635efSGarrett D'Amore 	v->value = mandoc_malloc(sizeof(char *));
713*95c635efSGarrett D'Amore 	v->value[0] = mandoc_strdup(p);
714*95c635efSGarrett D'Amore 
715*95c635efSGarrett D'Amore 	return(1);
716*95c635efSGarrett D'Amore }
717