1/* 2 * zle_tricky.c - expansion and completion 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1992-1997 Paul Falstad 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 Paul Falstad 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 Paul Falstad and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Paul Falstad 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 Paul Falstad and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30#include "zle.mdh" 31#include "zle_tricky.pro" 32 33/* 34 * The main part of ZLE maintains the line being edited as binary data, 35 * but here, where we interface with the lexer and other bits of zsh, we 36 * need the line metafied and, if necessary, converted from wide 37 * characters into multibyte strings. On entry to the 38 * expansion/completion system, we metafy the line from zleline into 39 * zlemetaline, with zlell and zlecs adjusted into zlemetall zlemetacs 40 * to match. zlemetall and zlemetacs refer to raw character positions, 41 * in other words a metafied character contributes 2 to each. All 42 * completion and expansion is done on the metafied line. Immediately 43 * before returning, the line is unmetafied again, so that zleline, 44 * zlell and zlecs are once again valid. (zlell and zlecs might have 45 * changed during completion, so they can't be merely saved and 46 * restored.) The various indexes into the line that are used in this 47 * file only are not translated: they remain indexes into the metafied 48 * line. 49 * 50 * zlemetaline is always NULL when not in use and non-NULL when in use. 51 * This can be used to test if the line is metafied. It would be 52 * possible to use zlecs and zlell directly, updated as appropriate when 53 * metafying and unmetafying, instead of zlemetacs and zlemetall, 54 * however the current system seems clearer. 55 */ 56 57#define inststr(X) inststrlen((X),1,-1) 58 59/* 60 * The state of the line being edited between metafy_line() 61 * unmetafy_line(). 62 * 63 * zlemetacs and zlemetall are defined in lex.c. 64 */ 65/**/ 66mod_export char *zlemetaline; 67/**/ 68mod_export int metalinesz; 69 70/* The line before completion was tried. */ 71 72/**/ 73mod_export char *origline; 74/**/ 75mod_export int origcs, origll; 76 77/* Words on the command line, for use in completion */ 78 79/**/ 80mod_export int clwsize, clwnum, clwpos; 81/**/ 82mod_export char **clwords; 83 84/* offs is the cursor position within the tokenized * 85 * current word after removing nulargs. */ 86 87/**/ 88mod_export int offs; 89 90/* These control the type of completion that will be done. They are * 91 * affected by the choice of ZLE command and by relevant shell options. * 92 * usemenu is set to 2 if we have to start automenu and 3 if we have to * 93 * insert a match as if for menucompletion but without really starting it. */ 94 95/**/ 96mod_export int usemenu, useglob; 97 98/* != 0 if we would insert a TAB if we weren't calling a completion widget. */ 99 100/**/ 101mod_export int wouldinstab; 102 103/* != 0 if we are in the middle of a menu completion. May be == 2 to force * 104 * menu completion even if using different widgets. */ 105 106/**/ 107mod_export int menucmp; 108 109/* Lists of brace-infos before/after cursor (first and last for each). */ 110 111/**/ 112mod_export Brinfo brbeg, lastbrbeg, brend, lastbrend; 113 114/**/ 115mod_export int nbrbeg, nbrend; 116 117/**/ 118mod_export char *lastprebr, *lastpostbr; 119 120/* !=0 if we have a valid completion list. */ 121 122/**/ 123mod_export int validlist; 124 125/* Non-zero if we have to redisplay the list of matches. */ 126 127/**/ 128mod_export int showagain = 0; 129 130/* This holds the word we are working on without braces removed. */ 131 132static char *origword; 133 134/* The quoted prefix/suffix and a flag saying if we want to add the 135 * closing quote. */ 136 137/**/ 138mod_export char *qipre, *qisuf, *autoq; 139 140/* This contains the name of the function to call if this is for a new * 141 * style completion. */ 142 143/**/ 144mod_export char *compfunc = NULL; 145 146/* Non-zero if the last completion done was ambiguous (used to find * 147 * out if AUTOMENU should start). More precisely, it's nonzero after * 148 * successfully doing any completion, unless the completion was * 149 * unambiguous and did not cause the display of a completion list. * 150 * From the other point of view, it's nonzero iff AUTOMENU (if set) * 151 * should kick in on another completion. * 152 * * 153 * If both AUTOMENU and BASHAUTOLIST are set, then we get a listing * 154 * on the second tab, a` la bash, and then automenu kicks in when * 155 * lastambig == 2. */ 156 157/**/ 158mod_export int lastambig, bashlistfirst; 159 160/* Arguments for and return value of completion widget. */ 161 162/**/ 163mod_export char **cfargs; 164/**/ 165mod_export int cfret; 166 167/* != 0 if recursive calls to completion are (temporarily) allowed */ 168 169/**/ 170mod_export int comprecursive; 171 172/* != 0 if there are any defined completion widgets. */ 173 174/**/ 175int hascompwidgets; 176 177/* 178 * Find out if we have to insert a tab (instead of trying to complete). 179 * The line is not metafied here. 180 */ 181 182/**/ 183static int 184usetab(void) 185{ 186 ZLE_STRING_T s = zleline + zlecs - 1; 187 188 if (keybuf[0] != '\t' || keybuf[1]) 189 return 0; 190 for (; s >= zleline && *s != ZWC('\n'); s--) 191 if (*s != ZWC('\t') && *s != ZWC(' ')) 192 return 0; 193 if (compfunc) { 194 wouldinstab = 1; 195 196 return 0; 197 } 198 return 1; 199} 200 201/**/ 202int 203completecall(char **args) 204{ 205 cfargs = args; 206 cfret = 0; 207 compfunc = compwidget->u.comp.func; 208 if (compwidget->u.comp.fn(zlenoargs) && !cfret) 209 cfret = 1; 210 compfunc = NULL; 211 212 return cfret; 213} 214 215/**/ 216int 217completeword(char **args) 218{ 219 usemenu = !!isset(MENUCOMPLETE); 220 useglob = isset(GLOBCOMPLETE); 221 wouldinstab = 0; 222 if (lastchar == '\t' && usetab()) 223 return selfinsert(args); 224 else { 225 int ret; 226 if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { 227 bashlistfirst = 1; 228 ret = docomplete(COMP_LIST_COMPLETE); 229 bashlistfirst = 0; 230 lastambig = 2; 231 } else 232 ret = docomplete(COMP_COMPLETE); 233 return ret; 234 } 235} 236 237/**/ 238mod_export int 239menucomplete(char **args) 240{ 241 usemenu = 1; 242 useglob = isset(GLOBCOMPLETE); 243 wouldinstab = 0; 244 if (lastchar == '\t' && usetab()) 245 return selfinsert(args); 246 else 247 return docomplete(COMP_COMPLETE); 248} 249 250/**/ 251int 252listchoices(UNUSED(char **args)) 253{ 254 usemenu = !!isset(MENUCOMPLETE); 255 useglob = isset(GLOBCOMPLETE); 256 wouldinstab = 0; 257 return docomplete(COMP_LIST_COMPLETE); 258} 259 260/**/ 261int 262spellword(UNUSED(char **args)) 263{ 264 usemenu = useglob = 0; 265 wouldinstab = 0; 266 return docomplete(COMP_SPELL); 267} 268 269/**/ 270int 271deletecharorlist(char **args) 272{ 273 usemenu = !!isset(MENUCOMPLETE); 274 useglob = isset(GLOBCOMPLETE); 275 wouldinstab = 0; 276 277 /* Line not yet metafied */ 278 if (zlecs != zlell) { 279 fixsuffix(); 280 invalidatelist(); 281 return deletechar(args); 282 } 283 return docomplete(COMP_LIST_COMPLETE); 284} 285 286/**/ 287int 288expandword(char **args) 289{ 290 usemenu = useglob = 0; 291 wouldinstab = 0; 292 if (lastchar == '\t' && usetab()) 293 return selfinsert(args); 294 else 295 return docomplete(COMP_EXPAND); 296} 297 298/**/ 299int 300expandorcomplete(char **args) 301{ 302 usemenu = !!isset(MENUCOMPLETE); 303 useglob = isset(GLOBCOMPLETE); 304 wouldinstab = 0; 305 if (lastchar == '\t' && usetab()) 306 return selfinsert(args); 307 else { 308 int ret; 309 if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) { 310 bashlistfirst = 1; 311 ret = docomplete(COMP_LIST_COMPLETE); 312 bashlistfirst = 0; 313 lastambig = 2; 314 } else 315 ret = docomplete(COMP_EXPAND_COMPLETE); 316 return ret; 317 } 318} 319 320/**/ 321int 322menuexpandorcomplete(char **args) 323{ 324 usemenu = 1; 325 useglob = isset(GLOBCOMPLETE); 326 wouldinstab = 0; 327 if (lastchar == '\t' && usetab()) 328 return selfinsert(args); 329 else 330 return docomplete(COMP_EXPAND_COMPLETE); 331} 332 333/**/ 334int 335listexpand(UNUSED(char **args)) 336{ 337 usemenu = !!isset(MENUCOMPLETE); 338 useglob = isset(GLOBCOMPLETE); 339 wouldinstab = 0; 340 return docomplete(COMP_LIST_EXPAND); 341} 342 343/**/ 344mod_export int 345reversemenucomplete(char **args) 346{ 347 wouldinstab = 0; 348 if (!menucmp) { 349 menucomplete(args); 350 /* 351 * Drop through, since we are now on the first item instead of 352 * the last. We've already updated the display, so this is a 353 * bit inefficient, but it's simple and it works. 354 */ 355 } 356 357 runhookdef(REVERSEMENUHOOK, NULL); 358 return 0; 359} 360 361/**/ 362int 363acceptandmenucomplete(char **args) 364{ 365 wouldinstab = 0; 366 if (!menucmp) 367 return 1; 368 runhookdef(ACCEPTCOMPHOOK, NULL); 369 return menucomplete(args); 370} 371 372/* These are flags saying if we are completing in the command * 373 * position, in a redirection, or in a parameter expansion. */ 374 375/**/ 376mod_export int lincmd, linredir, linarr; 377 378/* The string for the redirection operator. */ 379 380/**/ 381mod_export char *rdstr; 382 383static char rdstrbuf[20]; 384 385/* The list of redirections on the line. */ 386 387/**/ 388mod_export LinkList rdstrs; 389 390/* This holds the name of the current command (used to find the right * 391 * compctl). */ 392 393/**/ 394mod_export char *cmdstr; 395 396/* This hold the name of the variable we are working on. */ 397 398/**/ 399mod_export char *varname; 400 401/* 402 * != 0 if we are in a subscript. 403 * Of course, this being the completion code, you're expected to guess 404 * what the different numbers actually mean, but here's a cheat: 405 * 1: Key of an ordinary array 406 * 2: Key of a hash 407 * 3: Ummm.... this appears to be a special case of 2. After a lot 408 * of uncommented code looking for groups of brackets, we suddenly 409 * decide to set it to 2. The only upshot seems to be that compctl 410 * then doesn't add a matching ']' at the end, so I think it means 411 * there's one there already. 412 */ 413 414/**/ 415mod_export int insubscr; 416 417/* Parameter pointer for completing keys of an assoc array. */ 418 419/**/ 420mod_export Param keypm; 421 422/* 423 * instring takes one of the QT_* values defined in zsh.h. 424 * It's never QT_TICK, instead we use inbackt. 425 * TODO: can we combine the two? 426 */ 427 428/**/ 429mod_export int instring, inbackt; 430 431/* 432 * Convenience macro for calling quotestring (formerly bslashquote() (formerly 433 * quotename())). 434 * This uses the instring variable above. 435 */ 436 437#define quotename(s, e) \ 438quotestring(s, e, instring == QT_NONE ? QT_BACKSLASH : instring) 439 440/* Check if the given string is the name of a parameter and if this * 441 * parameter is one worth expanding. */ 442 443/**/ 444static int 445checkparams(char *p) 446{ 447 int t0, n, l = strlen(p), e = 0; 448 struct hashnode *hn; 449 450 for (t0 = paramtab->hsize - 1, n = 0; n < 2 && t0 >= 0; t0--) 451 for (hn = paramtab->nodes[t0]; n < 2 && hn; hn = hn->next) 452 if (pfxlen(p, hn->nam) == l) { 453 n++; 454 if ((int)strlen(hn->nam) == l) 455 e = 1; 456 } 457 return (n == 1) ? (getsparam(p) != NULL) : 458 (!menucmp && e && (!hascompmod || isset(RECEXACT))); 459} 460 461/* Check if the given string has wildcards. The difficulty is that we * 462 * have to treat things like job specifications (%...) and parameter * 463 * expressions correctly. */ 464 465/**/ 466static int 467cmphaswilds(char *str) 468{ 469 if ((*str == Inbrack || *str == Outbrack) && !str[1]) 470 return 0; 471 472 /* If a leading % is immediately followed by ?, then don't * 473 * treat that ? as a wildcard. This is so you don't have * 474 * to escape job references such as %?foo. */ 475 if (str[0] == '%' && str[1] ==Quest) 476 str += 2; 477 478 for (; *str;) { 479 if (*str == String || *str == Qstring) { 480 /* A parameter expression. */ 481 482 if (*++str == Inbrace) 483 skipparens(Inbrace, Outbrace, &str); 484 else if (*str == String || *str == Qstring) 485 str++; 486 else { 487 /* Skip all the things a parameter expression might start * 488 * with (before we come to the parameter name). */ 489 for (; *str; str++) 490 if (*str != '^' && *str != Hat && 491 *str != '=' && *str != Equals && 492 *str != '~' && *str != Tilde) 493 break; 494 if (*str == '#' || *str == Pound) 495 str++; 496 /* Star and Quest are parameter names here, not wildcards */ 497 if (*str == Star || *str == Quest) 498 str++; 499 } 500 } else { 501 /* Not a parameter expression so we check for wildcards */ 502 if (((*str == Pound || *str == Hat) && isset(EXTENDEDGLOB)) || 503 *str == Star || *str == Bar || *str == Quest || 504 !skipparens(Inbrack, Outbrack, &str) || 505 !skipparens(Inang, Outang, &str) || 506 (unset(IGNOREBRACES) && 507 !skipparens(Inbrace, Outbrace, &str)) || 508 (*str == Inpar && str[1] == ':' && 509 !skipparens(Inpar, Outpar, &str))) 510 return 1; 511 if (*str) 512 str++; 513 } 514 } 515 return 0; 516} 517 518/* Check if we have to complete a parameter name. */ 519 520/**/ 521char * 522parambeg(char *s) 523{ 524 char *p; 525 526 /* Try to find a `$'. */ 527 for (p = s + offs; p > s && *p != String && *p != Qstring; p--); 528 if (*p == String || *p == Qstring) { 529 /* Handle $$'s */ 530 while (p > s && (p[-1] == String || p[-1] == Qstring)) 531 p--; 532 while ((p[1] == String || p[1] == Qstring) && 533 (p[2] == String || p[2] == Qstring)) 534 p += 2; 535 } 536 if ((*p == String || *p == Qstring) && 537 p[1] != Inpar && p[1] != Inbrack && p[1] != '\'') { 538 /* 539 * This is really a parameter expression (not $(...) or $[...] 540 * or $'...'). 541 */ 542 char *b = p + 1, *e = b; 543 int n = 0, br = 1; 544 545 if (*b == Inbrace) { 546 char *tb = b; 547 548 /* If this is a ${...}, see if we are before the '}'. */ 549 if (!skipparens(Inbrace, Outbrace, &tb)) 550 return NULL; 551 552 /* Ignore the possible (...) flags. */ 553 b++, br++; 554 n = skipparens(Inpar, Outpar, &b); 555 } 556 557 /* Ignore the stuff before the parameter name. */ 558 for (; *b; b++) 559 if (*b != '^' && *b != Hat && 560 *b != '=' && *b != Equals && 561 *b != '~' && *b != Tilde) 562 break; 563 if (*b == '#' || *b == Pound || *b == '+') 564 b++; 565 566 e = b; 567 if (br) { 568 while (*e == Dnull) 569 e++; 570 } 571 /* Find the end of the name. */ 572 if (*e == Quest || *e == Star || *e == String || *e == Qstring || 573 *e == '?' || *e == '*' || *e == '$' || 574 *e == '-' || *e == '!' || *e == '@') 575 e++; 576 else if (idigit(*e)) 577 while (idigit(*e)) 578 e++; 579 else 580 e = itype_end(e, IIDENT, 0); 581 582 /* Now make sure that the cursor is inside the name. */ 583 if (offs <= e - s && offs >= b - s && n <= 0) { 584 if (br) { 585 p = e; 586 while (*p == Dnull) 587 p++; 588 } 589 /* It is. */ 590 return b; 591 } 592 } 593 return NULL; 594} 595 596/* The main entry point for completion. */ 597 598/**/ 599static int 600docomplete(int lst) 601{ 602 static int active = 0; 603 604 char *s, *ol; 605 int olst = lst, chl = 0, ne = noerrs, ocs, ret = 0, dat[2]; 606 607 if (active && !comprecursive) { 608 zwarn("completion cannot be used recursively (yet)"); 609 return 1; 610 } 611 active = 1; 612 comprecursive = 0; 613 makecommaspecial(0); 614 if (undoing) 615 setlastline(); 616 617 /* From the C-code's point of view, we can only use compctl as a default 618 * type of completion. Load it if it hasn't been loaded already and 619 * no completion widgets are defined. */ 620 621 if (!module_loaded("zsh/compctl") && !hascompwidgets) 622 (void)load_module("zsh/compctl", NULL, 0); 623 624 if (runhookdef(BEFORECOMPLETEHOOK, (void *) &lst)) { 625 active = 0; 626 return 0; 627 } 628 /* Expand history references before starting completion. If anything * 629 * changed, do no more. */ 630 631 if (doexpandhist()) { 632 active = 0; 633 return 0; 634 } 635 636 metafy_line(); 637 638 ocs = zlemetacs; 639 origline = dupstring(zlemetaline); 640 origcs = zlemetacs; 641 origll = zlemetall; 642 if (!isfirstln && (chline != NULL || zle_chline != NULL)) { 643 ol = dupstring(zlemetaline); 644 /* 645 * Make sure that chline is zero-terminated. 646 * zle_chline always is and hptr doesn't point into it anyway. 647 */ 648 if (!zle_chline) 649 *hptr = '\0'; 650 zlemetacs = 0; 651 inststr(zle_chline ? zle_chline : chline); 652 chl = zlemetacs; 653 zlemetacs += ocs; 654 } else 655 ol = NULL; 656 inwhat = IN_NOTHING; 657 zsfree(qipre); 658 qipre = ztrdup(""); 659 zsfree(qisuf); 660 qisuf = ztrdup(""); 661 zsfree(autoq); 662 autoq = NULL; 663 /* Get the word to complete. 664 * NOTE: get_comp_string() calls pushheap(), but not popheap(). */ 665 noerrs = 1; 666 s = get_comp_string(); 667 DPUTS(wb < 0 || zlemetacs < wb || zlemetacs > we, 668 "BUG: 0 <= wb <= zlemetacs <= we is not true!"); 669 noerrs = ne; 670 /* For vi mode, reset the start-of-insertion pointer to the beginning * 671 * of the word being completed, if it is currently later. Vi itself * 672 * would never change the pointer in the middle of an insertion, but * 673 * then vi doesn't have completion. More to the point, this is only * 674 * an emulation. */ 675 if (viinsbegin > ztrsub(zlemetaline + wb, zlemetaline)) 676 viinsbegin = ztrsub(zlemetaline + wb, zlemetaline); 677 /* If we added chline to the line buffer, reset the original contents. */ 678 if (ol) { 679 zlemetacs -= chl; 680 wb -= chl; 681 we -= chl; 682 if (wb < 0) { 683 strcpy(zlemetaline, ol); 684 zlemetall = strlen(zlemetaline); 685 zlemetacs = ocs; 686 popheap(); 687 unmetafy_line(); 688 zsfree(s); 689 active = 0; 690 makecommaspecial(0); 691 return 1; 692 } 693 ocs = zlemetacs; 694 zlemetacs = 0; 695 foredel(chl, CUT_RAW); 696 zlemetacs = ocs; 697 } 698 freeheap(); 699 /* Save the lexer state, in case the completion code uses the lexer * 700 * somewhere (e.g. when processing a compctl -s flag). */ 701 lexsave(); 702 if (inwhat == IN_ENV) 703 lincmd = 0; 704 if (s) { 705 if (lst == COMP_EXPAND_COMPLETE) { 706 /* Check if we have to do expansion or completion. */ 707 char *q = s; 708 709 if (*q == Equals) { 710 /* The word starts with `=', see if we can expand it. */ 711 q = s + 1; 712 if (cmdnamtab->getnode(cmdnamtab, q) || hashcmd(q, pathchecked)) { 713 if (!hascompmod || isset(RECEXACT)) 714 lst = COMP_EXPAND; 715 else { 716 int t0, n = 0; 717 struct hashnode *hn; 718 719 for (t0 = cmdnamtab->hsize - 1; t0 >= 0; t0--) 720 for (hn = cmdnamtab->nodes[t0]; hn; 721 hn = hn->next) { 722 if (strpfx(q, hn->nam) && findcmd(hn->nam, 0)) 723 n++; 724 if (n == 2) 725 break; 726 } 727 728 if (n == 1) 729 lst = COMP_EXPAND; 730 } 731 } 732 } 733 if (lst == COMP_EXPAND_COMPLETE) 734 do { 735 /* Check if there is a parameter expression. */ 736 for (; *q && *q != String; q++); 737 if (*q == String && q[1] != Inpar && q[1] != Inbrack) { 738 if (*++q == Inbrace) { 739 if (! skipparens(Inbrace, Outbrace, &q) && 740 q == s + zlemetacs - wb) 741 lst = COMP_EXPAND; 742 } else { 743 char *t, sav, sav2; 744 745 /* Skip the things parameter expressions might * 746 * start with (the things before the parameter * 747 * name). */ 748 for (; *q; q++) 749 if (*q != '^' && *q != Hat && 750 *q != '=' && *q != Equals && 751 *q != '~' && *q != Tilde) 752 break; 753 if ((*q == '#' || *q == Pound || *q == '+') && 754 q[1] != String) 755 q++; 756 757 sav2 = *(t = q); 758 if (*q == Quest || *q == Star || *q == String || 759 *q == Qstring) 760 *q = ztokens[*q - Pound], ++q; 761 else if (*q == '?' || *q == '*' || *q == '$' || 762 *q == '-' || *q == '!' || *q == '@') 763 q++; 764 else if (idigit(*q)) 765 do q++; while (idigit(*q)); 766 else 767 q = itype_end(q, IIDENT, 0); 768 sav = *q; 769 *q = '\0'; 770 if (zlemetacs - wb == q - s && 771 (idigit(sav2) || checkparams(t))) 772 lst = COMP_EXPAND; 773 *q = sav; 774 *t = sav2; 775 } 776 if (lst != COMP_EXPAND) 777 lst = COMP_COMPLETE; 778 } else 779 break; 780 } while (q < s + zlemetacs - wb); 781 if (lst == COMP_EXPAND_COMPLETE) { 782 /* If it is still not clear if we should use expansion or * 783 * completion and there is a `$' or a backtick in the word, * 784 * than do expansion. */ 785 for (q = s; *q; q++) 786 if (*q == Tick || *q == Qtick || 787 *q == String || *q == Qstring) 788 break; 789 lst = *q ? COMP_EXPAND : COMP_COMPLETE; 790 } 791 /* And do expansion if there are wildcards and globcomplete is * 792 * not used. */ 793 if (unset(GLOBCOMPLETE) && cmphaswilds(s)) 794 lst = COMP_EXPAND; 795 } 796 if (lincmd && (inwhat == IN_NOTHING)) 797 inwhat = IN_CMD; 798 799 if (lst == COMP_SPELL) { 800 char *w = dupstring(origword), *x, *q, *ox; 801 802 for (q = w; *q; q++) 803 if (inull(*q)) 804 *q = Nularg; 805 zlemetacs = wb; 806 foredel(we - wb, CUT_RAW); 807 808 untokenize(x = ox = dupstring(w)); 809 if (*w == Tilde || *w == Equals || *w == String) 810 *x = *w; 811 spckword(&x, 0, lincmd, 0); 812 ret = !strcmp(x, ox); 813 814 untokenize(x); 815 inststr(x); 816 } else if (COMP_ISEXPAND(lst)) { 817 /* Do expansion. */ 818 char *ol = (olst == COMP_EXPAND || 819 olst == COMP_EXPAND_COMPLETE) ? 820 dupstring(zlemetaline) : zlemetaline; 821 int ocs = zlemetacs, ne = noerrs; 822 823 noerrs = 1; 824 ret = doexpansion(origword, lst, olst, lincmd); 825 lastambig = 0; 826 noerrs = ne; 827 828 /* If expandorcomplete was invoked and the expansion didn't * 829 * change the command line, do completion. */ 830 if (olst == COMP_EXPAND_COMPLETE && 831 !strcmp(ol, zlemetaline)) { 832 zlemetacs = ocs; 833 errflag = 0; 834 835 if (!compfunc) { 836 char *p; 837 838 p = s; 839 if (*p == Tilde || *p == Equals) 840 p++; 841 for (; *p; p++) 842 if (itok(*p)) { 843 if (*p != String && *p != Qstring) 844 *p = ztokens[*p - Pound]; 845 else if (p[1] == Inbrace) 846 p++, skipparens(Inbrace, Outbrace, &p); 847 } 848 } 849 ret = docompletion(s, lst, lincmd); 850 } else { 851 if (ret) 852 clearlist = 1; 853 if (!strcmp(ol, zlemetaline)) { 854 /* We may have removed some quotes. For completion, other 855 * parts of the code re-install them, but for expansion 856 * we have to do it here. */ 857 zlemetacs = 0; 858 foredel(zlemetall, CUT_RAW); 859 spaceinline(origll); 860 memcpy(zlemetaline, origline, origll); 861 zlemetacs = origcs; 862 } 863 } 864 } else 865 /* Just do completion. */ 866 ret = docompletion(s, lst, lincmd); 867 zsfree(s); 868 } else 869 ret = 1; 870 /* Reset the lexer state, pop the heap. */ 871 lexrestore(); 872 popheap(); 873 874 dat[0] = lst; 875 dat[1] = ret; 876 runhookdef(AFTERCOMPLETEHOOK, (void *) dat); 877 unmetafy_line(); 878 879 active = 0; 880 makecommaspecial(0); 881 return dat[1]; 882} 883 884/* 1 if we are completing the prefix */ 885static int comppref; 886 887/* This function inserts an `x' in the command line at the cursor position. * 888 * * 889 * Oh, you want to know why? Well, if completion is tried somewhere on an * 890 * empty part of the command line, the lexer code would normally not be * 891 * able to give us the `word' we want to complete, since there is no word. * 892 * But we need to call the lexer to find out where we are (and for which * 893 * command we are completing and such things). So we temporarily add a `x' * 894 * (any character without special meaning would do the job) at the cursor * 895 * position, than the lexer gives us the word `x' and its beginning and end * 896 * positions and we can remove the `x'. * 897 * * 898 * If we are just completing the prefix (comppref set), we also insert a * 899 * space after the x to end the word. We never need to remove the space: * 900 * anywhere we are able to retrieve a word for completion it will be * 901 * discarded as whitespace. It has the effect of making any suffix * 902 * referrable to as the next word on the command line when indexing * 903 * from a completion function. */ 904 905/**/ 906static void 907addx(char **ptmp) 908{ 909 int addspace = 0; 910 911 if (!zlemetaline[zlemetacs] || zlemetaline[zlemetacs] == '\n' || 912 (iblank(zlemetaline[zlemetacs]) && 913 (!zlemetacs || zlemetaline[zlemetacs-1] != '\\')) || 914 zlemetaline[zlemetacs] == ')' || zlemetaline[zlemetacs] == '`' || 915 zlemetaline[zlemetacs] == '}' || 916 zlemetaline[zlemetacs] == ';' || zlemetaline[zlemetacs] == '|' || 917 zlemetaline[zlemetacs] == '&' || 918 zlemetaline[zlemetacs] == '>' || zlemetaline[zlemetacs] == '<' || 919 (instring != QT_NONE && (zlemetaline[zlemetacs] == '"' || 920 zlemetaline[zlemetacs] == '\'')) || 921 (addspace = (comppref && !iblank(zlemetaline[zlemetacs])))) { 922 *ptmp = zlemetaline; 923 zlemetaline = zhalloc(strlen(zlemetaline) + 3 + addspace); 924 memcpy(zlemetaline, *ptmp, zlemetacs); 925 zlemetaline[zlemetacs] = 'x'; 926 if (addspace) 927 zlemetaline[zlemetacs+1] = ' '; 928 strcpy(zlemetaline + zlemetacs + 1 + addspace, (*ptmp) + zlemetacs); 929 addedx = 1 + addspace; 930 } else { 931 addedx = 0; 932 *ptmp = NULL; 933 } 934} 935 936/* Like dupstring, but add an extra space at the end of the string. */ 937 938/**/ 939mod_export char * 940dupstrspace(const char *str) 941{ 942 int len = strlen(str); 943 char *t = (char *) hcalloc(len + 2); 944 strcpy(t, str); 945 strcpy(t+len, " "); 946 return t; 947} 948 949/* 950 * These functions metafy and unmetafy the ZLE buffer, as described at 951 * the top of this file. They *must* be called in matching pairs, 952 * around all the expansion/completion code. 953 * 954 * The variables zleline, zlell and zlecs are metafied into 955 * zlemetaline, zlemetall and zlemetacs. Only the latter variables 956 * should be referred to from above zle (i.e. in the main shell), 957 * or when using the completion API (if that's not too strong a 958 * way of referring to it). 959 */ 960 961/**/ 962mod_export void 963metafy_line(void) 964{ 965 UNMETACHECK(); 966 967 zlemetaline = zlelineasstring(zleline, zlell, zlecs, 968 &zlemetall, &zlemetacs, 0); 969 metalinesz = zlemetall; 970 971 /* 972 * We will always allocate a new zleline based on zlemetaline. 973 */ 974 free(zleline); 975 zleline = NULL; 976} 977 978/**/ 979mod_export void 980unmetafy_line(void) 981{ 982 METACHECK(); 983 984 /* paranoia */ 985 zlemetaline[zlemetall] = '\0'; 986 zleline = stringaszleline(zlemetaline, zlemetacs, &zlell, &linesz, &zlecs); 987 988 free(zlemetaline); 989 zlemetaline = NULL; 990 /* 991 * If we inserted combining characters under the cursor we 992 * won't have tested the effect yet. So fix it up now. 993 */ 994 CCRIGHT(); 995} 996 997/* Free a brinfo list. */ 998 999/**/ 1000mod_export void 1001freebrinfo(Brinfo p) 1002{ 1003 Brinfo n; 1004 1005 while (p) { 1006 n = p->next; 1007 zsfree(p->str); 1008 zfree(p, sizeof(*p)); 1009 1010 p = n; 1011 } 1012} 1013 1014/* Duplicate a brinfo list. */ 1015 1016/**/ 1017mod_export Brinfo 1018dupbrinfo(Brinfo p, Brinfo *last, int heap) 1019{ 1020 Brinfo ret = NULL, *q = &ret, n = NULL; 1021 1022 while (p) { 1023 n = *q = (heap ? (Brinfo) zhalloc(sizeof(*n)) : 1024 (Brinfo) zalloc(sizeof(*n))); 1025 q = &(n->next); 1026 1027 n->next = NULL; 1028 n->str = (heap ? dupstring(p->str) : ztrdup(p->str)); 1029 n->pos = p->pos; 1030 n->qpos = p->qpos; 1031 n->curpos = p->curpos; 1032 1033 p = p->next; 1034 } 1035 if (last) 1036 *last = n; 1037 1038 return ret; 1039} 1040 1041/* This is a bit like has_token(), but ignores nulls. */ 1042 1043static int 1044has_real_token(const char *s) 1045{ 1046 while (*s) { 1047 /* 1048 * Special action required for $' strings, which 1049 * need to be treated like nulls. 1050 */ 1051 if ((*s == Qstring && s[1] == '\'') || 1052 (*s == String && s[1] == Snull)) 1053 { 1054 s += 2; 1055 continue; 1056 } 1057 if (itok(*s) && !inull(*s)) 1058 return 1; 1059 s++; 1060 } 1061 return 0; 1062} 1063 1064 1065/* Lasciate ogni speranza. * 1066 * This function is a nightmare. It works, but I'm sure that nobody really * 1067 * understands why. The problem is: to make it cleaner we would need * 1068 * changes in the lexer code (and then in the parser, and then...). */ 1069 1070/**/ 1071static char * 1072get_comp_string(void) 1073{ 1074 enum lextok t0, tt0; 1075 int i, j, k, cp, rd, sl, ocs, ins, oins, ia, parct, varq = 0; 1076 int ona = noaliases; 1077 /* 1078 * Index of word being considered 1079 */ 1080 int wordpos; 1081 /* 1082 * qsub fixes up the offset into the current completion word 1083 * for changes made by the lexer. That currently means the 1084 * effect of RCQUOTES on embedded pairs of single quotes. 1085 * zlemetacs_qsub takes account of the effect of this offset 1086 * on the cursor position; it's only needed when using the 1087 * word we got from the lexer, which we only do sometimes because 1088 * otherwise it would be too easy. If looking at zlemetaline we 1089 * still use zlemetacs. 1090 */ 1091 int qsub, zlemetacs_qsub = 0; 1092 /* 1093 * redirpos is used to record string arguments for redirection 1094 * when they occur at the start of the line. In this case 1095 * the command word is not at index zero in the array. 1096 */ 1097 int redirpos; 1098 char *s = NULL, *tmp, *p, *tt = NULL, rdop[20]; 1099 char *linptr, *u; 1100 1101 METACHECK(); 1102 1103 freebrinfo(brbeg); 1104 freebrinfo(brend); 1105 brbeg = lastbrbeg = brend = lastbrend = NULL; 1106 nbrbeg = nbrend = 0; 1107 zsfree(lastprebr); 1108 zsfree(lastpostbr); 1109 lastprebr = lastpostbr = NULL; 1110 if (rdstrs) 1111 freelinklist(rdstrs, freestr); 1112 rdstrs = znewlinklist(); 1113 rdop[0] = '\0'; 1114 rdstr = NULL; 1115 1116 /* This global flag is used to signal the lexer code if it should * 1117 * expand aliases or not. */ 1118 noaliases = isset(COMPLETEALIASES); 1119 1120 /* Find out if we are somewhere in a `string', i.e. inside '...', * 1121 * "...", `...`, or ((...)). Nowadays this is only used to find * 1122 * out if we are inside `...`. */ 1123 1124 for (i = j = k = 0, u = zlemetaline; u < zlemetaline + zlemetacs; u++) { 1125 if (*u == '`' && !(k & 1)) 1126 i++; 1127 else if (*u == '\"' && !(k & 1) && !(i & 1)) 1128 j++; 1129 else if (*u == '\'' && !(j & 1)) 1130 k++; 1131 else if (*u == '\\' && u[1] && !(k & 1)) 1132 u++; 1133 } 1134 inbackt = (i & 1); 1135 instring = QT_NONE; 1136 addx(&tmp); 1137 linptr = zlemetaline; 1138 pushheap(); 1139 1140 start: 1141 inwhat = IN_NOTHING; 1142 /* Now set up the lexer and start it. */ 1143 parbegin = parend = -1; 1144 lincmd = incmdpos; 1145 linredir = inredir; 1146 zsfree(cmdstr); 1147 cmdstr = NULL; 1148 zsfree(varname); 1149 varname = NULL; 1150 insubscr = 0; 1151 clwpos = -1; 1152 lexsave(); 1153 lexflags = LEXFLAGS_ZLE; 1154 inpush(dupstrspace(linptr), 0, NULL); 1155 strinbeg(0); 1156 wordpos = cp = rd = ins = oins = linarr = parct = ia = redirpos = 0; 1157 tt0 = NULLTOK; 1158 1159 /* This loop is possibly the wrong way to do this. It goes through * 1160 * the previously massaged command line using the lexer. It stores * 1161 * each token in each command (commands being regarded, roughly, as * 1162 * being separated by tokens | & &! |& || &&). The loop stops when * 1163 * the end of the command containing the cursor is reached. What * 1164 * makes this messy is checking for things like redirections, loops * 1165 * and whatnot. */ 1166 1167 do { 1168 qsub = 0; 1169 1170 lincmd = ((incmdpos && !ins && !incond) || 1171 (oins == 2 && wordpos == 2) || 1172 (ins == 3 && wordpos == 1)); 1173 linredir = (inredir && !ins); 1174 oins = ins; 1175 /* Get the next token. */ 1176 if (linarr) 1177 incmdpos = 0; 1178 ctxtlex(); 1179 1180 if (tok == LEXERR) { 1181 if (!tokstr) 1182 break; 1183 for (j = 0, p = tokstr; *p; p++) 1184 if (*p == Snull || *p == Dnull) 1185 j++; 1186 if (j & 1) { 1187 if (lincmd && strchr(tokstr, '=')) { 1188 varq = 1; 1189 tok = ENVSTRING; 1190 } else 1191 tok = STRING; 1192 } 1193 } else if (tok == ENVSTRING) 1194 varq = 0; 1195 if (tok == ENVARRAY) { 1196 linarr = 1; 1197 zsfree(varname); 1198 varname = ztrdup(tokstr); 1199 } else if (tok == INPAR) 1200 parct++; 1201 else if (tok == OUTPAR) { 1202 if (parct) 1203 parct--; 1204 else 1205 linarr = 0; 1206 } 1207 if (inredir && IS_REDIROP(tok)) { 1208 rdstr = rdstrbuf; 1209 if (tokfd >= 0) 1210 sprintf(rdop, "%d%s", tokfd, tokstrings[tok]); 1211 else 1212 strcpy(rdop, tokstrings[tok]); 1213 strcpy(rdstr, rdop); 1214 /* Record if we haven't had the command word yet */ 1215 if (wordpos == redirpos) 1216 redirpos++; 1217 } 1218 if (tok == DINPAR) 1219 tokstr = NULL; 1220 1221 /* We reached the end. */ 1222 if (tok == ENDINPUT) 1223 break; 1224 if ((ins && (tok == DOLOOP || tok == SEPER)) || 1225 (ins == 2 && wordpos == 2) || (ins == 3 && wordpos == 3) || 1226 tok == BAR || tok == AMPER || 1227 tok == BARAMP || tok == AMPERBANG || 1228 ((tok == DBAR || tok == DAMPER) && !incond) || 1229 /* 1230 * Special case: we might reach a new command (incmdpos set) 1231 * if we've already found the string we're completing (tt set) 1232 * without hitting one of the above if we're using one of 1233 * the special zsh forms of delimiting for conditions and 1234 * loops that I really loathe having to support. 1235 */ 1236 (tt && incmdpos)) { 1237 /* This is one of the things that separate commands. If we * 1238 * already have the things we need (e.g. the token strings), * 1239 * leave the loop. */ 1240 if (tt) 1241 break; 1242 /* Otherwise reset the variables we are collecting data in. */ 1243 wordpos = cp = rd = ins = redirpos = 0; 1244 tt0 = NULLTOK; 1245 } 1246 if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH || 1247 tok == SELECT || tok == REPEAT || tok == CASE)) { 1248 /* The lexer says, this token is in command position, so * 1249 * store the token string (to find the right compctl). */ 1250 ins = (tok == REPEAT ? 2 : (tok != STRING)); 1251 zsfree(cmdstr); 1252 cmdstr = ztrdup(tokstr); 1253 /* If everything before is a redirection, don't reset the index */ 1254 if (wordpos != redirpos) 1255 wordpos = redirpos = 0; 1256 } 1257 if (!lexflags && tt0 == NULLTOK) { 1258 /* This is done when the lexer reached the word the cursor is on. */ 1259 tt = tokstr ? dupstring(tokstr) : NULL; 1260 1261 /* 1262 * If there was a proper interface between this 1263 * function and the lexical analyser, we wouldn't 1264 * have to fix things up. 1265 * 1266 * Fix up backslash-newline pairs in zlemetaline 1267 * that the lexer will have removed. As we're 1268 * looking back at the zlemetaline version it's 1269 * still using untokenized quotes. 1270 */ 1271 for (i = j = k = 0, u = zlemetaline + wb; 1272 u < zlemetaline + we; u++) { 1273 if (*u == '`' && !(k & 1)) 1274 i++; 1275 else if (*u == '\"' && !(k & 1) && !(i & 1)) 1276 j++; 1277 else if (*u == '\'' && !(j & 1)) 1278 k++; 1279 else if (*u == '\\' && u[1] && !(k & 1)) 1280 { 1281 if (u[1] == '\n') { 1282 /* Removed by lexer in tt */ 1283 qsub += 2; 1284 } 1285 u++; 1286 } 1287 } 1288 /* 1289 * Fix up RCQUOTES quotes that the 1290 * the lexer will also have removed. 1291 */ 1292 if (isset(RCQUOTES) && tt) { 1293 char *tt1, *e = tt + zlemetacs - wb - qsub; 1294 for (tt1 = tt; *tt1; tt1++) { 1295 if (*tt1 == Snull) { 1296 char *p; 1297 for (p = tt1; *p && p < e; p++) 1298 if (*p == '\'') 1299 qsub++; 1300 } 1301 } 1302 } 1303 /* If we added a `x', remove it. */ 1304 if (addedx && tt) 1305 chuck(tt + zlemetacs - wb - qsub); 1306 tt0 = tok; 1307 /* Store the number of this word. */ 1308 clwpos = wordpos; 1309 cp = lincmd; 1310 rd = linredir; 1311 ia = linarr; 1312 if (inwhat == IN_NOTHING && incond) 1313 inwhat = IN_COND; 1314 } else if (linredir) { 1315 if (rdop[0] && tokstr) 1316 zaddlinknode(rdstrs, tricat(rdop, ":", tokstr)); 1317 continue; 1318 } 1319 if (incond) { 1320 if (tok == DBAR) 1321 tokstr = "||"; 1322 else if (tok == DAMPER) 1323 tokstr = "&&"; 1324 } 1325 if (!tokstr) 1326 continue; 1327 /* Hack to allow completion after `repeat n do'. */ 1328 if (oins == 2 && !wordpos && !strcmp(tokstr, "do")) 1329 ins = 3; 1330 /* We need to store the token strings of all words (for some of * 1331 * the more complicated compctl -x things). They are stored in * 1332 * the clwords array. Make this array big enough. */ 1333 if (wordpos + 1 == clwsize) { 1334 int n; 1335 clwords = (char **)realloc(clwords, 1336 (clwsize *= 2) * sizeof(char *)); 1337 for(n = clwsize; --n > wordpos; ) 1338 clwords[n] = NULL; 1339 } 1340 zsfree(clwords[wordpos]); 1341 /* And store the current token string. */ 1342 clwords[wordpos] = ztrdup(tokstr); 1343 sl = strlen(tokstr); 1344 /* Sometimes the lexer gives us token strings ending with * 1345 * spaces we delete the spaces. */ 1346 while (sl && clwords[wordpos][sl - 1] == ' ' && 1347 (sl < 2 || (clwords[wordpos][sl - 2] != Bnull && 1348 clwords[wordpos][sl - 2] != Meta))) 1349 clwords[wordpos][--sl] = '\0'; 1350 /* If this is the word the cursor is in and we added a `x', * 1351 * remove it. */ 1352 if (clwpos == wordpos++ && addedx) { 1353 zlemetacs_qsub = zlemetacs - qsub; 1354 chuck(&clwords[wordpos - 1][((zlemetacs_qsub - wb) >= sl) ? 1355 (sl - 1) : (zlemetacs_qsub - wb)]); 1356 } 1357 } while (tok != LEXERR && tok != ENDINPUT && 1358 (tok != SEPER || (lexflags && tt0 == NULLTOK))); 1359 /* Calculate the number of words stored in the clwords array. */ 1360 clwnum = (tt || !wordpos) ? wordpos : wordpos - 1; 1361 zsfree(clwords[clwnum]); 1362 clwords[clwnum] = NULL; 1363 t0 = tt0; 1364 if (ia) { 1365 lincmd = linredir = 0; 1366 inwhat = IN_ENV; 1367 } else { 1368 lincmd = cp; 1369 linredir = rd; 1370 } 1371 strinend(); 1372 inpop(); 1373 errflag = lexflags = 0; 1374 if (parbegin != -1) { 1375 /* We are in command or process substitution if we are not in 1376 * a $((...)). */ 1377 if (parend >= 0 && !tmp) 1378 zlemetaline = dupstring(tmp = zlemetaline); 1379 linptr = zlemetaline + zlemetall + addedx - parbegin + 1; 1380 if ((linptr - zlemetaline) < 3 || *linptr != '(' || 1381 linptr[-1] != '(' || linptr[-2] != '$') { 1382 if (parend >= 0) { 1383 zlemetall -= parend; 1384 zlemetaline[zlemetall + addedx] = '\0'; 1385 } 1386 lexrestore(); 1387 tt = NULL; 1388 goto start; 1389 } 1390 } 1391 1392 if (inwhat == IN_MATH) 1393 s = NULL; 1394 else if (t0 == NULLTOK || t0 == ENDINPUT) { 1395 /* There was no word (empty line). */ 1396 s = ztrdup(""); 1397 we = wb = zlemetacs; 1398 clwpos = clwnum; 1399 t0 = STRING; 1400 } else if (t0 == STRING) { 1401 /* We found a simple string. */ 1402 s = ztrdup(clwords[clwpos]); 1403 } else if (t0 == ENVSTRING) { 1404 char sav; 1405 /* The cursor was inside a parameter assignment. */ 1406 1407 if (varq) 1408 tt = clwords[clwpos]; 1409 1410 s = itype_end(tt, IIDENT, 0); 1411 sav = *s; 1412 *s = '\0'; 1413 zsfree(varname); 1414 varname = ztrdup(tt); 1415 *s = sav; 1416 if (*s == '+') 1417 s++; 1418 if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + 1419 zlemetacs_qsub - wb) { 1420 s = NULL; 1421 inwhat = IN_MATH; 1422 if ((keypm = (Param) paramtab->getnode(paramtab, varname)) && 1423 (keypm->node.flags & PM_HASHED)) 1424 insubscr = 2; 1425 else 1426 insubscr = 1; 1427 } else if (*s == '=') { 1428 if (zlemetacs_qsub > wb + (s - tt)) { 1429 s++; 1430 wb += s - tt; 1431 s = ztrdup(s); 1432 inwhat = IN_ENV; 1433 } else { 1434 char *p = s; 1435 1436 if (p[-1] == '+') 1437 p--; 1438 sav = *p; 1439 *p = '\0'; 1440 inwhat = IN_PAR; 1441 s = ztrdup(tt); 1442 *p = sav; 1443 we = wb + p - tt; 1444 } 1445 t0 = STRING; 1446 } 1447 lincmd = 1; 1448 } 1449 if (we > zlemetall) 1450 we = zlemetall; 1451 tt = zlemetaline; 1452 if (tmp) { 1453 zlemetaline = tmp; 1454 zlemetall = strlen(zlemetaline); 1455 } 1456 if (t0 != STRING && inwhat != IN_MATH) { 1457 if (tmp) { 1458 tmp = NULL; 1459 linptr = zlemetaline; 1460 lexrestore(); 1461 addedx = 0; 1462 goto start; 1463 } 1464 noaliases = ona; 1465 lexrestore(); 1466 return NULL; 1467 } 1468 1469 noaliases = ona; 1470 1471 /* Check if we are in an array subscript. We simply assume that * 1472 * we are in a subscript if we are in brackets. Correct solution * 1473 * is very difficult. This is quite close, but gets things like * 1474 * foo[_ wrong (note no $). If we are in a subscript, treat it * 1475 * as being in math. */ 1476 if (inwhat != IN_MATH) { 1477 char *nnb, *nb = NULL, *ne = NULL; 1478 1479 i = 0; 1480 MB_METACHARINIT(); 1481 if (itype_end(s, IIDENT, 1) == s) 1482 nnb = s + MB_METACHARLEN(s); 1483 else 1484 nnb = s; 1485 for (tt = s; tt < s + zlemetacs_qsub - wb;) { 1486 if (*tt == Inbrack) { 1487 i++; 1488 nb = nnb; 1489 ne = tt; 1490 tt++; 1491 } else if (i && *tt == Outbrack) { 1492 i--; 1493 tt++; 1494 } else { 1495 int nclen = MB_METACHARLEN(tt); 1496 if (itype_end(tt, IIDENT, 1) == tt) 1497 nnb = tt + nclen; 1498 tt += nclen; 1499 } 1500 } 1501 if (i) { 1502 inwhat = IN_MATH; 1503 insubscr = 1; 1504 if (nb < ne) { 1505 char sav = *ne; 1506 *ne = '\0'; 1507 zsfree(varname); 1508 varname = ztrdup(nb); 1509 *ne = sav; 1510 if ((keypm = (Param) paramtab->getnode(paramtab, varname)) && 1511 (keypm->node.flags & PM_HASHED)) 1512 insubscr = 2; 1513 } 1514 } 1515 } 1516 if (inwhat == IN_MATH) { 1517 if (compfunc || insubscr == 2) { 1518 int lev; 1519 char *p; 1520 1521 for (wb = zlemetacs - 1, lev = 0; wb > 0; wb--) 1522 if (zlemetaline[wb] == ']' || zlemetaline[wb] == ')') 1523 lev++; 1524 else if (zlemetaline[wb] == '[') { 1525 if (!lev--) 1526 break; 1527 } else if (zlemetaline[wb] == '(') { 1528 if (!lev && zlemetaline[wb - 1] == '(') 1529 break; 1530 if (lev) 1531 lev--; 1532 } 1533 p = zlemetaline + wb; 1534 wb++; 1535 if (wb && (*p == '[' || *p == '(') && 1536 !skipparens(*p, (*p == '[' ? ']' : ')'), &p)) { 1537 we = (p - zlemetaline) - 1; 1538 if (insubscr == 2) 1539 insubscr = 3; 1540 } 1541 } else { 1542 /* In mathematical expression, we complete parameter names * 1543 * (even if they don't have a `$' in front of them). So we * 1544 * have to find that name. */ 1545 char *cspos = zlemetaline + zlemetacs, *wptr, *cptr; 1546 we = itype_end(cspos, IIDENT, 0) - zlemetaline; 1547 1548 /* 1549 * With multibyte characters we need to go forwards, 1550 * so start at the beginning of the line and continue 1551 * until cspos. 1552 */ 1553 wptr = cptr = zlemetaline; 1554 for (;;) { 1555 cptr = itype_end(wptr, IIDENT, 0); 1556 if (cptr == wptr) { 1557 /* not an ident character */ 1558 wptr = (cptr += MB_METACHARLEN(cptr)); 1559 } 1560 if (cptr >= cspos) { 1561 wb = wptr - zlemetaline; 1562 break; 1563 } 1564 wptr = cptr; 1565 } 1566 } 1567 zsfree(s); 1568 s = zalloc(we - wb + 1); 1569 strncpy(s, zlemetaline + wb, we - wb); 1570 s[we - wb] = '\0'; 1571 1572 if (wb > 2 && zlemetaline[wb - 1] == '[') { 1573 char *sqbr = zlemetaline + wb - 1, *cptr, *wptr; 1574 1575 /* Need to search forward for word characters */ 1576 cptr = wptr = zlemetaline; 1577 for (;;) { 1578 cptr = itype_end(wptr, IIDENT, 0); 1579 if (cptr == wptr) { 1580 /* not an ident character */ 1581 wptr = (cptr += MB_METACHARLEN(cptr)); 1582 } 1583 if (cptr >= sqbr) 1584 break; 1585 wptr = cptr; 1586 } 1587 1588 if (wptr < sqbr) { 1589 zsfree(varname); 1590 varname = ztrduppfx(wptr, sqbr - wptr); 1591 if ((keypm = (Param) paramtab->getnode(paramtab, varname)) && 1592 (keypm->node.flags & PM_HASHED)) { 1593 if (insubscr != 3) 1594 insubscr = 2; 1595 } else 1596 insubscr = 1; 1597 } 1598 } 1599 1600 parse_subst_string(s); 1601 } 1602 /* This variable will hold the current word in quoted form. */ 1603 offs = zlemetacs - wb; 1604 if ((p = parambeg(s))) { 1605 for (p = s; *p; p++) 1606 if (*p == Dnull) 1607 *p = '"'; 1608 else if (*p == Snull) 1609 *p = '\''; 1610 } else { 1611 int level = 0; 1612 1613 for (p = s; *p; p++) { 1614 if (level && *p == Snull) 1615 *p = '\''; 1616 else if (level && *p == Dnull) 1617 *p = '"'; 1618 else if ((*p == String || *p == Qstring) && p[1] == Inbrace) 1619 level++; 1620 else if (*p == Outbrace) 1621 level--; 1622 } 1623 } 1624 if ((*s == Snull || *s == Dnull || 1625 ((*s == String || *s == Qstring) && s[1] == Snull)) 1626 && !has_real_token(s + 1)) { 1627 int sl = strlen(s); 1628 char *q, *qtptr = s, *n; 1629 1630 switch (*s) { 1631 case Snull: 1632 q = "'"; 1633 instring = QT_SINGLE; 1634 break; 1635 1636 case Dnull: 1637 q = "\""; 1638 instring = QT_DOUBLE; 1639 break; 1640 1641 default: 1642 q = "$'"; 1643 instring = QT_DOLLARS; 1644 qtptr++; 1645 sl--; 1646 break; 1647 } 1648 1649 n = tricat(qipre, q, ""); 1650 zsfree(qipre); 1651 qipre = n; 1652 /* 1653 * TODO: it's certainly the case that the suffix for 1654 * $' is ', but exactly what does that affect? 1655 */ 1656 if (*q == '$') 1657 q++; 1658 if (sl > 1 && qtptr[sl - 1] == *qtptr) { 1659 n = tricat(q, qisuf, ""); 1660 zsfree(qisuf); 1661 qisuf = n; 1662 } 1663 autoq = ztrdup(q); 1664 1665 /* 1666 * \! in double quotes is extracted by the history code before normal 1667 * parsing, so sanitize it here, too. 1668 */ 1669 if (instring == QT_DOUBLE) { 1670 for (q = s; *q; q++) 1671 if (*q == '\\' && q[1] == '!') 1672 *q = Bnull; 1673 } 1674 } 1675 /* 1676 * Leading "=" gets tokenized in case the EQUALS options 1677 * changes afterwards. It's too late for that now, so restore it 1678 * to a plain "=" if the option is unset. 1679 */ 1680 if (*s == Equals && !isset(EQUALS)) 1681 *s = '='; 1682 /* While building the quoted form, we also clean up the command line. */ 1683 for (p = s, i = wb, j = 0; *p; p++, i++) { 1684 int skipchars; 1685 if (*p == String && p[1] == Snull) { 1686 char *pe; 1687 for (pe = p + 2; *pe && *pe != Snull && i + (pe - p) < zlemetacs; 1688 pe++) 1689 ; 1690 if (!*pe) { 1691 /* no terminating Snull, can't substitute */ 1692 skipchars = 2; 1693 } else { 1694 /* 1695 * Try and substitute the $'...' expression. 1696 */ 1697 int len, tlen; 1698 char *t = getkeystring(p + 2, &len, GETKEYS_DOLLARS_QUOTE, 1699 NULL); 1700 len += 2; 1701 tlen = strlen(t); 1702 skipchars = len - tlen; 1703 /* 1704 * If this makes the line longer, we don't attempt 1705 * to substitute it. This is because "we" don't 1706 * really understand what the heck is going on anyway 1707 * and have blindly copied the code here from 1708 * the sections below. 1709 */ 1710 if (skipchars >= 0) { 1711 /* Update the completion string */ 1712 memcpy(p, t, tlen); 1713 /* Update the version of the line we are operating on */ 1714 ocs = zlemetacs; 1715 zlemetacs = i; 1716 if (skipchars > 0) { 1717 /* Move the tail of the completion string up. */ 1718 char *dptr = p + tlen; 1719 char *sptr = p + len; 1720 while ((*dptr++ = *sptr++)) 1721 ; 1722 /* 1723 * If the character is before the cursor, we need to 1724 * update the offset into the completion string to the 1725 * cursor position, too. (Use ocs since we've hacked 1726 * zlemetacs at this point.) 1727 */ 1728 if (i < ocs) 1729 offs -= skipchars; 1730 /* Move the tail of the line up */ 1731 foredel(skipchars, CUT_RAW); 1732 /* 1733 * Update the offset into the command line to the 1734 * cursor position if that's after the current position. 1735 */ 1736 if ((zlemetacs = ocs) > i) 1737 zlemetacs -= skipchars; 1738 /* Always update the word end. */ 1739 we -= skipchars; 1740 } 1741 /* 1742 * Copy the unquoted string into place, which 1743 * now has the correct size. 1744 */ 1745 memcpy(zlemetaline + i, t, tlen); 1746 1747 /* 1748 * Move both the completion string pointer 1749 * and the command line offset to the end of 1750 * the chunk we've copied in (minus 1 for 1751 * the end of loop increment). The line 1752 * and completion string chunks are now the 1753 * same length. 1754 */ 1755 p += tlen - 1; 1756 i += tlen - 1; 1757 continue; 1758 } else { 1759 /* 1760 * We give up if the expansion is longer the original 1761 * string. That's because "we" don't really have the 1762 * first clue how the completion system actually works. 1763 */ 1764 skipchars = 2; 1765 } 1766 } 1767 } 1768 else if (*p == Qstring && p[1] == Snull) 1769 skipchars = 2; 1770 else if (inull(*p)) 1771 skipchars = 1; 1772 else 1773 skipchars = 0; 1774 if (skipchars) { 1775 if (i < zlemetacs) 1776 offs -= skipchars; 1777 if (*p == Snull && isset(RCQUOTES)) 1778 j = 1-j; 1779 if (p[1] || *p != Bnull) { 1780 if (*p == Bnull) { 1781 if (zlemetacs == i + 1) 1782 zlemetacs++, offs++; 1783 } else { 1784 ocs = zlemetacs; 1785 zlemetacs = i; 1786 foredel(skipchars, CUT_RAW); 1787 if ((zlemetacs = ocs) > (i -= skipchars)) 1788 zlemetacs -= skipchars; 1789 we -= skipchars; 1790 } 1791 } else { 1792 ocs = zlemetacs; 1793 zlemetacs = we; 1794 backdel(skipchars, CUT_RAW); 1795 if (ocs == we) 1796 zlemetacs = we - skipchars; 1797 else 1798 zlemetacs = ocs; 1799 we -= skipchars; 1800 } 1801 /* we need to get rid of all the quotation bits... */ 1802 while (skipchars--) 1803 chuck(p); 1804 /* but we only decrement once to confuse the loop increment. */ 1805 p--; 1806 } else if (j && *p == '\'' && i < zlemetacs) 1807 offs--; 1808 } 1809 1810 zsfree(origword); 1811 origword = ztrdup(s); 1812 1813 if (!isset(IGNOREBRACES)) { 1814 /* Try and deal with foo{xxx etc. */ 1815 char *curs = s + (isset(COMPLETEINWORD) ? offs : (int)strlen(s)); 1816 char *predup = dupstring(s), *dp = predup; 1817 char *bbeg = NULL, *bend = NULL, *dbeg = NULL; 1818 char *lastp = NULL, *firsts = NULL; 1819 int cant = 0, begi = 0, boffs = offs, hascom = 0; 1820 1821 for (i = 0, p = s; *p; p++, dp++, i++) { 1822 /* careful, ${... is not a brace expansion... 1823 * we try to get braces after a parameter expansion right, 1824 * but this may fail sometimes. sorry. 1825 */ 1826 if (*p == String || *p == Qstring) { 1827 if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) { 1828 char *tp = p + 1; 1829 1830 if (skipparens(*tp, (*tp == Inbrace ? Outbrace : 1831 (*tp == Inpar ? Outpar : Outbrack)), 1832 &tp)) { 1833 tt = NULL; 1834 break; 1835 } 1836 i += tp - p; 1837 dp += tp - p; 1838 p = tp; 1839 } else if (p[1] != Snull /* paranoia: should be gone now */) { 1840 char *tp = p + 1; 1841 1842 for (; *tp == '^' || *tp == Hat || 1843 *tp == '=' || *tp == Equals || 1844 *tp == '~' || *tp == Tilde || 1845 *tp == '#' || *tp == Pound || *tp == '+'; 1846 tp++); 1847 if (*tp == Quest || *tp == Star || *tp == String || 1848 *tp == Qstring || *tp == '?' || *tp == '*' || 1849 *tp == '$' || *tp == '-' || *tp == '!' || 1850 *tp == '@') 1851 p++, i++; 1852 else { 1853 char *ie; 1854 if (idigit(*tp)) 1855 while (idigit(*tp)) 1856 tp++; 1857 else if ((ie = itype_end(tp, IIDENT, 0)) != tp) 1858 tp = ie; 1859 else { 1860 tt = NULL; 1861 break; 1862 } 1863 if (*tp == Inbrace) { 1864 cant = 1; 1865 break; 1866 } 1867 tp--; 1868 i += tp - p; 1869 dp += tp - p; 1870 p = tp; 1871 } 1872 } 1873 } else if (p < curs) { 1874 if (*p == Outbrace) { 1875 /* 1876 * HERE: strip and remember code from last 1877 * comma to here. 1878 */ 1879 cant = 1; 1880 break; 1881 } 1882 if (*p == Inbrace) { 1883 char *tp = p; 1884 1885 if (!skipparens(Inbrace, Outbrace, &tp)) { 1886 /* 1887 * Balanced brace: skip. 1888 * We only deal with unfinished braces, so 1889 * something{foo<x>bar,morestuff}else 1890 * doesn't work 1891 * 1892 * HERE: instead, continue, look for a comma. 1893 * Stack tp and brace for popping when we 1894 * find a comma at each level. 1895 */ 1896 i += tp - p - 1; 1897 dp += tp - p - 1; 1898 p = tp - 1; 1899 continue; 1900 } 1901 makecommaspecial(1); 1902 if (bbeg) { 1903 Brinfo new; 1904 int len = bend - bbeg; 1905 1906 new = (Brinfo) zalloc(sizeof(*new)); 1907 nbrbeg++; 1908 1909 new->next = NULL; 1910 if (lastbrbeg) 1911 lastbrbeg->next = new; 1912 else 1913 brbeg = new; 1914 lastbrbeg = new; 1915 1916 new->next = NULL; 1917 new->str = dupstrpfx(bbeg, len); 1918 new->str = ztrdup(quotename(new->str, NULL)); 1919 untokenize(new->str); 1920 new->pos = begi; 1921 *dbeg = '\0'; 1922 new->qpos = strlen(quotename(predup, NULL)); 1923 *dbeg = '{'; 1924 i -= len; 1925 boffs -= len; 1926 memmove(dbeg, dbeg + len, 1+strlen(dbeg+len)); 1927 dp -= len; 1928 } 1929 bbeg = lastp = p; 1930 dbeg = dp; 1931 bend = p + 1; 1932 begi = i; 1933 } else if (*p == Comma && bbeg) { 1934 bend = p + 1; 1935 hascom = 1; 1936 } 1937 } else { 1938 /* On or after the cursor position */ 1939 if (*p == Inbrace) { 1940 char *tp = p; 1941 1942 if (!skipparens(Inbrace, Outbrace, &tp)) { 1943 /* 1944 * Balanced braces after the cursor. 1945 * Could do the same with these as 1946 * those before the cursor. 1947 */ 1948 i += tp - p - 1; 1949 dp += tp - p - 1; 1950 p = tp - 1; 1951 continue; 1952 } 1953 cant = 1; 1954 makecommaspecial(1); 1955 break; 1956 } 1957 if (p == curs) { 1958 /* 1959 * We've reached the cursor position. 1960 * If there's a pending open brace at this 1961 * point we need to stack the text. 1962 * We've marked the bit we don't want from 1963 * bbeg to bend, which might be a comma 1964 * between the opening brace and us. 1965 */ 1966 if (bbeg) { 1967 Brinfo new; 1968 int len = bend - bbeg; 1969 1970 new = (Brinfo) zalloc(sizeof(*new)); 1971 nbrbeg++; 1972 1973 new->next = NULL; 1974 if (lastbrbeg) 1975 lastbrbeg->next = new; 1976 else 1977 brbeg = new; 1978 lastbrbeg = new; 1979 1980 new->str = dupstrpfx(bbeg, len); 1981 new->str = ztrdup(quotename(new->str, NULL)); 1982 untokenize(new->str); 1983 new->pos = begi; 1984 *dbeg = '\0'; 1985 new->qpos = strlen(quotename(predup, NULL)); 1986 *dbeg = '{'; 1987 i -= len; 1988 boffs -= len; 1989 memmove(dbeg, dbeg + len, 1+strlen(dbeg+len)); 1990 dp -= len; 1991 } 1992 bbeg = NULL; 1993 } 1994 if (*p == Comma) { 1995 /* 1996 * Comma on or after cursor. 1997 * We set bbeg to NULL at the cursor; here 1998 * it's being used to find the first comma 1999 * afterwards. 2000 */ 2001 if (!bbeg) 2002 bbeg = p; 2003 hascom = 2; 2004 } else if (*p == Outbrace) { 2005 /* 2006 * Closing brace on or after the cursor. 2007 * Not sure how this can be after the cursor; 2008 * if it was matched, wouldn't we have skipped 2009 * over the group, and if it wasn't, surely we're 2010 * not interested in it? 2011 */ 2012 Brinfo new; 2013 int len; 2014 2015 if (!bbeg) 2016 bbeg = p; 2017 len = p + 1 - bbeg; 2018 if (!firsts) 2019 firsts = p + 1; 2020 2021 new = (Brinfo) zalloc(sizeof(*new)); 2022 nbrend++; 2023 2024 if (!lastbrend) 2025 lastbrend = new; 2026 2027 new->next = brend; 2028 brend = new; 2029 2030 new->str = dupstrpfx(bbeg, len); 2031 new->str = ztrdup(quotename(new->str, NULL)); 2032 untokenize(new->str); 2033 new->pos = dp - predup - len + 1; 2034 new->qpos = len; 2035 bbeg = NULL; 2036 } 2037 } 2038 } 2039 if (cant) { 2040 freebrinfo(brbeg); 2041 freebrinfo(brend); 2042 brbeg = lastbrbeg = brend = lastbrend = NULL; 2043 nbrbeg = nbrend = 0; 2044 } else { 2045 if (p == curs && bbeg) { 2046 Brinfo new; 2047 int len = bend - bbeg; 2048 2049 new = (Brinfo) zalloc(sizeof(*new)); 2050 nbrbeg++; 2051 2052 new->next = NULL; 2053 if (lastbrbeg) 2054 lastbrbeg->next = new; 2055 else 2056 brbeg = new; 2057 lastbrbeg = new; 2058 2059 new->str = dupstrpfx(bbeg, len); 2060 new->str = ztrdup(quotename(new->str, NULL)); 2061 untokenize(new->str); 2062 new->pos = begi; 2063 *dbeg = '\0'; 2064 new->qpos = strlen(quotename(predup, NULL)); 2065 *dbeg = '{'; 2066 boffs -= len; 2067 memmove(dbeg, dbeg + len, 1+strlen(dbeg+len)); 2068 } 2069 if (brend) { 2070 Brinfo bp, prev = NULL; 2071 int p, l; 2072 2073 for (bp = brend; bp; bp = bp->next) { 2074 bp->prev = prev; 2075 prev = bp; 2076 p = bp->pos; 2077 l = bp->qpos; 2078 bp->pos = strlen(predup + p + l); 2079 bp->qpos = strlen(quotename(predup + p + l, NULL)); 2080 memmove(predup + p, predup + p + l, 1+bp->pos); 2081 } 2082 } 2083 if (hascom) { 2084 if (lastp) { 2085 char sav = *lastp; 2086 2087 *lastp = '\0'; 2088 untokenize(lastprebr = ztrdup(s)); 2089 *lastp = sav; 2090 } 2091 if ((lastpostbr = ztrdup(firsts))) 2092 untokenize(lastpostbr); 2093 } 2094 zsfree(s); 2095 s = ztrdup(predup); 2096 offs = boffs; 2097 } 2098 } 2099 lexrestore(); 2100 2101 return (char *)s; 2102} 2103 2104/* Insert the given string into the command line. If move is non-zero, * 2105 * the cursor position is changed and len is the length of the string * 2106 * to insert (if it is -1, the length is calculated here). * 2107 * The last argument says if we should quote the string. */ 2108 2109/**/ 2110mod_export int 2111inststrlen(char *str, int move, int len) 2112{ 2113 if (!len || !str) 2114 return 0; 2115 if (len == -1) 2116 len = strlen(str); 2117 spaceinline(len); 2118 if (zlemetaline != NULL) { 2119 strncpy(zlemetaline + zlemetacs, str, len); 2120 if (move) 2121 zlemetacs += len; 2122 } else { 2123 char *instr; 2124 ZLE_STRING_T zlestr; 2125 int zlelen; 2126 2127 instr = ztrduppfx(str, len); 2128 zlestr = stringaszleline(instr, 0, &zlelen, NULL, NULL); 2129 ZS_strncpy(zleline + zlecs, zlestr, zlelen); 2130 free(zlestr); 2131 zsfree(instr); 2132 if (move) 2133 zlecs += len; 2134 } 2135 return len; 2136} 2137 2138/* Expand the current word. */ 2139 2140/**/ 2141static int 2142doexpansion(char *s, int lst, int olst, int explincmd) 2143{ 2144 int ret = 1, first = 1; 2145 LinkList vl; 2146 char *ss, *ts; 2147 2148 pushheap(); 2149 vl = newlinklist(); 2150 ss = dupstring(s); 2151 /* get_comp_string() leaves these quotes unchanged when they are 2152 * inside parameter expansions. */ 2153 for (ts = ss; *ts; ts++) 2154 if (*ts == '"') 2155 *ts = Dnull; 2156 else if (*ts == '\'') 2157 *ts = Snull; 2158 addlinknode(vl, ss); 2159 prefork(vl, 0); 2160 if (errflag) 2161 goto end; 2162 if (lst == COMP_LIST_EXPAND || lst == COMP_EXPAND) { 2163 int ng = opts[NULLGLOB]; 2164 2165 opts[NULLGLOB] = 1; 2166 globlist(vl, 1); 2167 opts[NULLGLOB] = ng; 2168 } 2169 if (errflag) 2170 goto end; 2171 if (empty(vl) || !*(char *)peekfirst(vl)) 2172 goto end; 2173 if (peekfirst(vl) == (void *) ss || 2174 (olst == COMP_EXPAND_COMPLETE && 2175 !nextnode(firstnode(vl)) && *s == Tilde && 2176 (ss = dupstring(s), filesubstr(&ss, 0)) && 2177 !strcmp(ss, (char *)peekfirst(vl)))) { 2178 /* If expansion didn't change the word, try completion if * 2179 * expandorcomplete was called, otherwise, just beep. */ 2180 if (lst == COMP_EXPAND_COMPLETE) 2181 docompletion(s, COMP_COMPLETE, explincmd); 2182 goto end; 2183 } 2184 if (lst == COMP_LIST_EXPAND) { 2185 /* Only the list of expansions was requested. Restore the 2186 * command line. */ 2187 zlemetacs = 0; 2188 foredel(zlemetall, CUT_RAW); 2189 spaceinline(origll); 2190 memcpy(zlemetaline, origline, origll); 2191 zlemetacs = origcs; 2192 ret = listlist(vl); 2193 showinglist = 0; 2194 goto end; 2195 } 2196 /* Remove the current word and put the expansions there. */ 2197 zlemetacs = wb; 2198 foredel(we - wb, CUT_RAW); 2199 while ((ss = (char *)ugetnode(vl))) { 2200 ret = 0; 2201 ss = quotename(ss, NULL); 2202 untokenize(ss); 2203 inststr(ss); 2204 if (nonempty(vl) || !first) { 2205 spaceinline(1); 2206 zlemetaline[zlemetacs++] = ' '; 2207 } 2208 first = 0; 2209 } 2210 end: 2211 popheap(); 2212 2213 return ret; 2214} 2215 2216/**/ 2217static int 2218docompletion(char *s, int lst, int incmd) 2219{ 2220 struct compldat dat; 2221 2222 dat.s = s; 2223 dat.lst = lst; 2224 dat.incmd = incmd; 2225 2226 return runhookdef(COMPLETEHOOK, (void *) &dat); 2227} 2228 2229/* 2230 * Return the length of the common prefix of s and t. 2231 * s and t are both metafied; the length returned is a raw byte count 2232 * into both strings, excluding any common bytes that form less than 2233 * a complete wide character. 2234 */ 2235 2236/**/ 2237mod_export int 2238pfxlen(char *s, char *t) 2239{ 2240 int i = 0; 2241 2242#ifdef MULTIBYTE_SUPPORT 2243 wchar_t wc; 2244 mbstate_t mbs; 2245 size_t cnt; 2246 int lasti = 0; 2247 char inc; 2248 2249 memset(&mbs, 0, sizeof mbs); 2250 while (*s) { 2251 if (*s == Meta) { 2252 if (*t != Meta || t[1] != s[1]) 2253 break; 2254 inc = s[1] ^ 32; 2255 i += 2; 2256 s += 2; 2257 t += 2; 2258 } else { 2259 if (*s != *t) 2260 break; 2261 inc = *s; 2262 i++; 2263 s++; 2264 t++; 2265 } 2266 2267 cnt = mbrtowc(&wc, &inc, 1, &mbs); 2268 if (cnt == MB_INVALID) { 2269 /* error */ 2270 break; 2271 } 2272 if (cnt != MB_INCOMPLETE) { 2273 /* successfully found complete character, record position */ 2274 lasti = i; 2275 } 2276 /* Otherwise, not found a complete character: keep trying. */ 2277 } 2278 return lasti; 2279#else 2280 while (*s && *s == *t) 2281 s++, t++, i++; 2282 return i; 2283#endif 2284} 2285 2286/* Return the length of the common suffix of s and t. */ 2287 2288#if 0 2289static int 2290sfxlen(char *s, char *t) 2291{ 2292 if (*s && *t) { 2293 int i = 0; 2294 char *s2 = s + strlen(s) - 1, *t2 = t + strlen(t) - 1; 2295 2296 while (s2 >= s && t2 >= t && *s2 == *t2) 2297 s2--, t2--, i++; 2298 2299 return i; 2300 } else 2301 return 0; 2302} 2303#endif 2304 2305/* This is zstrcmp with ignoring backslashes. */ 2306 2307/**/ 2308mod_export int 2309zstrbcmp(const char *a, const char *b) 2310{ 2311 const char *astart = a; 2312 2313 while (*a && *b) { 2314 if (*a == '\\') 2315 a++; 2316 if (*b == '\\') 2317 b++; 2318 if (*a != *b || !*a) 2319 break; 2320 a++; 2321 b++; 2322 } 2323 if (isset(NUMERICGLOBSORT) && (idigit(*a) || idigit(*b))) { 2324 for (; a > astart && idigit(a[-1]); a--, b--); 2325 if (idigit(*a) && idigit(*b)) { 2326 while (*a == '0') 2327 a++; 2328 while (*b == '0') 2329 b++; 2330 for (; idigit(*a) && *a == *b; a++, b++); 2331 if (idigit(*a) || idigit(*b)) { 2332 int cmp = (int) STOUC(*a) - (int) STOUC(*b); 2333 2334 while (idigit(*a) && idigit(*b)) 2335 a++, b++; 2336 if (idigit(*a) && !idigit(*b)) 2337 return 1; 2338 if (idigit(*b) && !idigit(*a)) 2339 return -1; 2340 2341 return cmp; 2342 } 2343 } 2344 } 2345#ifndef HAVE_STRCOLL 2346 return (int)(*a - *b); 2347#else 2348 return strcoll(a,b); 2349#endif 2350} 2351 2352/* This is used to print the strings (e.g. explanations). * 2353 * It returns the number of lines printed. */ 2354 2355/**/ 2356mod_export int 2357printfmt(char *fmt, int n, int dopr, int doesc) 2358{ 2359 char *p = fmt, nc[DIGBUFSIZE]; 2360 int l = 0, cc = 0, b = 0, s = 0, u = 0, m; 2361 2362 MB_METACHARINIT(); 2363 for (; *p; ) { 2364 /* Handle the `%' stuff (%% == %, %n == <number of matches>). */ 2365 if (doesc && *p == '%') { 2366 int arg = 0, is_fg; 2367 if (idigit(*++p)) 2368 arg = zstrtol(p, &p, 10); 2369 if (*p) { 2370 m = 0; 2371 switch (*p) { 2372 case '%': 2373 if (dopr) 2374 putc('%', shout); 2375 cc++; 2376 break; 2377 case 'n': 2378 sprintf(nc, "%d", n); 2379 if (dopr) 2380 fputs(nc, shout); 2381 cc += MB_METASTRWIDTH(nc); 2382 break; 2383 case 'B': 2384 b = 1; 2385 if (dopr) 2386 tcout(TCBOLDFACEBEG); 2387 break; 2388 case 'b': 2389 b = 0; m = 1; 2390 if (dopr) 2391 tcout(TCALLATTRSOFF); 2392 break; 2393 case 'S': 2394 s = 1; 2395 if (dopr) 2396 tcout(TCSTANDOUTBEG); 2397 break; 2398 case 's': 2399 s = 0; m = 1; 2400 if (dopr) 2401 tcout(TCSTANDOUTEND); 2402 break; 2403 case 'U': 2404 u = 1; 2405 if (dopr) 2406 tcout(TCUNDERLINEBEG); 2407 break; 2408 case 'u': 2409 u = 0; m = 1; 2410 if (dopr) 2411 tcout(TCUNDERLINEEND); 2412 break; 2413 case 'F': 2414 case 'K': 2415 is_fg = (*p == 'F'); 2416 if (p[1] == '{') { 2417 p += 2; 2418 arg = match_colour((const char **)&p, is_fg, 0); 2419 if (*p != '}') 2420 p--; 2421 } else 2422 arg = match_colour(NULL, is_fg, arg); 2423 if (arg >= 0) 2424 set_colour_attribute(arg, is_fg ? COL_SEQ_FG : 2425 COL_SEQ_BG, 0); 2426 break; 2427 case 'f': 2428 set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, 0); 2429 break; 2430 case 'k': 2431 set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, 0); 2432 break; 2433 case '{': 2434 if (arg) 2435 cc += arg; 2436 for (p++; *p && (*p != '%' || p[1] != '}'); p++) { 2437 if (*p == Meta) { 2438 p++; 2439 if (dopr) 2440 putc(*p ^ 32, shout); 2441 } 2442 else if (dopr) 2443 putc(*p, shout); 2444 } 2445 if (*p) 2446 p++; 2447 else 2448 p--; 2449 break; 2450 } 2451 if (dopr && m) { 2452 if (b) 2453 tcout(TCBOLDFACEBEG); 2454 if (s) 2455 tcout(TCSTANDOUTBEG); 2456 if (u) 2457 tcout(TCUNDERLINEBEG); 2458 } 2459 } else 2460 break; 2461 p++; 2462 } else { 2463 if (*p == '\n') { 2464 cc++; 2465 if (dopr) { 2466 if (tccan(TCCLEAREOL)) 2467 tcout(TCCLEAREOL); 2468 else { 2469 int s = zterm_columns - 1 - (cc % zterm_columns); 2470 2471 while (s-- > 0) 2472 putc(' ', shout); 2473 } 2474 } 2475 l += 1 + ((cc - 1) / zterm_columns); 2476 cc = 0; 2477 if (dopr) 2478 putc('\n', shout); 2479 p++; 2480 } else { 2481 convchar_t cchar; 2482 int clen = MB_METACHARLENCONV(p, &cchar); 2483 if (dopr) { 2484 while (clen--) { 2485 if (*p == Meta) { 2486 p++; 2487 clen--; 2488 putc(*p++ ^ 32, shout); 2489 } else 2490 putc(*p++, shout); 2491 } 2492 } else 2493 p += clen; 2494 cc += WCWIDTH_WINT(cchar); 2495 if (dopr && !(cc % zterm_columns)) 2496 fputs(" \010", shout); 2497 } 2498 } 2499 } 2500 if (dopr) { 2501 if (!(cc % zterm_columns)) 2502 fputs(" \010", shout); 2503 if (tccan(TCCLEAREOL)) 2504 tcout(TCCLEAREOL); 2505 else { 2506 int s = zterm_columns - 1 - (cc % zterm_columns); 2507 2508 while (s-- > 0) 2509 putc(' ', shout); 2510 } 2511 } 2512 /* 2513 * Experiments suggest that at this point not subtracting 1 from 2514 * cc is correct, i.e. if just misses wrapping we still add 1. 2515 * (Why?) 2516 */ 2517 return l + (cc / zterm_columns); 2518} 2519 2520/* This is used to print expansions. */ 2521 2522/**/ 2523int 2524listlist(LinkList l) 2525{ 2526 int num = countlinknodes(l); 2527 VARARR(char *, data, (num + 1)); 2528 LinkNode node; 2529 char **p; 2530 VARARR(int, lens, num); 2531 VARARR(int, widths, zterm_columns); 2532 int longest = 0, shortest = zterm_columns, totl = 0; 2533 int len, ncols, nlines, tolast, col, i, max, pack = 0, *lenp; 2534 2535 for (node = firstnode(l), p = data; node; incnode(node), p++) 2536 *p = (char *) getdata(node); 2537 *p = NULL; 2538 2539 strmetasort((char **)data, SORTIT_IGNORING_BACKSLASHES | 2540 (isset(NUMERICGLOBSORT) ? SORTIT_NUMERICALLY : 0), NULL); 2541 2542 for (p = data, lenp = lens; *p; p++, lenp++) { 2543 len = *lenp = ZMB_nicewidth(*p) + 2; 2544 if (len > longest) 2545 longest = len; 2546 if (len < shortest) 2547 shortest = len; 2548 totl += len; 2549 } 2550 if ((ncols = ((zterm_columns + 2) / longest))) { 2551 int tlines = 0, tline, tcols = 0, maxlen, nth, width; 2552 2553 nlines = (num + ncols - 1) / ncols; 2554 2555 if (isset(LISTPACKED)) { 2556 if (isset(LISTROWSFIRST)) { 2557 int count, tcol, first, maxlines = 0, llines; 2558 2559 for (tcols = zterm_columns / shortest; tcols > ncols; 2560 tcols--) { 2561 for (nth = first = maxlen = width = maxlines = 2562 llines = tcol = 0, 2563 count = num; 2564 count > 0; count--) { 2565 if (!(nth % tcols)) 2566 llines++; 2567 if (lens[nth] > maxlen) 2568 maxlen = lens[nth]; 2569 nth += tcols; 2570 tlines++; 2571 if (nth >= num) { 2572 if ((width += maxlen) >= zterm_columns) 2573 break; 2574 widths[tcol++] = maxlen; 2575 maxlen = 0; 2576 nth = ++first; 2577 if (llines > maxlines) 2578 maxlines = llines; 2579 llines = 0; 2580 } 2581 } 2582 if (nth < num) { 2583 widths[tcol++] = maxlen; 2584 width += maxlen; 2585 } 2586 if (!count && width < zterm_columns) 2587 break; 2588 } 2589 if (tcols > ncols) 2590 tlines = maxlines; 2591 } else { 2592 for (tlines = ((totl + zterm_columns) / zterm_columns); 2593 tlines < nlines; tlines++) { 2594 for (p = data, nth = tline = width = 2595 maxlen = tcols = 0; 2596 *p; nth++, p++) { 2597 if (lens[nth] > maxlen) 2598 maxlen = lens[nth]; 2599 if (++tline == tlines) { 2600 if ((width += maxlen) >= zterm_columns) 2601 break; 2602 widths[tcols++] = maxlen; 2603 maxlen = tline = 0; 2604 } 2605 } 2606 if (tline) { 2607 widths[tcols++] = maxlen; 2608 width += maxlen; 2609 } 2610 if (nth == num && width < zterm_columns) 2611 break; 2612 } 2613 } 2614 if ((pack = (tlines < nlines))) { 2615 nlines = tlines; 2616 ncols = tcols; 2617 } 2618 } 2619 } else { 2620 nlines = 0; 2621 for (p = data; *p; p++) 2622 nlines += 1 + (strlen(*p) / zterm_columns); 2623 } 2624 /* Set the cursor below the prompt. */ 2625 trashzle(); 2626 2627 tolast = ((zmult == 1) == !!isset(ALWAYSLASTPROMPT)); 2628 clearflag = (isset(USEZLE) && !termflags && tolast); 2629 2630 max = getiparam("LISTMAX"); 2631 if ((max && num > max) || (!max && nlines > zterm_lines)) { 2632 int qup, l; 2633 2634 zsetterm(); 2635 l = (num > 0 ? 2636 fprintf(shout, "zsh: do you wish to see all %d possibilities (%d lines)? ", 2637 num, nlines) : 2638 fprintf(shout, "zsh: do you wish to see all %d lines? ", nlines)); 2639 qup = ((l + zterm_columns - 1) / zterm_columns) - 1; 2640 fflush(shout); 2641 if (!getzlequery()) { 2642 if (clearflag) { 2643 putc('\r', shout); 2644 tcmultout(TCUP, TCMULTUP, qup); 2645 if (tccan(TCCLEAREOD)) 2646 tcout(TCCLEAREOD); 2647 tcmultout(TCUP, TCMULTUP, nlnct); 2648 } else 2649 putc('\n', shout); 2650 return 1; 2651 } 2652 if (clearflag) { 2653 putc('\r', shout); 2654 tcmultout(TCUP, TCMULTUP, qup); 2655 if (tccan(TCCLEAREOD)) 2656 tcout(TCCLEAREOD); 2657 } else 2658 putc('\n', shout); 2659 settyinfo(&shttyinfo); 2660 } 2661 lastlistlen = (clearflag ? nlines : 0); 2662 2663 if (ncols) { 2664 if (isset(LISTROWSFIRST)) { 2665 for (col = 1, p = data, lenp = lens; *p; 2666 p++, lenp++, col++) { 2667 nicezputs(*p, shout); 2668 if (col == ncols) { 2669 col = 0; 2670 if (p[1]) 2671 putc('\n', shout); 2672 } else { 2673 if ((i = (pack ? widths[col - 1] : longest) - *lenp + 2) > 0) 2674 while (i--) 2675 putc(' ', shout); 2676 } 2677 } 2678 } else { 2679 char **f; 2680 int *fl, line; 2681 2682 for (f = data, fl = lens, line = 0; line < nlines; 2683 f++, fl++, line++) { 2684 for (col = 1, p = f, lenp = fl; *p; col++) { 2685 nicezputs(*p, shout); 2686 if (col == ncols) 2687 break; 2688 if ((i = (pack ? widths[col - 1] : longest) - *lenp + 2) > 0) 2689 while (i--) 2690 putc(' ', shout); 2691 for (i = nlines; i && *p; i--, p++, lenp++); 2692 } 2693 if (line + 1 < nlines) 2694 putc('\n', shout); 2695 } 2696 } 2697 } else { 2698 for (p = data; *p; p++) { 2699 nicezputs(*p, shout); 2700 /* One column: newlines between elements, not after the last */ 2701 if (p[1]) 2702 putc('\n', shout); 2703 } 2704 } 2705 if (clearflag) { 2706 if ((nlines += nlnct - 1) < zterm_lines) { 2707 tcmultout(TCUP, TCMULTUP, nlines); 2708 showinglist = -1; 2709 } else 2710 clearflag = 0, putc('\n', shout); 2711 } else 2712 putc('\n', shout); 2713 2714 if (listshown) 2715 showagain = 1; 2716 2717 return !num; 2718} 2719 2720/* Expand the history references. */ 2721 2722/**/ 2723int 2724doexpandhist(void) 2725{ 2726 char *ol; 2727 int ne = noerrs, err, ona = noaliases; 2728 2729 UNMETACHECK(); 2730 2731 pushheap(); 2732 metafy_line(); 2733 zle_save_positions(); 2734 ol = dupstring(zlemetaline); 2735 expanding = 1; 2736 excs = zlemetacs; 2737 zlemetall = zlemetacs = 0; 2738 lexsave(); 2739 /* We push ol as it will remain unchanged */ 2740 inpush(ol, 0, NULL); 2741 strinbeg(1); 2742 noaliases = 1; 2743 noerrs = 1; 2744 exlast = inbufct; 2745 do { 2746 ctxtlex(); 2747 } while (tok != ENDINPUT && tok != LEXERR); 2748 while (!lexstop) 2749 hgetc(); 2750 /* We have to save errflags because it's reset in lexrestore. Since * 2751 * noerrs was set to 1 errflag is true if there was a habort() which * 2752 * means that the expanded string is unusable. */ 2753 err = errflag; 2754 noerrs = ne; 2755 noaliases = ona; 2756 strinend(); 2757 inpop(); 2758 lexrestore(); 2759 expanding = 0; 2760 2761 if (!err) { 2762 zlemetacs = excs; 2763 if (strcmp(zlemetaline, ol)) { 2764 unmetafy_line(); 2765 /* For vi mode -- reset the beginning-of-insertion pointer * 2766 * to the beginning of the line. This seems a little silly, * 2767 * if we are, for example, expanding "exec !!". */ 2768 if (viinsbegin > findbol()) 2769 viinsbegin = findbol(); 2770 popheap(); 2771 return 1; 2772 } 2773 } 2774 2775 strcpy(zlemetaline, ol); 2776 zle_restore_positions(); 2777 unmetafy_line(); 2778 2779 popheap(); 2780 2781 return 0; 2782} 2783 2784/**/ 2785void 2786fixmagicspace(void) 2787{ 2788 lastchar = ' '; 2789#ifdef MULTIBYTE_SUPPORT 2790 /* 2791 * This is redundant if the multibyte encoding extends ASCII, 2792 * since lastchar is a full character, but it's safer anyway... 2793 */ 2794 lastchar_wide = L' '; 2795 lastchar_wide_valid = 1; 2796#endif 2797} 2798 2799/**/ 2800int 2801magicspace(char **args) 2802{ 2803 ZLE_STRING_T bangq; 2804 ZLE_CHAR_T zlebangchar[1]; 2805 int ret; 2806#ifdef MULTIBYTE_SUPPORT 2807 mbstate_t mbs; 2808#endif 2809 2810 fixmagicspace(); 2811 2812#ifdef MULTIBYTE_SUPPORT 2813 /* 2814 * Use mbrtowc() here for consistency and to ensure the 2815 * state is initialised properly. bangchar is unsigned char, 2816 * but must be ASCII, so we simply cast the pointer. 2817 */ 2818 memset(&mbs, 0, sizeof(mbs)); 2819 if (mbrtowc(zlebangchar, (char *)&bangchar, 1, &mbs) == MB_INVALID) 2820 return selfinsert(args); 2821#else 2822 zlebangchar[0] = bangchar; 2823#endif 2824 for (bangq = zleline; bangq < zleline + zlell; bangq++) { 2825 if (*bangq != zlebangchar[0]) 2826 continue; 2827 if (bangq[1] == ZWC('"') && 2828 (bangq == zleline || bangq[-1] == ZWC('\\'))) 2829 break; 2830 } 2831 2832 if (!(ret = selfinsert(args)) && 2833 (!bangq || bangq + 2 > zleline + zlecs)) 2834 doexpandhist(); 2835 return ret; 2836} 2837 2838/**/ 2839int 2840expandhistory(UNUSED(char **args)) 2841{ 2842 if (!doexpandhist()) 2843 return 1; 2844 return 0; 2845} 2846 2847static int cmdwb, cmdwe; 2848 2849/**/ 2850static char * 2851getcurcmd(void) 2852{ 2853 int curlincmd; 2854 char *s = NULL; 2855 2856 lexsave(); 2857 lexflags = LEXFLAGS_ZLE; 2858 metafy_line(); 2859 inpush(dupstrspace(zlemetaline), 0, NULL); 2860 strinbeg(1); 2861 pushheap(); 2862 do { 2863 curlincmd = incmdpos; 2864 ctxtlex(); 2865 if (tok == ENDINPUT || tok == LEXERR) 2866 break; 2867 if (tok == STRING && curlincmd) { 2868 zsfree(s); 2869 s = ztrdup(tokstr); 2870 cmdwb = zlemetall - wordbeg; 2871 cmdwe = zlemetall + 1 - inbufct; 2872 } 2873 } 2874 while (tok != ENDINPUT && tok != LEXERR && lexflags); 2875 popheap(); 2876 strinend(); 2877 inpop(); 2878 errflag = 0; 2879 unmetafy_line(); 2880 lexrestore(); 2881 2882 return s; 2883} 2884 2885/**/ 2886int 2887processcmd(UNUSED(char **args)) 2888{ 2889 char *s; 2890 int m = zmult, na = noaliases; 2891 2892 noaliases = 1; 2893 s = getcurcmd(); 2894 noaliases = na; 2895 if (!s) 2896 return 1; 2897 zmult = 1; 2898 pushline(zlenoargs); 2899 zmult = m; 2900 inststr(bindk->nam); 2901 inststr(" "); 2902 untokenize(s); 2903 2904 inststr(quotename(s, NULL)); 2905 2906 zsfree(s); 2907 done = 1; 2908 return 0; 2909} 2910 2911/**/ 2912int 2913expandcmdpath(UNUSED(char **args)) 2914{ 2915 /* 2916 * zleline is not metafied for most of this function 2917 * (that happens within getcurcmd()). 2918 */ 2919 int oldcs = zlecs, na = noaliases, strll; 2920 char *s, *str; 2921 ZLE_STRING_T zlestr; 2922 2923 noaliases = 1; 2924 s = getcurcmd(); 2925 noaliases = na; 2926 if (!s) 2927 return 1; 2928 2929 if (cmdwb < 0 || cmdwe < cmdwb) { 2930 zsfree(s); 2931 return 1; 2932 } 2933 2934 str = findcmd(s, 1); 2935 zsfree(s); 2936 if (!str) 2937 return 1; 2938 zlecs = cmdwb; 2939 foredel(cmdwe - cmdwb, CUT_RAW); 2940 zlestr = stringaszleline(str, 0, &strll, NULL, NULL); 2941 spaceinline(strll); 2942 ZS_strncpy(zleline + zlecs, zlestr, strll); 2943 free(zlestr); 2944 zlecs = oldcs; 2945 if (zlecs >= cmdwe - 1) 2946 zlecs += cmdwe - cmdwb + strlen(str); 2947 if (zlecs > zlell) 2948 zlecs = zlell; 2949 return 0; 2950} 2951 2952/* Extra function added by AR Iano-Fletcher. */ 2953/* This is a expand/complete in the vein of wash. */ 2954 2955/**/ 2956int 2957expandorcompleteprefix(char **args) 2958{ 2959 int ret; 2960 2961 comppref = 1; 2962 ret = expandorcomplete(args); 2963 if (zlecs && zleline[zlecs - 1] == ZWC(' ')) 2964 makesuffixstr(NULL, "\\-", 0); 2965 comppref = 0; 2966 return ret; 2967} 2968 2969/**/ 2970int 2971endoflist(UNUSED(char **args)) 2972{ 2973 if (lastlistlen > 0) { 2974 int i; 2975 2976 clearflag = 0; 2977 trashzle(); 2978 2979 for (i = lastlistlen; i > 0; i--) 2980 putc('\n', shout); 2981 2982 showinglist = lastlistlen = 0; 2983 2984 if (sfcontext) 2985 zrefresh(); 2986 2987 return 0; 2988 } 2989 return 1; 2990} 2991