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