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