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