2 * hist.c - history expansion
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1992-1997 Paul Falstad
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.
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.
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.
33 /* Functions to call for getting/ungetting a character and for history
37 mod_export
int (*hgetc
) (void);
40 void (*hungetc
) (int);
46 void (*hwbegin
) (int);
49 void (*hwabort
) (void);
55 void (*addtoline
) (int);
57 /* != 0 means history substitution is turned off */
60 mod_export
int stophist
;
62 /* if != 0, we are expanding the current line */
65 mod_export
int expanding
;
67 /* these are used to modify the cursor position during expansion */
70 mod_export
int excs
, exlast
;
73 * Current history event number
75 * Note on curhist: with history inactive, this points to the
76 * last line actually added to the history list. With history active,
77 * the line does not get added to the list until hend(), if at all.
78 * However, curhist is incremented to reflect the current line anyway
79 * and a temporary history entry is inserted while the user is editing.
80 * If the resulting line was not added to the list, a flag is set so
81 * that curhist will be decremented in hbegin().
83 * Note curhist is passed to zle on variable length argument list:
84 * type must match that retrieved in zle_main_entry.
88 mod_export zlong curhist
;
91 struct histent curline
;
93 /* current line count of allocated history entries */
98 /* The history lines are kept in a hash, and also doubly-linked in a ring */
103 mod_export Histent hist_ring
;
105 /* capacity of history lists */
110 /* desired history-file size (in lines) */
115 /* if = 1, we have performed history substitution on the current line *
116 * if = 2, we have used the 'p' modifier */
121 /* state of the history mechanism */
126 /* Current setting of the associated option, but sometimes also includes
127 * the setting of the HIST_SAVE_NO_DUPS option. */
130 int hist_ignore_all_dups
;
132 /* What flags (if any) we should skip when moving through the history */
135 mod_export
int hist_skip_flags
;
137 /* Bits of histactive variable */
138 #define HA_ACTIVE (1<<0) /* History mechanism is active */
139 #define HA_NOINC (1<<1) /* Don't store, curhist not incremented */
140 #define HA_INWORD (1<<2) /* We're inside a word, don't add
141 start and end markers */
142 #define HA_UNGET (1<<3) /* Recursively ungetting */
144 /* Array of word beginnings and endings in current history line. */
149 /* Max, actual position in chwords.
150 * nwords = chwordpos/2 because we record beginning and end of words.
154 int chwordlen
, chwordpos
;
156 /* the last l for s/l/r/ history substitution */
161 /* the last r for s/l/r/ history substitution */
166 /* state of histsubstpattern at last substitution */
171 /* pointer into the history line */
174 mod_export
char *hptr
;
176 /* the current history line */
179 mod_export
char *chline
;
182 * The current history line as seen by ZLE.
183 * We modify chline for use in other contexts while ZLE may
184 * still be running; ZLE should see only the top-level value.
186 * To avoid having to modify this every time we modify chline,
187 * we set it when we push the stack, and unset it when we pop
188 * the appropriate value off the stack. As it's never modified
189 * on the stack this is the only maintenance we ever do on it.
190 * In return, ZLE has to check both zle_chline and (if that's
191 * NULL) chline to get the current value.
195 mod_export
char *zle_chline
;
197 /* true if the last character returned by hgetc was an escaped bangchar *
198 * if it is set and NOBANGHIST is unset hwaddc escapes bangchars */
203 /* max size of histline */
208 /* default event (usually curhist-1, that is, "!!") */
213 * Flag that we stopped reading line when we got to a comment,
214 * but we want to keep it in the histofy even if there were no words
215 * (i.e. the comment was the entire line).
217 static int hist_keep_comment
;
219 /* Remember the last line in the history file so we can find it again. */
220 static struct histfile_stats
{
228 static struct histsave
{
229 struct histfile_stats lasthist
;
239 static int histsave_stack_size
= 0;
240 static int histsave_stack_pos
= 0;
242 static zlong histfile_linect
;
244 /* save history context */
248 hist_context_save(struct hist_stack
*hs
, int toplevel
)
251 /* top level, make this version visible to ZLE */
253 /* ensure line stored is NULL-terminated */
257 hs
->histactive
= histactive
;
258 hs
->histdone
= histdone
;
259 hs
->stophist
= stophist
;
262 hs
->chwords
= chwords
;
263 hs
->chwordlen
= chwordlen
;
264 hs
->chwordpos
= chwordpos
;
266 hs
->hungetc
= hungetc
;
268 hs
->hwbegin
= hwbegin
;
269 hs
->hwabort
= hwabort
;
271 hs
->addtoline
= addtoline
;
272 hs
->hlinesz
= hlinesz
;
274 hs
->hist_keep_comment
= hist_keep_comment
;
276 * We save and restore the command stack with history
277 * as it's visible to the user interactively, so if
278 * we're preserving history state we'll continue to
279 * show the current set of commands from input.
281 hs
->cstack
= cmdstack
;
288 cmdstack
= (unsigned char *)zalloc(CMDSTACKSZ
);
292 /* restore history context */
296 hist_context_restore(const struct hist_stack
*hs
, int toplevel
)
299 /* Back to top level: don't need special ZLE value */
300 DPUTS(hs
->hline
!= zle_chline
, "BUG: Ouch, wrong chline for ZLE");
303 histactive
= hs
->histactive
;
304 histdone
= hs
->histdone
;
305 stophist
= hs
->stophist
;
308 chwords
= hs
->chwords
;
309 chwordlen
= hs
->chwordlen
;
310 chwordpos
= hs
->chwordpos
;
312 hungetc
= hs
->hungetc
;
314 hwbegin
= hs
->hwbegin
;
315 hwabort
= hs
->hwabort
;
317 addtoline
= hs
->addtoline
;
318 hlinesz
= hs
->hlinesz
;
320 hist_keep_comment
= hs
->hist_keep_comment
;
322 zfree(cmdstack
, CMDSTACKSZ
);
323 cmdstack
= hs
->cstack
;
328 * Mark that the current level of history is within a word whatever
329 * characters turn up, or turn that mode off. This is used for nested
330 * parsing of substitutions.
332 * The caller takes care only to turn this on or off at the start
333 * or end of recursive use of the same mode, so a single flag is
339 hist_in_word(int yesno
)
342 histactive
|= HA_INWORD
;
344 histactive
&= ~HA_INWORD
;
349 hist_is_in_word(void)
351 return (histactive
& HA_INWORD
) ? 1 : 0;
354 /* add a character to the current history word */
359 /* Only if history line exists and lexing has not finished. */
360 if (chline
&& !(errflag
|| lexstop
) &&
362 * If we're reading inside a word for command substitution
363 * we allow the lexer to expand aliases but don't deal
364 * with them here. Note matching code in ihungetc().
365 * TBD: it might be neater to deal with all aliases in this
366 * fashion as we never need the expansion in the history
367 * line, only in the lexer and above.
369 (inbufflags
& (INP_ALIAS
|INP_HIST
)) != INP_ALIAS
) {
370 /* Quote un-expanded bangs in the history line. */
371 if (c
== bangchar
&& stophist
< 2 && qbang
)
372 /* If qbang is not set, we do not escape this bangchar as it's *
373 * not necessary (e.g. it's a bang in !=, or it is followed *
374 * by a space). Roughly speaking, qbang is zero only if the *
375 * history interpreter has already digested this bang and *
376 * found that it is not necessary to escape it. */
380 /* Resize history line if necessary */
381 if (hptr
- chline
>= hlinesz
) {
382 int oldsiz
= hlinesz
;
384 chline
= realloc(chline
, hlinesz
= oldsiz
+ 64);
385 hptr
= chline
+ oldsiz
;
390 /* This function adds a character to the zle input line. It is used when *
391 * zsh expands history (see doexpandhist() in zle_tricky.c). It also *
392 * calculates the new cursor position after the expansion. It is called *
393 * from hgetc() and from gettok() in lex.c for characters in comments. */
399 if (!expanding
|| lexstop
)
401 if (qbang
&& c
== bangchar
&& stophist
< 2) {
403 zleentry(ZLE_CMD_ADD_TO_LINE
, '\\');
405 if (excs
> zlemetacs
) {
406 excs
+= 1 + inbufct
- exlast
;
407 if (excs
< zlemetacs
)
408 /* this case could be handled better but it is *
409 * so rare that it does not worth it */
413 zleentry(ZLE_CMD_ADD_TO_LINE
, itok(c
) ? ztokens
[c
- Pound
] : c
);
425 errflag
|= ERRFLAG_ERROR
;
429 if (!stophist
&& !(inbufflags
& INP_ALIAS
)) {
430 /* If necessary, expand history characters. */
435 errflag
|= ERRFLAG_ERROR
;
439 if ((inbufflags
& INP_HIST
) && !stophist
) {
440 /* the current character c came from a history expansion *
441 * (inbufflags & INP_HIST) and history is not disabled *
442 * (e.g. we are not inside single quotes). In that case, \! *
443 * should be treated as ! (since this \! came from a previous *
444 * history line where \ was used to escape the bang). So if *
445 * c == '\\' we fetch one more character to see if it's a bang, *
446 * and if it is not, we unget it and reset c back to '\\' */
448 if (c
== '\\' && !(qbang
= (c
= ingetc()) == bangchar
))
449 safeinungetc(c
), c
= '\\';
450 } else if (stophist
|| (inbufflags
& INP_ALIAS
))
451 /* If the result is a bangchar which came from history or alias *
452 * expansion, we treat it as an escaped bangchar, unless history *
453 * is disabled. If stophist == 1 it only means that history is *
454 * temporarily disabled by a !" which won't appear in the *
455 * history, so we still have an escaped bang. stophist > 1 if *
456 * history is disabled with NOBANGHIST or by someone else (e.g. *
457 * when the lexer scans single quoted text). */
458 qbang
= c
== bangchar
&& (stophist
< 2);
484 * The lex_add_raw test is needed if we are parsing a command
485 * substitution when expanding history for ZLE: strin is set but we
486 * need to finish off the input because the string we are reading is
487 * going to be used directly in the line that goes to ZLE.
489 * Note that this is a side effect --- this is not the usual reason
490 * for testing lex_add_raw which is to add the text to a different
491 * buffer used when we are actually parsing the command substitution
492 * (nothing to do with ZLE). Sorry.
494 while (inbufct
&& (!strin
|| lex_add_raw
)) {
504 * Extract :s/foo/bar/ delimiters and arguments
506 * The first character expected is the first delimiter.
507 * The arguments are stored in the hsubl and hsubr variables.
509 * subline is the part of the command line to be matched.
511 * If a ':' was found but was not followed by a 'G',
512 * *cflagp is set to 1 and the input is backed up to the
513 * character following the colon.
518 getsubsargs(UNUSED(char *subline
), int *gbalp
, int *cflagp
)
524 ptr1
= hdynread2(del
);
527 ptr2
= hdynread2(del
);
531 } else if (!hsubl
) { /* fail silently on this */
552 /* Get the maximum no. of words for a history entry. */
556 getargc(Histent ehist
)
558 return ehist
->nwords
? ehist
->nwords
-1 : 0;
566 zerr("substitution failed");
571 * Return a count given by decimal digits after a modifier.
576 int c
= ingetc(), count
;
581 count
= 10 * count
+ (c
- '0');
591 /* Perform history substitution, returning the next character afterwards. */
597 int farg
, evset
= -1, larg
, argc
, cflag
= 0, bflag
= 0;
599 static int marg
= -1;
600 static zlong mev
= -1;
608 * If accumulating raw input for use in command substitution,
609 * we don't want the history text, so mark it for later removal.
610 * It would be better to do this at a level above the history
611 * and below the lexer --- but there isn't one.
613 * Include the character we are attempting to substitute.
615 lexraw_mark
= zshlex_raw_mark(-1);
617 /* look, no goto's */
618 if (isfirstch
&& c
== hatchar
) {
621 /* Line begins ^foo^bar */
624 if (!(ehist
= gethist(defev
))
625 || !(sline
= getargs(ehist
, 0, getargc(ehist
))))
628 if (getsubsargs(sline
, &gbal
, &cflag
))
629 return substfailed();
632 if (subst(&sline
, hsubl
, hsubr
, gbal
, 0))
633 return substfailed();
635 /* Line doesn't begin ^foo^bar */
651 if ((c
= ingetc()) == '{') {
659 if ((!cflag
&& inblank(c
)) || c
== '=' || c
== '(' || lexstop
) {
664 ptr
= buf
= zhalloc(buflen
= 265);
666 /* get event number */
672 if (c
== '?' || c
== '\n' || lexstop
)
676 if (ptr
== buf
+ buflen
) {
677 buf
= hrealloc(buf
, buflen
, 2 * buflen
);
683 if (c
!= '\n' && !lexstop
)
686 mev
= ev
= hconsearch(hsubl
= ztrdup(buf
), &marg
);
691 zerr("no such event: %s", buf
);
698 if (inblank(c
) || c
== ';' || c
== ':' || c
== '^' ||
699 c
== '$' || c
== '*' || c
== '%' || c
== '}' ||
700 c
== '\'' || c
== '"' || c
== '`' || lexstop
)
705 if ((idigit(buf
[0]) || buf
[0] == '-') && !idigit(c
))
709 if (ptr
== buf
+ buflen
) {
710 buf
= hrealloc(buf
, buflen
, 2 * buflen
);
714 if (c
== '#' || c
== bangchar
) {
721 (c
== '}' || c
== ';' || c
== '\'' || c
== '"' || c
== '`')) {
722 /* Neither event nor word designator, no expansion */
730 if (isset(CSHJUNKIEHISTORY
))
731 ev
= addhistnum(curhist
,-1,HIST_FOREIGN
);
734 if (c
== ':' && evset
== -1)
745 } else if ((t0
= zstrtol(buf
, NULL
, 10))) {
746 ev
= (t0
< 0) ? addhistnum(curhist
,t0
,HIST_FOREIGN
) : t0
;
748 } else if ((unsigned)*buf
== bangchar
) {
749 ev
= addhistnum(curhist
,-1,HIST_FOREIGN
);
751 } else if (*buf
== '#') {
754 } else if ((ev
= hcomsearch(buf
)) == -1) {
757 zerr("event not found: %s", buf
);
765 if (!(ehist
= gethist(defev
= ev
))) {
769 /* extract the relevant arguments */
771 argc
= getargc(ehist
);
775 if (c
== '%' && marg
!= -1) {
777 ehist
= gethist(defev
= mev
);
778 argc
= getargc(ehist
);
782 zerr("ambiguous history reference");
794 larg
= farg
= getargspec(argc
, marg
, evset
);
805 } else if (c
== '-') {
807 larg
= getargspec(argc
, marg
, evset
);
821 if (!(sline
= getargs(ehist
, farg
, larg
))) {
828 /* do the modifiers */
831 c
= (cflag
) ? ':' : ingetc();
836 if ((c
= ingetc()) == 'g') {
839 if (c
!= 's' && c
!= 'S' && c
!= '&') {
840 zerr("'s' or '&' modifier expected after 'g'");
846 histdone
= HISTFLAG_DONE
| HISTFLAG_NOEXEC
;
849 if (!chabspath(&sline
)) {
851 zerr("modifier failed: a");
857 if (!chrealpath(&sline
, 'A', 1)) {
859 zerr("modifier failed: A");
864 if (!(sline
= equalsubstr(sline
, 0, 0))) {
866 zerr("modifier failed: c");
871 if (!remtpath(&sline
, digitcount())) {
873 zerr("modifier failed: h");
878 if (!rembutext(&sline
)) {
880 zerr("modifier failed: e");
885 if (!remtext(&sline
)) {
887 zerr("modifier failed: r");
892 if (!remlpaths(&sline
, digitcount())) {
894 zerr("modifier failed: t");
900 hsubpatopt
= (c
== 'S');
901 if (getsubsargs(sline
, &gbal
, &cflag
))
902 return -1; /* fall through */
904 if (hsubl
&& hsubr
) {
905 if (subst(&sline
, hsubl
, hsubr
, gbal
, hsubpatopt
))
906 return substfailed();
909 zerr("no previous substitution");
918 int one
= noerrs
, oef
= errflag
;
921 parse_subst_string(sline
);
923 errflag
= oef
| (errflag
& ERRFLAG_INT
);
932 sline
= casemodify(sline
, CASMOD_LOWER
);
935 sline
= casemodify(sline
, CASMOD_UPPER
);
939 char *here
= zgetcwd();
940 if (here
[strlen(here
)-1] != '/')
941 sline
= zhtricat(metafy(here
, -1, META_HEAPDUP
), "/", sline
);
943 sline
= dyncat(here
, sline
);
945 sline
= xsymlink(sline
, 1);
949 zerr("illegal modifier: %c", c
);
953 if (c
!= '}' || !bflag
)
955 if (c
!= '}' && bflag
) {
956 zerr("'}' expected");
963 zshlex_raw_back_to_mark(lexraw_mark
);
966 * Push the expanded value onto the input stack,
967 * marking this as a history word for purposes of the alias stack.
971 /* this function is called only called from hgetc and only if *
972 * !(inbufflags & INP_ALIAS). History expansion should never be *
973 * done with INP_ALIAS (to prevent recursive history expansion and *
974 * histoty expansion of aliases). Escapes are not removed here. *
975 * This is now handled in hgetc. */
976 inpush(sline
, INP_HIST
, NULL
); /* sline from heap, don't free */
977 histdone
|= HISTFLAG_DONE
;
978 if (isset(HISTVERIFY
))
979 histdone
|= HISTFLAG_NOEXEC
| HISTFLAG_RECALL
;
981 /* Don't try and re-expand line. */
985 /* unget a char and remove it from chline. It can only be used *
986 * to unget a character returned by hgetc. */
993 while (!lexstop
&& !errflag
) {
994 if (hptr
[-1] != (char) c
&& stophist
< 4 &&
995 hptr
> chline
+ 1 && hptr
[-1] == '\n' && hptr
[-2] == '\\' &&
996 !(histactive
& HA_UNGET
) &&
997 (inbufflags
& (INP_ALIAS
|INP_HIST
)) != INP_ALIAS
) {
998 histactive
|= HA_UNGET
;
1001 histactive
&= ~HA_UNGET
;
1009 if ((inbufflags
& (INP_ALIAS
|INP_HIST
)) != INP_ALIAS
) {
1010 DPUTS(hptr
<= chline
, "BUG: hungetc attempted at buffer start");
1012 DPUTS(*hptr
!= (char) c
, "BUG: wrong character in hungetc() ");
1013 qbang
= (c
== bangchar
&& stophist
< 2 &&
1014 hptr
> chline
&& hptr
[-1] == '\\');
1016 /* No active bangs in aliases */
1023 doit
= !stophist
&& ((inbufflags
& INP_HIST
) ||
1024 !(inbufflags
& INP_ALIAS
));
1029 /* begin reading a string */
1033 strinbeg(int dohist
)
1039 * Also initialise some variables owned by the parser but
1040 * used for communication between the parser and lexer.
1042 init_parse_status();
1045 /* done reading a string */
1052 DPUTS(!strin
, "BUG: strinend() called without strinbeg()");
1058 /* dummy functions to use instead of hwaddc(), hwbegin(), and hwend() when
1059 * they aren't needed */
1076 /* these functions handle adding/removing curline to/from the hist_ring */
1082 hist_ring
= curline
.up
= curline
.down
= &curline
;
1084 curline
.up
= hist_ring
;
1085 curline
.down
= hist_ring
->down
;
1086 hist_ring
->down
= hist_ring
->down
->up
= &curline
;
1087 hist_ring
= &curline
;
1089 curline
.histnum
= ++curhist
;
1095 curline
.up
->down
= curline
.down
;
1096 curline
.down
->up
= curline
.up
;
1097 if (hist_ring
== &curline
) {
1101 hist_ring
= curline
.up
;
1106 /* initialize the history mechanism */
1114 isfirstln
= isfirstch
= 1;
1115 errflag
&= ~ERRFLAG_ERROR
;
1119 else if (dohist
!= 2)
1120 stophist
= (!interact
|| unset(SHINSTDIN
)) ? 2 : 0;
1124 * pws: We used to test for "|| (inbufflags & INP_ALIAS)"
1125 * in this test, but at this point we don't have input
1126 * set up so this can trigger unnecessarily.
1127 * I don't see how the test at this point could ever be
1128 * useful, since we only get here when we're initialising
1129 * the history mechanism, before we've done any input.
1131 * (I also don't see any point where this function is called with
1134 if (stophist
== 2) {
1135 chline
= hptr
= NULL
;
1143 hwabort
= nohwabort
;
1147 chline
= hptr
= zshcalloc(hlinesz
= 64);
1148 chwords
= zalloc((chwordlen
= 64) * sizeof(short));
1155 addtoline
= iaddtoline
;
1156 if (!isset(BANGHIST
))
1161 if (hist_ring
&& !hist_ring
->ftim
&& !strin
)
1162 hist_ring
->ftim
= time(NULL
);
1163 if ((dohist
== 2 || (interact
&& isset(SHINSTDIN
))) && !strin
) {
1164 histactive
= HA_ACTIVE
;
1167 defev
= addhistnum(curhist
, -1, HIST_FOREIGN
);
1169 histactive
= HA_ACTIVE
| HA_NOINC
;
1172 * For INCAPPENDHISTORYTIME, when interactive, save the history here
1173 * as it gives a better estimate of the times of commands.
1175 * If INCAPPENDHISTORY is also set we've already done it.
1177 * If SHAREHISTORY is also set continue to do so in the
1178 * standard place, because that's safer about reading and
1179 * rewriting history atomically.
1181 * The histsave_stack_pos test won't usually fail here.
1182 * We need to test the opposite for the hend() case because we
1183 * need to save in the history file we've switched to, but then
1184 * we pop immediately after that so the variable becomes zero.
1185 * We will already have saved the line and restored the history
1186 * so that (correctly) nothing happens here. But it shows
1187 * I thought about it.
1189 if (isset(INCAPPENDHISTORYTIME
) && !isset(SHAREHISTORY
) &&
1190 !isset(INCAPPENDHISTORY
) &&
1191 !(histactive
& HA_NOINC
) && !strin
&& histsave_stack_pos
== 0) {
1192 hf
= getsparam("HISTFILE");
1193 savehistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1199 histreduceblanks(void)
1201 int i
, len
, pos
, needblank
, spacecount
= 0, trunc_ok
;
1202 char *lastptr
, *ptr
;
1204 if (isset(HISTIGNORESPACE
))
1205 while (chline
[spacecount
] == ' ') spacecount
++;
1207 for (i
= 0, len
= spacecount
; i
< chwordpos
; i
+= 2) {
1208 len
+= chwords
[i
+1] - chwords
[i
]
1209 + (i
> 0 && chwords
[i
] > chwords
[i
-1]);
1211 if (chline
[len
] == '\0')
1214 /* Remember where the delimited words end */
1216 lastptr
= chline
+ chwords
[chwordpos
-1];
1220 for (i
= 0, pos
= spacecount
; i
< chwordpos
; i
+= 2) {
1221 len
= chwords
[i
+1] - chwords
[i
];
1222 needblank
= (i
< chwordpos
-2 && chwords
[i
+2] > chwords
[i
+1]);
1223 if (pos
!= chwords
[i
]) {
1224 memmove(chline
+ pos
, chline
+ chwords
[i
], len
+ needblank
);
1226 chwords
[i
+1] = chwords
[i
] + len
;
1228 pos
+= len
+ needblank
;
1232 * A terminating comment isn't recorded as a word.
1233 * Only truncate the line if just whitespace remains.
1236 for (ptr
= lastptr
; *ptr
; ptr
++) {
1237 if (!inblank(*ptr
)) {
1247 while ((*ptr
++ = *lastptr
++))
1254 histremovedups(void)
1257 for (he
= hist_ring
; he
; he
= next
) {
1258 next
= up_histent(he
);
1259 if (he
->node
.flags
& HIST_DUP
)
1260 freehistnode(&he
->node
);
1266 addhistnum(zlong hl
, int n
, int xflags
)
1268 int dir
= n
< 0? -1 : n
> 0? 1 : 0;
1269 Histent he
= gethistent(hl
, dir
);
1273 if (he
->histnum
!= hl
)
1276 he
= movehistent(he
, n
, xflags
);
1278 return dir
< 0? firsthist() - 1 : curhist
+ 1;
1284 movehistent(Histent he
, int n
, int xflags
)
1287 if (!(he
= up_histent(he
)))
1289 if (!(he
->node
.flags
& xflags
))
1293 if (!(he
= down_histent(he
)))
1295 if (!(he
->node
.flags
& xflags
))
1304 up_histent(Histent he
)
1306 return !he
|| he
->up
== hist_ring
? NULL
: he
->up
;
1311 down_histent(Histent he
)
1313 return he
== hist_ring
? NULL
: he
->down
;
1318 gethistent(zlong ev
, int nearmatch
)
1325 if (ev
- hist_ring
->down
->histnum
< hist_ring
->histnum
- ev
) {
1326 for (he
= hist_ring
->down
; he
->histnum
< ev
; he
= he
->down
) ;
1327 if (he
->histnum
!= ev
) {
1329 || (nearmatch
< 0 && (he
= up_histent(he
)) == NULL
))
1334 for (he
= hist_ring
; he
->histnum
> ev
; he
= he
->up
) ;
1335 if (he
->histnum
!= ev
) {
1337 || (nearmatch
> 0 && (he
= down_histent(he
)) == NULL
))
1347 putoldhistentryontop(short keep_going
)
1349 static Histent next
= NULL
;
1350 Histent he
= (keep_going
|| !hist_ring
) ? next
: hist_ring
->down
;
1355 if (isset(HISTEXPIREDUPSFIRST
) && !(he
->node
.flags
& HIST_DUP
)) {
1356 static zlong max_unique_ct
= 0;
1358 max_unique_ct
= savehistsiz
;
1360 if (max_unique_ct
-- <= 0 || he
== hist_ring
) {
1363 he
= hist_ring
->down
;
1369 } while (!(he
->node
.flags
& HIST_DUP
));
1371 /* Is it really possible for hist_ring to be NULL here? */
1372 if (he
&& (!hist_ring
|| he
!= hist_ring
->down
)) {
1373 he
->up
->down
= he
->down
;
1374 he
->down
->up
= he
->up
;
1377 he
->down
= hist_ring
->down
;
1378 hist_ring
->down
= he
;
1387 prepnexthistent(void)
1390 int curline_in_ring
= hist_ring
== &curline
;
1392 if (curline_in_ring
)
1394 if (hist_ring
&& hist_ring
->node
.flags
& HIST_TMPSTORE
) {
1396 freehistnode(&hist_ring
->node
);
1399 if (histlinect
< histsiz
|| !hist_ring
) {
1400 he
= (Histent
)zshcalloc(sizeof *he
);
1402 hist_ring
= he
->up
= he
->down
= he
;
1405 he
->down
= hist_ring
->down
;
1406 hist_ring
->down
= he
->down
->up
= he
;
1412 putoldhistentryontop(0);
1413 freehistdata(hist_ring
, 0);
1416 he
->histnum
= ++curhist
;
1417 if (curline_in_ring
)
1422 /* A helper function for hend() */
1425 should_ignore_line(Eprog prog
)
1427 if (isset(HISTIGNORESPACE
)) {
1428 if (*chline
== ' ' || aliasspaceflag
)
1435 if (isset(HISTNOFUNCTIONS
)) {
1436 Wordcode pc
= prog
->prog
;
1437 wordcode code
= *pc
;
1438 if (wc_code(code
) == WC_LIST
&& WC_LIST_TYPE(code
) & Z_SIMPLE
1439 && wc_code(pc
[2]) == WC_FUNCDEF
)
1443 if (isset(HISTNOSTORE
)) {
1444 char *b
= getjobtext(prog
, NULL
);
1446 if (*b
== 'b' && strncmp(b
,"builtin ",8) == 0) {
1451 if (*b
== 'h' && strncmp(b
,"history",7) == 0 && (!b
[7] || b
[7] == ' ')
1452 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"history")))
1454 if (*b
== 'r' && (!b
[1] || b
[1] == ' ')
1455 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"r")))
1457 if (*b
== 'f' && b
[1] == 'c' && b
[2] == ' ' && b
[3] == '-'
1458 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"fc"))) {
1463 } while (ialpha(*b
));
1470 /* say we're done using the history mechanism */
1476 int flag
, hookret
= 0, stack_pos
= histsave_stack_pos
;
1481 * -1: save temporarily, delete after next line
1482 * -2: save internally but mark for not writing
1487 DPUTS(stophist
!= 2 && !(inbufflags
& INP_ALIAS
) && !chline
,
1488 "BUG: chline is NULL in hend()");
1490 if (histdone
& HISTFLAG_SETTY
)
1491 settyinfo(&shttyinfo
);
1492 if (!(histactive
& HA_NOINC
))
1494 if (histactive
& HA_NOINC
) {
1495 zfree(chline
, hlinesz
);
1496 zfree(chwords
, chwordlen
*sizeof(short));
1497 chline
= hptr
= NULL
;
1503 if (hist_ignore_all_dups
!= isset(HISTIGNOREALLDUPS
)
1504 && (hist_ignore_all_dups
= isset(HISTIGNOREALLDUPS
)) != 0)
1509 * Added the following in case the test "hptr < chline + 1"
1510 * is more than just paranoia.
1512 DPUTS(hptr
< chline
, "History end pointer off start of line");
1516 LinkList hookargs
= newlinklist();
1517 int save_errflag
= errflag
;
1520 addlinknode(hookargs
, "zshaddhistory");
1521 addlinknode(hookargs
, chline
);
1522 callhookfunc("zshaddhistory", hookargs
, 1, &hookret
);
1524 errflag
&= ~ERRFLAG_ERROR
;
1525 errflag
|= save_errflag
;
1527 /* For history sharing, lock history file once for both read and write */
1528 hf
= getsparam("HISTFILE");
1529 if (isset(SHAREHISTORY
) && !lockhistfile(hf
, 0)) {
1530 readhistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1531 curline
.histnum
= curhist
+1;
1535 if (hptr
< chline
+ 1)
1538 if (hptr
[-1] == '\n') {
1544 if (chwordpos
<= 2 && !hist_keep_comment
)
1546 else if (should_ignore_line(prog
))
1548 else if (hookret
== 2)
1553 if (flag
& (HISTFLAG_DONE
| HISTFLAG_RECALL
)) {
1556 ptr
= ztrdup(chline
);
1557 if ((flag
& (HISTFLAG_DONE
| HISTFLAG_RECALL
)) == HISTFLAG_DONE
) {
1562 if (flag
& HISTFLAG_RECALL
) {
1563 zpushnode(bufstack
, ptr
);
1568 if (save
|| *chline
== ' ') {
1570 for (he
= hist_ring
; he
&& he
->node
.flags
& HIST_FOREIGN
;
1571 he
= up_histent(he
)) ;
1572 if (he
&& he
->node
.flags
& HIST_TMPSTORE
) {
1573 if (he
== hist_ring
)
1574 curline
.histnum
= curhist
--;
1575 freehistnode(&he
->node
);
1583 /* debugging only */
1586 DPUTS(1, "BUG: uncompleted line in history");
1589 /* get rid of pesky \n which we've already nulled out */
1590 if (chwordpos
> 1 && !chline
[chwords
[chwordpos
-2]]) {
1592 /* strip superfluous blanks, if desired */
1593 if (isset(HISTREDUCEBLANKS
))
1597 newflags
= HIST_TMPSTORE
;
1598 else if (save
== -2)
1599 newflags
= HIST_NOWRITE
;
1602 if ((isset(HISTIGNOREDUPS
) || isset(HISTIGNOREALLDUPS
)) && save
> 0
1603 && hist_ring
&& histstrcmp(chline
, hist_ring
->node
.nam
) == 0) {
1604 /* This history entry compares the same as the previous.
1605 * In case minor changes were made, we overwrite the
1606 * previous one with the current one. This also gets the
1607 * timestamp right. Perhaps, preserve the HIST_OLD flag.
1610 newflags
|= he
->node
.flags
& HIST_OLD
; /* Avoid re-saving */
1611 freehistdata(he
, 0);
1612 curline
.histnum
= curhist
;
1614 he
= prepnexthistent();
1616 he
->node
.nam
= ztrdup(chline
);
1617 he
->stim
= time(NULL
);
1619 he
->node
.flags
= newflags
;
1621 if ((he
->nwords
= chwordpos
/2)) {
1622 he
->words
= (short *)zalloc(chwordpos
* sizeof(short));
1623 memcpy(he
->words
, chwords
, chwordpos
* sizeof(short));
1625 if (!(newflags
& HIST_TMPSTORE
))
1626 addhistnode(histtab
, he
->node
.nam
, he
);
1628 zfree(chline
, hlinesz
);
1629 zfree(chwords
, chwordlen
*sizeof(short));
1630 chline
= hptr
= NULL
;
1634 * For normal INCAPPENDHISTORY case and reasoning, see hbegin().
1636 if (isset(SHAREHISTORY
) ? histfileIsLocked() :
1637 (isset(INCAPPENDHISTORY
) || (isset(INCAPPENDHISTORYTIME
) &&
1638 histsave_stack_pos
!= 0)))
1639 savehistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1640 unlockhistfile(hf
); /* It's OK to call this even if we aren't locked */
1642 * No good reason for the user to push the history more than once, but
1643 * it's easy to be tidy...
1645 while (histsave_stack_pos
> stack_pos
)
1647 hist_keep_comment
= 0;
1649 return !(flag
& HISTFLAG_NOEXEC
|| errflag
);
1656 ihwbegin(int offset
)
1658 int pos
= hptr
- chline
+ offset
;
1659 if (stophist
== 2 || (histactive
& HA_INWORD
) ||
1660 (inbufflags
& (INP_ALIAS
|INP_HIST
)) == INP_ALIAS
)
1663 chwordpos
--; /* make sure we're on a word start, not end */
1664 DPUTS1(pos
< 0, "History word position < 0 in %s",
1665 dupstrpfx(chline
, hptr
-chline
));
1668 chwords
[chwordpos
++] = pos
;
1671 /* Abort current history word, not needed */
1679 hist_keep_comment
= 1;
1682 /* add a word to the history List */
1688 if (stophist
== 2 || (histactive
& HA_INWORD
) ||
1689 (inbufflags
& (INP_ALIAS
|INP_HIST
)) == INP_ALIAS
)
1691 if (chwordpos
%2 && chline
) {
1692 /* end of word reached and we've already begun a word */
1693 if (hptr
> chline
+ chwords
[chwordpos
-1]) {
1694 chwords
[chwordpos
++] = hptr
- chline
;
1695 if (chwordpos
>= chwordlen
) {
1696 chwords
= (short *) realloc(chwords
,
1701 /* scrub that last word, it doesn't exist */
1707 /* Go back to immediately after the last word, skipping space. */
1713 if (!(chwordpos
%2) && chwordpos
)
1714 hptr
= chline
+ chwords
[chwordpos
-1];
1717 /* Get the start and end point of the current history word */
1721 hwget(char **startptr
)
1723 int pos
= chwordpos
- 2;
1726 /* debugging only */
1728 /* no words available */
1729 DPUTS(1, "BUG: hwget() called with no words");
1733 else if (chwordpos
%2) {
1734 DPUTS(1, "BUG: hwget() called in middle of word");
1740 *startptr
= chline
+ chwords
[pos
];
1741 chline
[chwords
[++pos
]] = '\0';
1744 /* Replace the current history word with rep, if different */
1753 if (!strcmp(rep
, start
))
1757 chwordpos
= chwordpos
- 2;
1765 /* Get the entire current line, deleting it in the history. */
1771 /* Currently only used by pushlineoredit().
1772 * It's necessary to prevent that from getting too pally with
1777 if (!chline
|| hptr
== chline
)
1780 ret
= dupstring(chline
);
1789 /* get an argument specification */
1793 getargspec(int argc
, int marg
, int evset
)
1797 if ((c
= ingetc()) == '0')
1802 ret
= ret
* 10 + c
- '0';
1806 } else if (c
== '^')
1810 else if (c
== '%') {
1813 zerr("Ambiguous history reference");
1818 zerr("%% with no previous word matched");
1827 /* do ?foo? search */
1831 hconsearch(char *str
, int *marg
)
1837 for (he
= up_histent(hist_ring
); he
; he
= up_histent(he
)) {
1838 if (he
->node
.flags
& HIST_FOREIGN
)
1840 if ((s
= strstr(he
->node
.nam
, str
))) {
1841 int pos
= s
- he
->node
.nam
;
1842 while (t1
< he
->nwords
&& he
->words
[2*t1
] <= pos
)
1851 /* do !foo search */
1855 hcomsearch(char *str
)
1858 int len
= strlen(str
);
1860 for (he
= up_histent(hist_ring
); he
; he
= up_histent(he
)) {
1861 if (he
->node
.flags
& HIST_FOREIGN
)
1863 if (strncmp(he
->node
.nam
, str
, len
) == 0)
1869 /* various utilities for : modifiers */
1873 chabspath(char **junkptr
)
1875 char *current
, *dest
;
1880 if (**junkptr
!= '/') {
1881 char *here
= zgetcwd();
1882 if (here
[strlen(here
)-1] != '/')
1883 *junkptr
= zhtricat(metafy(here
, -1, META_HEAPDUP
), "/", *junkptr
);
1885 *junkptr
= dyncat(here
, *junkptr
);
1891 #ifdef HAVE_SUPERROOT
1892 while (*current
== '/' && current
[1] == '.' && current
[2] == '.' &&
1893 (!current
[3] || current
[3] == '/')) {
1902 if (*current
== '/') {
1904 if (current
== *junkptr
&& current
[1] == '/')
1905 *dest
++ = *current
++;
1907 *dest
++ = *current
++;
1908 while (*current
== '/')
1910 } else if (!*current
) {
1911 while (dest
> *junkptr
+ 1 && dest
[-1] == '/')
1915 } else if (current
[0] == '.' && current
[1] == '.' &&
1916 (!current
[2] || current
[2] == '/')) {
1917 if (current
== *junkptr
|| dest
== *junkptr
) {
1921 } else if (dest
> *junkptr
+ 2 &&
1922 !strncmp(dest
- 3, "../", 3)) {
1926 } else if (dest
> *junkptr
+ 1) {
1929 dest
> *junkptr
+ 1 && dest
[-1] != '/';
1931 if (dest
[-1] != '/')
1934 if (*current
== '/')
1936 } else if (dest
== *junkptr
+ 1) {
1937 /* This might break with Cygwin's leading double slashes? */
1942 } else if (current
[0] == '.' && (current
[1] == '/' || !current
[1])) {
1943 while (*++current
== '/');
1945 while (*current
!= '/' && *current
!= '\0')
1946 if ((*dest
++ = *current
++) == Meta
)
1947 *dest
++ = *current
++;
1954 * Resolve symlinks in junkptr.
1956 * If mode is 'A', resolve dot-dot before symlinks. Else, mode should be 'P'.
1957 * Refer to the documentation of the :A and :P modifiers for details.
1959 * use_heap is 1 if the result is to be allocated on the heap, 0 otherwise.
1961 * Return 0 for error, non-zero for success.
1966 chrealpath(char **junkptr
, char mode
, int use_heap
)
1969 #ifdef HAVE_REALPATH
1970 # ifdef REALPATH_ACCEPTS_NULL
1971 char *lastpos
, *nonreal
, *real
;
1973 char *lastpos
, *nonreal
, pathbuf
[PATH_MAX
+1];
1974 char *real
= pathbuf
;
1978 DPUTS1(mode
!= 'A' && mode
!= 'P', "chrealpath: mode='%c' is invalid", mode
);
1984 if (!chabspath(junkptr
))
1987 #ifndef HAVE_REALPATH
1991 * Notice that this means you cannot pass relative paths into this
1994 if (**junkptr
!= '/')
1997 unmetafy(*junkptr
, NULL
);
1999 lastpos
= strend(*junkptr
);
2000 nonreal
= lastpos
+ 1;
2003 #ifdef REALPATH_ACCEPTS_NULL
2004 /* realpath() with a NULL second argument uses malloc() to get
2005 * memory so we don't need to worry about overflowing PATH_MAX */
2006 (real
= realpath(*junkptr
, NULL
))
2008 realpath(*junkptr
, real
)
2011 if (errno
== EINVAL
|| errno
== ENOMEM
)
2014 if (nonreal
== *junkptr
) {
2015 #ifndef REALPATH_ACCEPTS_NULL
2021 while (*nonreal
!= '/' && nonreal
>= *junkptr
)
2027 while (str
<= lastpos
) {
2033 use_heap
= (use_heap
? META_HEAPDUP
: META_DUP
);
2035 *junkptr
= metafy(str
= bicat(real
, nonreal
), -1, use_heap
);
2037 #ifdef REALPATH_ACCEPTS_NULL
2041 *junkptr
= metafy(nonreal
, lastpos
- nonreal
+ 1, use_heap
);
2050 remtpath(char **junkptr
, int count
)
2052 char *str
= strend(*junkptr
);
2054 /* ignore trailing slashes */
2055 while (str
>= *junkptr
&& IS_DIRSEP(*str
))
2059 while (str
>= *junkptr
&& !IS_DIRSEP(*str
))
2062 if (str
< *junkptr
) {
2063 if (IS_DIRSEP(**junkptr
))
2064 *junkptr
= dupstring ("/");
2066 *junkptr
= dupstring (".");
2074 * Return this many components, so start from the front.
2075 * Leading slash counts as one component, consistent with
2076 * behaviour of repeated applications of :h.
2078 char *strp
= *junkptr
;
2079 while (strp
< str
) {
2080 if (IS_DIRSEP(*strp
)) {
2082 if (strp
== *junkptr
)
2087 /* Count consecutive separators as one */
2088 while (IS_DIRSEP(strp
[1]))
2094 /* Full string needed */
2098 /* repeated slashes are considered like a single slash */
2099 while (str
> *junkptr
&& IS_DIRSEP(str
[-1]))
2101 /* never erase the root slash */
2102 if (str
== *junkptr
) {
2104 /* Leading doubled slashes (`//') have a special meaning on cygwin
2105 and some old flavor of UNIX, so we do not assimilate them to
2106 a single slash. However a greater number is ok to squeeze. */
2107 if (IS_DIRSEP(*str
) && !IS_DIRSEP(str
[1]))
2116 remtext(char **junkptr
)
2120 for (str
= strend(*junkptr
); str
>= *junkptr
&& !IS_DIRSEP(*str
); --str
)
2130 rembutext(char **junkptr
)
2134 for (str
= strend(*junkptr
); str
>= *junkptr
&& !IS_DIRSEP(*str
); --str
)
2136 *junkptr
= dupstring(str
+ 1); /* .xx or xx? */
2140 *junkptr
= dupstring ("");
2146 remlpaths(char **junkptr
, int count
)
2148 char *str
= strend(*junkptr
);
2150 if (IS_DIRSEP(*str
)) {
2151 /* remove trailing slashes */
2152 while (str
>= *junkptr
&& IS_DIRSEP(*str
))
2157 for (; str
>= *junkptr
; --str
) {
2158 if (IS_DIRSEP(*str
)) {
2160 if (str
> *junkptr
) {
2164 /* Whole string needed */
2169 *junkptr
= dupstring(str
+ 1);
2173 /* Count consecutive separators as 1 */
2174 while (str
>= *junkptr
&& IS_DIRSEP(*str
))
2176 if (str
<= *junkptr
)
2183 * Return modified version of str from the heap with modification
2184 * according to one of the CASMOD_* types defined in zsh.h; CASMOD_NONE
2185 * is not handled, for obvious reasons.
2190 casemodify(char *str
, int how
)
2192 char *str2
= zhalloc(2 * strlen(str
) + 1);
2196 #ifdef MULTIBYTE_SUPPORT
2197 if (isset(MULTIBYTE
)) {
2198 VARARR(char, mbstr
, MB_CUR_MAX
);
2202 memset(&ps
, 0, sizeof(ps
));
2205 int len
= mb_metacharlenconv(str
, &wc
), mod
= 0, len2
;
2207 * wc is set to WEOF if the start of str couldn't be
2208 * converted. Presumably WEOF doesn't match iswlower(), but
2214 /* not alphanumeric */
2234 default: /* shuts up compiler */
2235 if (IS_COMBINING(wc
))
2239 else if (nextupper
) {
2245 } else if (iswupper(wc
)) {
2251 if (mod
&& (len2
= wcrtomb(mbstr
, wc
, &ps
)) > 0) {
2254 for (mbptr
= mbstr
; mbptr
< mbstr
+ len2
; mbptr
++) {
2255 if (imeta((unsigned char) *mbptr
)) {
2257 *ptr2
++ = *mbptr
^ 32;
2274 c
= (unsigned char) (str
[1] ^ 32);
2277 c
= (unsigned char) *str
++;
2294 default: /* shuts up compiler */
2297 else if (nextupper
) {
2303 } else if (isupper(c
)) {
2309 if (mod
&& imeta(c
)) {
2321 * Substitute "in" for "out" in "*strptr" and update "*strptr".
2322 * If "gbal", do global substitution.
2324 * This returns a result from the heap. There seems to have
2325 * been some confusion on this point.
2330 subst(char **strptr
, char *in
, char *out
, int gbal
, int forcepat
)
2332 char *str
= *strptr
, *substcut
, *sptr
;
2333 int off
, inlen
, outlen
;
2338 if (isset(HISTSUBSTPATTERN
) || forcepat
) {
2339 int fl
= SUB_LONG
|SUB_REST
|SUB_RETFAIL
;
2343 if (*in
== '#' || *in
== Pound
) {
2344 /* anchor at head, flag needed if SUB_END is also set */
2349 /* anchor at tail */
2354 /* no anchor, substring match */
2359 if (parse_subst_string(in
) || errflag
)
2361 if (parse_subst_string(out
) || errflag
)
2364 if (getmatch(strptr
, in
, fl
, 1, out
))
2367 if ((substcut
= (char *)strstr(str
, in
))) {
2369 sptr
= convamps(out
, in
, inlen
);
2370 outlen
= strlen(sptr
);
2374 off
= substcut
- *strptr
+ outlen
;
2376 *strptr
= zhtricat(*strptr
, sptr
, substcut
);
2377 str
= (char *)*strptr
+ off
;
2378 } while (gbal
&& (substcut
= (char *)strstr(str
, in
)));
2389 convamps(char *out
, char *in
, int inlen
)
2391 char *ptr
, *ret
, *pp
;
2394 for (ptr
= out
, slen
= 0; *ptr
; ptr
++, slen
++)
2397 else if (*ptr
== '&')
2398 slen
+= inlen
- 1, sdup
= 1;
2401 ret
= pp
= (char *) zhalloc(slen
+ 1);
2402 for (ptr
= out
; *ptr
; ptr
++)
2405 else if (*ptr
== '&') {
2416 checkcurline(Histent he
)
2418 if (he
->histnum
== curhist
&& (histactive
& HA_ACTIVE
)) {
2419 curline
.node
.nam
= chline
;
2420 curline
.nwords
= chwordpos
/2;
2421 curline
.words
= chwords
;
2427 quietgethist(int ev
)
2429 return gethistent(ev
, GETHIST_EXACT
);
2438 ret
= quietgethist(ev
);
2441 zerr("no such event: %d", ev
);
2448 getargs(Histent elist
, int arg1
, int arg2
)
2450 short *words
= elist
->words
;
2451 int pos1
, pos2
, nwords
= elist
->nwords
;
2453 if (arg2
< arg1
|| arg1
>= nwords
|| arg2
>= nwords
) {
2454 /* remember, argN is indexed from 0, nwords is total no. of words */
2456 zerr("no such word in event");
2460 /* optimization for accessing entire history event */
2461 if (arg1
== 0 && arg2
== nwords
- 1)
2462 return dupstring(elist
->node
.nam
);
2464 pos1
= words
[2*arg1
];
2465 pos2
= words
[2*arg2
+1];
2467 /* a word has to be at least one character long, so if the position
2468 * of a word is less than its index, we've overflowed our signed
2469 * short integer word range and the recorded position is garbage. */
2470 if (pos1
< 0 || pos1
< arg1
|| pos2
< 0 || pos2
< arg2
) {
2472 zerr("history event too long, can't index requested words");
2475 return dupstrpfx(elist
->node
.nam
+ pos1
, pos2
- pos1
);
2482 char *ptr
, *rptr
, **str
= tr
;
2486 for (ptr
= *str
; *ptr
; ptr
++, len
++)
2493 } else if (inblank(*ptr
) && !inquotes
&& ptr
[-1] != '\\')
2496 *str
= rptr
= (char *) zhalloc(len
);
2508 } else if (inblank(*ptr
) && !inquotes
&& ptr
[-1] != '\\') {
2521 quotebreak(char **tr
)
2523 char *ptr
, *rptr
, **str
= tr
;
2526 for (ptr
= *str
; *ptr
; ptr
++, len
++)
2529 else if (inblank(*ptr
))
2532 *str
= rptr
= (char *) zhalloc(len
);
2541 } else if (inblank(*ptr
)) {
2552 /* read an arbitrary amount of data into a buffer until stop is found */
2558 int bsiz
= 256, ct
= 0, c
;
2559 char *buf
= (char *)zalloc(bsiz
), *ptr
;
2562 while ((c
= ingetc()) != stop
&& c
!= '\n' && !lexstop
) {
2567 buf
= realloc(buf
, bsiz
*= 2);
2574 zerr("delimiter expected");
2586 int bsiz
= 256, ct
= 0, c
;
2587 char *buf
= (char *)zalloc(bsiz
), *ptr
;
2590 while ((c
= ingetc()) != stop
&& c
!= '\n' && !lexstop
) {
2595 buf
= realloc(buf
, bsiz
*= 2);
2614 resizehistents(void)
2616 if (histlinect
> histsiz
) {
2617 /* The reason we don't just call freehistnode(hist_ring->down) is
2618 * so that we can honor the HISTEXPIREDUPSFIRST setting. */
2619 putoldhistentryontop(0);
2620 freehistnode(&hist_ring
->node
);
2621 while (histlinect
> histsiz
) {
2622 putoldhistentryontop(1);
2623 freehistnode(&hist_ring
->node
);
2629 readhistline(int start
, char **bufp
, int *bufsiz
, FILE *in
, int *readbytes
)
2632 if (fgets(buf
+ start
, *bufsiz
- start
, in
)) {
2633 int len
= strlen(buf
+ start
);
2638 if (buf
[len
- 1] != '\n') {
2640 if (len
< (*bufsiz
) - 1)
2642 *bufp
= zrealloc(buf
, 2 * (*bufsiz
));
2643 *bufsiz
= 2 * (*bufsiz
);
2644 return readhistline(len
, bufp
, bufsiz
, in
, readbytes
);
2649 buf
[len
- 1] = '\0';
2650 if (len
> 1 && buf
[len
- 2] == '\\') {
2651 buf
[--len
- 1] = '\n';
2653 return readhistline(len
, bufp
, bufsiz
, in
, readbytes
);
2657 while (spc
>= 0 && buf
[spc
] == ' ')
2659 if (spc
!= len
- 2 && buf
[spc
] == '\\')
2660 buf
[--len
- 1] = '\0';
2669 readhistfile(char *fn
, int err
, int readflags
)
2671 char *buf
, *start
= NULL
;
2674 time_t stim
, ftim
, tim
= time(NULL
);
2678 int nwordpos
, nwords
, bufsiz
;
2679 int searching
, newflags
, l
, ret
, uselex
, readbytes
;
2681 if (!fn
&& !(fn
= getsparam("HISTFILE")))
2683 if (stat(unmeta(fn
), &sb
) < 0 ||
2686 if (readflags
& HFILE_FAST
) {
2687 if (!lasthist
.interrupted
&&
2688 ((lasthist
.fsiz
== sb
.st_size
&& lasthist
.mtim
== sb
.st_mtime
)
2689 || lockhistfile(fn
, 0)))
2691 lasthist
.fsiz
= sb
.st_size
;
2692 lasthist
.mtim
= sb
.st_mtime
;
2693 lasthist
.interrupted
= 0;
2694 } else if ((ret
= lockhistfile(fn
, 1))) {
2696 zwarn("locking failed for %s: %e: reading anyway", fn
, errno
);
2698 zerr("locking failed for %s: %e", fn
, errno
);
2702 if ((in
= fopen(unmeta(fn
), "r"))) {
2704 words
= (short *)zalloc(nwords
*sizeof(short));
2706 buf
= zalloc(bufsiz
);
2709 if (readflags
& HFILE_FAST
&& lasthist
.text
) {
2710 if (lasthist
.fpos
< lasthist
.fsiz
) {
2711 fseek(in
, lasthist
.fpos
, SEEK_SET
);
2715 histfile_linect
= 0;
2723 newflags
= HIST_OLD
| HIST_READ
;
2724 if (readflags
& HFILE_FAST
)
2725 newflags
|= HIST_FOREIGN
;
2726 if (readflags
& HFILE_SKIPOLD
2727 || (hist_ignore_all_dups
&& newflags
& hist_skip_flags
))
2728 newflags
|= HIST_MAKEUNIQUE
;
2729 while (fpos
+= readbytes
, readbytes
= 0, (l
= readhistline(0, &buf
, &bufsiz
, in
, &readbytes
))) {
2734 zerr("corrupt history file %s", fn
);
2739 * Handle the special case that we're reading from an
2740 * old shell with fewer meta characters, so we need to
2741 * metafy some more. (It's not clear why the history
2742 * file is metafied at all; some would say this is plain
2743 * stupid. But we're stuck with it now without some
2744 * hairy workarounds for compatibility).
2746 * This is rare so doesn't need to be that efficient; just
2747 * allocate space off the heap.
2749 for (pt
= buf
; *pt
; pt
++) {
2750 if (*pt
== Meta
&& pt
[1])
2752 else if (imeta(*pt
)) {
2758 unmetafy(buf
, &remeta
);
2759 pt
= metafy(buf
, remeta
, META_USEHEAP
);
2766 stim
= zstrtol(pt
, NULL
, 0);
2767 for (; *pt
!= ':' && *pt
; pt
++);
2770 ftim
= zstrtol(pt
, NULL
, 0);
2771 for (; *pt
!= ';' && *pt
; pt
++);
2777 if (*pt
== '\\' && pt
[1] == ':')
2783 if (searching
> 0) {
2784 if (stim
== lasthist
.stim
2785 && histstrcmp(pt
, lasthist
.text
) == 0)
2788 fseek(in
, 0, SEEK_SET
);
2789 histfile_linect
= 0;
2794 else if (stim
< lasthist
.stim
) {
2801 if (readflags
& HFILE_USE_OPTIONS
) {
2803 lasthist
.fpos
= fpos
;
2804 lasthist
.stim
= stim
;
2807 he
= prepnexthistent();
2808 he
->node
.nam
= ztrdup(pt
);
2809 he
->node
.flags
= newflags
;
2810 if ((he
->stim
= stim
) == 0)
2811 he
->stim
= he
->ftim
= tim
;
2812 else if (ftim
< stim
)
2813 he
->ftim
= stim
+ ftim
;
2818 * Divide up the words.
2821 uselex
= isset(HISTLEXWORDS
) && !(readflags
& HFILE_FAST
);
2822 histsplitwords(pt
, &words
, &nwords
, &nwordpos
, uselex
);
2824 he
->nwords
= nwordpos
/2;
2826 he
->words
= (short *)zalloc(nwordpos
*sizeof(short));
2827 memcpy(he
->words
, words
, nwordpos
*sizeof(short));
2829 he
->words
= (short *)NULL
;
2830 addhistnode(histtab
, he
->node
.nam
, he
);
2831 if (he
->node
.flags
& HIST_DUP
) {
2832 freehistnode(&he
->node
);
2836 * Do this last out of paranoia in case use of
2837 * heap is disguised...
2839 if (uselex
|| remeta
)
2841 if (errflag
& ERRFLAG_INT
) {
2842 /* Can't assume fast read next time if interrupted. */
2843 lasthist
.interrupted
= 1;
2847 if (start
&& readflags
& HFILE_USE_OPTIONS
) {
2848 zsfree(lasthist
.text
);
2849 lasthist
.text
= ztrdup(start
);
2851 zfree(words
, nwords
*sizeof(short));
2857 zerr("can't read history file %s", fn
);
2862 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
2866 static int flock_fd
= -1;
2869 * Lock file using fcntl(). Return 0 on success, 1 on failure of
2870 * locking mechanism, 2 on permanent failure (e.g. permission).
2874 flockhistfile(char *fn
, int keep_trying
)
2877 long sleep_us
= 0x10000; /* about 67 ms */
2881 return 0; /* already locked */
2883 if ((flock_fd
= open(unmeta(fn
), O_RDWR
| O_NOCTTY
)) < 0)
2884 return errno
== ENOENT
? 0 : 2; /* "successfully" locked missing file */
2886 lck
.l_type
= F_WRLCK
;
2887 lck
.l_whence
= SEEK_SET
;
2889 lck
.l_len
= 0; /* lock the whole file */
2892 * Timeout is ten seconds.
2894 end_time
= time(NULL
) + (time_t)10;
2895 while (fcntl(flock_fd
, F_SETLKW
, &lck
) == -1) {
2896 if (!keep_trying
|| time(NULL
) >= end_time
||
2898 * Randomise wait to minimise clashes with shells exiting at
2901 !zsleep_random(sleep_us
, end_time
)) {
2915 savehistfile(char *fn
, int err
, int writeflags
)
2917 char *t
, *tmpfile
, *start
= NULL
;
2920 zlong xcurhist
= curhist
- !!(histactive
& HA_ACTIVE
);
2921 int extended_history
= isset(EXTENDEDHISTORY
);
2924 if (!interact
|| savehistsiz
<= 0 || !hist_ring
2925 || (!fn
&& !(fn
= getsparam("HISTFILE"))))
2927 if (writeflags
& HFILE_FAST
) {
2928 he
= gethistent(lasthist
.next_write_ev
, GETHIST_DOWNWARD
);
2929 while (he
&& he
->node
.flags
& HIST_OLD
) {
2930 lasthist
.next_write_ev
= he
->histnum
+ 1;
2931 he
= down_histent(he
);
2933 if (!he
|| lockhistfile(fn
, 0))
2935 if (histfile_linect
> savehistsiz
+ savehistsiz
/ 5)
2936 writeflags
&= ~HFILE_FAST
;
2939 if (lockhistfile(fn
, 1)) {
2940 zerr("locking failed for %s: %e", fn
, errno
);
2943 he
= hist_ring
->down
;
2945 if (writeflags
& HFILE_USE_OPTIONS
) {
2946 if (isset(APPENDHISTORY
) || isset(INCAPPENDHISTORY
)
2947 || isset(INCAPPENDHISTORYTIME
) || isset(SHAREHISTORY
))
2948 writeflags
|= HFILE_APPEND
| HFILE_SKIPOLD
;
2950 histfile_linect
= 0;
2951 if (isset(HISTSAVENODUPS
))
2952 writeflags
|= HFILE_SKIPDUPS
;
2953 if (isset(SHAREHISTORY
))
2954 extended_history
= 1;
2957 if (writeflags
& HFILE_APPEND
) {
2958 int fd
= open(unmeta(fn
), O_CREAT
| O_WRONLY
| O_APPEND
| O_NOCTTY
, 0600);
2960 out
= fd
>= 0 ? fdopen(fd
, "a") : NULL
;
2961 } else if (!isset(HISTSAVEBYCOPY
)) {
2962 int fd
= open(unmeta(fn
), O_CREAT
| O_WRONLY
| O_TRUNC
| O_NOCTTY
, 0600);
2964 out
= fd
>= 0 ? fdopen(fd
, "w") : NULL
;
2966 tmpfile
= bicat(unmeta(fn
), ".new");
2967 if (unlink(tmpfile
) < 0 && errno
!= ENOENT
)
2971 int old_exists
= stat(unmeta(fn
), &sb
) == 0;
2972 uid_t euid
= geteuid();
2975 #if defined HAVE_FCHMOD && defined HAVE_FCHOWN
2978 && sb
.st_uid
!= euid
) {
2982 if (isset(APPENDHISTORY
) || isset(INCAPPENDHISTORY
)
2983 || isset(INCAPPENDHISTORYTIME
) || isset(SHAREHISTORY
))
2984 zerr("rewriting %s would change its ownership -- skipped", fn
);
2986 zerr("rewriting %s would change its ownership -- history not saved", fn
);
2987 err
= 0; /* Don't report a generic error below. */
2991 int fd
= open(tmpfile
, O_CREAT
| O_WRONLY
| O_EXCL
, 0600);
2993 out
= fdopen(fd
, "w");
3001 if (old_exists
&& out
) {
3003 if (fchown(fileno(out
), sb
.st_uid
, sb
.st_gid
) < 0) {} /* IGNORE FAILURE */
3005 if (fchmod(fileno(out
), sb
.st_mode
) < 0) {} /* IGNORE FAILURE */
3011 char *history_ignore
;
3012 Patprog histpat
= NULL
;
3016 if ((history_ignore
= getsparam("HISTORY_IGNORE")) != NULL
) {
3017 tokenize(history_ignore
= dupstring(history_ignore
));
3018 remnulargs(history_ignore
);
3019 histpat
= patcompile(history_ignore
, 0, NULL
);
3023 for (; he
&& he
->histnum
<= xcurhist
; he
= down_histent(he
)) {
3024 int end_backslashes
= 0;
3026 if ((writeflags
& HFILE_SKIPDUPS
&& he
->node
.flags
& HIST_DUP
)
3027 || (writeflags
& HFILE_SKIPFOREIGN
&& he
->node
.flags
& HIST_FOREIGN
)
3028 || he
->node
.flags
& HIST_TMPSTORE
)
3031 pattry(histpat
, metafy(he
->node
.nam
, -1, META_HEAPDUP
))) {
3034 if (writeflags
& HFILE_SKIPOLD
) {
3035 if (he
->node
.flags
& (HIST_OLD
|HIST_NOWRITE
))
3037 he
->node
.flags
|= HIST_OLD
;
3038 if (writeflags
& HFILE_USE_OPTIONS
)
3039 lasthist
.next_write_ev
= he
->histnum
+ 1;
3041 if (writeflags
& HFILE_USE_OPTIONS
) {
3042 lasthist
.fpos
= ftell(out
);
3043 lasthist
.stim
= he
->stim
;
3046 t
= start
= he
->node
.nam
;
3047 if (extended_history
) {
3048 ret
= fprintf(out
, ": %ld:%ld;", (long)he
->stim
,
3049 he
->ftim
? (long)(he
->ftim
- he
->stim
) : 0L);
3050 } else if (*t
== ':')
3051 ret
= fputc('\\', out
);
3053 for (; ret
>= 0 && *t
; t
++) {
3055 if ((ret
= fputc('\\', out
)) < 0)
3057 end_backslashes
= (*t
== '\\' || (end_backslashes
&& *t
== ' '));
3058 if ((ret
= fputc(*t
, out
)) < 0)
3063 if (end_backslashes
)
3064 ret
= fputc(' ', out
);
3065 if (ret
< 0 || (ret
= fputc('\n', out
)) < 0)
3068 if (ret
>= 0 && start
&& writeflags
& HFILE_USE_OPTIONS
) {
3070 if ((ret
= fflush(out
)) >= 0) {
3071 if (fstat(fileno(out
), &sb
) == 0) {
3072 lasthist
.fsiz
= sb
.st_size
;
3073 lasthist
.mtim
= sb
.st_mtime
;
3075 zsfree(lasthist
.text
);
3076 lasthist
.text
= ztrdup(start
);
3079 if (fclose(out
) < 0 && ret
>= 0)
3083 if (rename(tmpfile
, unmeta(fn
)) < 0) {
3084 zerr("can't rename %s.new to $HISTFILE", fn
);
3089 /* We renamed over the locked HISTFILE, so close fd.
3090 * If we do more writing, we'll get a lock then. */
3091 if (flock_fd
>= 0) {
3099 if (ret
>= 0 && writeflags
& HFILE_SKIPOLD
3100 && !(writeflags
& (HFILE_FAST
| HFILE_NO_REWRITE
))) {
3101 int remember_histactive
= histactive
;
3103 /* Zeroing histactive avoids unnecessary munging of curline. */
3105 /* The NULL leaves HISTFILE alone, preserving fn's value. */
3106 pushhiststack(NULL
, savehistsiz
, savehistsiz
, -1);
3108 hist_ignore_all_dups
|= isset(HISTSAVENODUPS
);
3109 readhistfile(fn
, err
, 0);
3110 hist_ignore_all_dups
= isset(HISTIGNOREALLDUPS
);
3112 savehistfile(fn
, err
, 0);
3115 histactive
= remember_histactive
;
3123 if (ret
< 0 && err
) {
3125 zerr("failed to write history file %s.new: %e", fn
, errno
);
3127 zerr("failed to write history file %s: %e", fn
, errno
);
3135 static int lockhistct
;
3138 checklocktime(char *lockfile
, long *sleep_usp
, time_t then
)
3140 time_t now
= time(NULL
);
3142 if (now
+ 10 < then
) {
3143 /* File is more than 10 seconds in the future? */
3148 if (now
- then
< 10) {
3150 * To give the effect of a gradually increasing backoff,
3151 * we'll sleep a period based on the time we've spent so far.
3153 DPUTS(now
< then
, "time flowing backwards through history");
3155 * Randomise to minimise clashes with shells exiting at the same
3158 (void)zsleep_random(*sleep_usp
, then
+ 10);
3167 * Lock history file. Return 0 on success, 1 on failure to lock this
3168 * time, 2 on permanent failure (e.g. permission).
3173 lockhistfile(char *fn
, int keep_trying
)
3175 int ct
= lockhistct
;
3177 long sleep_us
= 0x10000; /* about 67 ms */
3179 if (!fn
&& !(fn
= getsparam("HISTFILE")))
3182 if (!lockhistct
++) {
3187 # ifdef HAVE_SYMLINK
3188 char pidbuf
[32], *lnk
;
3195 if (isset(HISTFCNTLLOCK
))
3196 return flockhistfile(fn
, keep_trying
);
3199 lockfile
= bicat(unmeta(fn
), ".LOCK");
3200 /* NOTE: only use symlink locking on a link()-having host in order to
3201 * avoid a change from open()-based locking to symlink()-based. */
3203 # ifdef HAVE_SYMLINK
3204 sprintf(pidbuf
, "/pid-%ld/host-", (long)mypid
);
3205 lnk
= getsparam("HOST");
3206 lnk
= bicat(pidbuf
, lnk
? lnk
: "");
3207 /* We'll abuse fd as our success flag. */
3208 while ((fd
= symlink(lnk
, lockfile
)) < 0) {
3209 if (errno
!= EEXIST
) {
3212 } else if (!keep_trying
) {
3216 if (lstat(lockfile
, &sb
) < 0) {
3217 if (errno
== ENOENT
)
3221 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
3229 # else /* not HAVE_SYMLINK */
3230 if ((fd
= gettempfile(fn
, 0, &tmpfile
)) >= 0) {
3231 FILE *out
= fdopen(fd
, "w");
3233 fprintf(out
, "%ld %s\n", (long)getpid(), getsparam("HOST"));
3237 while (link(tmpfile
, lockfile
) < 0) {
3238 if (errno
!= EEXIST
) {
3241 } else if (!keep_trying
) {
3244 } else if (lstat(lockfile
, &sb
) < 0) {
3245 if (errno
== ENOENT
)
3249 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
3261 # endif /* not HAVE_SYMLINK */
3262 #else /* not HAVE_LINK */
3263 while ((fd
= open(lockfile
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644)) < 0) {
3264 if (errno
!= EEXIST
) {
3267 } else if (!keep_trying
) {
3271 if (lstat(lockfile
, &sb
) < 0) {
3272 if (errno
== ENOENT
)
3277 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
3285 FILE *out
= fdopen(fd
, "w");
3287 fprintf(out
, "%ld %s\n", (long)mypid
, getsparam("HOST"));
3292 #endif /* not HAVE_LINK */
3296 if (ct
== lockhistct
) {
3298 if (flock_fd
>= 0) {
3303 DPUTS(ret
== 0, "BUG: return value non-zero on locking error");
3309 /* Unlock the history file if this corresponds to the last nested lock
3310 * request. If we don't have the file locked, just return.
3315 unlockhistfile(char *fn
)
3317 if (!fn
&& !(fn
= getsparam("HISTFILE")))
3326 lockfile
= zalloc(strlen(fn
) + 5 + 1);
3327 sprintf(lockfile
, "%s.LOCK", fn
);
3331 if (flock_fd
>= 0) {
3341 histfileIsLocked(void)
3343 return lockhistct
> 0;
3347 * Get the words in the current buffer. Using the lexer.
3349 * As far as I can make out, this is a gross hack based on a gross hack.
3350 * When analysing lines from within zle, we tweak the metafied line
3351 * positions (zlemetall and zlemetacs) directly in the lexer. That's
3352 * bad enough, but this function appears to be designed to be called
3353 * from outside zle, pretending to be in zle and calling out, so
3354 * we set zlemetall and zlemetacs locally and copy the current zle line,
3355 * which may not even be valid at this point.
3357 * However, I'm so confused it could simply be baking Bakewell tarts.
3359 * list may be an existing linked list (off the heap), in which case
3360 * it will be appended to; otherwise it will be created.
3362 * If buf is set we will take input from that string, else we will
3363 * attempt to use ZLE directly in a way they tell you not to do on all
3364 * programming courses.
3366 * If index is non-NULL, and input is from a string in ZLE, *index
3367 * is set to the position of the end of the current editor word.
3369 * flags is passed directly to lexflags, see lex.c, except that
3370 * we 'or' in the bit LEXFLAGS_ACTIVE to make sure the variable
3376 bufferwords(LinkList list
, char *buf
, int *index
, int flags
)
3378 int num
= 0, cur
= -1, got
= 0, ne
= noerrs
;
3379 int owb
= wb
, owe
= we
, oadx
= addedx
, onc
= nocomments
;
3380 int ona
= noaliases
, ocs
= zlemetacs
, oll
= zlemetall
;
3381 int forloop
= 0, rcquotes
= opts
[RCQUOTES
];
3383 char *p
, *addedspaceptr
;
3386 list
= newlinklist();
3389 * With RC_QUOTES, 'foo '' bar' comes back as 'foo ' bar'. That's
3390 * not very useful. As nothing in here requires the fully processed
3391 * string expression, we just turn the option off for this function.
3397 lexflags
= flags
| LEXFLAGS_ACTIVE
;
3399 * Are we handling comments?
3401 nocomments
= !(flags
& (LEXFLAGS_COMMENTS_KEEP
|
3402 LEXFLAGS_COMMENTS_STRIP
));
3404 int l
= strlen(buf
);
3406 p
= (char *) zhalloc(l
+ 2);
3409 * I'm sure this space is here for a reason, but it's
3410 * a pain in the neck: when we get back a string that's
3411 * not finished it's very hard to tell if a space at the
3412 * end is this one or not. We use two tricks below to
3415 addedspaceptr
= p
+ l
;
3416 *addedspaceptr
= ' ';
3417 addedspaceptr
[1] = '\0';
3419 zlemetall
= strlen(p
) ;
3420 zlemetacs
= zlemetall
+ 1;
3425 linein
= zleentry(ZLE_CMD_GET_LINE
, &ll
, &cs
);
3426 zlemetall
= ll
+ 1; /* length of line plus space added below */
3429 if (!isfirstln
&& chline
) {
3430 p
= (char *) zhalloc(hptr
- chline
+ ll
+ 2);
3431 memcpy(p
, chline
, hptr
- chline
);
3432 memcpy(p
+ (hptr
- chline
), linein
, ll
);
3433 addedspaceptr
= p
+ (hptr
- chline
) + ll
;
3434 *addedspaceptr
= ' ';
3435 addedspaceptr
[1] = '\0';
3439 * advance line length and character position over
3442 zlemetall
+= hptr
- chline
;
3443 zlemetacs
+= hptr
- chline
;
3445 p
= (char *) zhalloc(ll
+ 2);
3446 memcpy(p
, linein
, ll
);
3447 addedspaceptr
= p
+ ll
;
3448 *addedspaceptr
= ' ';
3449 p
[zlemetall
] = '\0';
3460 incond
= 1 + (tok
!= DINBRACK
&& tok
!= INPAR
&&
3461 tok
!= DBAR
&& tok
!= DAMPER
&&
3464 if (tok
== ENDINPUT
|| tok
== LEXERR
)
3467 * After an array assignment, return to the initial
3468 * start-of-command state. There could be a second ENVARRAY.
3470 if (tok
== OUTPAR
&& envarray
) {
3476 * The way for (( expr1 ; expr2; expr3 )) is parsed is:
3478 * - a DINPAR with no tokstr
3479 * - two DINPARS with tokstr's expr1, expr2.
3480 * - a DOUTPAR with tokstr expr3.
3482 * We'll decrement the variable forloop as we verify
3483 * the various stages.
3485 * Don't ask me, ma'am, I'm just the programmer.
3510 p
= dyncat(tokstr
, "=(");
3517 p
= dyncat(tokstr
, ";");
3520 * Mathematical expressions analysed as a single
3521 * word. That's correct because it behaves like
3522 * double quotes. Whitespace in the middle is
3523 * similarly retained, so just add the parentheses back.
3525 p
= zhtricat("((", tokstr
, "))");
3530 p
= dupstring(tokstr
);
3535 if (ingetptr() == addedspaceptr
+ 1) {
3537 * Whoops, we've read past the space we added, probably
3538 * because we were expecting a terminator but when
3539 * it didn't turn up we shrugged our shoulders thinking
3540 * it might as well be a complete string anyway.
3541 * So remove the space. C.f. below for the case
3542 * where the missing terminator caused a lex error.
3543 * We use the same paranoid test.
3545 int plen
= strlen(p
);
3546 if (plen
&& p
[plen
-1] == ' ' &&
3547 (plen
== 1 || p
[plen
-2] != Meta
))
3550 addlinknode(list
, p
);
3554 if (IS_REDIROP(tok
) && tokfd
>= 0) {
3557 sprintf(b
, "%d%s", tokfd
, tokstrings
[tok
]);
3558 addlinknode(list
, dupstring(b
));
3560 } else if (tok
!= NEWLIN
) {
3561 addlinknode(list
, dupstring(tokstrings
[tok
]));
3568 * Final "))" of for loop to match opening,
3569 * since we've just added the preceding element.
3571 addlinknode(list
, dupstring("))"));
3575 if (!got
&& !lexflags
) {
3579 } while (tok
!= ENDINPUT
&& tok
!= LEXERR
&& !(errflag
& ERRFLAG_INT
));
3580 if (buf
&& tok
== LEXERR
&& tokstr
&& *tokstr
) {
3582 untokenize((p
= dupstring(tokstr
)));
3585 * Strip the space we added for lexing but which won't have
3586 * been swallowed by the lexer because we aborted early.
3587 * The test is paranoia.
3589 if (plen
&& p
[plen
-1] == ' ' && (plen
== 1 || p
[plen
-2] != Meta
))
3591 addlinknode(list
, p
);
3599 errflag
&= ~ERRFLAG_ERROR
;
3608 opts
[RCQUOTES
] = rcquotes
;
3617 * Split up a line into words for use in a history file.
3619 * lineptr is the line to be split.
3621 * *wordsp and *nwordsp are an array already allocated to hold words
3622 * and its length. The array holds both start and end positions,
3623 * so *nwordsp actually counts twice the number of words in the
3624 * original string. *nwordsp may be zero in which case the array
3625 * will be allocated.
3627 * *nwordposp returns the used length of *wordsp in the same units as
3628 * *nwordsp, i.e. twice the number of words in the input line.
3630 * If uselex is 1, attempt to do this using the lexical analyser.
3631 * This is more accurate, but slower; for reading history files it's
3632 * controlled by the option HISTLEXWORDS. If this failed (which
3633 * indicates a bug in the shell) it falls back to whitespace-separated
3634 * strings, printing a message if in debug mode.
3636 * If uselex is 0, just look for whitespace-separated words; the only
3637 * special handling is for a backslash-newline combination as used
3638 * by the history file format to save multiline buffers.
3642 histsplitwords(char *lineptr
, short **wordsp
, int *nwordsp
, int *nwordposp
,
3645 int nwords
= *nwordsp
, nwordpos
= 0;
3646 short *words
= *wordsp
;
3647 char *start
= lineptr
;
3654 wordlist
= bufferwords(NULL
, lineptr
, NULL
,
3655 LEXFLAGS_COMMENTS_KEEP
);
3658 nwords_max
= 2 * countlinknodes(wordlist
);
3659 if (nwords_max
> nwords
) {
3660 *nwordsp
= nwords
= nwords_max
;
3661 *wordsp
= words
= (short *)zrealloc(words
, nwords
*sizeof(short));
3663 for (wordnode
= firstnode(wordlist
);
3665 incnode(wordnode
)) {
3666 char *word
= getdata(wordnode
);
3667 char *lptr
, *wptr
= word
;
3668 int loop_next
= 0, skipping
;
3670 /* Skip stuff at the start of the word */
3673 * Not really an oddity: "\\\n" is
3674 * removed from input as if whitespace.
3676 if (inblank(*lineptr
))
3678 else if (lineptr
[0] == '\\' && lineptr
[1] == '\n') {
3680 * Optimisation: we handle this in the loop below,
3689 * Skip chunks of word with possible intervening
3690 * backslash-newline.
3692 * To get round C's annoying lack of ability to
3693 * reference the outer loop, we'll break from this
3695 * loop_next = 0: carry on as normal
3696 * loop_next = 1: break from outer loop
3697 * loop_next = 2: continue round outer loop.
3701 if (strpfx(wptr
, lptr
)) {
3703 * Normal case: word from lexer matches start of
3704 * string from line. Just advance over it.
3707 if (!strcmp(wptr
, ";") && strpfx(";;", lptr
)) {
3709 * Don't get confused between a semicolon that's
3710 * probably really a newline and a double
3711 * semicolon that's terminating a case.
3721 * Didn't get to the end of the word.
3726 * Oddity 1: newlines turn into semicolons.
3728 if (!strcmp(wptr
, ";"))
3736 * End of the word before the end of the
3744 * Oddity 2: !'s turn into |'s.
3746 if (*lptr
== *wptr
||
3747 (*lptr
== '!' && *wptr
== '|')) {
3751 } else if (lptr
[0] == '\\' &&
3754 * \\\n can occur in the middle of a word;
3755 * wptr is already pointing at this, we
3756 * just need to skip over the break
3757 * in lptr and look at the next chunk.
3770 dputs(ERRMSG("bad wordsplit reading history: "
3771 "%s\nat: %s\nword: %s"),
3772 start
, lineptr
, word
);
3786 /* Record position of current word... */
3787 words
[nwordpos
++] = lineptr
- start
;
3788 words
[nwordpos
++] = lptr
- start
;
3790 /* ready for start of next word. */
3797 if (inblank(*lineptr
))
3799 else if (lineptr
[0] == '\\' && lineptr
[1] == '\n')
3805 if (nwordpos
>= nwords
) {
3806 *nwordsp
= nwords
= nwords
+ 64;
3807 *wordsp
= words
= (short *)
3808 zrealloc(words
, nwords
*sizeof(*words
));
3810 words
[nwordpos
++] = lineptr
- start
;
3812 if (*lineptr
== Meta
&& lineptr
[1])
3814 else if (!inblank(*lineptr
))
3819 words
[nwordpos
++] = lineptr
- start
;
3824 *nwordposp
= nwordpos
;
3827 /* Move the current history list out of the way and prepare a fresh history
3828 * list using hf for HISTFILE, hs for HISTSIZE, and shs for SAVEHIST. If
3829 * the hf value is an empty string, HISTFILE will be unset from the new
3830 * environment; if it is NULL, HISTFILE will not be changed, not even by the
3831 * pop function (this functionality is used internally to rewrite the current
3832 * history file without affecting pointers into the environment).
3837 pushhiststack(char *hf
, zlong hs
, zlong shs
, int level
)
3840 int curline_in_ring
= (histactive
& HA_ACTIVE
) && hist_ring
== &curline
;
3842 if (histsave_stack_pos
== histsave_stack_size
) {
3843 histsave_stack_size
+= 5;
3844 histsave_stack
= zrealloc(histsave_stack
,
3845 histsave_stack_size
* sizeof (struct histsave
));
3848 if (curline_in_ring
)
3851 h
= &histsave_stack
[histsave_stack_pos
++];
3853 h
->lasthist
= lasthist
;
3855 if ((h
->histfile
= getsparam("HISTFILE")) != NULL
&& *h
->histfile
)
3856 h
->histfile
= ztrdup(h
->histfile
);
3861 h
->histtab
= histtab
;
3862 h
->hist_ring
= hist_ring
;
3863 h
->curhist
= curhist
;
3864 h
->histlinect
= histlinect
;
3865 h
->histsiz
= histsiz
;
3866 h
->savehistsiz
= savehistsiz
;
3867 h
->locallevel
= level
;
3869 memset(&lasthist
, 0, sizeof lasthist
);
3872 setsparam("HISTFILE", ztrdup(hf
));
3874 unsetparam("HISTFILE");
3877 curhist
= histlinect
= 0;
3879 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
3882 inithist(); /* sets histtab */
3884 if (curline_in_ring
)
3887 return histsave_stack_pos
;
3896 int curline_in_ring
= (histactive
& HA_ACTIVE
) && hist_ring
== &curline
;
3898 if (histsave_stack_pos
== 0)
3901 if (curline_in_ring
)
3904 deletehashtable(histtab
);
3905 zsfree(lasthist
.text
);
3907 h
= &histsave_stack
[--histsave_stack_pos
];
3909 lasthist
= h
->lasthist
;
3912 setsparam("HISTFILE", h
->histfile
);
3914 unsetparam("HISTFILE");
3916 histtab
= h
->histtab
;
3917 hist_ring
= h
->hist_ring
;
3918 curhist
= h
->curhist
;
3920 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
3921 histlinect
= h
->histlinect
;
3922 histsiz
= h
->histsiz
;
3923 savehistsiz
= h
->savehistsiz
;
3925 if (curline_in_ring
)
3928 return histsave_stack_pos
+ 1;
3931 /* If pop_through > 0, pop all array items >= the 1-relative index value.
3932 * If pop_through <= 0, pop (-1)*pop_through levels off the stack.
3933 * If the (new) top of stack is from a higher locallevel, auto-pop until
3939 saveandpophiststack(int pop_through
, int writeflags
)
3941 if (pop_through
<= 0) {
3942 pop_through
+= histsave_stack_pos
+ 1;
3943 if (pop_through
<= 0)
3946 while (pop_through
> 1
3947 && histsave_stack
[pop_through
-2].locallevel
> locallevel
)
3949 if (histsave_stack_pos
< pop_through
)
3953 savehistfile(NULL
, 1, writeflags
);
3955 } while (histsave_stack_pos
>= pop_through
);