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