1/* 2 * computil.c - completion utilities 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1999 Sven Wischnowsky 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Sven Wischnowsky or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Sven Wischnowsky and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Sven Wischnowsky and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30#include "computil.mdh" 31#include "computil.pro" 32 33 34/* Help for `_describe'. */ 35 36typedef struct cdset *Cdset; 37typedef struct cdstr *Cdstr; 38typedef struct cdrun *Cdrun; 39 40struct cdstate { 41 int showd; /* != 0 if descriptions should be shown */ 42 char *sep; /* the separator string */ 43 int slen; /* its metafied length */ 44 int swidth; /* its screen width */ 45 int maxmlen; /* maximum length to allow for the matches */ 46 Cdset sets; /* the sets of matches */ 47 int pre; /* longest prefix length (before description) */ 48 int premaxw; /* ... and its screen width */ 49 int suf; /* longest suffix (description) */ 50 int maxg; /* size of largest group */ 51 int maxglen; /* columns for matches of largest group */ 52 int groups; /* number of groups */ 53 int descs; /* number of non-group matches with desc */ 54 int gprew; /* prefix screen width for group display */ 55 Cdrun runs; /* runs to report to shell code */ 56}; 57 58struct cdstr { 59 Cdstr next; /* the next one in this set */ 60 char *str; /* the string to display */ 61 char *desc; /* the description or NULL */ 62 char *match; /* the match to add */ 63 char *sortstr; /* unmetafied string used to sort matches */ 64 int len; /* length of str or match */ 65 int width; /* ... and its screen width */ 66 Cdstr other; /* next string with the same description */ 67 int kind; /* 0: not in a group, 1: the first, 2: other */ 68 Cdset set; /* the set this string is in */ 69 Cdstr run; /* next in this run */ 70}; 71 72struct cdrun { 73 Cdrun next; /* ... */ 74 int type; /* see CRT_* below */ 75 Cdstr strs; /* strings in this run */ 76 int count; /* number of strings in this run */ 77}; 78 79#define CRT_SIMPLE 0 80#define CRT_DESC 1 81#define CRT_SPEC 2 82#define CRT_DUMMY 3 83#define CRT_EXPL 4 84 85struct cdset { 86 Cdset next; /* guess what */ 87 char **opts; /* the compadd-options */ 88 Cdstr strs; /* the strings/matches */ 89 int count; /* number of matches in this set */ 90 int desc; /* number of matches with description */ 91}; 92 93static struct cdstate cd_state; 94static int cd_parsed = 0; 95 96static void 97freecdsets(Cdset p) 98{ 99 Cdset n; 100 Cdstr s, sn; 101 Cdrun r, rn; 102 103 for (; p; p = n) { 104 n = p->next; 105 if (p->opts) 106 freearray(p->opts); 107 for (s = p->strs; s; s = sn) { 108 sn = s->next; 109 zfree(s->sortstr, strlen(s->str) + 1); 110 zsfree(s->str); 111 zsfree(s->desc); 112 if (s->match != s->str) 113 zsfree(s->match); 114 zfree(s, sizeof(*s)); 115 } 116 for (r = cd_state.runs; r; r = rn) { 117 rn = r->next; 118 zfree(r, sizeof(*r)); 119 } 120 zfree(p, sizeof(*p)); 121 } 122} 123 124/* Find matches with same descriptions and group them. */ 125 126static void 127cd_group(int maxg) 128{ 129 Cdset set1, set2; 130 Cdstr str1, str2, *strp; 131 int num, width; 132 133 cd_state.groups = cd_state.descs = cd_state.maxglen = 0; 134 cd_state.maxg = 0; 135 136 for (set1 = cd_state.sets; set1; set1 = set1->next) 137 for (str1 = set1->strs; str1; str1 = str1->next) { 138 str1->kind = 0; 139 str1->other = NULL; 140 } 141 142 for (set1 = cd_state.sets; set1; set1 = set1->next) { 143 for (str1 = set1->strs; str1; str1 = str1->next) { 144 if (!str1->desc || str1->kind != 0) 145 continue; 146 147 num = 1; 148 width = str1->width + cd_state.swidth; 149 if (width > cd_state.maxglen) 150 cd_state.maxglen = width; 151 strp = &(str1->other); 152 153 for (set2 = set1; set2; set2 = set2->next) { 154 for (str2 = (set2 == set1 ? str1->next : set2->strs); 155 str2; str2 = str2->next) 156 if (str2->desc && !strcmp(str1->desc, str2->desc)) { 157 width += CM_SPACE + str2->width; 158 if (width > cd_state.maxmlen || num == maxg) 159 break; 160 if (width > cd_state.maxglen) 161 cd_state.maxglen = width; 162 str1->kind = 1; 163 str2->kind = 2; 164 num++; 165 *strp = str2; 166 strp = &(str2->other); 167 } 168 if (str2) 169 break; 170 } 171 *strp = NULL; 172 173 if (num > 1) 174 cd_state.groups++; 175 else 176 cd_state.descs++; 177 178 if (num > cd_state.maxg) 179 cd_state.maxg = num; 180 } 181 } 182} 183 184/* Calculate longest prefix and suffix and count the strings with 185 * descriptions. */ 186 187static void 188cd_calc() 189{ 190 Cdset set; 191 Cdstr str; 192 int l; 193 194 cd_state.pre = cd_state.suf = 0; 195 196 for (set = cd_state.sets; set; set = set->next) { 197 set->count = set->desc = 0; 198 for (str = set->strs; str; str = str->next) { 199 set->count++; 200 if ((l = strlen(str->str)) > cd_state.pre) 201 cd_state.pre = l; 202 if ((l = MB_METASTRWIDTH(str->str)) > cd_state.premaxw) 203 cd_state.premaxw = l; 204 if (str->desc) { 205 set->desc++; 206 if ((l = strlen(str->desc)) > cd_state.suf) 207 cd_state.suf = l; 208 } 209 } 210 } 211} 212 213static int 214cd_sort(const void *a, const void *b) 215{ 216 return zstrcmp((*((Cdstr *) a))->sortstr, (*((Cdstr *) b))->sortstr, 0); 217} 218 219static int 220cd_prep() 221{ 222 Cdrun run, *runp; 223 Cdset set; 224 Cdstr str, *strp; 225 226 runp = &(cd_state.runs); 227 228 if (cd_state.groups) { 229 int preplines = cd_state.groups + cd_state.descs; 230 VARARR(Cdstr, grps, preplines); 231 VARARR(int, wids, cd_state.maxg); 232 Cdstr gs, gp, gn, *gpp; 233 int i, j, d; 234 Cdrun expl; 235 Cdstr *strp2; 236 237 memset(wids, 0, cd_state.maxg * sizeof(int)); 238 strp = grps; 239 240 for (set = cd_state.sets; set; set = set->next) 241 for (str = set->strs; str; str = str->next) { 242 if (str->kind != 1) { 243 if (!str->kind && str->desc) { 244 if (str->width > wids[0]) 245 wids[0] = str->width; 246 str->other = NULL; 247 *strp++ = str; 248 } 249 continue; 250 } 251 gs = str; 252 gs->kind = 2; 253 gp = str->other; 254 gs->other = NULL; 255 for (; gp; gp = gn) { 256 gn = gp->other; 257 gp->other = NULL; 258 for (gpp = &gs; *gpp && (*gpp)->width > gp->width; 259 gpp = &((*gpp)->other)); 260 gp->other = *gpp; 261 *gpp = gp; 262 } 263 for (gp = gs, i = 0; gp; gp = gp->other, i++) 264 if (gp->width > wids[i]) 265 wids[i] = gp->width; 266 267 *strp++ = gs; 268 } 269 270 cd_state.gprew = 0; 271 for (i = 0; i < cd_state.maxg; i++) { 272 cd_state.gprew += wids[i] + CM_SPACE; 273 } 274 275 if (cd_state.gprew > cd_state.maxmlen && cd_state.maxglen > 1) 276 return 1; 277 278 for (i = 0; i < preplines; i++) { 279 Cdstr s = grps[i]; 280 int dummy; 281 282 s->sortstr = ztrdup(s->str); 283 unmetafy(s->sortstr, &dummy); 284 } 285 286 qsort(grps, preplines, sizeof(Cdstr), cd_sort); 287 288 for (i = preplines, strp = grps; i > 1; i--, strp++) { 289 strp2 = strp + 1; 290 if (!strcmp((*strp)->desc, (*strp2)->desc)) 291 continue; 292 for (j = i - 2, strp2++; j > 0; j--, strp2++) 293 if (!strcmp((*strp)->desc, (*strp2)->desc)) { 294 Cdstr tmp = *strp2; 295 296 memmove(strp + 2, strp + 1, 297 (strp2 - strp - 1) * sizeof(Cdstr)); 298 299 *++strp = tmp; 300 i--; 301 } 302 } 303 expl = (Cdrun) zalloc(sizeof(*run)); 304 expl->type = CRT_EXPL; 305 expl->strs = grps[0]; 306 expl->count = preplines; 307 308 for (i = preplines, strp = grps, strp2 = NULL; i; i--, strp++) { 309 str = *strp; 310 *strp = str->other; 311 if (strp2) 312 *strp2 = str; 313 strp2 = &(str->run); 314 315 *runp = run = (Cdrun) zalloc(sizeof(*run)); 316 runp = &(run->next); 317 run->type = CRT_SPEC; 318 run->strs = str; 319 run->count = 1; 320 } 321 *strp2 = NULL; 322 323 for (i = cd_state.maxg - 1; i; i--) { 324 for (d = 0, j = preplines, strp = grps; j; j--, strp++) { 325 if ((str = *strp)) { 326 if (d) { 327 *runp = run = (Cdrun) zalloc(sizeof(*run)); 328 runp = &(run->next); 329 run->type = CRT_DUMMY; 330 run->strs = expl->strs; 331 run->count = d; 332 d = 0; 333 } 334 *runp = run = (Cdrun) zalloc(sizeof(*run)); 335 runp = &(run->next); 336 run->type = CRT_SPEC; 337 run->strs = str; 338 run->strs->run = NULL; 339 run->count = 1; 340 341 *strp = str->other; 342 } else 343 d++; 344 } 345 if (d) { 346 *runp = run = (Cdrun) zalloc(sizeof(*run)); 347 runp = &(run->next); 348 run->type = CRT_DUMMY; 349 run->strs = expl->strs; 350 run->count = d; 351 } 352 } 353 *runp = expl; 354 runp = &(expl->next); 355 356 for (set = cd_state.sets; set; set = set->next) { 357 for (i = 0, gs = NULL, gpp = &gs, str = set->strs; 358 str; str = str->next) { 359 if (str->kind || str->desc) 360 continue; 361 362 i++; 363 *gpp = str; 364 gpp = &(str->run); 365 } 366 *gpp = NULL; 367 if (i) { 368 *runp = run = (Cdrun) zalloc(sizeof(*run)); 369 runp = &(run->next); 370 run->type = CRT_SIMPLE; 371 run->strs = gs; 372 run->count = i; 373 } 374 } 375 } else if (cd_state.showd) { 376 for (set = cd_state.sets; set; set = set->next) { 377 if (set->desc) { 378 *runp = run = (Cdrun) zalloc(sizeof(*run)); 379 runp = &(run->next); 380 run->type = CRT_DESC; 381 strp = &(run->strs); 382 for (str = set->strs; str; str = str->next) 383 if (str->desc) { 384 *strp = str; 385 strp = &(str->run); 386 } 387 *strp = NULL; 388 run->count = set->desc; 389 } 390 if (set->desc != set->count) { 391 *runp = run = (Cdrun) zalloc(sizeof(*run)); 392 runp = &(run->next); 393 run->type = CRT_SIMPLE; 394 strp = &(run->strs); 395 for (str = set->strs; str; str = str->next) 396 if (!str->desc) { 397 *strp = str; 398 strp = &(str->run); 399 } 400 *strp = NULL; 401 run->count = set->count - set->desc; 402 } 403 } 404 } else { 405 for (set = cd_state.sets; set; set = set->next) 406 if (set->count) { 407 *runp = run = (Cdrun) zalloc(sizeof(*run)); 408 runp = &(run->next); 409 run->type = CRT_SIMPLE; 410 run->strs = set->strs; 411 for (str = set->strs; str; str = str->next) 412 str->run = str->next; 413 run->count = set->count; 414 } 415 } 416 *runp = NULL; 417 418 return 0; 419} 420 421/* Duplicate and concatenate two arrays. Return the result. */ 422 423static char ** 424cd_arrcat(char **a, char **b) 425{ 426 if (!b) 427 return zarrdup(a); 428 else { 429 char **r = (char **) zalloc((arrlen(a) + arrlen(b) + 1) * 430 sizeof(char *)); 431 char **p = r; 432 433 for (; *a; a++) 434 *p++ = ztrdup(*a); 435 for (; *b; b++) 436 *p++ = ztrdup(*b); 437 438 *p = NULL; 439 440 return r; 441 } 442} 443 444/* Initialisation. Store and calculate the string and matches and so on. */ 445 446static int 447cd_init(char *nam, char *hide, char *mlen, char *sep, 448 char **opts, char **args, int disp) 449{ 450 Cdset *setp, set; 451 Cdstr *strp, str; 452 char **ap, *tmp; 453 int grp = 0, itmp; 454 455 if (cd_parsed) { 456 zsfree(cd_state.sep); 457 freecdsets(cd_state.sets); 458 cd_parsed = 0; 459 } 460 setp = &(cd_state.sets); 461 cd_state.sep = ztrdup(sep); 462 cd_state.slen = strlen(sep); 463 cd_state.swidth = MB_METASTRWIDTH(sep); 464 cd_state.sets = NULL; 465 cd_state.showd = disp; 466 cd_state.maxg = cd_state.groups = cd_state.descs = 0; 467 cd_state.maxmlen = atoi(mlen); 468 cd_state.premaxw = 0; 469 itmp = zterm_columns - cd_state.swidth - 4; 470 if (cd_state.maxmlen > itmp) 471 cd_state.maxmlen = itmp; 472 if (cd_state.maxmlen < 4) 473 cd_state.maxmlen = 4; 474 if (*args && !strcmp(*args, "-g")) { 475 args++; 476 grp = 1; 477 } 478 while (*args) { 479 *setp = set = (Cdset) zshcalloc(sizeof(*set)); 480 setp = &(set->next); 481 *setp = NULL; 482 set->opts = NULL; 483 set->strs = NULL; 484 485 if (!(ap = get_user_var(*args))) { 486 zwarnnam(nam, "invalid argument: %s", *args); 487 zsfree(cd_state.sep); 488 freecdsets(cd_state.sets); 489 return 1; 490 } 491 for (str = NULL, strp = &(set->strs); *ap; ap++) { 492 *strp = str = (Cdstr) zalloc(sizeof(*str)); 493 strp = &(str->next); 494 495 str->kind = 0; 496 str->other = NULL; 497 str->set = set; 498 499 for (tmp = *ap; *tmp && *tmp != ':'; tmp++) 500 if (*tmp == '\\' && tmp[1]) 501 tmp++; 502 503 if (*tmp) 504 str->desc = ztrdup(rembslash(tmp + 1)); 505 else 506 str->desc = NULL; 507 *tmp = '\0'; 508 str->str = str->match = ztrdup(rembslash(*ap)); 509 str->len = strlen(str->str); 510 str->width = MB_METASTRWIDTH(str->str); 511 str->sortstr = NULL; 512 } 513 if (str) 514 str->next = NULL; 515 516 if (*++args && **args != '-') { 517 if (!(ap = get_user_var(*args))) { 518 zwarnnam(nam, "invalid argument: %s", *args); 519 zsfree(cd_state.sep); 520 freecdsets(cd_state.sets); 521 return 1; 522 } 523 for (str = set->strs; str && *ap; str = str->next, ap++) 524 str->match = ztrdup(*ap); 525 526 args++; 527 } 528 if (hide && *hide) { 529 for (str = set->strs; str; str = str->next) { 530 if (str->str == str->match) 531 str->str = ztrdup(str->str); 532 if (hide[1] && str->str[0] == '-' && str->str[1] == '-') 533 strcpy(str->str, str->str + 2); 534 else if (str->str[0] == '-' || str->str[0] == '+') 535 strcpy(str->str, str->str + 1); 536 } 537 } 538 for (ap = args; *args && 539 (args[0][0] != '-' || args[0][1] != '-' || args[0][2]); 540 args++); 541 542 tmp = *args; 543 *args = NULL; 544 set->opts = cd_arrcat(ap, opts); 545 if ((*args = tmp)) 546 args++; 547 } 548 if (disp && grp) { 549 int mg = zterm_columns; 550 551 do { 552 cd_group(mg); 553 mg = cd_state.maxg - 1; 554 cd_calc(); 555 } while (cd_prep()); 556 557 } else { 558 cd_calc(); 559 cd_prep(); 560 } 561 cd_parsed = 1; 562 return 0; 563} 564 565/* Copy an array with one element in reserve (at the beginning). */ 566 567static char ** 568cd_arrdup(char **a) 569{ 570 char **r = (char **) zalloc((arrlen(a) + 2) * sizeof(char *)); 571 char **p = r + 1; 572 573 while (*a) 574 *p++ = ztrdup(*a++); 575 *p = NULL; 576 577 return r; 578} 579 580/* Get the next set. */ 581 582static int 583cd_get(char **params) 584{ 585 Cdrun run; 586 587 if ((run = cd_state.runs)) { 588 Cdstr str; 589 char **mats, **mp, **dpys, **dp, **opts, *csl = ""; 590 591 cd_state.runs = run->next; 592 593 switch (run->type) { 594 case CRT_SIMPLE: 595 mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *)); 596 dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *)); 597 598 for (str = run->strs; str; str = str->run) { 599 *mp++ = ztrdup(str->match); 600 *dp++ = ztrdup(str->str ? str->str : str->match); 601 } 602 *mp = *dp = NULL; 603 opts = zarrdup(run->strs->set->opts); 604 if (cd_state.groups) { 605 /* We are building a columnised list with dummy matches 606 * but there are also matches without descriptions. 607 * Those end up in a different group, so make sure that 608 * group doesn't have an explanation. */ 609 610 for (mp = dp = opts; *mp; mp++) { 611 if (dp[0][0] == '-' && dp[0][1] == 'X') { 612 if (!dp[0][2] && dp[1]) 613 mp++; 614 } else 615 *dp++ = *mp; 616 } 617 *dp = NULL; 618 } 619 break; 620 621 case CRT_DESC: 622 { 623 /* 624 * The buffer size: 625 * max prefix length (cd_state.pre) + 626 * max padding (cd_state.premaxw generously :) + 627 * separator length (cd_state.slen) + 628 * inter matches gap (CM_SPACE) + 629 * max description length (cd_state.suf) + 630 * trailing \0 631 */ 632 VARARR(char, buf, 633 cd_state.pre + cd_state.suf + 634 cd_state.premaxw + cd_state.slen + 3); 635 mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *)); 636 dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *)); 637 638 for (str = run->strs; str; str = str->run) { 639 char *p = buf, *pp, *d; 640 int l, remw, w; 641 642 *mp++ = ztrdup(str->match); 643 strcpy(p, str->str); 644 p += str->len; 645 memset(p, ' ', (l = (cd_state.premaxw - str->width + CM_SPACE))); 646 p += l; 647 648 remw = zterm_columns - cd_state.premaxw - 649 cd_state.swidth - 3; 650 while (remw < 0 && zterm_columns) { 651 /* line wrapped, use remainder of the extra line */ 652 remw += zterm_columns; 653 } 654 if (cd_state.slen < remw) { 655 strcpy(p, cd_state.sep); 656 p += cd_state.slen; 657 remw -= cd_state.slen; 658 659 /* 660 * copy a character at once until no more screen 661 * width is available. Leave 1 character at the 662 * end of screen as safety margin 663 */ 664 d = str->desc; 665 w = MB_METASTRWIDTH(d); 666 if (w <= remw) 667 strcpy(p, d); 668 else { 669 pp = p; 670 while (remw > 0 && *d) { 671 l = MB_METACHARLEN(d); 672 memcpy(pp, d, l); 673 pp[l] = '\0'; 674 w = MB_METASTRWIDTH(pp); 675 if (w > remw) { 676 *pp = '\0'; 677 break; 678 } 679 680 pp += l; 681 d += l; 682 remw -= w; 683 } 684 } 685 } 686 687 *dp++ = ztrdup(buf); 688 } 689 *mp = *dp = NULL; 690 opts = cd_arrdup(run->strs->set->opts); 691 opts[0] = ztrdup("-l"); 692 break; 693 } 694 695 case CRT_SPEC: 696 mats = (char **) zalloc(2 * sizeof(char *)); 697 dpys = (char **) zalloc(2 * sizeof(char *)); 698 mats[0] = ztrdup(run->strs->match); 699 dpys[0] = ztrdup(run->strs->str); 700 mats[1] = dpys[1] = NULL; 701 opts = cd_arrdup(run->strs->set->opts); 702 for (dp = opts + 1; *dp; dp++) 703 if (dp[0][0] == '-' && dp[0][1] == 'J') 704 break; 705 if (*dp) { 706 char *s = tricat("-2V", "", dp[0] + 2); 707 708 zsfree(*dp); 709 *dp = s; 710 711 memmove(opts, opts + 1, 712 (arrlen(opts + 1) + 1) * sizeof(char *)); 713 714 } else 715 opts[0] = ztrdup("-2V-default-"); 716 csl = "packed"; 717 break; 718 719 case CRT_DUMMY: 720 { 721 char buf[20]; 722 723 sprintf(buf, "-E%d", run->count); 724 725 mats = (char **) zalloc(sizeof(char *)); 726 dpys = (char **) zalloc(sizeof(char *)); 727 mats[0] = dpys[0] = NULL; 728 729 opts = cd_arrdup(run->strs->set->opts); 730 opts[0] = ztrdup(buf); 731 732 csl = "packed"; 733 } 734 break; 735 736 default: /* This silences the "might be used uninitialized" warnings */ 737 case CRT_EXPL: 738 { 739 /* add columns as safety margin */ 740 VARARR(char, dbuf, cd_state.suf + cd_state.slen + 741 zterm_columns); 742 char buf[20], *p, *pp, *d; 743 int i = run->count, remw, w, l; 744 745 sprintf(buf, "-E%d", i); 746 747 mats = (char **) zalloc(sizeof(char *)); 748 dpys = (char **) zalloc((i + 1) * sizeof(char *)); 749 750 for (dp = dpys, str = run->strs; str; str = str->run) { 751 if (str->run && !strcmp(str->desc, str->run->desc)) { 752 *dp++ = ztrdup(""); 753 continue; 754 } 755 756 strcpy(dbuf, cd_state.sep); 757 remw = zterm_columns - cd_state.gprew - 758 cd_state.swidth - CM_SPACE; 759 p = pp = dbuf + cd_state.slen; 760 d = str->desc; 761 w = MB_METASTRWIDTH(d); 762 if (w <= remw) { 763 strcpy(p, d); 764 remw -= w; 765 pp += strlen(d); 766 } else 767 while (remw > 0 && *d) { 768 l = MB_METACHARLEN(d); 769 memcpy(pp, d, l); 770 pp[l] = '\0'; 771 w = MB_METASTRWIDTH(pp); 772 if (w > remw) { 773 *pp = '\0'; 774 break; 775 } 776 777 pp += l; 778 d += l; 779 remw -= w; 780 } 781 782 while (remw-- > 0) 783 *pp++ = ' '; 784 *pp = '\0'; 785 786 *dp++ = ztrdup(dbuf); 787 } 788 mats[0] = *dp = NULL; 789 790 opts = cd_arrdup(run->strs->set->opts); 791 opts[0] = ztrdup(buf); 792 793 csl = "packed"; 794 } 795 break; 796 } 797 setsparam(params[0], ztrdup(csl)); 798 setaparam(params[1], opts); 799 setaparam(params[2], mats); 800 setaparam(params[3], dpys); 801 802 zfree(run, sizeof(*run)); 803 804 return 0; 805 } 806 return 1; 807} 808 809/**/ 810static int 811bin_compdescribe(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 812{ 813 int n = arrlen(args); 814 815 if (incompfunc != 1) { 816 zwarnnam(nam, "can only be called from completion function"); 817 return 1; 818 } 819 if (!args[0][0] || !args[0][1] || args[0][2]) { 820 zwarnnam(nam, "invalid argument: %s", args[0]); 821 return 1; 822 } 823 switch (args[0][1]) { 824 case 'i': 825 if (n < 3) { 826 zwarnnam(nam, "not enough arguments"); 827 828 return 1; 829 } 830 return cd_init(nam, args[1], args[2], "", NULL, args + 3, 0); 831 case 'I': 832 if (n < 6) { 833 zwarnnam(nam, "not enough arguments"); 834 835 return 1; 836 } else { 837 char **opts; 838 839 if (!(opts = getaparam(args[4]))) { 840 zwarnnam(nam, "unknown parameter: %s", args[4]); 841 return 1; 842 } 843 return cd_init(nam, args[1], args[2], args[3], opts, args + 5, 1); 844 } 845 case 'g': 846 if (cd_parsed) { 847 if (n != 5) { 848 zwarnnam(nam, (n < 5 ? "not enough arguments" : 849 "too many arguments")); 850 return 1; 851 } 852 return cd_get(args + 1); 853 } else { 854 zwarnnam(nam, "no parsed state"); 855 return 1; 856 } 857 } 858 zwarnnam(nam, "invalid option: %s", args[0]); 859 return 1; 860} 861 862/* Help for `_arguments'. */ 863 864typedef struct cadef *Cadef; 865typedef struct caopt *Caopt; 866typedef struct caarg *Caarg; 867 868/* Cache for a set of _arguments-definitions. */ 869 870struct cadef { 871 Cadef next; /* next in cache */ 872 Cadef snext; /* next set */ 873 Caopt opts; /* the options */ 874 int nopts, ndopts, nodopts; /* number of options/direct/optional direct */ 875 Caarg args; /* the normal arguments */ 876 Caarg rest; /* the rest-argument */ 877 char **defs; /* the original strings */ 878 int ndefs; /* number of ... */ 879 int lastt; /* last time this was used */ 880 Caopt *single; /* array of single-letter options */ 881 char *match; /* -M spec to use */ 882 int argsactive; /* if arguments are still allowed */ 883 /* used while parsing a command line */ 884 char *set; /* set name prefix (<name>-), shared */ 885 char *sname; /* set name */ 886 int flags; /* see CDF_* below */ 887 char *nonarg; /* pattern for non-args (-A argument) */ 888}; 889 890#define CDF_SEP 1 891 892/* Description for an option. */ 893 894struct caopt { 895 Caopt next; 896 char *name; /* option name */ 897 char *descr; /* the description */ 898 char **xor; /* if this, then not ... */ 899 int type; /* type, CAO_* */ 900 Caarg args; /* option arguments */ 901 int active; /* still allowed on command line */ 902 int num; /* it's the num'th option */ 903 char *set; /* set name, shared */ 904 int not; /* don't complete this option (`!...') */ 905}; 906 907#define CAO_NEXT 1 908#define CAO_DIRECT 2 909#define CAO_ODIRECT 3 910#define CAO_EQUAL 4 911#define CAO_OEQUAL 5 912 913/* Description for an argument */ 914 915struct caarg { 916 Caarg next; 917 char *descr; /* description */ 918 char **xor; /* if this, then not ... */ 919 char *action; /* what to do for it */ 920 int type; /* CAA_* below */ 921 char *end; /* end-pattern for ::<pat>:... */ 922 char *opt; /* option name if for an option */ 923 int num; /* it's the num'th argument */ 924 int min; /* it's also this argument, using opt. args */ 925 int direct; /* number was given directly */ 926 int active; /* still allowed on command line */ 927 char *set; /* set name, shared */ 928}; 929 930#define CAA_NORMAL 1 931#define CAA_OPT 2 932#define CAA_REST 3 933#define CAA_RARGS 4 934#define CAA_RREST 5 935 936/* The cache of parsed descriptons. */ 937 938#define MAX_CACACHE 8 939static Cadef cadef_cache[MAX_CACACHE]; 940 941/* Compare two arrays of strings for equality. */ 942 943static int 944arrcmp(char **a, char **b) 945{ 946 if (!a && !b) 947 return 1; 948 else if (!a || !b) 949 return 0; 950 else { 951 while (*a && *b) 952 if (strcmp(*a++, *b++)) 953 return 0; 954 955 return (!*a && !*b); 956 } 957} 958 959/* Memory stuff. Obviously. */ 960 961static void 962freecaargs(Caarg a) 963{ 964 Caarg n; 965 966 for (; a; a = n) { 967 n = a->next; 968 zsfree(a->descr); 969 if (a->xor) 970 freearray(a->xor); 971 zsfree(a->action); 972 zsfree(a->end); 973 zsfree(a->opt); 974 zfree(a, sizeof(*a)); 975 } 976} 977 978static void 979freecadef(Cadef d) 980{ 981 Cadef s; 982 Caopt p, n; 983 984 while (d) { 985 s = d->snext; 986 zsfree(d->match); 987 zsfree(d->set); 988 zsfree(d->sname); 989 if (d->defs) 990 freearray(d->defs); 991 992 for (p = d->opts; p; p = n) { 993 n = p->next; 994 zsfree(p->name); 995 zsfree(p->descr); 996 if (p->xor) 997 freearray(p->xor); 998 freecaargs(p->args); 999 zfree(p, sizeof(*p)); 1000 } 1001 freecaargs(d->args); 1002 freecaargs(d->rest); 1003 zsfree(d->nonarg); 1004 if (d->single) 1005 zfree(d->single, 256 * sizeof(Caopt)); 1006 zfree(d, sizeof(*d)); 1007 d = s; 1008 } 1009} 1010 1011/* Remove backslashes before colons. */ 1012 1013static char * 1014rembslashcolon(char *s) 1015{ 1016 char *p, *r; 1017 1018 r = p = s = dupstring(s); 1019 1020 while (*s) { 1021 if (s[0] != '\\' || s[1] != ':') 1022 *p++ = *s; 1023 s++; 1024 } 1025 *p = '\0'; 1026 1027 return r; 1028} 1029 1030/* Add backslashes before colons. */ 1031 1032static char * 1033bslashcolon(char *s) 1034{ 1035 char *p, *r; 1036 1037 r = p = zhalloc((2 * strlen(s)) + 1); 1038 1039 while (*s) { 1040 if (*s == ':') 1041 *p++ = '\\'; 1042 *p++ = *s++; 1043 } 1044 *p = '\0'; 1045 1046 return r; 1047} 1048 1049/* Parse an argument definition. */ 1050 1051static Caarg 1052parse_caarg(int mult, int type, int num, int opt, char *oname, char **def, 1053 char *set) 1054{ 1055 Caarg ret = (Caarg) zalloc(sizeof(*ret)); 1056 char *p = *def, *d, sav; 1057 1058 ret->next = NULL; 1059 ret->descr = ret->action = ret->end = NULL; 1060 ret->xor = NULL; 1061 ret->num = num; 1062 ret->min = num - opt; 1063 ret->type = type; 1064 ret->opt = ztrdup(oname); 1065 ret->direct = 0; 1066 ret->set = set; 1067 1068 /* Get the description. */ 1069 1070 for (d = p; *p && *p != ':'; p++) 1071 if (*p == '\\' && p[1]) 1072 p++; 1073 sav = *p; 1074 *p = '\0'; 1075 ret->descr = ztrdup(rembslashcolon(d)); 1076 1077 /* Get the action if there is one. */ 1078 1079 if (sav) { 1080 if (mult) { 1081 for (d = ++p; *p && *p != ':'; p++) 1082 if (*p == '\\' && p[1]) 1083 p++; 1084 sav = *p; 1085 *p = '\0'; 1086 ret->action = ztrdup(rembslashcolon(d)); 1087 if (sav) 1088 *p = ':'; 1089 } else 1090 ret->action = ztrdup(rembslashcolon(p + 1)); 1091 } else 1092 ret->action = ztrdup(""); 1093 *def = p; 1094 1095 return ret; 1096} 1097 1098static Cadef 1099alloc_cadef(char **args, int single, char *match, char *nonarg, int flags) 1100{ 1101 Cadef ret; 1102 1103 ret = (Cadef) zalloc(sizeof(*ret)); 1104 ret->next = ret->snext = NULL; 1105 ret->opts = NULL; 1106 ret->args = ret->rest = NULL; 1107 ret->nonarg = ztrdup(nonarg); 1108 if (args) { 1109 ret->defs = zarrdup(args); 1110 ret->ndefs = arrlen(args); 1111 } else { 1112 ret->defs = NULL; 1113 ret->ndefs = 0; 1114 } 1115 ret->lastt = time(0); 1116 ret->set = ret->sname = NULL; 1117 if (single) { 1118 ret->single = (Caopt *) zalloc(256 * sizeof(Caopt)); 1119 memset(ret->single, 0, 256 * sizeof(Caopt)); 1120 } else 1121 ret->single = NULL; 1122 ret->match = ztrdup(match); 1123 ret->flags = flags; 1124 1125 return ret; 1126} 1127 1128static void 1129set_cadef_opts(Cadef def) 1130{ 1131 Caarg argp; 1132 int xnum; 1133 1134 for (argp = def->args, xnum = 0; argp; argp = argp->next) { 1135 if (!argp->direct) 1136 argp->min = argp->num - xnum; 1137 if (argp->type == CAA_OPT) 1138 xnum++; 1139 } 1140} 1141 1142/* Parse an array of definitions. */ 1143 1144static Cadef 1145parse_cadef(char *nam, char **args) 1146{ 1147 Cadef all, ret; 1148 Caopt *optp; 1149 char **orig_args = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs; 1150 char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL; 1151 char *nonarg = NULL; 1152 int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0; 1153 int state = 0, not = 0; 1154 1155 nopts = ndopts = nodopts = 0; 1156 1157 /* First string is the auto-description definition. */ 1158 1159 for (p = args[0]; *p && (p[0] != '%' || p[1] != 'd'); p++); 1160 1161 if (*p) { 1162 *p = '\0'; 1163 adpre = dupstring(args[0]); 1164 *p = '%'; 1165 adsuf = dupstring(p + 2); 1166 } else 1167 adpre = adsuf = NULL; 1168 1169 /* Now get the -s, -A, -S and -M options. */ 1170 1171 args++; 1172 while ((p = *args) && *p == '-' && p[1]) { 1173 for (q = ++p; *q; q++) 1174 if (*q == 'M' || *q == 'A') { 1175 q = ""; 1176 break; 1177 } else if (*q != 's' && *q != 'S') 1178 break; 1179 1180 if (*q) 1181 break; 1182 1183 for (; *p; p++) { 1184 if (*p == 's') 1185 single = 1; 1186 else if (*p == 'S') 1187 flags |= CDF_SEP; 1188 else if (*p == 'A') { 1189 if (p[1]) { 1190 nonarg = p + 1; 1191 p = "" - 1; 1192 } else if (args[1]) 1193 nonarg = *++args; 1194 else 1195 break; 1196 } else if (*p == 'M') { 1197 if (p[1]) { 1198 match = p + 1; 1199 p = "" - 1; 1200 } else if (args[1]) 1201 match = *++args; 1202 else 1203 break; 1204 } 1205 } 1206 if (*p) 1207 break; 1208 1209 args++; 1210 } 1211 if (*args && !strcmp(*args, ":")) 1212 args++; 1213 if (!*args) 1214 return NULL; 1215 1216 if (nonarg) 1217 tokenize(nonarg = dupstring(nonarg)); 1218 1219 /* Looks good. Optimistically allocate the cadef structure. */ 1220 1221 all = ret = alloc_cadef(orig_args, single, match, nonarg, flags); 1222 optp = &(ret->opts); 1223 anum = 1; 1224 1225 sargs = args; 1226 1227 /* Get the definitions. */ 1228 1229 for (; *args; args++) { 1230 if (args[0][0] == '-' && !args[0][1] && args[1]) { 1231 if (!state) { 1232 char *p; 1233 int l; 1234 1235 if (setp) 1236 args = setp; 1237 p = *++args; 1238 l = strlen(p) - 1; 1239 if (*p == '(' && p[l] == ')') { 1240 axor = p = dupstring(p + 1); 1241 p[l - 1] = '\0'; 1242 } else 1243 axor = NULL; 1244 ret->set = doset = tricat(p, "-", ""); 1245 ret->sname = ztrdup(p); 1246 state = 1; 1247 } else { 1248 setp = args; 1249 state = 0; 1250 args = sargs - 1; 1251 doset = NULL; 1252 ret->nopts = nopts; 1253 ret->ndopts = ndopts; 1254 ret->nodopts = nodopts; 1255 set_cadef_opts(ret); 1256 ret = ret->snext = alloc_cadef(NULL, single, NULL, nonarg, flags); 1257 optp = &(ret->opts); 1258 nopts = ndopts = nodopts = 0; 1259 anum = 1; 1260 } 1261 continue; 1262 } 1263 p = dupstring(*args); 1264 xnum = 0; 1265 if ((not = (*p == '!'))) 1266 p++; 1267 if (*p == '(') { 1268 /* There is a xor list, get it. */ 1269 1270 LinkList list = newlinklist(); 1271 LinkNode node; 1272 char **xp, sav; 1273 1274 while (*p && *p != ')') { 1275 for (p++; inblank(*p); p++); 1276 1277 if (*p == ')') 1278 break; 1279 for (q = p++; *p && *p != ')' && !inblank(*p); p++); 1280 1281 if (!*p) 1282 break; 1283 1284 sav = *p; 1285 *p = '\0'; 1286 addlinknode(list, dupstring(q)); 1287 xnum++; 1288 *p = sav; 1289 } 1290 /* Oops, end-of-string. */ 1291 if (*p != ')') { 1292 freecadef(all); 1293 zwarnnam(nam, "invalid argument: %s", *args); 1294 return NULL; 1295 } 1296 if (doset && axor) 1297 xnum++; 1298 xor = (char **) zalloc((xnum + 2) * sizeof(char *)); 1299 for (node = firstnode(list), xp = xor; node; incnode(node), xp++) 1300 *xp = ztrdup((char *) getdata(node)); 1301 if (doset && axor) 1302 *xp++ = ztrdup(axor); 1303 xp[0] = xp[1] = NULL; 1304 1305 p++; 1306 } else if (doset && axor) { 1307 xnum = 1; 1308 xor = (char **) zalloc(3 * sizeof(char *)); 1309 xor[0] = ztrdup(axor); 1310 xor[1] = xor[2] = NULL; 1311 } else 1312 xor = NULL; 1313 1314 if (*p == '-' || *p == '+' || 1315 (*p == '*' && (p[1] == '-' || p[1] == '+'))) { 1316 /* It's an option. */ 1317 Caopt opt; 1318 Caarg oargs = NULL; 1319 int multi, otype = CAO_NEXT, again = 0; 1320 char *name, *descr, c, *againp = NULL; 1321 1322 rec: 1323 1324 /* Allowed more than once? */ 1325 if ((multi = (*p == '*'))) 1326 p++; 1327 1328 if (((p[0] == '-' && p[1] == '+') || 1329 (p[0] == '+' && p[1] == '-')) && 1330 p[2] && p[2] != ':' && p[2] != '[' && 1331 p[2] != '=' && p[2] != '-' && p[2] != '+') { 1332 /* It's a -+ or +- definition. We just execute the whole 1333 * stuff twice for such things. */ 1334 againp = dupstring(p); 1335 name = ++p; 1336 *p = (again ? '-' : '+'); 1337 again++; 1338 } else { 1339 name = p; 1340 /* If it's a long option skip over the first `-'. */ 1341 if (p[0] == '-' && p[1] == '-') 1342 p++; 1343 } 1344 if (!p[1]) { 1345 freecadef(all); 1346 zwarnnam(nam, "invalid argument: %s", *args); 1347 return NULL; 1348 } 1349 1350 /* Skip over the name. */ 1351 for (p++; *p && *p != ':' && *p != '[' && 1352 ((*p != '-' && *p != '+') || 1353 (p[1] != ':' && p[1] != '[')) && 1354 (*p != '=' || 1355 (p[1] != ':' && p[1] != '[' && p[1] != '-')); p++) 1356 if (*p == '\\' && p[1]) 1357 p++; 1358 1359 /* The character after the option name specifies the type. */ 1360 c = *p; 1361 *p = '\0'; 1362 if (c == '-') { 1363 otype = CAO_DIRECT; 1364 c = *++p; 1365 } else if (c == '+') { 1366 otype = CAO_ODIRECT; 1367 c = *++p; 1368 } else if (c == '=') { 1369 otype = CAO_OEQUAL; 1370 if ((c = *++p) == '-') { 1371 otype = CAO_EQUAL; 1372 c = *++p; 1373 } 1374 } 1375 /* Get the optional description, if any. */ 1376 if (c == '[') { 1377 for (descr = ++p; *p && *p != ']'; p++) 1378 if (*p == '\\' && p[1]) 1379 p++; 1380 1381 if (!*p) { 1382 freecadef(all); 1383 zwarnnam(nam, "invalid option definition: %s", *args); 1384 return NULL; 1385 } 1386 *p++ = '\0'; 1387 c = *p; 1388 } else 1389 descr = NULL; 1390 1391 if (c && c != ':') { 1392 freecadef(all); 1393 zwarnnam(nam, "invalid option definition: %s", *args); 1394 return NULL; 1395 } 1396 /* Add the option name to the xor list if not `*-...'. */ 1397 if (!multi) { 1398 if (!xor) { 1399 xor = (char **) zalloc(2 * sizeof(char *)); 1400 xor[0] = xor[1] = NULL; 1401 } 1402 zsfree(xor[xnum]); 1403 xor[xnum] = ztrdup(rembslashcolon(name)); 1404 } 1405 if (c == ':') { 1406 /* There's at least one argument. */ 1407 1408 Caarg *oargp = &oargs; 1409 int atype, rest, oanum = 1, onum = 0; 1410 char *end; 1411 1412 /* Loop over the arguments. */ 1413 1414 while (c == ':') { 1415 rest = 0; 1416 end = NULL; 1417 1418 /* Get the argument type. */ 1419 if (*++p == ':') { 1420 atype = CAA_OPT; 1421 p++; 1422 } else if (*p == '*') { 1423 if (*++p != ':') { 1424 char sav; 1425 1426 for (end = p++; *p && *p != ':'; p++) 1427 if (*p == '\\' && p[1]) 1428 p++; 1429 sav = *p; 1430 *p = '\0'; 1431 end = dupstring(end); 1432 tokenize(end); 1433 *p = sav; 1434 } 1435 if (*p != ':') { 1436 freecadef(all); 1437 freecaargs(oargs); 1438 zwarnnam(nam, "invalid option definition: %s", 1439 *args); 1440 return NULL; 1441 } 1442 if (*++p == ':') { 1443 if (*++p == ':') { 1444 atype = CAA_RREST; 1445 p++; 1446 } else 1447 atype = CAA_RARGS; 1448 } else 1449 atype = CAA_REST; 1450 rest = 1; 1451 } else 1452 atype = CAA_NORMAL; 1453 1454 /* And the definition. */ 1455 1456 *oargp = parse_caarg(!rest, atype, oanum++, onum, 1457 name, &p, doset); 1458 if (atype == CAA_OPT) 1459 onum++; 1460 if (end) 1461 (*oargp)->end = ztrdup(end); 1462 oargp = &((*oargp)->next); 1463 if (rest) 1464 break; 1465 c = *p; 1466 } 1467 } 1468 /* Store the option definition. */ 1469 1470 *optp = opt = (Caopt) zalloc(sizeof(*opt)); 1471 optp = &((*optp)->next); 1472 1473 opt->next = NULL; 1474 opt->set = doset; 1475 opt->name = ztrdup(rembslashcolon(name)); 1476 if (descr) 1477 opt->descr = ztrdup(descr); 1478 else if (adpre && oargs && !oargs->next) { 1479 char *d; 1480 1481 for (d = oargs->descr; *d; d++) 1482 if (!iblank(*d)) 1483 break; 1484 1485 if (*d) 1486 opt->descr = tricat(adpre, oargs->descr, adsuf); 1487 else 1488 opt->descr = NULL; 1489 } else 1490 opt->descr = NULL; 1491 opt->xor = (again == 1 && xor ? zarrdup(xor) : xor); 1492 opt->type = otype; 1493 opt->args = oargs; 1494 opt->num = nopts++; 1495 opt->not = not; 1496 1497 if (otype == CAO_DIRECT || otype == CAO_EQUAL) 1498 ndopts++; 1499 else if (otype == CAO_ODIRECT || otype == CAO_OEQUAL) 1500 nodopts++; 1501 1502 /* If this is for single-letter option we also store a 1503 * pointer for the definition in the array for fast lookup. */ 1504 1505 if (single && name[1] && !name[2]) 1506 ret->single[STOUC(name[1])] = opt; 1507 1508 if (again == 1) { 1509 /* Do it all again for `*-...'. */ 1510 p = againp; 1511 goto rec; 1512 } 1513 } else if (*p == '*') { 1514 /* It's a rest-argument definition. */ 1515 1516 int type = CAA_REST; 1517 1518 if (not) 1519 continue; 1520 1521 if (*++p != ':') { 1522 freecadef(all); 1523 zwarnnam(nam, "invalid rest argument definition: %s", *args); 1524 return NULL; 1525 } 1526 if (ret->rest) { 1527 freecadef(all); 1528 zwarnnam(nam, "doubled rest argument definition: %s", *args); 1529 return NULL; 1530 } 1531 if (*++p == ':') { 1532 if (*++p == ':') { 1533 type = CAA_RREST; 1534 p++; 1535 } else 1536 type = CAA_RARGS; 1537 } 1538 ret->rest = parse_caarg(0, type, -1, 0, NULL, &p, doset); 1539 ret->rest->xor = xor; 1540 } else { 1541 /* It's a normal argument definition. */ 1542 1543 int type = CAA_NORMAL, direct; 1544 Caarg arg, tmp, pre; 1545 1546 if (not) 1547 continue; 1548 1549 if ((direct = idigit(*p))) { 1550 /* Argment number is given. */ 1551 int num = 0; 1552 1553 while (*p && idigit(*p)) 1554 num = (num * 10) + (((int) *p++) - '0'); 1555 1556 anum = num + 1; 1557 } else 1558 /* Default number. */ 1559 anum++; 1560 1561 if (*p != ':') { 1562 freecadef(all); 1563 zwarnnam(nam, "invalid argument: %s", *args); 1564 if (xor) 1565 free(xor); 1566 return NULL; 1567 } 1568 if (*++p == ':') { 1569 /* Optional argument. */ 1570 type = CAA_OPT; 1571 p++; 1572 } 1573 arg = parse_caarg(0, type, anum - 1, 0, NULL, &p, doset); 1574 arg->xor = xor; 1575 arg->direct = direct; 1576 1577 /* Sort the new definition into the existing list. */ 1578 1579 for (tmp = ret->args, pre = NULL; 1580 tmp && tmp->num < anum - 1; 1581 pre = tmp, tmp = tmp->next); 1582 1583 if (tmp && tmp->num == anum - 1) { 1584 freecadef(all); 1585 freecaargs(arg); 1586 zwarnnam(nam, "doubled argument definition: %s", *args); 1587 return NULL; 1588 } 1589 arg->next = tmp; 1590 if (pre) 1591 pre->next = arg; 1592 else 1593 ret->args = arg; 1594 } 1595 } 1596 ret->nopts = nopts; 1597 ret->ndopts = ndopts; 1598 ret->nodopts = nodopts; 1599 set_cadef_opts(ret); 1600 1601 return all; 1602} 1603 1604/* Given an array of definitions, return the cadef for it. From the cache 1605 * are newly built. */ 1606 1607static Cadef 1608get_cadef(char *nam, char **args) 1609{ 1610 Cadef *p, *min, new; 1611 int i, na = arrlen(args); 1612 1613 for (i = MAX_CACACHE, p = cadef_cache, min = NULL; i && *p; p++, i--) 1614 if (*p && na == (*p)->ndefs && arrcmp(args, (*p)->defs)) { 1615 (*p)->lastt = time(0); 1616 1617 return *p; 1618 } else if (!min || !*p || (*p)->lastt < (*min)->lastt) 1619 min = p; 1620 if (i > 0) 1621 min = p; 1622 if ((new = parse_cadef(nam, args))) { 1623 freecadef(*min); 1624 *min = new; 1625 } 1626 return new; 1627} 1628 1629/* 1630 * Get the option used in a word from the line, if any. 1631 * 1632 * "d" is a complete set of argument/option definitions to scan. 1633 * "line" is the word we are scanning. 1634 * "full" indicates that the option must match a full word; otherwise 1635 * we look for "=" arguments or prefixes. 1636 * *"end" is set to point to the end of the option, in some cases 1637 * leaving an option argument after it. 1638 */ 1639 1640static Caopt 1641ca_get_opt(Cadef d, char *line, int full, char **end) 1642{ 1643 Caopt p; 1644 1645 /* The full string may be an option. */ 1646 1647 for (p = d->opts; p; p = p->next) 1648 if (p->active && !strcmp(p->name, line)) { 1649 if (end) 1650 *end = line + strlen(line); 1651 1652 return p; 1653 } 1654 1655 if (!full) { 1656 /* The string from the line probably only begins with an option. */ 1657 for (p = d->opts; p; p = p->next) 1658 if (p->active && ((!p->args || p->type == CAO_NEXT) ? 1659 !strcmp(p->name, line) : strpfx(p->name, line))) { 1660 if (end) { 1661 /* Return a pointer to the end of the option. */ 1662 int l = strlen(p->name); 1663 1664 if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && 1665 line[l] == '=') 1666 l++; 1667 1668 *end = line + l; 1669 } 1670 return p; 1671 } 1672 } 1673 return NULL; 1674} 1675 1676/* Same as above, only for single-letter-style. */ 1677 1678static Caopt 1679ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp) 1680{ 1681 Caopt p, pp = NULL; 1682 char pre = *line++; 1683 LinkList l = NULL; 1684 1685 *lp = NULL; 1686 for (p = NULL; *line; line++) { 1687 if ((p = d->single[STOUC(*line)]) && p->active && 1688 p->args && p->name[0] == pre) { 1689 if (p->type == CAO_NEXT) { 1690 if (!l) 1691 *lp = l = newlinklist(); 1692 addlinknode(l, p); 1693 } else { 1694 if (end) { 1695 line++; 1696 if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && 1697 *line == '=') 1698 line++; 1699 *end = line; 1700 } 1701 pp = p; 1702 break; 1703 } 1704 } else if (!p || (p && !p->active)) 1705 return NULL; 1706 pp = (p->name[0] == pre ? p : NULL); 1707 p = NULL; 1708 } 1709 if (pp && end) 1710 *end = line; 1711 return pp; 1712} 1713 1714/* Return the n'th argument definition. */ 1715 1716static Caarg 1717ca_get_arg(Cadef d, int n) 1718{ 1719 if (d->argsactive) { 1720 Caarg a = d->args; 1721 1722 while (a && (!a->active || n < a->min || n > a->num)) { 1723 if (!a->active) 1724 n++; 1725 a = a->next; 1726 } 1727 if (a && a->min <= n && a->num >= n && a->active) 1728 return a; 1729 1730 return (d->rest && d->rest->active ? d->rest : NULL); 1731 } 1732 return NULL; 1733} 1734 1735/* Use a xor list, marking options as inactive. */ 1736 1737static LinkList ca_xor; 1738 1739static int 1740ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname) 1741{ 1742 if ((xor || opts) && cur <= compcurrent) { 1743 Caopt opt; 1744 char *x; 1745 int sl = (d->set ? (int)strlen(d->set) : -1), set = 0; 1746 1747 for (; (x = (opts ? "-" : *xor)); xor++) { 1748 if (optname && optname[0] == x[0] && strcmp(optname, x)) 1749 continue; 1750 if (ca_xor) 1751 addlinknode(ca_xor, x); 1752 set = 0; 1753 if (sl > 0) { 1754 if (strpfx(d->set, x)) { 1755 x += sl; 1756 set = 1; 1757 } else if (!strncmp(d->set, x, sl - 1)) { 1758 Caopt p; 1759 1760 for (p = d->opts; p; p = p->next) 1761 if (p->set) 1762 p->active = 0; 1763 1764 x = ":"; 1765 set = 1; 1766 } 1767 } 1768 if (x[0] == ':' && !x[1]) { 1769 if (set) { 1770 Caarg a; 1771 1772 for (a = d->args; a; a = a->next) 1773 if (a->set) 1774 a->active = 0; 1775 if (d->rest && (!set || d->rest->set)) 1776 d->rest->active = 0; 1777 } else 1778 d->argsactive = 0; 1779 } else if (x[0] == '-' && !x[1]) { 1780 Caopt p; 1781 1782 for (p = d->opts; p; p = p->next) 1783 if (!set || p->set) 1784 p->active = 0; 1785 } else if (x[0] == '*' && !x[1]) { 1786 if (d->rest && (!set || d->rest->set)) 1787 d->rest->active = 0; 1788 } else if (idigit(x[0])) { 1789 int n = atoi(x); 1790 Caarg a = d->args; 1791 1792 while (a && a->num < n) 1793 a = a->next; 1794 1795 if (a && a->num == n && (!set || a->set)) 1796 a->active = 0; 1797 } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set)) 1798 opt->active = 0; 1799 1800 if (opts) 1801 break; 1802 } 1803 } 1804 return 0; 1805} 1806 1807/* State when parsing a command line. */ 1808 1809typedef struct castate *Castate; 1810 1811/* 1812 * **** DOCUMENT ME **** 1813 * 1814 * This structure and its use are a nightmare. 1815 */ 1816 1817struct castate { 1818 Castate snext; 1819 Cadef d; 1820 int nopts; 1821 Caarg def, ddef; 1822 Caopt curopt, dopt; 1823 int opt, arg, argbeg, optbeg, nargbeg, restbeg, curpos, argend; 1824 int inopt, inrest, inarg, nth, doff, singles, oopt, actopts; 1825 LinkList args; 1826 LinkList *oargs; 1827}; 1828 1829static struct castate ca_laststate; 1830static int ca_parsed = 0, ca_alloced = 0; 1831 1832static void 1833freecastate(Castate s) 1834{ 1835 int i; 1836 LinkList *p; 1837 1838 freelinklist(s->args, freestr); 1839 for (i = s->nopts, p = s->oargs; i--; p++) 1840 if (*p) 1841 freelinklist(*p, freestr); 1842 zfree(s->oargs, s->d->nopts * sizeof(LinkList)); 1843} 1844 1845/* Return a copy of an option's argument, ignoring possible quoting 1846 * in the option name. */ 1847 1848static char * 1849ca_opt_arg(Caopt opt, char *line) 1850{ 1851 char *o = opt->name; 1852 1853 while (1) { 1854 if (*o == '\\') 1855 o++; 1856 if (*line == '\\' || *line == '\'' || *line == '"') 1857 line++; 1858 if (!*o || *o != *line) 1859 break; 1860 o++; 1861 line++; 1862 } 1863 if (*line && (opt->type == CAO_EQUAL || opt->type == CAO_OEQUAL)) { 1864 if (*line == '\\') 1865 line++; 1866 if (*line == '=') 1867 line++; 1868 } 1869 return ztrdup(line); 1870} 1871 1872/* Parse a command line. */ 1873 1874static int 1875ca_parse_line(Cadef d, int multi, int first) 1876{ 1877 Caarg adef, ddef; 1878 Caopt ptr, wasopt = NULL, dopt; 1879 struct castate state; 1880 char *line, *oline, *pe, **argxor = NULL; 1881 int cur, doff, argend, arglast; 1882 Patprog endpat = NULL, napat = NULL; 1883 LinkList sopts = NULL; 1884#if 0 1885 int ne; 1886#endif 1887 1888 /* Free old state. */ 1889 1890 if (first && ca_alloced) { 1891 Castate s = &ca_laststate, ss; 1892 1893 while (s) { 1894 ss = s->snext; 1895 freecastate(s); 1896 s = ss; 1897 } 1898 } 1899 /* Mark everything as active. */ 1900 1901 for (ptr = d->opts; ptr; ptr = ptr->next) 1902 ptr->active = 1; 1903 d->argsactive = 1; 1904 if (d->rest) 1905 d->rest->active = 1; 1906 for (adef = d->args; adef; adef = adef->next) 1907 adef->active = 1; 1908 1909 /* Default values for the state. */ 1910 1911 state.snext = NULL; 1912 state.d = d; 1913 state.nopts = d->nopts; 1914 state.def = state.ddef = NULL; 1915 state.curopt = state.dopt = NULL; 1916 state.argbeg = state.optbeg = state.nargbeg = state.restbeg = state.actopts = 1917 state.nth = state.inopt = state.inarg = state.opt = state.arg = 1; 1918 state.argend = argend = arrlen(compwords) - 1; 1919 state.inrest = state.doff = state.singles = state.oopt = 0; 1920 state.curpos = compcurrent; 1921 state.args = znewlinklist(); 1922 state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList)); 1923 memset(state.oargs, 0, d->nopts * sizeof(LinkList)); 1924 1925 ca_alloced = 1; 1926 1927 memcpy(&ca_laststate, &state, sizeof(state)); 1928 1929 if (!compwords[1]) { 1930 ca_laststate.opt = ca_laststate.arg = 0; 1931 1932 goto end; 1933 } 1934 if (d->nonarg) 1935 napat = patcompile(d->nonarg, 0, NULL); 1936 1937 /* Loop over the words from the line. */ 1938 1939 for (line = compwords[1], cur = 2, state.curopt = NULL, state.def = NULL; 1940 line; line = compwords[cur++]) { 1941 ddef = adef = NULL; 1942 dopt = NULL; 1943 doff = state.singles = arglast = 0; 1944 1945 oline = line; 1946#if 0 1947 /* 1948 * remove quotes. 1949 * This is commented out: it doesn't allow you to discriminate 1950 * between command line values that can be expanded and those 1951 * that can't, and in some cases this generates inconsistency; 1952 * for example, ~/foo\[bar unqotes to ~/foo[bar which doesn't 1953 * work either way---it's wrong if the ~ is quoted, and 1954 * wrong if the [ isn't quoted.. So it's now up to the caller to 1955 * unquote. 1956 */ 1957 line = dupstring(line); 1958 ne = noerrs; 1959 noerrs = 2; 1960 parse_subst_string(line); 1961 noerrs = ne; 1962#endif 1963 remnulargs(line); 1964 untokenize(line); 1965 1966 if (ca_inactive(d, argxor, cur, 0, NULL) || 1967 ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--"))) { 1968 if (ca_inactive(d, NULL, cur, 1, NULL)) 1969 return 1; 1970 continue; 1971 } 1972 /* We've got a definition for an argument, skip to the next. */ 1973 1974 if (state.def) { 1975 state.arg = 0; 1976 if (state.curopt) 1977 zaddlinknode(state.oargs[state.curopt->num], ztrdup(oline)); 1978 1979 if ((state.opt = (state.def->type == CAA_OPT)) && state.def->opt) 1980 state.oopt++; 1981 1982 if (state.def->type == CAA_REST || state.def->type == CAA_RARGS || 1983 state.def->type == CAA_RREST) { 1984 if (state.def->end && pattry(endpat, line)) { 1985 state.def = NULL; 1986 state.curopt = NULL; 1987 state.opt = state.arg = 1; 1988 state.argend = ca_laststate.argend = cur - 1; 1989 goto cont; 1990 } 1991 } else if ((state.def = state.def->next)) { 1992 state.argbeg = cur; 1993 state.argend = argend; 1994 } else if (sopts && nonempty(sopts)) { 1995 state.curopt = (Caopt) uremnode(sopts, firstnode(sopts)); 1996 state.def = state.curopt->args; 1997 state.opt = 0; 1998 state.argbeg = state.optbeg = state.inopt = cur; 1999 state.argend = argend; 2000 doff = state.doff = 0; 2001 state.singles = 1; 2002 if (!state.oargs[state.curopt->num]) 2003 state.oargs[state.curopt->num] = znewlinklist(); 2004 goto cont; 2005 } else { 2006 state.curopt = NULL; 2007 state.opt = 1; 2008 } 2009 } else { 2010 state.opt = state.arg = 1; 2011 state.curopt = NULL; 2012 } 2013 if (state.opt) 2014 state.opt = (line[0] ? (line[1] ? 2 : 1) : 0); 2015 2016 pe = NULL; 2017 2018 wasopt = NULL; 2019 2020 /* See if it's an option. */ 2021 2022 if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) && 2023 (state.curopt->type == CAO_OEQUAL ? 2024 (compwords[cur] || pe[-1] == '=') : 2025 (state.curopt->type == CAO_EQUAL ? 2026 (pe[-1] == '=' || !pe[0]) : 1))) { 2027 2028 if ((ddef = state.def = ((state.curopt->type != CAO_EQUAL || 2029 pe[-1] == '=') ? 2030 state.curopt->args : NULL))) 2031 dopt = state.curopt; 2032 2033 doff = pe - line; 2034 state.optbeg = state.argbeg = state.inopt = cur; 2035 state.argend = argend; 2036 state.singles = (d->single && (!pe || !*pe) && 2037 state.curopt->name[1] && !state.curopt->name[2]); 2038 2039 if (!state.oargs[state.curopt->num]) 2040 state.oargs[state.curopt->num] = znewlinklist(); 2041 2042 if (ca_inactive(d, state.curopt->xor, cur, 0, 2043 (cur == compcurrent ? state.curopt->name : NULL))) 2044 return 1; 2045 2046 /* Collect the argument strings. Maybe. */ 2047 2048 if (state.def && 2049 (state.curopt->type == CAO_DIRECT || 2050 state.curopt->type == CAO_EQUAL || 2051 (state.curopt->type == CAO_ODIRECT && pe[0]) || 2052 (state.curopt->type == CAO_OEQUAL && 2053 (pe[0] || pe[-1] == '=')))) { 2054 if (state.def->type != CAA_REST && 2055 state.def->type != CAA_RARGS && 2056 state.def->type != CAA_RREST) 2057 state.def = state.def->next; 2058 2059 zaddlinknode(state.oargs[state.curopt->num], 2060 ca_opt_arg(state.curopt, oline)); 2061 } 2062 if (state.def) 2063 state.opt = 0; 2064 else { 2065 if (!d->single || (state.curopt->name[1] && state.curopt->name[2])) 2066 wasopt = state.curopt; 2067 state.curopt = NULL; 2068 } 2069 } else if (state.opt == 2 && d->single && 2070 ((state.curopt = ca_get_sopt(d, line, &pe, &sopts)) || 2071 (cur != compcurrent && sopts && nonempty(sopts)))) { 2072 /* Or maybe it's a single-letter option? */ 2073 2074 char *p; 2075 Caopt tmpopt; 2076 2077 if (cur != compcurrent && sopts && nonempty(sopts)) 2078 state.curopt = (Caopt) uremnode(sopts, firstnode(sopts)); 2079 2080 if (!state.oargs[state.curopt->num]) 2081 state.oargs[state.curopt->num] = znewlinklist(); 2082 2083 state.def = state.curopt->args; 2084 ddef = (state.curopt->type == CAO_NEXT && cur == compcurrent ? 2085 NULL : state.def); 2086 dopt = state.curopt; 2087 doff = pe - line; 2088 state.optbeg = state.argbeg = state.inopt = cur; 2089 state.argend = argend; 2090 state.singles = (!pe || !*pe); 2091 2092 for (p = line + 1; p < pe; p++) { 2093 if ((tmpopt = d->single[STOUC(*p)])) { 2094 if (!state.oargs[tmpopt->num]) 2095 state.oargs[tmpopt->num] = znewlinklist(); 2096 2097 if (ca_inactive(d, tmpopt->xor, cur, 0, 2098 (cur == compcurrent ? tmpopt->name : NULL))) 2099 return 1; 2100 } 2101 } 2102 if (state.def && 2103 (state.curopt->type == CAO_DIRECT || 2104 state.curopt->type == CAO_EQUAL || 2105 (state.curopt->type == CAO_ODIRECT && pe[0]) || 2106 (state.curopt->type == CAO_OEQUAL && 2107 (pe[0] || pe[-1] == '=')))) { 2108 if (state.def->type != CAA_REST && 2109 state.def->type != CAA_RARGS && 2110 state.def->type != CAA_RREST) 2111 state.def = state.def->next; 2112 2113 zaddlinknode(state.oargs[state.curopt->num], 2114 ca_opt_arg(state.curopt, line)); 2115 } 2116 if (state.def) 2117 state.opt = 0; 2118 else 2119 state.curopt = NULL; 2120 } else if (multi && (*line == '-' || *line == '+') && cur != compcurrent 2121#if 0 2122 /**** Ouch. Using this will disable the mutual exclusion 2123 of different sets. Not using it will make the -A 2124 pattern be effectively ignored with multiple sets. */ 2125 && (!napat || !pattry(napat, line)) 2126#endif 2127 ) 2128 return 1; 2129 else if (state.arg && (!napat || !pattry(napat, line))) { 2130 /* Otherwise it's a normal argument. */ 2131 if (napat && ca_inactive(d, NULL, cur + 1, 1, NULL)) 2132 return 1; 2133 2134 arglast = 1; 2135 if (state.inopt) { 2136 state.inopt = 0; 2137 state.nargbeg = cur - 1; 2138 state.argend = argend; 2139 } 2140 if (!d->args && !d->rest && *line && *line != '-' && *line != '+') { 2141 if (!multi && cur > compcurrent) 2142 break; 2143 return 1; 2144 } 2145 if ((adef = state.def = ca_get_arg(d, state.nth)) && 2146 (state.def->type == CAA_RREST || 2147 state.def->type == CAA_RARGS)) { 2148 2149 /* Bart 2009/11/17: 2150 * We've reached the "rest" definition. If at this point 2151 * we already found another definition that describes the 2152 * current word, use that instead. If not, prep for the 2153 * "narrowing" of scope to only the remaining words. 2154 * 2155 * We can't test ca_laststate.def in the loop conditions 2156 * at the top because this same loop also handles the 2157 * ':*PATTERN:MESSAGE:ACTION' form for multiple arguments 2158 * after an option, which may need to continue scanning. 2159 * There might be an earlier point at which this test can 2160 * be made but tracking it down is not worth the effort. 2161 */ 2162 if (ca_laststate.def) 2163 break; 2164 2165 state.inrest = 0; 2166 state.opt = (cur == state.nargbeg + 1 && 2167 (!multi || !*line || 2168 *line == '-' || *line == '+')); 2169 state.optbeg = state.nargbeg; 2170 state.argbeg = cur - 1; 2171 state.argend = argend; 2172 2173 for (; line; line = compwords[cur++]) 2174 zaddlinknode(state.args, ztrdup(line)); 2175 2176 memcpy(&ca_laststate, &state, sizeof(state)); 2177 ca_laststate.ddef = NULL; 2178 ca_laststate.dopt = NULL; 2179 ca_laststate.doff = 0; 2180 break; 2181 } 2182 zaddlinknode(state.args, ztrdup(line)); 2183 if (adef) 2184 state.oopt = adef->num - state.nth; 2185 2186 if (state.def) 2187 argxor = state.def->xor; 2188 2189 if (state.def && state.def->type != CAA_NORMAL && 2190 state.def->type != CAA_OPT && state.inarg) { 2191 state.restbeg = cur; 2192 state.inarg = 0; 2193 } else if (!state.def || state.def->type == CAA_NORMAL || 2194 state.def->type == CAA_OPT) 2195 state.inarg = 1; 2196 state.nth++; 2197 state.def = NULL; 2198 } 2199 /* Do the end-pattern test if needed. */ 2200 2201 if (state.def && state.curopt && 2202 (state.def->type == CAA_RREST || state.def->type == CAA_RARGS)) { 2203 if (state.def->end) 2204 endpat = patcompile(state.def->end, 0, NULL); 2205 else { 2206 LinkList l = state.oargs[state.curopt->num]; 2207 2208 if (cur < compcurrent) 2209 memcpy(&ca_laststate, &state, sizeof(state)); 2210 2211 for (; line; line = compwords[cur++]) 2212 zaddlinknode(l, ztrdup(line)); 2213 2214 ca_laststate.ddef = NULL; 2215 ca_laststate.dopt = NULL; 2216 ca_laststate.doff = 0; 2217 break; 2218 } 2219 } else if (state.def && state.def->end) 2220 endpat = patcompile(state.def->end, 0, NULL); 2221 2222 /* Copy the state into the global one. */ 2223 2224 cont: 2225 2226 if (cur + 1 == compcurrent) { 2227 memcpy(&ca_laststate, &state, sizeof(state)); 2228 ca_laststate.ddef = NULL; 2229 ca_laststate.dopt = NULL; 2230 ca_laststate.doff = 0; 2231 } else if (cur == compcurrent && !ca_laststate.def) { 2232 if ((ca_laststate.def = ddef)) { 2233 ca_laststate.singles = state.singles; 2234 if (state.curopt && state.curopt->type == CAO_NEXT) { 2235 ca_laststate.ddef = ddef; 2236 ca_laststate.dopt = dopt; 2237 ca_laststate.def = NULL; 2238 ca_laststate.opt = 1; 2239 state.curopt->active = 1; 2240 } else { 2241 ca_laststate.doff = doff; 2242 ca_laststate.opt = 0; 2243 } 2244 } else { 2245 ca_laststate.def = adef; 2246 ca_laststate.opt = (!arglast || !multi || !*line || 2247 *line == '-' || *line == '+'); 2248 ca_laststate.ddef = NULL; 2249 ca_laststate.dopt = NULL; 2250 ca_laststate.optbeg = state.nargbeg; 2251 ca_laststate.argbeg = state.restbeg; 2252 ca_laststate.argend = state.argend; 2253 ca_laststate.singles = state.singles; 2254 ca_laststate.oopt = state.oopt; 2255 if (wasopt) 2256 wasopt->active = 1; 2257 } 2258 } 2259 } 2260 end: 2261 2262 ca_laststate.actopts = 0; 2263 for (ptr = d->opts; ptr; ptr = ptr->next) 2264 if (ptr->active) 2265 ca_laststate.actopts++; 2266 2267 return 0; 2268} 2269 2270/* Build a colon-list from a list. */ 2271 2272static char * 2273ca_colonlist(LinkList l) 2274{ 2275 if (l) { 2276 LinkNode n; 2277 int len = 0; 2278 char *p, *ret, *q; 2279 2280 for (n = firstnode(l); n; incnode(n)) { 2281 len++; 2282 for (p = (char *) getdata(n); *p; p++) 2283 len += (*p == ':' ? 2 : 1); 2284 } 2285 ret = q = (char *) zalloc(len); 2286 2287 for (n = firstnode(l); n;) { 2288 for (p = (char *) getdata(n); *p; p++) { 2289 if (*p == ':') 2290 *q++ = '\\'; 2291 *q++ = *p; 2292 } 2293 incnode(n); 2294 if (n) 2295 *q++ = ':'; 2296 } 2297 *q = '\0'; 2298 2299 return ret; 2300 } else 2301 return ztrdup(""); 2302} 2303 2304/* 2305 * This function adds the current set of descriptions, actions, 2306 * and subcontext descriptions to the given linked list for passing 2307 * up in comparguments -D and comparguments -L. opt is the 2308 * option string (may be NULL if this isn't an option argument) and arg the 2309 * argument structure (either an option argument or a normal argument 2310 * as determined by arg->type). 2311 */ 2312 2313static void 2314ca_set_data(LinkList descr, LinkList act, LinkList subc, 2315 char *opt, Caarg arg, Caopt optdef, int single) 2316{ 2317 LinkNode dnode, anode; 2318 char nbuf[40], *buf; 2319 int restr = 0, onum, miss = 0, rest, oopt = 1, lopt = 0, addopt; 2320 2321 rec: 2322 2323 addopt = (opt ? 0 : ca_laststate.oopt); 2324 2325 for (; arg && (opt || (arg->num < 0 || 2326 (arg->min <= ca_laststate.nth + addopt && 2327 arg->num >= ca_laststate.nth)));) { 2328 lopt = (arg->type == CAA_OPT); 2329 if (!opt && !lopt && oopt > 0) 2330 oopt = 0; 2331 2332 for (dnode = firstnode(descr), anode = firstnode(act); 2333 dnode; incnode(dnode), incnode(anode)) 2334 if (!strcmp((char *) getdata(dnode), arg->descr) && 2335 !strcmp((char *) getdata(anode), arg->action)) 2336 break; 2337 2338 if (!dnode) { 2339 addlinknode(descr, arg->descr); 2340 addlinknode(act, arg->action); 2341 2342 if (!restr) { 2343 if ((restr = (arg->type == CAA_RARGS))) 2344 restrict_range(ca_laststate.optbeg, ca_laststate.argend); 2345 else if ((restr = (arg->type == CAA_RREST))) 2346 restrict_range(ca_laststate.argbeg, ca_laststate.argend); 2347 } 2348 if (arg->opt) { 2349 buf = (char *) zhalloc((arg->set ? strlen(arg->set) : 0) + 2350 strlen(arg->opt) + 40); 2351 if (arg->num > 0 && arg->type < CAA_REST) 2352 sprintf(buf, "%soption%s-%d", 2353 (arg->set ? arg->set : ""), arg->opt, arg->num); 2354 else 2355 sprintf(buf, "%soption%s-rest", 2356 (arg->set ? arg->set : ""), arg->opt); 2357 } else if (arg->num > 0) { 2358 sprintf(nbuf, "argument-%d", arg->num); 2359 buf = (arg->set ? dyncat(arg->set, nbuf) : dupstring(nbuf)); 2360 } else 2361 buf = (arg->set ? dyncat(arg->set, "argument-rest") : 2362 dupstring("argument-rest")); 2363 2364 addlinknode(subc, buf); 2365 } 2366 /* 2367 * If this is an argument to an option, and the option definition says 2368 * the argument to the option is required and in the following 2369 * (i.e. this) word, then it must match what we've just told it to 2370 * match---don't try to match normal arguments. 2371 * 2372 * This test may be too stringent for what we need, or it 2373 * may be too loose; I've simply tweaked it until it gets 2374 * the case above right. 2375 */ 2376 if (arg->type == CAA_NORMAL && 2377 opt && optdef && optdef->type == CAO_NEXT) 2378 return; 2379 if (single) 2380 break; 2381 2382 if (!opt) { 2383 if (arg->num >= 0 && !arg->next && miss) 2384 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ? 2385 ca_laststate.d->rest : NULL); 2386 else { 2387 onum = arg->num; 2388 rest = (onum != arg->min && onum == ca_laststate.nth); 2389 if ((arg = arg->next)) { 2390 if (arg->num != onum + 1) 2391 miss = 1; 2392 } else if (rest || (oopt > 0 && !opt)) { 2393 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ? 2394 ca_laststate.d->rest : NULL); 2395 oopt = -1; 2396 } 2397 } 2398 } else { 2399 if (!lopt) 2400 break; 2401 arg = arg->next; 2402 } 2403 } 2404 if (!single && opt && (lopt || ca_laststate.oopt)) { 2405 opt = NULL; 2406 arg = ca_get_arg(ca_laststate.d, ca_laststate.nth); 2407 2408 goto rec; 2409 } 2410 if (!opt && oopt > 0) { 2411 oopt = -1; 2412 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ? 2413 ca_laststate.d->rest : NULL); 2414 2415 goto rec; 2416 } 2417} 2418 2419static int 2420bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 2421{ 2422 int min, max, n; 2423 Castate lstate = &ca_laststate; 2424 2425 if (incompfunc != 1) { 2426 zwarnnam(nam, "can only be called from completion function"); 2427 return 1; 2428 } 2429 if (args[0][0] != '-' || !args[0][1] || args[0][2]) { 2430 zwarnnam(nam, "invalid argument: %s", args[0]); 2431 return 1; 2432 } 2433 if (args[0][1] != 'i' && args[0][1] != 'I' && !ca_parsed) { 2434 zwarnnam(nam, "no parsed state"); 2435 return 1; 2436 } 2437 switch (args[0][1]) { 2438 case 'i': min = 2; max = -1; break; 2439 case 'D': min = 3; max = 3; break; 2440 case 'O': min = 4; max = 4; break; 2441 case 'L': min = 3; max = 4; break; 2442 case 's': min = 1; max = 1; break; 2443 case 'M': min = 1; max = 1; break; 2444 case 'a': min = 0; max = 0; break; 2445 case 'W': min = 2; max = 2; break; 2446 case 'n': min = 1; max = 1; break; 2447 default: 2448 zwarnnam(nam, "invalid option: %s", args[0]); 2449 return 1; 2450 } 2451 n = arrlen(args) - 1; 2452 if (n < min) { 2453 zwarnnam(nam, "not enough arguments"); 2454 return 1; 2455 } else if (max >= 0 && n > max) { 2456 zwarnnam(nam, "too many arguments"); 2457 return 1; 2458 } 2459 switch (args[0][1]) { 2460 case 'i': 2461 /* This initialises the internal data structures. Arguments are the 2462 * auto-description string, the optional -s, -S, -A and -M options 2463 * given to _arguments and the specs. */ 2464 if (compcurrent > 1 && compwords[0]) { 2465 Cadef def; 2466 int cap = ca_parsed, multi, first = 1, use, ret = 0; 2467 LinkList cax = ca_xor, nx; 2468 LinkNode node; 2469 Castate states = NULL, sp; 2470 char *xor[2]; 2471 2472 ca_parsed = 0; 2473 xor[1] = NULL; 2474 2475 if (!(def = get_cadef(nam, args + 1))) 2476 return 1; 2477 2478 multi = !!def->snext; 2479 ca_parsed = cap; 2480 ca_xor = (multi ? newlinklist() : NULL); 2481 2482 while (def) { 2483 use = !ca_parse_line(def, multi, first); 2484 nx = ca_xor; 2485 ca_xor = NULL; 2486 while ((def = def->snext)) { 2487 if (nx) { 2488 for (node = firstnode(nx); node; incnode(node)) { 2489 xor[0] = (char *) getdata(node); 2490 if (!strcmp(xor[0], def->sname) || 2491 ca_inactive(def, xor, compcurrent, 0, NULL)) 2492 break; 2493 } 2494 if (!node) 2495 break; 2496 } 2497 } 2498 ca_xor = nx; 2499 if (use && def) { 2500 sp = (Castate) zalloc(sizeof(*sp)); 2501 memcpy(sp, &ca_laststate, sizeof(*sp)); 2502 sp->snext = states; 2503 states = sp; 2504 } else if (!use && !def) { 2505 if (states) { 2506 freecastate(&ca_laststate); 2507 memcpy(&ca_laststate, states, sizeof(*sp)); 2508 sp = states->snext; 2509 zfree(states, sizeof(*states)); 2510 states = sp; 2511 } else 2512 ret = 1; 2513 } 2514 first = 0; 2515 } 2516 ca_xor = cax; 2517 ca_parsed = 1; 2518 ca_laststate.snext = states; 2519 2520 return ret; 2521 } 2522 return 1; 2523 2524 case 'D': 2525 /* This returns the descriptions, actions and sub-contexts for the 2526 * things _arguments has to execute at this place on the line (the 2527 * sub-contexts are used as tags). 2528 * The return value is particularly important here, it says if 2529 * there are arguments to completely at all. */ 2530 { 2531 LinkList descr, act, subc; 2532 Caarg arg; 2533 int ign = 0, ret = 1; 2534 2535 descr = newlinklist(); 2536 act = newlinklist(); 2537 subc = newlinklist(); 2538 2539 while (lstate) { 2540 arg = lstate->def; 2541 2542 if (arg) { 2543 ret = 0; 2544 if (!ign && lstate->doff > 0) { 2545 ign = 1; 2546 ignore_prefix(lstate->doff); 2547 } 2548 ca_set_data(descr, act, subc, arg->opt, arg, 2549 lstate->curopt, (lstate->doff > 0)); 2550 } 2551 lstate = lstate->snext; 2552 } 2553 if (!ret) { 2554 set_list_array(args[1], descr); 2555 set_list_array(args[2], act); 2556 set_list_array(args[3], subc); 2557 } 2558 return ret; 2559 } 2560 case 'O': 2561 /* This returns the descriptions for the options in the arrays whose 2562 * names are given as arguments. The descriptions are strings in a 2563 * form usable by _describe. The return value says if there are any 2564 * options to be completed. */ 2565 { 2566 LinkList next = newlinklist(); 2567 LinkList direct = newlinklist(); 2568 LinkList odirect = newlinklist(); 2569 LinkList equal = newlinklist(), l; 2570 LinkNode node; 2571 Caopt p; 2572 char *str; 2573 int ret = 1; 2574 2575 for (; lstate; lstate = lstate->snext) { 2576 if (lstate->actopts && 2577 (lstate->opt || (lstate->doff && lstate->def) || 2578 (lstate->def && lstate->def->opt && 2579 (lstate->def->type == CAA_OPT || 2580 (lstate->def->type >= CAA_RARGS && 2581 lstate->def->num < 0)))) && 2582 (!lstate->def || lstate->def->type < CAA_RARGS || 2583 (lstate->def->type == CAA_RARGS ? 2584 (lstate->curpos == lstate->argbeg + 1) : 2585 (compcurrent == 1)))) { 2586 ret = 0; 2587 for (p = lstate->d->opts; p; p = p->next) { 2588 if (p->active && !p->not) { 2589 switch (p->type) { 2590 case CAO_NEXT: l = next; break; 2591 case CAO_DIRECT: l = direct; break; 2592 case CAO_ODIRECT: l = odirect; break; 2593 default: l = equal; break; 2594 } 2595 if (p->descr) { 2596 char *n = bslashcolon(p->name); 2597 int len = strlen(n) + strlen(p->descr) + 2; 2598 2599 str = (char *) zhalloc(len); 2600 strcpy(str, n); 2601 strcat(str, ":"); 2602 strcat(str, p->descr); 2603 } else 2604 str = bslashcolon(p->name); 2605 2606 for (node = firstnode(l); node; incnode(node)) 2607 if (!strcmp(str, (char *) getdata(node))) 2608 break; 2609 2610 if (!node) 2611 addlinknode(l, str); 2612 } 2613 } 2614 } 2615 } 2616 if (!ret) { 2617 set_list_array(args[1], next); 2618 set_list_array(args[2], direct); 2619 set_list_array(args[3], odirect); 2620 set_list_array(args[4], equal); 2621 2622 return 0; 2623 } 2624 return (ca_laststate.singles ? 2 : 1); 2625 } 2626 case 'L': 2627 /* This tests if the beginning of the current word matches an option. 2628 * It is for cases like `./configure --pre=/<TAB>' which should 2629 * complete to `--prefix=/...'. The options name isn't fully typed 2630 * and _arguments finds out that there is no option `--pre' and that 2631 * it should complete some argument to an option. It then uses -L 2632 * to find the option the argument is for. */ 2633 { 2634 LinkList descr, act, subc; 2635 Caopt opt; 2636 int ret = 1; 2637 2638 descr = newlinklist(); 2639 act = newlinklist(); 2640 subc = newlinklist(); 2641 2642 while (lstate) { 2643 opt = ca_get_opt(lstate->d, args[1], 1, NULL); 2644 2645 if (opt && opt->args) { 2646 ret = 0; 2647 ca_set_data(descr, act, subc, opt->name, opt->args, opt, 1); 2648 } 2649 lstate = lstate->snext; 2650 } 2651 if (!ret) { 2652 set_list_array(args[2], descr); 2653 set_list_array(args[3], act); 2654 set_list_array(args[4], subc); 2655 } 2656 return ret; 2657 } 2658 case 's': 2659 /* This returns zero if we are completing single letter options. 2660 * It also uses its argument as the name of a parameter and sets 2661 * that to a string describing the argument behaviour of the last 2662 * option in the current word so that we can get the auto-suffix 2663 * right. */ 2664 for (; lstate; lstate = lstate->snext) 2665 if (lstate->d->single && lstate->singles && 2666 lstate->actopts 2667#if 0 2668 /* let's try without, for the -W option of _arguments */ 2669 && lstate->opt 2670#endif 2671 ) { 2672 setsparam(args[1], 2673 ztrdup((lstate->ddef && lstate->dopt) ? 2674 (lstate->dopt->type == CAO_DIRECT ? 2675 "direct" : 2676 ((lstate->dopt->type == CAO_OEQUAL || 2677 lstate->dopt->type == CAO_EQUAL) ? 2678 "equal" : "next")) : "")); 2679 return 0; 2680 } 2681 return 1; 2682 case 'M': 2683 /* This returns the match specs defined for the set of specs we are 2684 * using. Returned, as usual in a parameter whose name is given as 2685 * the argument. */ 2686 setsparam(args[1], ztrdup(ca_laststate.d->match)); 2687 return 0; 2688 case 'a': 2689 /* This just sets the return value. To zero if there would be or 2690 * were any normal arguments to be completed. Used to decide if 2691 * _arguments should say `no arguments' or `no more arguments'. */ 2692 for (; lstate; lstate = lstate->snext) 2693 if (lstate->d->args || lstate->d->rest) 2694 return 0; 2695 return 1; 2696 case 'W': 2697 /* This gets two parameter names as arguments. The first is set to 2698 * the current word sans any option prefixes handled by comparguments. 2699 * The second parameter is set to an array containing the options on 2700 * the line and their arguments. I.e. the stuff _arguments returns 2701 * to its caller in the `line' and `opt_args' parameters. */ 2702 { 2703 Castate s; 2704 char **ret, **p; 2705 LinkNode n; 2706 LinkList *a; 2707 Caopt o; 2708 int num; 2709 2710 for (num = 0, s = lstate; s; s = s->snext) 2711 num += countlinknodes(s->args); 2712 2713 ret = p = zalloc((num + 1) * sizeof(char *)); 2714 2715 for (s = lstate; s; s = s->snext) 2716 for (n = firstnode(s->args); n; incnode(n)) 2717 *p++ = ztrdup((char *) getdata(n)); 2718 *p = NULL; 2719 2720 setaparam(args[1], ret); 2721 2722 for (num = 0, s = lstate; s; s = s->snext) 2723 for (o = s->d->opts, a = s->oargs; o; o = o->next, a++) 2724 if (*a) 2725 num += 2; 2726 2727 ret = p = zalloc((num + 1) * sizeof(char *)); 2728 2729 for (s = lstate; s; s = s->snext) 2730 for (o = s->d->opts, a = s->oargs; o; o = o->next, a++) 2731 if (*a) { 2732 *p++ = (o->set ? tricat(o->set, o->name, "") : 2733 ztrdup(o->name)); 2734 *p++ = ca_colonlist(*a); 2735 } 2736 *p = NULL; 2737 2738 sethparam(args[2], ret); 2739 } 2740 return 0; 2741 case 'n': 2742 /* 2743 * This returns the array index of the word where normal 2744 * arguments began. It uses optbeg rather than nargbeg 2745 * (the value used when parsing) because nargbeg is assigned 2746 * to optbeg in the returned value and nargbeg isn't 2747 * used. 2748 * 2749 * -->PLEASE DON'T ASK<-- 2750 * 2751 * Thank you. 2752 */ 2753 setiparam(args[1], (zlong)ca_laststate.optbeg + !isset(KSHARRAYS)); 2754 return 0; 2755 } 2756 return 1; 2757} 2758 2759/* Help for `_values'. */ 2760 2761typedef struct cvdef *Cvdef; 2762typedef struct cvval *Cvval; 2763 2764/* Definitions for _values. */ 2765 2766struct cvdef { 2767 char *descr; /* global description */ 2768 int hassep; /* multiple values allowed */ 2769 char sep; /* separator character */ 2770 char argsep; /* argument separator */ 2771 Cvdef next; /* next in cache */ 2772 Cvval vals; /* value definitions */ 2773 char **defs; /* original strings */ 2774 int ndefs; /* number of ... */ 2775 int lastt; /* last time used */ 2776 int words; /* if to look at other words */ 2777}; 2778 2779/* One value definition. */ 2780 2781struct cvval { 2782 Cvval next; 2783 char *name; /* value name */ 2784 char *descr; /* description */ 2785 char **xor; /* xor-list */ 2786 int type; /* CVV_* below */ 2787 Caarg arg; /* argument definition */ 2788 int active; /* still allowed */ 2789}; 2790 2791#define CVV_NOARG 0 2792#define CVV_ARG 1 2793#define CVV_OPT 2 2794 2795/* Cache. */ 2796 2797#define MAX_CVCACHE 8 2798static Cvdef cvdef_cache[MAX_CVCACHE]; 2799 2800/* Memory stuff. */ 2801 2802static void 2803freecvdef(Cvdef d) 2804{ 2805 if (d) { 2806 Cvval p, n; 2807 2808 zsfree(d->descr); 2809 if (d->defs) 2810 freearray(d->defs); 2811 2812 for (p = d->vals; p; p = n) { 2813 n = p->next; 2814 zsfree(p->name); 2815 zsfree(p->descr); 2816 if (p->xor) 2817 freearray(p->xor); 2818 freecaargs(p->arg); 2819 zfree(p, sizeof(*p)); 2820 } 2821 zfree(d, sizeof(*d)); 2822 } 2823} 2824 2825/* Parse option definitions. */ 2826 2827static Cvdef 2828parse_cvdef(char *nam, char **args) 2829{ 2830 Cvdef ret; 2831 Cvval val, *valp; 2832 Caarg arg; 2833 char **oargs = args, sep = '\0', asep = '=', *name, *descr, *p, *q, **xor, c; 2834 int xnum, multi, vtype, hassep = 0, words = 0; 2835 2836 while (args && args[0] && args[1] && 2837 args[0][0] == '-' && 2838 (args[0][1] == 's' || args[0][1] == 'S' || args[0][1] == 'w') && 2839 !args[0][2]) { 2840 2841 if (args[0][1] == 's') { 2842 hassep = 1; 2843 sep = args[1][0]; 2844 args += 2; 2845 } else if (args[0][1] == 'S') { 2846 asep = args[1][0]; 2847 args += 2; 2848 } else { 2849 words = 1; 2850 args++; 2851 } 2852 } 2853 if (!args[0] || !args[1]) { 2854 zwarnnam(nam, "not enough arguments"); 2855 return NULL; 2856 } 2857 descr = *args++; 2858 2859 ret = (Cvdef) zalloc(sizeof(*ret)); 2860 ret->descr = ztrdup(descr); 2861 ret->hassep = hassep; 2862 ret->sep = sep; 2863 ret->argsep = asep; 2864 ret->next = NULL; 2865 ret->vals = NULL; 2866 ret->defs = zarrdup(oargs); 2867 ret->ndefs = arrlen(oargs); 2868 ret->lastt = time(0); 2869 ret->words = words; 2870 2871 for (valp = &(ret->vals); *args; args++) { 2872 int bs = 0; 2873 p = dupstring(*args); 2874 xnum = 0; 2875 2876 /* xor list? */ 2877 if (*p == '(') { 2878 LinkList list = newlinklist(); 2879 LinkNode node; 2880 char **xp, sav; 2881 2882 while (*p && *p != ')') { 2883 for (p++; inblank(*p); p++); 2884 2885 if (*p == ')') 2886 break; 2887 for (q = p++; *p && *p != ')' && !inblank(*p); p++); 2888 2889 if (!*p) 2890 break; 2891 2892 sav = *p; 2893 *p = '\0'; 2894 addlinknode(list, dupstring(q)); 2895 xnum++; 2896 *p = sav; 2897 } 2898 if (*p != ')') { 2899 freecvdef(ret); 2900 zwarnnam(nam, "invalid argument: %s", *args); 2901 return NULL; 2902 } 2903 xor = (char **) zalloc((xnum + 2) * sizeof(char *)); 2904 for (node = firstnode(list), xp = xor; node; incnode(node), xp++) 2905 *xp = ztrdup((char *) getdata(node)); 2906 xp[0] = xp[1] = NULL; 2907 2908 p++; 2909 } else 2910 xor = NULL; 2911 2912 /* More than once allowed? */ 2913 if ((multi = (*p == '*'))) 2914 p++; 2915 2916 /* Skip option name. */ 2917 2918 for (name = p; *p && *p != ':' && *p != '['; p++) 2919 if (*p == '\\' && p[1]) 2920 p++, bs = 1; 2921 2922 if (hassep && !sep && name + bs + 1 < p) { 2923 freecvdef(ret); 2924 zwarnnam(nam, "no multi-letter values with empty separator allowed"); 2925 return NULL; 2926 } 2927 /* Optional description? */ 2928 2929 if ((c = *p) == '[') { 2930 *p = '\0'; 2931 for (descr = ++p; *p && *p != ']'; p++) 2932 if (*p == '\\' && p[1]) 2933 p++; 2934 2935 if (!*p) { 2936 freecvdef(ret); 2937 zwarnnam(nam, "invalid value definition: %s", *args); 2938 return NULL; 2939 } 2940 *p++ = '\0'; 2941 c = *p; 2942 } else { 2943 *p = '\0'; 2944 descr = NULL; 2945 } 2946 if (c && c != ':') { 2947 freecvdef(ret); 2948 zwarnnam(nam, "invalid value definition: %s", *args); 2949 return NULL; 2950 } 2951 /* Get argument? */ 2952 2953 if (c == ':') { 2954 if (hassep && !sep) { 2955 freecvdef(ret); 2956 zwarnnam(nam, "no value with argument with empty separator allowed"); 2957 return NULL; 2958 } 2959 if (*++p == ':') { 2960 p++; 2961 vtype = CVV_OPT; 2962 } else 2963 vtype = CVV_ARG; 2964 arg = parse_caarg(0, 0, 0, 0, name, &p, NULL); 2965 } else { 2966 vtype = CVV_NOARG; 2967 arg = NULL; 2968 } 2969 if (!multi) { 2970 if (!xor) { 2971 xor = (char **) zalloc(2 * sizeof(char *)); 2972 xor[1] = NULL; 2973 } 2974 xor[xnum] = ztrdup(name); 2975 } 2976 *valp = val = (Cvval) zalloc(sizeof(*val)); 2977 valp = &((*valp)->next); 2978 2979 val->next = NULL; 2980 val->name = ztrdup(name); 2981 val->descr = ztrdup(descr); 2982 val->xor = xor; 2983 val->type = vtype; 2984 val->arg = arg; 2985 } 2986 return ret; 2987} 2988 2989/* Get the definition from the cache or newly built. */ 2990 2991static Cvdef 2992get_cvdef(char *nam, char **args) 2993{ 2994 Cvdef *p, *min, new; 2995 int i, na = arrlen(args); 2996 2997 for (i = MAX_CVCACHE, p = cvdef_cache, min = NULL; *p && i--; p++) 2998 if (*p && na == (*p)->ndefs && arrcmp(args, (*p)->defs)) { 2999 (*p)->lastt = time(0); 3000 3001 return *p; 3002 } else if (!min || !*p || (*p)->lastt < (*min)->lastt) 3003 min = p; 3004 if (i > 0) 3005 min = p; 3006 if ((new = parse_cvdef(nam, args))) { 3007 freecvdef(*min); 3008 *min = new; 3009 } 3010 return new; 3011} 3012 3013/* Get the definition for a value. */ 3014 3015static Cvval 3016cv_get_val(Cvdef d, char *name) 3017{ 3018 Cvval p; 3019 3020 for (p = d->vals; p; p = p->next) 3021 if (!strcmp(name, p->name)) 3022 return p; 3023 3024 return NULL; 3025} 3026 3027static Cvval 3028cv_quote_get_val(Cvdef d, char *name) 3029{ 3030 int ne; 3031 3032 /* remove quotes */ 3033 name = dupstring(name); 3034 ne = noerrs; 3035 noerrs = 2; 3036 parse_subst_string(name); 3037 noerrs = ne; 3038 remnulargs(name); 3039 untokenize(name); 3040 3041 return cv_get_val(d, name); 3042} 3043 3044/* Handle a xor list. */ 3045 3046static void 3047cv_inactive(Cvdef d, char **xor) 3048{ 3049 if (xor) { 3050 Cvval val; 3051 3052 for (; *xor; xor++) 3053 if ((val = cv_get_val(d, *xor))) 3054 val->active = 0; 3055 } 3056} 3057 3058/* Parse state. */ 3059 3060struct cvstate { 3061 Cvdef d; 3062 Caarg def; 3063 Cvval val; 3064 LinkList vals; 3065}; 3066 3067static struct cvstate cv_laststate; 3068static int cv_parsed = 0, cv_alloced = 0; 3069 3070/* Get the next value in the string. Return it's definition and update the 3071 * sp pointer to point to the end of the value (plus argument, if any). 3072 * If there is no next value, the string pointer is set to null. In any 3073 * case ap will point to the beginning of the argument or will be a null 3074 * pointer if there is no argument. 3075 */ 3076 3077static Cvval 3078cv_next(Cvdef d, char **sp, char **ap) 3079{ 3080 Cvval r = NULL; 3081 char *s = *sp; 3082 3083 if (!*s) { 3084 *sp = *ap = NULL; 3085 3086 return NULL; 3087 } 3088 if ((d->hassep && !d->sep) || !d->argsep) { 3089 char sav, ec, *v = s, *os; 3090 3091 ec = ((d->hassep && d->sep) ? d->sep : d->argsep); 3092 3093 do { 3094 sav = *++s; 3095 *s = '\0'; 3096 if ((r = cv_quote_get_val(d, v))) { 3097 *s = sav; 3098 3099 break; 3100 } 3101 *s = sav; 3102 } while (*s && *s != ec); 3103 3104 os = s; 3105 3106 if (d->hassep && d->sep) { 3107 if ((s = strchr(s, d->sep))) 3108 *sp = s + 1; 3109 else 3110 *sp = NULL; 3111 } else 3112 *sp = s; 3113 if (d->argsep && *os == d->argsep) { 3114 *ap = os + 1; 3115 *sp = NULL; 3116 } else if (r && r->type != CVV_NOARG) 3117 *ap = os; 3118 else 3119 *ap = NULL; 3120 3121 return r; 3122 3123 } else if (d->hassep) { 3124 char *ns = strchr(s, d->sep), *as = 0, *sap, sav = 0; 3125 int skip = 0; 3126 3127 if (d->argsep && (as = strchr(s, d->argsep)) && (!ns || as <= ns)) { 3128 *ap = as + 1; 3129 ns = strchr(as + 1, d->sep); 3130 skip = 1; 3131 sap = as; 3132 } else { 3133 *ap = NULL; 3134 sap = ns; 3135 } 3136 if (sap) { 3137 sav = *sap; 3138 *sap = '\0'; 3139 } 3140 if ((!(r = cv_quote_get_val(d, s)) || r->type == CVV_NOARG) && skip) 3141 ns = as; 3142 3143 if (sap) 3144 *sap = sav; 3145 3146 *sp = ((!ns || (ns == as && r && r->type != CVV_NOARG)) ? NULL : ns + 1); 3147 3148 return r; 3149 } else { 3150 char *as = strchr(s, d->argsep), *sap, sav = 0; 3151 3152 *sp = NULL; 3153 3154 if (as) { 3155 *ap = as + 1; 3156 sap = as; 3157 sav = *as; 3158 *sap = '\0'; 3159 } else 3160 *ap = sap = NULL; 3161 3162 r = cv_quote_get_val(d, s); 3163 3164 if (sap) 3165 *sap = sav; 3166 3167 return r; 3168 } 3169} 3170 3171/* Parse the current word. */ 3172 3173static void 3174cv_parse_word(Cvdef d) 3175{ 3176 Cvval val; 3177 struct cvstate state; 3178 char *str, *arg = NULL, *pign = compprefix; 3179 int nosfx = 0; 3180 3181 if (cv_alloced) 3182 freelinklist(cv_laststate.vals, freestr); 3183 3184 for (val = d->vals; val; val = val->next) 3185 val->active = 1; 3186 3187 state.d = d; 3188 state.def = NULL; 3189 state.val = NULL; 3190 state.vals = (LinkList) znewlinklist(); 3191 3192 cv_alloced = 1; 3193 3194 if (d->words && compwords[0]) { 3195 int i; 3196 3197 for (i = 1; compwords[i]; i++) 3198 if (i != compcurrent - 1) 3199 for (str = compwords[i]; str && *str; ) { 3200 if ((val = cv_next(d, &str, &arg))) { 3201 zaddlinknode(state.vals, ztrdup(val->name)); 3202 if (arg) { 3203 char sav = '\0'; 3204 3205 if (str) { 3206 sav = str[-1]; 3207 str[-1] = '\0'; 3208 } 3209 zaddlinknode(state.vals, ztrdup(arg)); 3210 if (str) 3211 str[-1] = sav; 3212 } else 3213 zaddlinknode(state.vals, ztrdup("")); 3214 3215 if (i + 1 < compcurrent) 3216 cv_inactive(d, val->xor); 3217 } 3218 } 3219 3220 val = NULL; 3221 arg = NULL; 3222 } 3223 for (str = compprefix; str && *str; ) { 3224 if ((val = cv_next(d, &str, &arg))) { 3225 zaddlinknode(state.vals, ztrdup(val->name)); 3226 if (arg) { 3227 if (str) { 3228 char sav = str[-1]; 3229 3230 str[-1] = '\0'; 3231 zaddlinknode(state.vals, ztrdup(arg)); 3232 str[-1] = sav; 3233 } else { 3234 zaddlinknode(state.vals, tricat(arg, compsuffix, "")); 3235 nosfx = 1; 3236 } 3237 } else 3238 zaddlinknode(state.vals, ztrdup("")); 3239 3240 cv_inactive(d, val->xor); 3241 3242 if (str) 3243 pign = str; 3244 else 3245 val->active = 1; 3246 } 3247 } 3248 state.val = val; 3249 if (val && arg && !str) 3250 state.def = val->arg; 3251 3252 if (!nosfx && d->hassep) { 3253 int ign = 0; 3254 char *more = NULL; 3255 3256 ignore_prefix(pign - compprefix); 3257 3258 if (!d->sep && (!val || val->type == CVV_NOARG)) { 3259 ign = strlen(compsuffix); 3260 more = compsuffix; 3261 } else { 3262 if (d->sep) { 3263 char *ns = strchr(compsuffix, d->sep), *as; 3264 3265 if (d->argsep && (as = strchr(compsuffix, d->argsep)) && 3266 (!ns || as <= ns)) { 3267 ign = strlen(as); 3268 } else 3269 ign = (ns ? strlen(ns) : 0); 3270 3271 more = (ns ? ns + 1 : NULL); 3272 } else if (d->argsep) { 3273 char *as; 3274 3275 if ((as = strchr(compsuffix, d->argsep))) 3276 ign = strlen(as); 3277 } 3278 } 3279 more = dupstring(more); 3280 3281 if (ign) 3282 ignore_suffix(ign); 3283 3284 while (more && *more) { 3285 if ((val = cv_next(d, &more, &arg))) { 3286 zaddlinknode(state.vals, ztrdup(val->name)); 3287 if (arg) { 3288 if (more) { 3289 char sav = more[-1]; 3290 3291 more[-1] = '\0'; 3292 zaddlinknode(state.vals, ztrdup(arg)); 3293 more[-1] = sav; 3294 } else { 3295 zaddlinknode(state.vals, tricat(arg, compsuffix, "")); 3296 nosfx = 1; 3297 } 3298 } else 3299 zaddlinknode(state.vals, ztrdup("")); 3300 3301 cv_inactive(d, val->xor); 3302 } 3303 } 3304 } else if (arg) 3305 ignore_prefix(arg - compprefix); 3306 else 3307 ignore_prefix(pign - compprefix); 3308 3309 memcpy(&cv_laststate, &state, sizeof(state)); 3310} 3311 3312static int 3313bin_compvalues(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 3314{ 3315 int min, max, n; 3316 3317 if (incompfunc != 1) { 3318 zwarnnam(nam, "can only be called from completion function"); 3319 return 1; 3320 } 3321 if (args[0][0] != '-' || !args[0][1] || args[0][2]) { 3322 zwarnnam(nam, "invalid argument: %s", args[0]); 3323 return 1; 3324 } 3325 if (args[0][1] != 'i' && !cv_parsed) { 3326 zwarnnam(nam, "no parsed state"); 3327 return 1; 3328 } 3329 switch (args[0][1]) { 3330 case 'i': min = 2; max = -1; break; 3331 case 'D': min = 2; max = 2; break; 3332 case 'C': min = 1; max = 1; break; 3333 case 'V': min = 3; max = 3; break; 3334 case 's': min = 1; max = 1; break; 3335 case 'S': min = 1; max = 1; break; 3336 case 'd': min = 1; max = 1; break; 3337 case 'L': min = 3; max = 4; break; 3338 case 'v': min = 1; max = 1; break; 3339 default: 3340 zwarnnam(nam, "invalid option: %s", args[0]); 3341 return 1; 3342 } 3343 n = arrlen(args) - 1; 3344 if (n < min) { 3345 zwarnnam(nam, "not enough arguments"); 3346 return 1; 3347 } else if (max >= 0 && n > max) { 3348 zwarnnam(nam, "too many arguments"); 3349 return 1; 3350 } 3351 switch (args[0][1]) { 3352 case 'i': 3353 /* This initialises the internal data structures. The arguments are 3354 * just the arguments that were given to _values itself. */ 3355 { 3356 Cvdef def = get_cvdef(nam, args + 1); 3357 int cvp = cv_parsed; 3358 3359 cv_parsed = 0; 3360 3361 if (!def) 3362 return 1; 3363 3364 cv_parsed = cvp; 3365 cv_parse_word(def); 3366 cv_parsed = 1; 3367 3368 return 0; 3369 } 3370 3371 case 'D': 3372 /* This returns the description and action to use if we are at 3373 * a place where some action has to be used at all. In that case 3374 * zero is returned and non-zero otherwise. */ 3375 { 3376 Caarg arg = cv_laststate.def; 3377 3378 if (arg) { 3379 setsparam(args[1], ztrdup(arg->descr)); 3380 setsparam(args[2], ztrdup(arg->action)); 3381 3382 return 0; 3383 } 3384 return 1; 3385 } 3386 case 'C': 3387 /* This returns the sub-context (i.e.: the tag) to use when executing 3388 * an action. */ 3389 { 3390 Caarg arg = cv_laststate.def; 3391 3392 if (arg) { 3393 setsparam(args[1], ztrdup(arg->opt)); 3394 3395 return 0; 3396 } 3397 return 1; 3398 } 3399 case 'V': 3400 /* This is what -O is for comparguments: it returns (in three arrays) 3401 * the values for values without arguments, with arguments and with 3402 * optional arguments (so that we can get the auto-suffixes right). 3403 * As for comparguments, the strings returned are usable for _describe. */ 3404 { 3405 LinkList noarg = newlinklist(); 3406 LinkList arg = newlinklist(); 3407 LinkList opt = newlinklist(), l; 3408 Cvval p; 3409 char *str; 3410 3411 for (p = cv_laststate.d->vals; p; p = p->next) { 3412 if (p->active) { 3413 switch (p->type) { 3414 case CVV_NOARG: l = noarg; break; 3415 case CVV_ARG: l = arg; break; 3416 default: l = opt; break; 3417 } 3418 if (p->descr) { 3419 int len = strlen(p->name) + strlen(p->descr) + 2; 3420 3421 str = (char *) zhalloc(len); 3422 strcpy(str, p->name); 3423 strcat(str, ":"); 3424 strcat(str, p->descr); 3425 } else 3426 str = p->name; 3427 addlinknode(l, str); 3428 } 3429 } 3430 set_list_array(args[1], noarg); 3431 set_list_array(args[2], arg); 3432 set_list_array(args[3], opt); 3433 3434 return 0; 3435 } 3436 case 's': 3437 /* This returns the value separator, if any, and sets the return 3438 * value to say if there is such a separator. */ 3439 if (cv_laststate.d->hassep) { 3440 char tmp[2]; 3441 3442 tmp[0] = cv_laststate.d->sep; 3443 tmp[1] = '\0'; 3444 setsparam(args[1], ztrdup(tmp)); 3445 3446 return 0; 3447 } 3448 return 1; 3449 case 'S': 3450 /* Like -s, but for the separator between values and their arguments. */ 3451 { 3452 char tmp[2]; 3453 3454 tmp[0] = cv_laststate.d->argsep; 3455 tmp[1] = '\0'; 3456 setsparam(args[1], ztrdup(tmp)); 3457 } 3458 return 0; 3459 case 'd': 3460 /* This returns the description string (first argument to _values) 3461 * which is passed down to _describe. */ 3462 setsparam(args[1], ztrdup(cv_laststate.d->descr)); 3463 return 0; 3464 case 'L': 3465 /* Almost the same as for comparguments. This gets a value name 3466 * and returns the description and action of its first argument, if 3467 * any. The rest (prefix matching) is in _values. Return non-zero 3468 * if there is no such option. */ 3469 { 3470 Cvval val = cv_get_val(cv_laststate.d, args[1]); 3471 3472 if (val && val->arg) { 3473 setsparam(args[2], val->arg->descr); 3474 setsparam(args[3], val->arg->action); 3475 3476 if (args[4]) 3477 setsparam(args[4], ztrdup(val->name)); 3478 3479 return 0; 3480 } 3481 return 1; 3482 } 3483 case 'v': 3484 /* Again, as for comparguments. This returns the values and their 3485 * arguments as an array which will be stored in val_args in _values. */ 3486 if (cv_laststate.vals) { 3487 char **ret; 3488 3489 ret = zlinklist2array(cv_laststate.vals); 3490 sethparam(args[1], ret); 3491 3492 return 0; 3493 } 3494 return 1; 3495 } 3496 return 1; 3497} 3498 3499static char * 3500comp_quote(char *str, int prefix) 3501{ 3502 int x; 3503 char *ret; 3504 3505 if ((x = (prefix && *str == '='))) 3506 *str = 'x'; 3507 3508 ret = quotestring(str, NULL, *compqstack); 3509 3510 if (x) 3511 *str = *ret = '='; 3512 3513 return ret; 3514} 3515 3516static int 3517bin_compquote(char *nam, char **args, Options ops, UNUSED(int func)) 3518{ 3519 char *name; 3520 struct value vbuf; 3521 Value v; 3522 3523 if (incompfunc != 1) { 3524 zwarnnam(nam, "can only be called from completion function"); 3525 return 1; 3526 } 3527 /* Anything to do? */ 3528 3529 if (!compqstack || !*compqstack) 3530 return 0; 3531 3532 /* For all parameters given... */ 3533 3534 while ((name = *args++)) { 3535 name = dupstring(name); 3536 queue_signals(); 3537 if ((v = getvalue(&vbuf, &name, 0))) { 3538 switch (PM_TYPE(v->pm->node.flags)) { 3539 case PM_SCALAR: 3540 setstrvalue(v, ztrdup(comp_quote(getstrvalue(v), 3541 OPT_ISSET(ops,'p')))); 3542 break; 3543 case PM_ARRAY: 3544 { 3545 char **val = v->pm->gsu.a->getfn(v->pm); 3546 char **new = (char **) zalloc((arrlen(val) + 1) * 3547 sizeof(char *)); 3548 char **p = new; 3549 3550 for (; *val; val++, p++) 3551 *p = ztrdup(comp_quote(*val, OPT_ISSET(ops,'p'))); 3552 *p = NULL; 3553 3554 setarrvalue(v, new); 3555 } 3556 break; 3557 default: 3558 zwarnnam(nam, "invalid parameter type: %s", args[-1]); 3559 } 3560 } else 3561 zwarnnam(nam, "unknown parameter: %s", args[-1]); 3562 unqueue_signals(); 3563 } 3564 return 0; 3565} 3566 3567/* Tags stuff. */ 3568 3569typedef struct ctags *Ctags; 3570typedef struct ctset *Ctset; 3571 3572/* A bunch of tag sets. */ 3573 3574struct ctags { 3575 char **all; /* all tags offered */ 3576 char *context; /* the current context */ 3577 int init; /* not yet used */ 3578 Ctset sets; /* the tag sets */ 3579}; 3580 3581/* A tag set. */ 3582 3583struct ctset { 3584 Ctset next; 3585 char **tags; /* the tags */ 3586 char *tag; /* last tag checked for -A */ 3587 char **ptr; /* ptr into tags for -A */ 3588}; 3589 3590/* Array of tag-set infos. Index is the locallevel. */ 3591 3592#define MAX_TAGS 256 3593static Ctags comptags[MAX_TAGS]; 3594 3595/* locallevel at last comptags -i */ 3596 3597static int lasttaglevel; 3598 3599static void 3600freectset(Ctset s) 3601{ 3602 Ctset n; 3603 3604 while (s) { 3605 n = s->next; 3606 3607 if (s->tags) 3608 freearray(s->tags); 3609 zsfree(s->tag); 3610 zfree(s, sizeof(*s)); 3611 3612 s = n; 3613 } 3614} 3615 3616static void 3617freectags(Ctags t) 3618{ 3619 if (t) { 3620 if (t->all) 3621 freearray(t->all); 3622 zsfree(t->context); 3623 freectset(t->sets); 3624 zfree(t, sizeof(*t)); 3625 } 3626} 3627 3628/* Set the tags for the current local level. */ 3629 3630static void 3631settags(int level, char **tags) 3632{ 3633 Ctags t; 3634 3635 if (comptags[level]) 3636 freectags(comptags[level]); 3637 3638 comptags[level] = t = (Ctags) zalloc(sizeof(*t)); 3639 3640 t->all = zarrdup(tags + 1); 3641 t->context = ztrdup(*tags); 3642 t->sets = NULL; 3643 t->init = 1; 3644} 3645 3646/* Check if an array contains a string. */ 3647 3648/**/ 3649static int 3650arrcontains(char **a, char *s, int colon) 3651{ 3652 char *p, *q; 3653 3654 while (*a) { 3655 if (colon) { 3656 for (p = s, q = *a++; *p && *q && *p != ':' && *q != ':'; p++, q++) 3657 if (*p != *q) 3658 break; 3659 if ((!*p || *p == ':') && (!*q || *q == ':')) 3660 return 1; 3661 } else if (!strcmp(*a++, s)) 3662 return 1; 3663 } 3664 return 0; 3665} 3666 3667static int 3668bin_comptags(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 3669{ 3670 int min, max, n, level; 3671 3672 if (incompfunc != 1) { 3673 zwarnnam(nam, "can only be called from completion function"); 3674 return 1; 3675 } 3676 if (args[0][0] != '-' || !args[0][1] || 3677 (args[0][2] && (args[0][2] != '-' || args[0][3]))) { 3678 zwarnnam(nam, "invalid argument: %s", args[0]); 3679 return 1; 3680 } 3681 level = locallevel - (args[0][2] ? 1 : 0); 3682 if (level >= MAX_TAGS) { 3683 zwarnnam(nam, "nesting level too deep"); 3684 return 1; 3685 } 3686 if (args[0][1] != 'i' && args[0][1] != 'I' && !comptags[level]) { 3687 zwarnnam(nam, "no tags registered"); 3688 return 1; 3689 } 3690 switch (args[0][1]) { 3691 case 'i': min = 2; max = -1; break; 3692 case 'C': min = 1; max = 1; break; 3693 case 'T': min = 0; max = 0; break; 3694 case 'N': min = 0; max = 0; break; 3695 case 'R': min = 1; max = 1; break; 3696 case 'S': min = 1; max = 1; break; 3697 case 'A': min = 2; max = 3; break; 3698 default: 3699 zwarnnam(nam, "invalid option: %s", args[0]); 3700 return 1; 3701 } 3702 n = arrlen(args) - 1; 3703 if (n < min) { 3704 zwarnnam(nam, "not enough arguments"); 3705 return 1; 3706 } else if (max >= 0 && n > max) { 3707 zwarnnam(nam, "too many arguments"); 3708 return 1; 3709 } 3710 switch (args[0][1]) { 3711 case 'i': 3712 settags(level, args + 1); 3713 lasttaglevel = level; 3714 break; 3715 case 'C': 3716 setsparam(args[1], ztrdup(comptags[level]->context)); 3717 break; 3718 case 'T': 3719 return !comptags[level]->sets; 3720 case 'N': 3721 { 3722 Ctset s; 3723 3724 if (comptags[level]->init) 3725 comptags[level]->init = 0; 3726 else if ((s = comptags[level]->sets)) { 3727 comptags[level]->sets = s->next; 3728 s->next = NULL; 3729 freectset(s); 3730 } 3731 return !comptags[level]->sets; 3732 } 3733 case 'R': 3734 { 3735 Ctset s; 3736 3737 return !((s = comptags[level]->sets) && 3738 arrcontains(s->tags, args[1], 1)); 3739 } 3740 case 'A': 3741 { 3742 Ctset s; 3743 3744 if (comptags[level] && (s = comptags[level]->sets)) { 3745 char **q, *v = NULL; 3746 int l = strlen(args[1]); 3747 3748 if (!s->tag || strcmp(s->tag, args[1])) { 3749 zsfree(s->tag); 3750 s->tag = ztrdup(args[1]); 3751 s->ptr = s->tags; 3752 } 3753 for (q = s->ptr; *q; q++) { 3754 if (strpfx(args[1], *q)) { 3755 if (!(*q)[l]) { 3756 v = *q; 3757 break; 3758 } else if ((*q)[l] == ':') { 3759 v = (*q) + l + 1; 3760 break; 3761 } 3762 } 3763 } 3764 if (!v) { 3765 zsfree(s->tag); 3766 s->tag = NULL; 3767 return 1; 3768 } 3769 s->ptr = q + 1; 3770 setsparam(args[2], ztrdup(*v == '-' ? dyncat(args[1], v) : v)); 3771 if (args[3]) { 3772 char *r = dupstring(*q), *p; 3773 3774 for (p = r + (v - *q); *p && *p != ':'; p++); 3775 *p = '\0'; 3776 3777 setsparam(args[3], ztrdup(r)); 3778 } 3779 return 0; 3780 } 3781 return 1; 3782 } 3783 case 'S': 3784 if (comptags[level]->sets) { 3785 char **ret; 3786 3787 ret = zarrdup(comptags[level]->sets->tags); 3788 setaparam(args[1], ret); 3789 } else 3790 return 1; 3791 3792 break; 3793 } 3794 return 0; 3795} 3796 3797static int 3798bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 3799{ 3800 if (incompfunc != 1) { 3801 zwarnnam(nam, "can only be called from completion function"); 3802 return 1; 3803 } 3804 if (!lasttaglevel || !comptags[lasttaglevel]) { 3805 zwarnnam(nam, "no tags registered"); 3806 return 1; 3807 } 3808 if (*args) { 3809 if (!strcmp(*args, "-m")) { 3810 char *s, *p, *q, *c, **all = comptags[lasttaglevel]->all; 3811 LinkList list = newlinklist(); 3812 int num = 0; 3813 Ctset set; 3814 3815 while ((s = *++args)) { 3816 while (*s) { 3817 while (*s && iblank(*s)) 3818 s++; 3819 for (p = q = s, c = NULL; *s && !inblank(*s); s++) { 3820 if (!c && *s == ':') 3821 c = p; 3822 if (*s == '\\' && s[1]) 3823 s++; 3824 *p++ = *s; 3825 } 3826 if (*s) 3827 s++; 3828 *p = '\0'; 3829 if (*q) { 3830 char *qq, *qqq; 3831 3832 if (c) 3833 *c = '\0'; 3834 3835 qqq = qq = dupstring(q); 3836 while (*qqq) { 3837 if (*qqq == '\\' && qqq[1]) 3838 qqq++; 3839 else if (*qqq == '{') 3840 *qqq = Inbrace; 3841 else if (*qqq == '}') 3842 *qqq = Outbrace; 3843 else if (*qqq == ',') 3844 *qqq = Comma; 3845 qqq++; 3846 } 3847 tokenize(qq); 3848 if (haswilds(qq) || hasbraces(qq)) { 3849 Patprog prog; 3850 LinkNode bnode, node; 3851 LinkList blist = newlinklist(); 3852 3853 addlinknode(blist, qq); 3854 for (bnode = firstnode(blist); bnode; incnode(bnode)) 3855 while (hasbraces(getdata(bnode))) 3856 xpandbraces(blist, &bnode); 3857 3858 for (bnode = firstnode(blist); bnode; incnode(bnode)) { 3859 qq = (char *) getdata(bnode); 3860 if ((prog = patcompile(qq, PAT_STATIC, NULL))) { 3861 char **a, *n; 3862 int l = (c ? strlen(c + 1) + 2 : 1), al; 3863 3864 for (a = all; *a; a++) { 3865 for (node = firstnode(list); node; 3866 incnode(node)) { 3867 char *as, *ls; 3868 3869 for (as = *a, ls = (char *) getdata(node); 3870 *as && *ls && *ls != ':'; as++, ls++) 3871 if (*as != *ls) 3872 break; 3873 if (!*as && (!*ls || *ls == ':')) 3874 break; 3875 } 3876 if (node) 3877 continue; 3878 if (pattry(prog, *a)) { 3879 n = (char *) zhalloc((al = strlen(*a)) + l); 3880 strcpy(n, *a); 3881 if (c) { 3882 n[al] = ':'; 3883 strcpy(n + al + 1, c + 1); 3884 } 3885 addlinknode(list, n); 3886 num++; 3887 } 3888 } 3889 } 3890 } 3891 } else if (arrcontains(all, q, 0)) { 3892 for (set = comptags[lasttaglevel]->sets; set; 3893 set = set->next) 3894 if (arrcontains(set->tags, q, 0)) 3895 break; 3896 if (!set) { 3897 addlinknode(list, q); 3898 num++; 3899 } 3900 } 3901 if (c) 3902 *c = ':'; 3903 } 3904 } 3905 if (num) { 3906 Ctset l; 3907 3908 set = (Ctset) zalloc(sizeof(*set)); 3909 3910 set->tags = zlinklist2array(list); 3911 set->next = NULL; 3912 set->ptr = NULL; 3913 set->tag = NULL; 3914 3915 if ((l = comptags[lasttaglevel]->sets)) { 3916 while (l->next) 3917 l = l->next; 3918 3919 l->next = set; 3920 } else 3921 comptags[lasttaglevel]->sets = set; 3922 } 3923 } 3924 } else { 3925 char **p, **q, **all; 3926 int sep = 0; 3927 3928 if ((sep = !strcmp(*args, "-s"))) 3929 args++; 3930 3931 for (p = q = args, all = comptags[lasttaglevel]->all; *p; p++) 3932 if (arrcontains(all, *p, 1)) { 3933 Ctset s; 3934 3935 for (s = comptags[lasttaglevel]->sets; s; s = s->next) 3936 if (arrcontains(s->tags, *p, 0)) 3937 break; 3938 3939 if (!s) 3940 *q++ = *p; 3941 } 3942 *q = NULL; 3943 3944 if (*args) { 3945 char *dummy[2]; 3946 3947 do { 3948 Ctset s = (Ctset) zalloc(sizeof(*s)), l; 3949 3950 if (sep) { 3951 dummy[0] = *args++; 3952 dummy[1] = NULL; 3953 s->tags = zarrdup(dummy); 3954 } else 3955 s->tags = zarrdup(args); 3956 s->next = NULL; 3957 s->ptr = NULL; 3958 s->tag = NULL; 3959 3960 if ((l = comptags[lasttaglevel]->sets)) { 3961 while (l->next) 3962 l = l->next; 3963 3964 l->next = s; 3965 } else 3966 comptags[lasttaglevel]->sets = s; 3967 } while (sep && *args); 3968 } 3969 } 3970 } 3971 return 0; 3972} 3973 3974#define PATH_MAX2 (PATH_MAX * 2) 3975 3976/* 3977 * Return a list of files we should accept exactly, without 3978 * trying pattern matching. 3979 * 3980 * This is based on the accept-exact style, which may be 3981 * an array so is passed in via "accept". The trial files 3982 * are input in "names". "skipped" is passed down straight 3983 * from the file completion function: it's got something to 3984 * do with other components in the path but it's hard to work out 3985 * quite what. 3986 * 3987 * There is one extra trick here for Cygwin. Regardless of the style, 3988 * if the file ends in a colon it has to be a drive or a special device 3989 * file and we always accept it exactly because treating it as a pattern 3990 * won't work. 3991 */ 3992static LinkList 3993cfp_test_exact(LinkList names, char **accept, char *skipped) 3994{ 3995 char buf[PATH_MAX2 + 1], *suf, *p; 3996 int l, sl, found = 0; 3997 struct stat st; 3998 LinkNode node; 3999 LinkList ret = newlinklist(), alist = NULL; 4000#ifdef __CYGWIN__ 4001 int accept_off = 0; 4002#endif 4003 4004 /* 4005 * Don't do this unless completion has provided either a 4006 * prefix or suffix from the command line. 4007 */ 4008 if (!(compprefix && *compprefix) && !(compsuffix && *compsuffix)) 4009 return NULL; 4010 4011 /* 4012 * See if accept-exact is off, implicitly or explicitly. 4013 */ 4014 if (!accept || !*accept || 4015 ((!strcmp(*accept, "false") || !strcmp(*accept, "no") || 4016 !strcmp(*accept, "off") || !strcmp(*accept, "0")) && !accept[1])) { 4017#ifdef __CYGWIN__ 4018 accept_off = 1; 4019#else 4020 /* If not Cygwin, nothing to do here. */ 4021 return NULL; 4022#endif 4023 } 4024 4025 /* 4026 * See if the style is something other than just a boolean. 4027 */ 4028 if ( 4029#ifdef __CYGWIN__ 4030 !accept_off && 4031#endif 4032 (accept[1] || 4033 (strcmp(*accept, "true") && strcmp(*accept, "yes") && 4034 strcmp(*accept, "on") && strcmp(*accept, "1")))) { 4035 Patprog prog; 4036 4037 alist = newlinklist(); 4038 4039 for (; (p = *accept); accept++) { 4040 if (*p == '*' && !p[1]) { 4041 alist = NULL; 4042 break; 4043 } 4044 tokenize(p = dupstring(p)); 4045 if ((prog = patcompile(p, 0, NULL))) 4046 addlinknode(alist, prog); 4047 } 4048 } 4049 /* 4050 * Assemble the bits other than the set of file names: 4051 * the other components, and the prefix and suffix. 4052 */ 4053 sl = strlen(skipped) + (compprefix ? strlen(compprefix) : 0) + 4054 (compsuffix ? strlen(compsuffix) : 0); 4055 4056 if (sl > PATH_MAX2) 4057 return NULL; 4058 4059 suf = dyncat(skipped, rembslash(dyncat(compprefix, compsuffix))); 4060 4061 for (node = firstnode(names); node; incnode(node)) { 4062 l = strlen(p = (char *) getdata(node)); 4063 if (l + sl < PATH_MAX2) { 4064#ifdef __CYGWIN__ 4065 char *testbuf; 4066#define TESTBUF testbuf 4067#else 4068#define TESTBUF buf 4069#endif 4070 strcpy(buf, p); 4071 strcpy(buf + l, suf); 4072#ifdef __CYGWIN__ 4073 if (accept_off) { 4074 int sl = strlen(buf); 4075 /* 4076 * If accept-exact is not set, accept this only if 4077 * it looks like a special file such as a drive. 4078 * We still test if it exists. 4079 */ 4080 if (!sl || strchr(buf, '/') || buf[sl-1] != ':') 4081 continue; 4082 if (sl == 2) { 4083 /* 4084 * Recent versions of Cygwin only recognise "c:/", 4085 * but not "c:", as special directories. So 4086 * we have to append the slash for the purpose of 4087 * the test. 4088 */ 4089 testbuf = zhalloc(sl + 2); 4090 strcpy(testbuf, buf); 4091 testbuf[sl] = '/'; 4092 testbuf[sl+1] = '\0'; 4093 } else { 4094 /* Don't do this with stuff like PRN: */ 4095 testbuf = buf; 4096 } 4097 } else { 4098 testbuf = buf; 4099 } 4100#endif 4101 if (!ztat(TESTBUF, &st, 0)) { 4102 /* 4103 * File exists; if accept-exact contained non-boolean 4104 * values it must match those, too. 4105 */ 4106 if (alist) { 4107 LinkNode anode; 4108 4109 for (anode = firstnode(alist); anode; incnode(anode)) 4110 if (pattry((Patprog) getdata(anode), buf)) 4111 break; 4112 4113 if (!anode) 4114 continue; 4115 } 4116 found = 1; 4117 addlinknode(ret, dupstring(buf)); 4118 } 4119 } 4120 } 4121 return (found ? ret : NULL); 4122} 4123 4124 4125/* 4126 * This code constructs (from heap) and returns a string that 4127 * corresponds to a series of matches; when compiled as a pattern, at 4128 * each position it matches either the character from the string "add" 4129 * or the corresponding single-character match from the set of matchers. 4130 * To take a simple case, if add is "a" and the single matcher for the 4131 * character position matches "[0-9]", the pattern returned is "[0-9a]". 4132 * We take account of equivalences between the word and line, too. 4133 * 4134 * As there are virtually no comments in this file, I don't really 4135 * know why we're doing this, but it's to do with a matcher which 4136 * is passed as an argument to the utility compfiles -p/-P. 4137 */ 4138static char * 4139cfp_matcher_range(Cmatcher *ms, char *add) 4140{ 4141 Cmatcher *mp, m; 4142 int len = 0, mt; 4143 char *ret = NULL, *p = NULL, *adds = add; 4144 4145 /* 4146 * Do this twice: once to work out the length of the 4147 * string in len, the second time to build it in ret. 4148 * This is probably worthwhile because otherwise memory 4149 * management is difficult. 4150 */ 4151 for (;;) { 4152 MB_METACHARINIT(); 4153 for (mp = ms; *add; ) { 4154 convchar_t addc; 4155 int addlen; 4156 4157 addlen = MB_METACHARLENCONV(add, &addc); 4158#ifdef MULTIBYTE_SUPPORT 4159 if (addc == WEOF) 4160 addc = (wchar_t)(*p == Meta ? p[1] ^ 32 : *p); 4161#endif 4162 4163 if (!(m = *mp)) { 4164 /* 4165 * No matcher, so just match the character 4166 * itself. 4167 * 4168 * TODO: surely this needs quoting if it's a 4169 * metacharacter? 4170 */ 4171 if (ret) { 4172 memcpy(p, add, addlen); 4173 p += addlen; 4174 } else 4175 len += addlen; 4176 } else if (m->flags & CMF_RIGHT) { 4177 /* 4178 * Right-anchored: match anything followed 4179 * by the character itself. 4180 */ 4181 if (ret) { 4182 *p++ = '*'; 4183 /* TODO: quote again? */ 4184 memcpy(p, add, addlen); 4185 p += addlen; 4186 } else 4187 len += addlen + 1; 4188 } else { 4189 /* The usual set of matcher possibilities. */ 4190 convchar_t ind; 4191 if (m->line->tp == CPAT_EQUIV && 4192 m->word->tp == CPAT_EQUIV) { 4193 /* 4194 * Genuine equivalence. Add the character to match 4195 * and the equivalent character from the word 4196 * pattern. 4197 * 4198 * TODO: we could be more careful here with special 4199 * cases as we are in the basic character class 4200 * code below. 4201 */ 4202 if (ret) { 4203 *p++ = '['; 4204 memcpy(p, add, addlen); 4205 p += addlen; 4206 } else 4207 len += addlen + 1; 4208 if (PATMATCHRANGE(m->line->u.str, addc, &ind, &mt)) { 4209 /* 4210 * Find the equivalent match for ind in the 4211 * word pattern. 4212 */ 4213 if ((ind = pattern_match_equivalence 4214 (m->word, ind, mt, addc)) != CHR_INVALID) { 4215 if (ret) { 4216 if (imeta(ind)) { 4217 *p++ = Meta; 4218 *p++ = ind ^ 32; 4219 } else 4220 *p++ = ind; 4221 } else 4222 len += imeta(ind) ? 2 : 1; 4223 } 4224 } 4225 if (ret) 4226 *p++ = ']'; 4227 else 4228 len++; 4229 } else { 4230 int newlen, addadd; 4231 4232 switch (m->word->tp) { 4233 case CPAT_NCLASS: 4234 /* 4235 * TODO: the old logic implies that we need to 4236 * match *add, i.e. it should be deleted from 4237 * the set of character's we're not allowed to 4238 * match. That's too much like hard work for 4239 * now. Indeed, in general it's impossible 4240 * without trickery. Consider *add == 'A', 4241 * range == "[^[:upper:]]": we would have to 4242 * resort to something like "(A|[^[:upper:]])"; 4243 * and in an expression like that *add may or 4244 * may not need backslashing. So we're deep 4245 * into see-if-we-can-get-away-without 4246 * territory. 4247 */ 4248 if (ret) { 4249 *p++ = '['; 4250 *p++ = '^'; 4251 } else 4252 len += 2; 4253 /* 4254 * Convert the compiled range string back 4255 * to an ordinary string. 4256 */ 4257 newlen = 4258 pattern_range_to_string(m->word->u.str, p); 4259 DPUTS(!newlen, "empty character range"); 4260 if (ret) { 4261 p += newlen; 4262 *p++ = ']'; 4263 } else 4264 len += newlen + 1; 4265 break; 4266 4267 case CPAT_CCLASS: 4268 /* 4269 * If there is an equivalence only on one 4270 * side it's not equivalent to anything. 4271 * Treat it as an ordinary character class. 4272 */ 4273 case CPAT_EQUIV: 4274 case CPAT_CHAR: 4275 if (ret) 4276 *p++ = '['; 4277 else 4278 len++; 4279 /* 4280 * We needed to add *add specially only if 4281 * it is not covered by the range. This 4282 * is necessary for correct syntax---consider 4283 * if *add is ] and ] is also the first 4284 * character in the range. 4285 */ 4286 addadd = !pattern_match1(m->word, addc, &mt); 4287 if (addadd && *add == ']') { 4288 if (ret) 4289 *p++ = *add; 4290 else 4291 len++; 4292 } 4293 if (m->word->tp == CPAT_CHAR) { 4294 /* 4295 * The matcher just matches a single 4296 * character, but we need to be able 4297 * to match *add, too, hence we do 4298 * this as a [...]. 4299 */ 4300 if (ret) { 4301 if (imeta(m->word->u.chr)) { 4302 *p++ = Meta; 4303 *p++ = m->word->u.chr ^ 32; 4304 } else 4305 *p++ = m->word->u.chr; 4306 } else 4307 len += imeta(m->word->u.chr) ? 2 : 1; 4308 } else { 4309 /* 4310 * Convert the compiled range string back 4311 * to an ordinary string. 4312 */ 4313 newlen = 4314 pattern_range_to_string(m->word->u.str, p); 4315 DPUTS(!newlen, "empty character range"); 4316 if (ret) 4317 p += newlen; 4318 else 4319 len += newlen; 4320 } 4321 if (addadd && *add != ']') { 4322 if (ret) { 4323 memcpy(p, add, addlen); 4324 p += addlen; 4325 } else 4326 len += addlen; 4327 } 4328 if (ret) 4329 *p++ = ']'; 4330 else 4331 len++; 4332 break; 4333 4334 case CPAT_ANY: 4335 if (ret) 4336 *p++ = '?'; 4337 else 4338 len++; 4339 break; 4340 } 4341 } 4342 } 4343 add += addlen; 4344 mp++; 4345 } 4346 if (ret) { 4347 *p = '\0'; 4348 return ret; 4349 } 4350 p = ret = zhalloc(len + 1); 4351 add = adds; 4352 } 4353} 4354 4355 4356static char * 4357cfp_matcher_pats(char *matcher, char *add) 4358{ 4359 Cmatcher m = parse_cmatcher(NULL, matcher); 4360 4361 if (m && m != pcm_err) { 4362 char *tmp; 4363 int al = strlen(add), zl = ztrlen(add), tl, cl; 4364 VARARR(Cmatcher, ms, zl); 4365 Cmatcher *mp; 4366 Cpattern stopp; 4367 int stopl = 0; 4368 4369 memset(ms, 0, zl * sizeof(Cmatcher)); 4370 4371 for (; m && *add; m = m->next) { 4372 stopp = NULL; 4373 if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) { 4374 if (m->llen == 1 && m->wlen == 1) { 4375 for (tmp = add, tl = al, mp = ms; tl; ) { 4376 if (pattern_match(m->line, tmp, NULL, NULL)) { 4377 if (*mp) { 4378 *tmp = '\0'; 4379 al = tmp - add; 4380 break; 4381 } else 4382 *mp = m; 4383 } 4384 cl = (*tmp == Meta) ? 2 : 1; 4385 tl -= cl; 4386 tmp += cl; 4387 mp += cl; 4388 } 4389 } else { 4390 stopp = m->line; 4391 stopl = m->llen; 4392 } 4393 } else if (m->flags & CMF_RIGHT) { 4394 if (m->wlen < 0 && !m->llen && m->ralen == 1) { 4395 for (tmp = add, tl = al, mp = ms; tl; ) { 4396 if (pattern_match(m->right, tmp, NULL, NULL)) { 4397 if (*mp || (tmp == add && *tmp == '.')) { 4398 *tmp = '\0'; 4399 al = tmp - add; 4400 break; 4401 } else 4402 *mp = m; 4403 } 4404 cl = (*tmp == Meta) ? 2 : 1; 4405 tl -= cl; 4406 tmp += cl; 4407 mp += cl; 4408 } 4409 } else if (m->llen) { 4410 stopp = m->line; 4411 stopl = m->llen; 4412 } else { 4413 stopp = m->right; 4414 stopl = m->ralen; 4415 } 4416 } else { 4417 if (!m->lalen) 4418 return ""; 4419 4420 stopp = m->left; 4421 stopl = m->lalen; 4422 } 4423 if (stopp) 4424 for (tmp = add, tl = al; tl >= stopl; ) { 4425 if (pattern_match(stopp, tmp, NULL, NULL)) { 4426 *tmp = '\0'; 4427 al = tmp - add; 4428 break; 4429 } 4430 cl = (*tmp == Meta) ? 2 : 1; 4431 tl -= cl; 4432 tmp += cl; 4433 } 4434 } 4435 if (*add) 4436 return cfp_matcher_range(ms, add); 4437 } 4438 return add; 4439} 4440 4441static void 4442cfp_opt_pats(char **pats, char *matcher) 4443{ 4444 char *add, **p, *q, *t, *s; 4445 4446 if (!compprefix || !*compprefix) 4447 return; 4448 4449 if (comppatmatch && *comppatmatch) { 4450 tokenize(t = rembslash(dyncat(compprefix, compsuffix))); 4451 remnulargs(t); 4452 if (haswilds(t)) 4453 return; 4454 } 4455 add = (char *) zhalloc(strlen(compprefix) * 2 + 1); 4456 for (s = compprefix, t = add; *s; s++) { 4457 if (*s != '\\' || !s[1] || s[1] == '*' || s[1] == '?' || 4458 s[1] == '<' || s[1] == '>' || s[1] == '(' || s[1] == ')' || 4459 s[1] == '[' || s[1] == ']' || s[1] == '|' || s[1] == '#' || 4460 s[1] == '^' || s[1] == '~' || s[1] == '=') { 4461 if ((s == compprefix || s[-1] != '\\') && 4462 (*s == '*' || *s == '?' || *s == '<' || *s == '>' || 4463 *s == '(' || *s == ')' || *s == '[' || *s == ']' || 4464 *s == '|' || *s == '#' || *s == '^' || *s == '~' || 4465 *s == '=')) 4466 *t++ = '\\'; 4467 *t++ = *s; 4468 } 4469 } 4470 *t = '\0'; 4471 for (p = pats; *add && (q = *p); p++) { 4472 if (*q) { 4473 q = dupstring(q); 4474 t = q + strlen(q) - 1; 4475 if (*t == ')') { 4476 for (s = t--; t > q; t--) 4477 if (*t == ')' || *t == '|' || *t == '~' || *t == '(') 4478 break; 4479 if (t != q && *t == '(') 4480 *t = '\0'; 4481 } 4482 for (; *q && *add; q++) { 4483 if (*q == '\\' && q[1]) { 4484 for (s = add, q++; *s && *s != *q; s++); 4485 *s = '\0'; 4486 } else if (*q == '<') { 4487 for (s = add; *s && !idigit(*s); s++); 4488 *s = '\0'; 4489 } else if (*q == '[') { 4490 int not; 4491 char *x = ++q; 4492 4493 if ((not = (*x == '!' || *x == '^'))) 4494 x++; 4495 for (; *x; x++) { 4496 if (x[1] == '-' && x[2]) { 4497 char c1 = *x, c2 = x[2]; 4498 4499 for (s = add; *s && (*x < c1 || *x > c2); s++); 4500 *s = '\0'; 4501 } else { 4502 for (s = add; *s && *s != *x; s++); 4503 *s = '\0'; 4504 } 4505 } 4506 } else if (*q != '?' && *q != '*' && *q != '(' && *q != ')' && 4507 *q != '|' && *q != '~' && *q != '#') { 4508 for (s = add; *s && *s != *q; s++); 4509 *s = '\0'; 4510 } 4511 } 4512 } 4513 } 4514 if (*add) { 4515 if (*matcher && !(add = cfp_matcher_pats(matcher, add))) 4516 return; 4517 4518 for (p = pats; *p; p++) 4519 if (**p == '*') 4520 *p = dyncat(add, *p); 4521 } 4522} 4523 4524static LinkList 4525cfp_bld_pats(UNUSED(int dirs), LinkList names, char *skipped, char **pats) 4526{ 4527 LinkList ret = newlinklist(); 4528 LinkNode node; 4529 int ol, sl = strlen(skipped), pl, dot; 4530 char **p, *o, *str; 4531 4532 dot = (unset(GLOBDOTS) && compprefix && *compprefix == '.'); 4533 for (node = firstnode(names); node; incnode(node)) { 4534 ol = strlen(o = (char *) getdata(node)); 4535 for (p = pats; *p; p++) { 4536 pl = strlen(*p); 4537 str = (char *) zhalloc(ol + sl + pl + 1); 4538 strcpy(str, o); 4539 strcpy(str + ol, skipped); 4540 strcpy(str + ol + sl, *p); 4541 addlinknode(ret, str); 4542 if (dot && **p != '.') { 4543 str = (char *) zhalloc(ol + sl + pl + 2); 4544 strcpy(str, o); 4545 strcpy(str + ol, skipped); 4546 str[ol + sl] = '.'; 4547 strcpy(str + ol + sl + 1, *p); 4548 addlinknode(ret, str); 4549 } 4550 } 4551 } 4552 return ret; 4553} 4554 4555static LinkList 4556cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, 4557 char *sdirs, char **fake) 4558{ 4559 int add = 0; 4560 4561 if (*sdirs && (isset(GLOBDOTS) || (compprefix && *compprefix == '.'))) { 4562 if (!strcmp(sdirs, "yes") || !strcmp(sdirs, "true") || 4563 !strcmp(sdirs, "on") || !strcmp(sdirs, "1")) 4564 add = 2; 4565 else if (!strcmp(sdirs, "..")) 4566 add = 1; 4567 } 4568 if (add) { 4569 LinkNode node; 4570 char *s1 = dyncat(skipped, ".."); 4571 char *s2 = (add == 2 ? dyncat(skipped, ".") : NULL), *m; 4572 4573 for (node = firstnode(orig); node; incnode(node)) { 4574 if ((m = (char *) getdata(node))) { 4575 addlinknode(final, dyncat(m, s1)); 4576 if (s2) 4577 addlinknode(final, dyncat(m, s2)); 4578 } 4579 } 4580 } 4581 if (fake && *fake) { 4582 LinkNode node; 4583 char *m, *f, *p, *t, *a, c; 4584 int sl = strlen(skipped) + 1; 4585 struct stat st1, st2; 4586 Patprog pprog; 4587 4588 for (; (f = *fake); fake++) { 4589 f = dupstring(f); 4590 for (p = t = f; *p; p++) { 4591 if (*p == ':') 4592 break; 4593 else if (*p == '\\' && p[1] == ':') { 4594 /* 4595 * strip quoted colons here; rely 4596 * on tokenization to strip other backslashes 4597 */ 4598 p++; 4599 } 4600 *t++ = *p; 4601 } 4602 if (*p) { 4603 *t = *p++ = '\0'; 4604 if (!*p) 4605 continue; 4606 4607 tokenize(f); 4608 pprog = patcompile(f, PAT_STATIC, NULL); 4609 untokenize(f); 4610 for (node = firstnode(orig); node; incnode(node)) { 4611 if ((m = (char *) getdata(node)) && 4612 ((pprog ? pattry(pprog, m) : !strcmp(f, m)) || 4613 (!stat(f, &st1) && !stat((*m ? m : "."), &st2) && 4614 st1.st_dev == st2.st_dev && 4615 st1.st_ino == st2.st_ino))) { 4616 while (*p) { 4617 while (*p && inblank(*p)) 4618 p++; 4619 if (!*p) 4620 break; 4621 for (f = t = p; *p; p++) { 4622 if (inblank(*p)) 4623 break; 4624 else if (*p == '\\' && p[1]) 4625 p++; 4626 *t++ = *p; 4627 } 4628 c = *t; 4629 *t = '\0'; 4630 a = (char *) zhalloc(strlen(m) + sl + strlen(f)); 4631 strcpy(a, m); 4632 strcat(a, skipped); 4633 strcat(a, f); 4634 addlinknode(final, a); 4635 *t = c; 4636 } 4637 } 4638 } 4639 } 4640 } 4641 } 4642 return final; 4643} 4644 4645static LinkList 4646cf_pats(int dirs, int noopt, LinkList names, char **accept, char *skipped, 4647 char *matcher, char *sdirs, char **fake, char **pats) 4648{ 4649 LinkList ret; 4650 char *dpats[2]; 4651 4652 if ((ret = cfp_test_exact(names, accept, skipped))) 4653 return cfp_add_sdirs(ret, names, skipped, sdirs, fake); 4654 4655 if (dirs) { 4656 dpats[0] = "*(-/)"; 4657 dpats[1] = NULL; 4658 pats = dpats; 4659 } 4660 if (!noopt) 4661 cfp_opt_pats(pats, matcher); 4662 4663 return cfp_add_sdirs(cfp_bld_pats(dirs, names, skipped, pats), 4664 names, skipped, sdirs, fake); 4665} 4666 4667/* 4668 * This function looks at device/inode pairs to determine if 4669 * a file is one we should ignore because of its relationship 4670 * to the current or parent directory. 4671 * 4672 * We don't follow symbolic links here, because typically 4673 * a user will not want an explicit link to the current or parent 4674 * directory ignored. 4675 */ 4676static void 4677cf_ignore(char **names, LinkList ign, char *style, char *path) 4678{ 4679 int pl = strlen(path), tpar, tpwd, found; 4680 struct stat nst, est, st; 4681 char *n, *c, *e; 4682 4683 tpar = !!strstr(style, "parent"); 4684 if ((tpwd = !!strstr(style, "pwd")) && lstat(pwd, &est)) 4685 tpwd = 0; 4686 4687 if (!tpar && !tpwd) 4688 return; 4689 4690 for (; (n = *names); names++) { 4691 if (!ztat(n, &nst, 1) && S_ISDIR(nst.st_mode)) { 4692 if (tpwd && nst.st_dev == est.st_dev && nst.st_ino == est.st_ino) { 4693 addlinknode(ign, quotestring(n, NULL, QT_BACKSLASH)); 4694 continue; 4695 } 4696 if (tpar && !strncmp((c = dupstring(n)), path, pl)) { 4697 found = 0; 4698 while ((e = strrchr(c, '/')) && e > c + pl) { 4699 *e = '\0'; 4700 if (!ztat(c, &st, 0) && 4701 st.st_dev == nst.st_dev && st.st_ino == nst.st_ino) { 4702 found = 1; 4703 break; 4704 } 4705 } 4706 if (found || ((e = strrchr(c, '/')) && e > c + pl && 4707 !ztat(c, &st, 1) && st.st_dev == nst.st_dev && 4708 st.st_ino == nst.st_ino)) 4709 addlinknode(ign, quotestring(n, NULL, QT_BACKSLASH)); 4710 } 4711 } 4712 } 4713} 4714 4715static LinkList 4716cf_remove_other(char **names, char *pre, int *amb) 4717{ 4718 char *p; 4719 4720 if ((p = strchr(pre, '/'))) { 4721 char **n; 4722 4723 *p = '\0'; 4724 pre = dyncat(pre, "/"); 4725 *p = '/'; 4726 4727 for (n = names; *n; n++) 4728 if (strpfx(pre, *n)) 4729 break; 4730 4731 if (*n) { 4732 LinkList ret = newlinklist(); 4733 4734 for (; *names; names++) 4735 if (strpfx(pre, *names)) 4736 addlinknode(ret, dupstring(*names)); 4737 4738 *amb = 0; 4739 4740 return ret; 4741 } else { 4742 if (!(p = *names++)) 4743 *amb = 0; 4744 else { 4745 char *q; 4746 4747 if ((q = strchr((p = dupstring(p)), '/'))) 4748 *q = '\0'; 4749 4750 p = dyncat(p, "/"); 4751 4752 for (; *names; names++) 4753 if (!strpfx(p, *names)) { 4754 *amb = 1; 4755 return NULL; 4756 } 4757 } 4758 } 4759 } else { 4760 if (!(p = *names++)) 4761 *amb = 0; 4762 else 4763 for (; *names; names++) 4764 if (strcmp(p, *names)) { 4765 *amb = 1; 4766 return NULL; 4767 } 4768 } 4769 return NULL; 4770} 4771 4772static int 4773bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 4774{ 4775 if (incompfunc != 1) { 4776 zwarnnam(nam, "can only be called from completion function"); 4777 return 1; 4778 } 4779 if (**args != '-') { 4780 zwarnnam(nam, "missing option: %s", *args); 4781 return 1; 4782 } 4783 switch (args[0][1]) { 4784 case 'p': 4785 case 'P': 4786 if (args[0][2] && (args[0][2] != '-' || args[0][3])) { 4787 zwarnnam(nam, "invalid option: %s", *args); 4788 return 1; 4789 } else { 4790 char **tmp; 4791 LinkList l; 4792 4793 if (!args[1] || !args[2] || !args[3] || !args[4] || !args[5] || 4794 !args[6] || (args[0][1] == 'p' && !args[7])) { 4795 zwarnnam(nam, "too few arguments"); 4796 return 1; 4797 } 4798 queue_signals(); 4799 if (!(tmp = getaparam(args[1]))) { 4800 zwarnnam(nam, "unknown parameter: %s", args[1]); 4801 return 0; 4802 } 4803 for (l = newlinklist(); *tmp; tmp++) 4804 addlinknode(l, *tmp); 4805 set_list_array(args[1], cf_pats((args[0][1] == 'P'), !!args[0][2], 4806 l, getaparam(args[2]), args[3], 4807 args[4], args[5], 4808 getaparam(args[6]), args + 7)); 4809 unqueue_signals(); 4810 return 0; 4811 } 4812 case 'i': 4813 if (args[0][2]) { 4814 zwarnnam(nam, "invalid option: %s", *args); 4815 return 1; 4816 } else { 4817 char **tmp; 4818 LinkList l; 4819 4820 if (!args[1] || !args[2] || !args[3] || !args[4]) { 4821 zwarnnam(nam, "too few arguments"); 4822 return 1; 4823 } 4824 if (args[5]) { 4825 zwarnnam(nam, "too many arguments"); 4826 return 1; 4827 } 4828 queue_signals(); 4829 tmp = getaparam(args[2]); 4830 l = newlinklist(); 4831 if (tmp) 4832 for (; *tmp; tmp++) 4833 addlinknode(l, *tmp); 4834 if (!(tmp = getaparam(args[1]))) { 4835 unqueue_signals(); 4836 zwarnnam(nam, "unknown parameter: %s", args[1]); 4837 return 0; 4838 } 4839 cf_ignore(tmp, l, args[3], args[4]); 4840 unqueue_signals(); 4841 set_list_array(args[2], l); 4842 return 0; 4843 } 4844 case 'r': 4845 { 4846 char **tmp; 4847 LinkList l; 4848 int ret = 0; 4849 4850 if (!args[1] || !args[2]) { 4851 zwarnnam(nam, "too few arguments"); 4852 return 1; 4853 } 4854 if (args[3]) { 4855 zwarnnam(nam, "too many arguments"); 4856 return 1; 4857 } 4858 queue_signals(); 4859 if (!(tmp = getaparam(args[1]))) { 4860 unqueue_signals(); 4861 zwarnnam(nam, "unknown parameter: %s", args[1]); 4862 return 0; 4863 } 4864 if ((l = cf_remove_other(tmp, args[2], &ret))) 4865 set_list_array(args[1], l); 4866 unqueue_signals(); 4867 return ret; 4868 } 4869 } 4870 zwarnnam(nam, "invalid option: %s", *args); 4871 return 1; 4872} 4873 4874static int 4875bin_compgroups(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 4876{ 4877 Heap oldheap; 4878 char *n; 4879 4880 if (incompfunc != 1) { 4881 zwarnnam(nam, "can only be called from completion function"); 4882 return 1; 4883 } 4884 SWITCHHEAPS(oldheap, compheap) { 4885 while ((n = *args++)) { 4886 endcmgroup(NULL); 4887 begcmgroup(n, CGF_NOSORT|CGF_UNIQCON); 4888 endcmgroup(NULL); 4889 begcmgroup(n, CGF_UNIQALL); 4890 endcmgroup(NULL); 4891 begcmgroup(n, CGF_NOSORT|CGF_UNIQCON); 4892 endcmgroup(NULL); 4893 begcmgroup(n, CGF_UNIQALL); 4894 endcmgroup(NULL); 4895 begcmgroup(n, CGF_NOSORT); 4896 endcmgroup(NULL); 4897 begcmgroup(n, 0); 4898 } 4899 } SWITCHBACKHEAPS(oldheap); 4900 4901 return 0; 4902} 4903 4904static struct builtin bintab[] = { 4905 BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL), 4906 BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL), 4907 BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL), 4908 BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL), 4909 BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, "p", NULL), 4910 BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL), 4911 BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL), 4912 BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL) 4913}; 4914 4915static struct features module_features = { 4916 bintab, sizeof(bintab)/sizeof(*bintab), 4917 NULL, 0, 4918 NULL, 0, 4919 NULL, 0, 4920 0 4921}; 4922 4923 4924/**/ 4925int 4926setup_(UNUSED(Module m)) 4927{ 4928 memset(cadef_cache, 0, sizeof(cadef_cache)); 4929 memset(cvdef_cache, 0, sizeof(cvdef_cache)); 4930 4931 memset(comptags, 0, sizeof(comptags)); 4932 4933 lasttaglevel = 0; 4934 4935 return 0; 4936} 4937 4938/**/ 4939int 4940features_(Module m, char ***features) 4941{ 4942 *features = featuresarray(m, &module_features); 4943 return 0; 4944} 4945 4946/**/ 4947int 4948enables_(Module m, int **enables) 4949{ 4950 return handlefeatures(m, &module_features, enables); 4951} 4952 4953/**/ 4954int 4955boot_(Module m) 4956{ 4957 return 0; 4958} 4959 4960/**/ 4961int 4962cleanup_(Module m) 4963{ 4964 return setfeatureenables(m, &module_features, NULL); 4965} 4966 4967/**/ 4968int 4969finish_(UNUSED(Module m)) 4970{ 4971 int i; 4972 4973 for (i = 0; i < MAX_CACACHE; i++) 4974 freecadef(cadef_cache[i]); 4975 for (i = 0; i < MAX_CVCACHE; i++) 4976 freecvdef(cvdef_cache[i]); 4977 4978 for (i = 0; i < MAX_TAGS; i++) 4979 freectags(comptags[i]); 4980 4981 return 0; 4982} 4983