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