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));
43 void (*hwaddc
) _((int));
46 void (*hwbegin
) _((int));
49 void (*hwend
) _((void));
52 void (*addtoline
) _((int));
54 /* != 0 means history substitution is turned off */
57 mod_export
int stophist
;
59 /* if != 0, we are expanding the current line */
62 mod_export
int expanding
;
64 /* these are used to modify the cursor position during expansion */
67 mod_export
int excs
, exlast
;
70 * Current history event number
72 * Note on curhist: with history inactive, this points to the
73 * last line actually added to the history list. With history active,
74 * the line does not get added to the list until hend(), if at all.
75 * However, curhist is incremented to reflect the current line anyway
76 * and a temporary history entry is inserted while the user is editing.
77 * If the resulting line was not added to the list, a flag is set so
78 * that curhist will be decremented in hbegin().
80 * Note curhist is passed to zle on variable length argument list:
81 * type must match that retrieved in zle_main_entry.
85 mod_export zlong curhist
;
88 struct histent curline
;
90 /* current line count of allocated history entries */
95 /* The history lines are kept in a hash, and also doubly-linked in a ring */
100 mod_export Histent hist_ring
;
102 /* capacity of history lists */
107 /* desired history-file size (in lines) */
112 /* if = 1, we have performed history substitution on the current line *
113 * if = 2, we have used the 'p' modifier */
118 /* state of the history mechanism */
123 /* Current setting of the associated option, but sometimes also includes
124 * the setting of the HIST_SAVE_NO_DUPS option. */
127 int hist_ignore_all_dups
;
129 /* What flags (if any) we should skip when moving through the history */
132 mod_export
int hist_skip_flags
;
134 /* Bits of histactive variable */
135 #define HA_ACTIVE (1<<0) /* History mechanism is active */
136 #define HA_NOINC (1<<1) /* Don't store, curhist not incremented */
137 #define HA_INWORD (1<<2) /* We're inside a word, don't add
138 start and end markers */
140 /* Array of word beginnings and endings in current history line. */
145 /* Max, actual position in chwords.
146 * nwords = chwordpos/2 because we record beginning and end of words.
150 int chwordlen
, chwordpos
;
152 /* the last l for s/l/r/ history substitution */
157 /* the last r for s/l/r/ history substitution */
162 /* pointer into the history line */
165 mod_export
char *hptr
;
167 /* the current history line */
170 mod_export
char *chline
;
173 * The current history line as seen by ZLE.
174 * We modify chline for use in other contexts while ZLE may
175 * still be running; ZLE should see only the top-level value.
177 * To avoid having to modify this every time we modify chline,
178 * we set it when we push the stack, and unset it when we pop
179 * the appropriate value off the stack. As it's never modified
180 * on the stack this is the only maintainance we ever do on it.
181 * In return, ZLE has to check both zle_chline and (if that's
182 * NULL) chline to get the current value.
186 mod_export
char *zle_chline
;
188 /* true if the last character returned by hgetc was an escaped bangchar *
189 * if it is set and NOBANGHIST is unset hwaddc escapes bangchars */
194 /* max size of histline */
199 /* default event (usually curhist-1, that is, "!!") */
203 /* Remember the last line in the history file so we can find it again. */
204 static struct histfile_stats
{
211 static struct histsave
{
212 struct histfile_stats lasthist
;
222 static int histsave_stack_size
= 0;
223 static int histsave_stack_pos
= 0;
225 static zlong histfile_linect
;
227 /* save history context */
231 hist_context_save(struct hist_stack
*hs
, int toplevel
)
234 /* top level, make this version visible to ZLE */
236 /* ensure line stored is NULL-terminated */
240 hs
->histactive
= histactive
;
241 hs
->histdone
= histdone
;
242 hs
->stophist
= stophist
;
245 hs
->chwords
= chwords
;
246 hs
->chwordlen
= chwordlen
;
247 hs
->chwordpos
= chwordpos
;
249 hs
->hungetc
= hungetc
;
251 hs
->hwbegin
= hwbegin
;
253 hs
->addtoline
= addtoline
;
254 hs
->hlinesz
= hlinesz
;
256 * We save and restore the command stack with history
257 * as it's visible to the user interactively, so if
258 * we're preserving history state we'll continue to
259 * show the current set of commands from input.
261 hs
->cstack
= cmdstack
;
268 cmdstack
= (unsigned char *)zalloc(CMDSTACKSZ
);
272 /* restore history context */
276 hist_context_restore(const struct hist_stack
*hs
, int toplevel
)
279 /* Back to top level: don't need special ZLE value */
280 DPUTS(hs
->hline
!= zle_chline
, "BUG: Ouch, wrong chline for ZLE");
283 histactive
= hs
->histactive
;
284 histdone
= hs
->histdone
;
285 stophist
= hs
->stophist
;
288 chwords
= hs
->chwords
;
289 chwordlen
= hs
->chwordlen
;
290 chwordpos
= hs
->chwordpos
;
292 hungetc
= hs
->hungetc
;
294 hwbegin
= hs
->hwbegin
;
296 addtoline
= hs
->addtoline
;
297 hlinesz
= hs
->hlinesz
;
299 zfree(cmdstack
, CMDSTACKSZ
);
300 cmdstack
= hs
->cstack
;
305 * Mark that the current level of history is within a word whatever
306 * characters turn up, or turn that mode off. This is used for nested
307 * parsing of substitutions.
309 * The caller takes care only to turn this on or off at the start
310 * or end of recursive use of the same mode, so a single flag is
316 hist_in_word(int yesno
)
319 histactive
|= HA_INWORD
;
321 histactive
&= ~HA_INWORD
;
324 /* add a character to the current history word */
329 /* Only if history line exists and lexing has not finished. */
330 if (chline
&& !(errflag
|| lexstop
) &&
332 * If we're reading inside a word for command substitution
333 * we allow the lexer to expand aliases but don't deal
334 * with them here. Note matching code in ihungetc().
335 * TBD: it might be neater to deal with all aliases in this
336 * fashion as we never need the expansion in the history
337 * line, only in the lexer and above.
339 (inbufflags
& (INP_ALIAS
|INP_HIST
)) != INP_ALIAS
) {
340 /* Quote un-expanded bangs in the history line. */
341 if (c
== bangchar
&& stophist
< 2 && qbang
)
342 /* If qbang is not set, we do not escape this bangchar as it's *
343 * not necessary (e.g. it's a bang in !=, or it is followed *
344 * by a space). Roughly speaking, qbang is zero only if the *
345 * history interpreter has already digested this bang and *
346 * found that it is not necessary to escape it. */
350 /* Resize history line if necessary */
351 if (hptr
- chline
>= hlinesz
) {
352 int oldsiz
= hlinesz
;
354 chline
= realloc(chline
, hlinesz
= oldsiz
+ 64);
355 hptr
= chline
+ oldsiz
;
360 /* This function adds a character to the zle input line. It is used when *
361 * zsh expands history (see doexpandhist() in zle_tricky.c). It also *
362 * calculates the new cursor position after the expansion. It is called *
363 * from hgetc() and from gettok() in lex.c for characters in comments. */
369 if (!expanding
|| lexstop
)
371 if (qbang
&& c
== bangchar
&& stophist
< 2) {
373 zleentry(ZLE_CMD_ADD_TO_LINE
, '\\');
375 if (excs
> zlemetacs
) {
376 excs
+= 1 + inbufct
- exlast
;
377 if (excs
< zlemetacs
)
378 /* this case could be handled better but it is *
379 * so rare that it does not worth it */
383 zleentry(ZLE_CMD_ADD_TO_LINE
, itok(c
) ? ztokens
[c
- Pound
] : c
);
393 if (!stophist
&& !(inbufflags
& INP_ALIAS
)) {
394 /* If necessary, expand history characters. */
399 errflag
|= ERRFLAG_ERROR
;
403 if ((inbufflags
& INP_HIST
) && !stophist
) {
404 /* the current character c came from a history expansion *
405 * (inbufflags & INP_HIST) and history is not disabled *
406 * (e.g. we are not inside single quotes). In that case, \! *
407 * should be treated as ! (since this \! came from a previous *
408 * history line where \ was used to escape the bang). So if *
409 * c == '\\' we fetch one more character to see if it's a bang, *
410 * and if it is not, we unget it and reset c back to '\\' */
412 if (c
== '\\' && !(qbang
= (c
= ingetc()) == bangchar
))
413 safeinungetc(c
), c
= '\\';
414 } else if (stophist
|| (inbufflags
& INP_ALIAS
))
415 /* If the result is a bangchar which came from history or alias *
416 * expansion, we treat it as an escaped bangchar, unless history *
417 * is disabled. If stophist == 1 it only means that history is *
418 * temporarily disabled by a !" which won't appear in the *
419 * history, so we still have an escaped bang. stophist > 1 if *
420 * history is disabled with NOBANGHIST or by someone else (e.g. *
421 * when the lexer scans single quoted text). */
422 qbang
= c
== bangchar
&& (stophist
< 2);
445 while (!lexstop
&& inbufct
&& !strin
)
450 * Extract :s/foo/bar/ delimiters and arguments
452 * The first character expected is the first delimiter.
453 * The arguments are stored in the hsubl and hsubr variables.
455 * subline is the part of the command line to be matched.
457 * If a ':' was found but was not followed by a 'G',
458 * *cflagp is set to 1 and the input is backed up to the
459 * character following the colon.
464 getsubsargs(char *subline
, int *gbalp
, int *cflagp
)
470 ptr1
= hdynread2(del
);
473 ptr2
= hdynread2(del
);
477 } else if (!hsubl
) { /* fail silently on this */
498 /* Get the maximum no. of words for a history entry. */
502 getargc(Histent ehist
)
504 return ehist
->nwords
? ehist
->nwords
-1 : 0;
512 zerr("substitution failed");
516 /* Perform history substitution, returning the next character afterwards. */
522 int farg
, evset
= -1, larg
, argc
, cflag
= 0, bflag
= 0;
524 static int marg
= -1;
525 static zlong mev
= -1;
533 * If accumulating raw input for use in command substitution,
534 * we don't want the history text, so mark it for later removal.
535 * It would be better to do this at a level above the history
536 * and below the lexer --- but there isn't one.
538 * Include the character we are attempting to substitute.
540 lexraw_mark
= zshlex_raw_mark(-1);
542 /* look, no goto's */
543 if (isfirstch
&& c
== hatchar
) {
546 /* Line begins ^foo^bar */
549 if (!(ehist
= gethist(defev
))
550 || !(sline
= getargs(ehist
, 0, getargc(ehist
))))
553 if (getsubsargs(sline
, &gbal
, &cflag
))
554 return substfailed();
557 if (subst(&sline
, hsubl
, hsubr
, gbal
))
558 return substfailed();
560 /* Line doesn't begin ^foo^bar */
576 if ((c
= ingetc()) == '{') {
584 if ((!cflag
&& inblank(c
)) || c
== '=' || c
== '(' || lexstop
) {
589 ptr
= buf
= zhalloc(buflen
= 265);
591 /* get event number */
597 if (c
== '?' || c
== '\n' || lexstop
)
601 if (ptr
== buf
+ buflen
) {
602 buf
= hrealloc(buf
, buflen
, 2 * buflen
);
608 if (c
!= '\n' && !lexstop
)
611 mev
= ev
= hconsearch(hsubl
= ztrdup(buf
), &marg
);
616 zerr("no such event: %s", buf
);
623 if (inblank(c
) || c
== ';' || c
== ':' || c
== '^' ||
624 c
== '$' || c
== '*' || c
== '%' || c
== '}' ||
625 c
== '\'' || c
== '"' || c
== '`' || lexstop
)
630 if ((idigit(buf
[0]) || buf
[0] == '-') && !idigit(c
))
634 if (ptr
== buf
+ buflen
) {
635 buf
= hrealloc(buf
, buflen
, 2 * buflen
);
639 if (c
== '#' || c
== bangchar
) {
646 (c
== '}' || c
== ';' || c
== '\'' || c
== '"' || c
== '`')) {
647 /* Neither event nor word designator, no expansion */
654 if (isset(CSHJUNKIEHISTORY
))
655 ev
= addhistnum(curhist
,-1,HIST_FOREIGN
);
658 if (c
== ':' && evset
== -1)
669 } else if ((t0
= zstrtol(buf
, NULL
, 10))) {
670 ev
= (t0
< 0) ? addhistnum(curhist
,t0
,HIST_FOREIGN
) : t0
;
672 } else if ((unsigned)*buf
== bangchar
) {
673 ev
= addhistnum(curhist
,-1,HIST_FOREIGN
);
675 } else if (*buf
== '#') {
678 } else if ((ev
= hcomsearch(buf
)) == -1) {
681 zerr("event not found: %s", buf
);
689 if (!(ehist
= gethist(defev
= ev
))) {
693 /* extract the relevant arguments */
695 argc
= getargc(ehist
);
699 if (c
== '%' && marg
!= -1) {
701 ehist
= gethist(defev
= mev
);
702 argc
= getargc(ehist
);
706 zerr("ambiguous history reference");
718 larg
= farg
= getargspec(argc
, marg
, evset
);
729 } else if (c
== '-') {
731 larg
= getargspec(argc
, marg
, evset
);
745 if (!(sline
= getargs(ehist
, farg
, larg
))) {
752 /* do the modifiers */
755 c
= (cflag
) ? ':' : ingetc();
760 if ((c
= ingetc()) == 'g') {
763 if (c
!= 's' && c
!= '&') {
764 zerr("'s' or '&' modifier expected after 'g'");
770 histdone
= HISTFLAG_DONE
| HISTFLAG_NOEXEC
;
773 if (!chabspath(&sline
)) {
775 zerr("modifier failed: a");
781 if (!chrealpath(&sline
)) {
783 zerr("modifier failed: A");
788 if (!(sline
= equalsubstr(sline
, 0, 0))) {
790 zerr("modifier failed: c");
795 if (!remtpath(&sline
)) {
797 zerr("modifier failed: h");
802 if (!rembutext(&sline
)) {
804 zerr("modifier failed: e");
809 if (!remtext(&sline
)) {
811 zerr("modifier failed: r");
816 if (!remlpaths(&sline
)) {
818 zerr("modifier failed: t");
823 if (getsubsargs(sline
, &gbal
, &cflag
))
824 return -1; /* fall through */
826 if (hsubl
&& hsubr
) {
827 if (subst(&sline
, hsubl
, hsubr
, gbal
))
828 return substfailed();
831 zerr("no previous substitution");
840 int one
= noerrs
, oef
= errflag
;
843 parse_subst_string(sline
);
845 errflag
= oef
| (errflag
& ERRFLAG_INT
);
854 sline
= casemodify(sline
, CASMOD_LOWER
);
857 sline
= casemodify(sline
, CASMOD_UPPER
);
861 zerr("illegal modifier: %c", c
);
865 if (c
!= '}' || !bflag
)
867 if (c
!= '}' && bflag
) {
868 zerr("'}' expected");
875 zshlex_raw_back_to_mark(lexraw_mark
);
878 * Push the expanded value onto the input stack,
879 * marking this as a history word for purposes of the alias stack.
883 /* this function is called only called from hgetc and only if *
884 * !(inbufflags & INP_ALIAS). History expansion should never be *
885 * done with INP_ALIAS (to prevent recursive history expansion and *
886 * histoty expansion of aliases). Escapes are not removed here. *
887 * This is now handled in hgetc. */
888 inpush(sline
, INP_HIST
, NULL
); /* sline from heap, don't free */
889 histdone
|= HISTFLAG_DONE
;
890 if (isset(HISTVERIFY
))
891 histdone
|= HISTFLAG_NOEXEC
| HISTFLAG_RECALL
;
893 /* Don't try and re-expand line. */
897 /* unget a char and remove it from chline. It can only be used *
898 * to unget a character returned by hgetc. */
905 while (!lexstop
&& !errflag
) {
906 if (hptr
[-1] != (char) c
&& stophist
< 4 &&
907 hptr
> chline
+ 1 && hptr
[-1] == '\n' && hptr
[-2] == '\\')
908 hungetc('\n'), hungetc('\\');
915 if ((inbufflags
& (INP_ALIAS
|INP_HIST
)) != INP_ALIAS
) {
916 DPUTS(hptr
<= chline
, "BUG: hungetc attempted at buffer start");
918 DPUTS(*hptr
!= (char) c
, "BUG: wrong character in hungetc() ");
919 qbang
= (c
== bangchar
&& stophist
< 2 &&
920 hptr
> chline
&& hptr
[-1] == '\\');
922 /* No active bangs in aliases */
929 doit
= !stophist
&& ((inbufflags
& INP_HIST
) ||
930 !(inbufflags
& INP_ALIAS
));
935 /* begin reading a string */
945 * Also initialise some variables owned by the parser but
946 * used for communication between the parser and lexer.
951 /* done reading a string */
958 DPUTS(!strin
, "BUG: strinend() called without strinbeg()");
964 /* dummy functions to use instead of hwaddc(), hwbegin(), and hwend() when
965 * they aren't needed */
977 /* these functions handle adding/removing curline to/from the hist_ring */
983 hist_ring
= curline
.up
= curline
.down
= &curline
;
985 curline
.up
= hist_ring
;
986 curline
.down
= hist_ring
->down
;
987 hist_ring
->down
= hist_ring
->down
->up
= &curline
;
988 hist_ring
= &curline
;
990 curline
.histnum
= ++curhist
;
996 curline
.up
->down
= curline
.down
;
997 curline
.down
->up
= curline
.up
;
998 if (hist_ring
== &curline
) {
1002 hist_ring
= curline
.up
;
1007 /* initialize the history mechanism */
1015 isfirstln
= isfirstch
= 1;
1016 errflag
&= ~ERRFLAG_ERROR
;
1020 else if (dohist
!= 2)
1021 stophist
= (!interact
|| unset(SHINSTDIN
)) ? 2 : 0;
1025 * pws: We used to test for "|| (inbufflags & INP_ALIAS)"
1026 * in this test, but at this point we don't have input
1027 * set up up so this can trigger unnecessarily.
1028 * I don't see how the test at this point could ever be
1029 * useful, since we only get here when we're initialising
1030 * the history mechanism, before we've done any input.
1032 * (I also don't see any point where this function is called with
1035 if (stophist
== 2) {
1036 chline
= hptr
= NULL
;
1047 chline
= hptr
= zshcalloc(hlinesz
= 64);
1048 chwords
= zalloc((chwordlen
= 64) * sizeof(short));
1054 addtoline
= iaddtoline
;
1055 if (!isset(BANGHIST
))
1060 if (hist_ring
&& !hist_ring
->ftim
&& !strin
)
1061 hist_ring
->ftim
= time(NULL
);
1062 if ((dohist
== 2 || (interact
&& isset(SHINSTDIN
))) && !strin
) {
1063 histactive
= HA_ACTIVE
;
1066 defev
= addhistnum(curhist
, -1, HIST_FOREIGN
);
1068 histactive
= HA_ACTIVE
| HA_NOINC
;
1070 hf
= getsparam("HISTFILE");
1072 * For INCAPPENDHISTORYTIME, when interactive, save the history here
1073 * as it gives a better estimate of the times of commands.
1075 * If INCAPPENDHISTORY is also set we've already done it.
1077 * If SHAREHISTORY is also set continue to do so in the
1078 * standard place, because that's safer about reading and
1079 * rewriting history atomically.
1081 * The histsave_stack_pos test won't usually fail here.
1082 * We need to test the opposite for the hend() case because we
1083 * need to save in the history file we've switched to, but then
1084 * we pop immediately after that so the variable becomes zero.
1085 * We will already have saved the line and restored the history
1086 * so that (correctly) nothing happens here. But it shows
1087 * I thought about it.
1089 if (isset(INCAPPENDHISTORYTIME
) && !isset(SHAREHISTORY
) &&
1090 !isset(INCAPPENDHISTORY
) &&
1091 !(histactive
& HA_NOINC
) && !strin
&& histsave_stack_pos
== 0)
1092 savehistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1097 histreduceblanks(void)
1099 int i
, len
, pos
, needblank
, spacecount
= 0, trunc_ok
;
1100 char *lastptr
, *ptr
;
1102 if (isset(HISTIGNORESPACE
))
1103 while (chline
[spacecount
] == ' ') spacecount
++;
1105 for (i
= 0, len
= spacecount
; i
< chwordpos
; i
+= 2) {
1106 len
+= chwords
[i
+1] - chwords
[i
]
1107 + (i
> 0 && chwords
[i
] > chwords
[i
-1]);
1109 if (chline
[len
] == '\0')
1112 /* Remember where the delimited words end */
1114 lastptr
= chline
+ chwords
[chwordpos
-1];
1118 for (i
= 0, pos
= spacecount
; i
< chwordpos
; i
+= 2) {
1119 len
= chwords
[i
+1] - chwords
[i
];
1120 needblank
= (i
< chwordpos
-2 && chwords
[i
+2] > chwords
[i
+1]);
1121 if (pos
!= chwords
[i
]) {
1122 memmove(chline
+ pos
, chline
+ chwords
[i
], len
+ needblank
);
1124 chwords
[i
+1] = chwords
[i
] + len
;
1126 pos
+= len
+ needblank
;
1130 * A terminating comment isn't recorded as a word.
1131 * Only truncate the line if just whitespace remains.
1134 for (ptr
= lastptr
; *ptr
; ptr
++) {
1135 if (!inblank(*ptr
)) {
1144 while ((*ptr
++ = *lastptr
++))
1151 histremovedups(void)
1154 for (he
= hist_ring
; he
; he
= next
) {
1155 next
= up_histent(he
);
1156 if (he
->node
.flags
& HIST_DUP
)
1157 freehistnode(&he
->node
);
1163 addhistnum(zlong hl
, int n
, int xflags
)
1165 int dir
= n
< 0? -1 : n
> 0? 1 : 0;
1166 Histent he
= gethistent(hl
, dir
);
1170 if (he
->histnum
!= hl
)
1173 he
= movehistent(he
, n
, xflags
);
1175 return dir
< 0? firsthist() - 1 : curhist
+ 1;
1181 movehistent(Histent he
, int n
, int xflags
)
1184 if (!(he
= up_histent(he
)))
1186 if (!(he
->node
.flags
& xflags
))
1190 if (!(he
= down_histent(he
)))
1192 if (!(he
->node
.flags
& xflags
))
1201 up_histent(Histent he
)
1203 return !he
|| he
->up
== hist_ring
? NULL
: he
->up
;
1208 down_histent(Histent he
)
1210 return he
== hist_ring
? NULL
: he
->down
;
1215 gethistent(zlong ev
, int nearmatch
)
1222 if (ev
- hist_ring
->down
->histnum
< hist_ring
->histnum
- ev
) {
1223 for (he
= hist_ring
->down
; he
->histnum
< ev
; he
= he
->down
) ;
1224 if (he
->histnum
!= ev
) {
1226 || (nearmatch
< 0 && (he
= up_histent(he
)) == NULL
))
1231 for (he
= hist_ring
; he
->histnum
> ev
; he
= he
->up
) ;
1232 if (he
->histnum
!= ev
) {
1234 || (nearmatch
> 0 && (he
= down_histent(he
)) == NULL
))
1244 putoldhistentryontop(short keep_going
)
1246 static Histent next
= NULL
;
1247 Histent he
= (keep_going
|| !hist_ring
) ? next
: hist_ring
->down
;
1252 if (isset(HISTEXPIREDUPSFIRST
) && !(he
->node
.flags
& HIST_DUP
)) {
1253 static zlong max_unique_ct
= 0;
1255 max_unique_ct
= savehistsiz
;
1257 if (max_unique_ct
-- <= 0 || he
== hist_ring
) {
1259 he
= hist_ring
->down
;
1265 } while (!(he
->node
.flags
& HIST_DUP
));
1267 if (he
!= hist_ring
->down
) {
1268 he
->up
->down
= he
->down
;
1269 he
->down
->up
= he
->up
;
1271 he
->down
= hist_ring
->down
;
1272 hist_ring
->down
= he
->down
->up
= he
;
1279 prepnexthistent(void)
1282 int curline_in_ring
= hist_ring
== &curline
;
1284 if (curline_in_ring
)
1286 if (hist_ring
&& hist_ring
->node
.flags
& HIST_TMPSTORE
) {
1288 freehistnode(&hist_ring
->node
);
1291 if (histlinect
< histsiz
|| !hist_ring
) {
1292 he
= (Histent
)zshcalloc(sizeof *he
);
1294 hist_ring
= he
->up
= he
->down
= he
;
1297 he
->down
= hist_ring
->down
;
1298 hist_ring
->down
= he
->down
->up
= he
;
1304 putoldhistentryontop(0);
1305 freehistdata(hist_ring
, 0);
1308 he
->histnum
= ++curhist
;
1309 if (curline_in_ring
)
1314 /* A helper function for hend() */
1317 should_ignore_line(Eprog prog
)
1319 if (isset(HISTIGNORESPACE
)) {
1320 if (*chline
== ' ' || aliasspaceflag
)
1327 if (isset(HISTNOFUNCTIONS
)) {
1328 Wordcode pc
= prog
->prog
;
1329 wordcode code
= *pc
;
1330 if (wc_code(code
) == WC_LIST
&& WC_LIST_TYPE(code
) & Z_SIMPLE
1331 && wc_code(pc
[2]) == WC_FUNCDEF
)
1335 if (isset(HISTNOSTORE
)) {
1336 char *b
= getjobtext(prog
, NULL
);
1338 if (*b
== 'b' && strncmp(b
,"builtin ",8) == 0) {
1343 if (*b
== 'h' && strncmp(b
,"history",7) == 0 && (!b
[7] || b
[7] == ' ')
1344 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"history")))
1346 if (*b
== 'r' && (!b
[1] || b
[1] == ' ')
1347 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"r")))
1349 if (*b
== 'f' && b
[1] == 'c' && b
[2] == ' ' && b
[3] == '-'
1350 && (saw_builtin
|| !shfunctab
->getnode(shfunctab
,"fc"))) {
1355 } while (ialpha(*b
));
1362 /* say we're done using the history mechanism */
1368 LinkList hookargs
= newlinklist();
1369 int flag
, hookret
, stack_pos
= histsave_stack_pos
;
1374 * -1: save temporarily, delete after next line
1375 * -2: save internally but mark for not writing
1380 DPUTS(stophist
!= 2 && !(inbufflags
& INP_ALIAS
) && !chline
,
1381 "BUG: chline is NULL in hend()");
1383 if (histdone
& HISTFLAG_SETTY
)
1384 settyinfo(&shttyinfo
);
1385 if (!(histactive
& HA_NOINC
))
1387 if (histactive
& HA_NOINC
) {
1388 zfree(chline
, hlinesz
);
1389 zfree(chwords
, chwordlen
*sizeof(short));
1390 chline
= hptr
= NULL
;
1396 if (hist_ignore_all_dups
!= isset(HISTIGNOREALLDUPS
)
1397 && (hist_ignore_all_dups
= isset(HISTIGNOREALLDUPS
)) != 0)
1402 * Added the following in case the test "hptr < chline + 1"
1403 * is more than just paranoia.
1405 DPUTS(hptr
< chline
, "History end pointer off start of line");
1408 addlinknode(hookargs
, "zshaddhistory");
1409 addlinknode(hookargs
, chline
);
1410 callhookfunc("zshaddhistory", hookargs
, 1, &hookret
);
1411 /* For history sharing, lock history file once for both read and write */
1412 hf
= getsparam("HISTFILE");
1413 if (isset(SHAREHISTORY
) && !lockhistfile(hf
, 0)) {
1414 readhistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1415 curline
.histnum
= curhist
+1;
1419 if (hptr
< chline
+ 1)
1422 if (hptr
[-1] == '\n') {
1430 else if (should_ignore_line(prog
))
1432 else if (hookret
== 2)
1437 if (flag
& (HISTFLAG_DONE
| HISTFLAG_RECALL
)) {
1440 ptr
= ztrdup(chline
);
1441 if ((flag
& (HISTFLAG_DONE
| HISTFLAG_RECALL
)) == HISTFLAG_DONE
) {
1446 if (flag
& HISTFLAG_RECALL
) {
1447 zpushnode(bufstack
, ptr
);
1452 if (save
|| *chline
== ' ') {
1454 for (he
= hist_ring
; he
&& he
->node
.flags
& HIST_FOREIGN
;
1455 he
= up_histent(he
)) ;
1456 if (he
&& he
->node
.flags
& HIST_TMPSTORE
) {
1457 if (he
== hist_ring
)
1458 curline
.histnum
= curhist
--;
1459 freehistnode(&he
->node
);
1467 /* debugging only */
1470 DPUTS(1, "BUG: uncompleted line in history");
1473 /* get rid of pesky \n which we've already nulled out */
1474 if (chwordpos
> 1 && !chline
[chwords
[chwordpos
-2]]) {
1476 /* strip superfluous blanks, if desired */
1477 if (isset(HISTREDUCEBLANKS
))
1481 newflags
= HIST_TMPSTORE
;
1482 else if (save
== -2)
1483 newflags
= HIST_NOWRITE
;
1486 if ((isset(HISTIGNOREDUPS
) || isset(HISTIGNOREALLDUPS
)) && save
> 0
1487 && hist_ring
&& histstrcmp(chline
, hist_ring
->node
.nam
) == 0) {
1488 /* This history entry compares the same as the previous.
1489 * In case minor changes were made, we overwrite the
1490 * previous one with the current one. This also gets the
1491 * timestamp right. Perhaps, preserve the HIST_OLD flag.
1494 newflags
|= he
->node
.flags
& HIST_OLD
; /* Avoid re-saving */
1495 freehistdata(he
, 0);
1496 curline
.histnum
= curhist
;
1498 he
= prepnexthistent();
1500 he
->node
.nam
= ztrdup(chline
);
1501 he
->stim
= time(NULL
);
1503 he
->node
.flags
= newflags
;
1505 if ((he
->nwords
= chwordpos
/2)) {
1506 he
->words
= (short *)zalloc(chwordpos
* sizeof(short));
1507 memcpy(he
->words
, chwords
, chwordpos
* sizeof(short));
1509 if (!(newflags
& HIST_TMPSTORE
))
1510 addhistnode(histtab
, he
->node
.nam
, he
);
1512 zfree(chline
, hlinesz
);
1513 zfree(chwords
, chwordlen
*sizeof(short));
1514 chline
= hptr
= NULL
;
1518 * For normal INCAPPENDHISTORY case and reasoning, see hbegin().
1520 if (isset(SHAREHISTORY
) ? histfileIsLocked() :
1521 (isset(INCAPPENDHISTORY
) || (isset(INCAPPENDHISTORYTIME
) &&
1522 histsave_stack_pos
!= 0)))
1523 savehistfile(hf
, 0, HFILE_USE_OPTIONS
| HFILE_FAST
);
1524 unlockhistfile(hf
); /* It's OK to call this even if we aren't locked */
1526 * No good reason for the user to push the history more than once, but
1527 * it's easy to be tidy...
1529 while (histsave_stack_pos
> stack_pos
)
1532 return !(flag
& HISTFLAG_NOEXEC
|| errflag
);
1539 ihwbegin(int offset
)
1541 if (stophist
== 2 || (histactive
& HA_INWORD
) ||
1542 (inbufflags
& (INP_ALIAS
|INP_HIST
)) == INP_ALIAS
)
1545 chwordpos
--; /* make sure we're on a word start, not end */
1546 chwords
[chwordpos
++] = hptr
- chline
+ offset
;
1549 /* add a word to the history List */
1555 if (stophist
== 2 || (histactive
& HA_INWORD
) ||
1556 (inbufflags
& (INP_ALIAS
|INP_HIST
)) == INP_ALIAS
)
1558 if (chwordpos
%2 && chline
) {
1559 /* end of word reached and we've already begun a word */
1560 if (hptr
> chline
+ chwords
[chwordpos
-1]) {
1561 chwords
[chwordpos
++] = hptr
- chline
;
1562 if (chwordpos
>= chwordlen
) {
1563 chwords
= (short *) realloc(chwords
,
1568 /* scrub that last word, it doesn't exist */
1574 /* Go back to immediately after the last word, skipping space. */
1580 if (!(chwordpos
%2) && chwordpos
)
1581 hptr
= chline
+ chwords
[chwordpos
-1];
1584 /* Get the start and end point of the current history word */
1588 hwget(char **startptr
)
1590 int pos
= chwordpos
- 2;
1593 /* debugging only */
1595 /* no words available */
1596 DPUTS(1, "BUG: hwget() called with no words");
1600 else if (chwordpos
%2) {
1601 DPUTS(1, "BUG: hwget() called in middle of word");
1607 *startptr
= chline
+ chwords
[pos
];
1608 chline
[chwords
[++pos
]] = '\0';
1611 /* Replace the current history word with rep, if different */
1620 if (!strcmp(rep
, start
))
1624 chwordpos
= chwordpos
- 2;
1632 /* Get the entire current line, deleting it in the history. */
1638 /* Currently only used by pushlineoredit().
1639 * It's necessary to prevent that from getting too pally with
1644 if (!chline
|| hptr
== chline
)
1647 ret
= dupstring(chline
);
1656 /* get an argument specification */
1660 getargspec(int argc
, int marg
, int evset
)
1664 if ((c
= ingetc()) == '0')
1669 ret
= ret
* 10 + c
- '0';
1673 } else if (c
== '^')
1677 else if (c
== '%') {
1680 zerr("Ambiguous history reference");
1685 zerr("%% with no previous word matched");
1694 /* do ?foo? search */
1698 hconsearch(char *str
, int *marg
)
1704 for (he
= up_histent(hist_ring
); he
; he
= up_histent(he
)) {
1705 if (he
->node
.flags
& HIST_FOREIGN
)
1707 if ((s
= strstr(he
->node
.nam
, str
))) {
1708 int pos
= s
- he
->node
.nam
;
1709 while (t1
< he
->nwords
&& he
->words
[2*t1
] <= pos
)
1718 /* do !foo search */
1722 hcomsearch(char *str
)
1725 int len
= strlen(str
);
1727 for (he
= up_histent(hist_ring
); he
; he
= up_histent(he
)) {
1728 if (he
->node
.flags
& HIST_FOREIGN
)
1730 if (strncmp(he
->node
.nam
, str
, len
) == 0)
1736 /* various utilities for : modifiers */
1740 chabspath(char **junkptr
)
1742 char *current
, *dest
;
1747 if (**junkptr
!= '/') {
1748 *junkptr
= zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP
), "/", *junkptr
);
1754 #ifdef HAVE_SUPERROOT
1755 while (*current
== '/' && current
[1] == '.' && current
[2] == '.' &&
1756 (!current
[3] || current
[3] == '/')) {
1765 if (*current
== '/') {
1767 if (current
== *junkptr
&& current
[1] == '/')
1768 *dest
++ = *current
++;
1770 *dest
++ = *current
++;
1771 while (*current
== '/')
1773 } else if (!*current
) {
1774 while (dest
> *junkptr
+ 1 && dest
[-1] == '/')
1778 } else if (current
[0] == '.' && current
[1] == '.' &&
1779 (!current
[2] || current
[2] == '/')) {
1780 if (current
== *junkptr
|| dest
== *junkptr
) {
1784 } else if (dest
> *junkptr
+ 2 &&
1785 !strncmp(dest
- 3, "../", 3)) {
1789 } else if (dest
> *junkptr
+ 1) {
1792 dest
> *junkptr
+ 1 && dest
[-1] != '/';
1794 if (dest
[-1] != '/')
1797 if (*current
== '/')
1799 } else if (dest
== *junkptr
+ 1) {
1800 /* This might break with Cygwin's leading double slashes? */
1805 } else if (current
[0] == '.' && (current
[1] == '/' || !current
[1])) {
1806 while (*++current
== '/');
1808 while (*current
!= '/' && *current
!= '\0')
1809 if ((*dest
++ = *current
++) == Meta
)
1810 *dest
++ = *current
++;
1818 chrealpath(char **junkptr
)
1821 #ifdef HAVE_REALPATH
1822 # ifdef REALPATH_ACCEPTS_NULL
1823 char *lastpos
, *nonreal
, *real
;
1825 char *lastpos
, *nonreal
, pathbuf
[PATH_MAX
];
1826 char *real
= pathbuf
;
1833 /* Notice that this means ..'s are applied before symlinks are resolved! */
1834 if (!chabspath(junkptr
))
1837 #ifndef HAVE_REALPATH
1841 * Notice that this means you cannot pass relative paths into this
1844 if (**junkptr
!= '/')
1847 unmetafy(*junkptr
, NULL
);
1849 lastpos
= strend(*junkptr
);
1850 nonreal
= lastpos
+ 1;
1853 #ifdef REALPATH_ACCEPTS_NULL
1854 /* realpath() with a NULL second argument uses malloc() to get
1855 * memory so we don't need to worry about overflowing PATH_MAX */
1856 (real
= realpath(*junkptr
, NULL
))
1858 realpath(*junkptr
, real
)
1861 if (errno
== EINVAL
|| errno
== ENOMEM
)
1864 if (nonreal
== *junkptr
) {
1865 #ifndef REALPATH_ACCEPTS_NULL
1871 while (*nonreal
!= '/' && nonreal
>= *junkptr
)
1877 while (str
<= lastpos
) {
1884 *junkptr
= metafy(str
= bicat(real
, nonreal
), -1, META_HEAPDUP
);
1886 #ifdef REALPATH_ACCEPTS_NULL
1890 *junkptr
= metafy(nonreal
, lastpos
- nonreal
+ 1, META_HEAPDUP
);
1899 remtpath(char **junkptr
)
1901 char *str
= strend(*junkptr
);
1903 /* ignore trailing slashes */
1904 while (str
>= *junkptr
&& IS_DIRSEP(*str
))
1907 while (str
>= *junkptr
&& !IS_DIRSEP(*str
))
1909 if (str
< *junkptr
) {
1910 if (IS_DIRSEP(**junkptr
))
1911 *junkptr
= dupstring ("/");
1913 *junkptr
= dupstring (".");
1917 /* repeated slashes are considered like a single slash */
1918 while (str
> *junkptr
&& IS_DIRSEP(str
[-1]))
1920 /* never erase the root slash */
1921 if (str
== *junkptr
) {
1923 /* Leading doubled slashes (`//') have a special meaning on cygwin
1924 and some old flavor of UNIX, so we do not assimilate them to
1925 a single slash. However a greater number is ok to squeeze. */
1926 if (IS_DIRSEP(*str
) && !IS_DIRSEP(str
[1]))
1935 remtext(char **junkptr
)
1939 for (str
= strend(*junkptr
); str
>= *junkptr
&& !IS_DIRSEP(*str
); --str
)
1949 rembutext(char **junkptr
)
1953 for (str
= strend(*junkptr
); str
>= *junkptr
&& !IS_DIRSEP(*str
); --str
)
1955 *junkptr
= dupstring(str
+ 1); /* .xx or xx? */
1959 *junkptr
= dupstring ("");
1965 remlpaths(char **junkptr
)
1967 char *str
= strend(*junkptr
);
1969 if (IS_DIRSEP(*str
)) {
1970 /* remove trailing slashes */
1971 while (str
>= *junkptr
&& IS_DIRSEP(*str
))
1975 for (; str
>= *junkptr
; --str
)
1976 if (IS_DIRSEP(*str
)) {
1978 *junkptr
= dupstring(str
+ 1);
1985 * Return modified version of str from the heap with modification
1986 * according to one of the CASMOD_* types defined in zsh.h; CASMOD_NONE
1987 * is not handled, for obvious reasons.
1992 casemodify(char *str
, int how
)
1994 char *str2
= zhalloc(2 * strlen(str
) + 1);
1998 #ifdef MULTIBYTE_SUPPORT
1999 if (isset(MULTIBYTE
)) {
2000 VARARR(char, mbstr
, MB_CUR_MAX
);
2004 memset(&ps
, 0, sizeof(ps
));
2007 int len
= mb_metacharlenconv(str
, &wc
), mod
= 0, len2
;
2009 * wc is set to WEOF if the start of str couldn't be
2010 * converted. Presumably WEOF doesn't match iswlower(), but
2016 /* not alphanumeric */
2036 default: /* shuts up compiler */
2037 if (IS_COMBINING(wc
))
2041 else if (nextupper
) {
2047 } else if (iswupper(wc
)) {
2053 if (mod
&& (len2
= wcrtomb(mbstr
, wc
, &ps
)) > 0) {
2056 for (mbptr
= mbstr
; mbptr
< mbstr
+ len2
; mbptr
++) {
2057 if (imeta(STOUC(*mbptr
))) {
2059 *ptr2
++ = *mbptr
^ 32;
2091 default: /* shuts up compiler */
2094 else if (nextupper
) {
2098 } else if (isupper(c
))
2114 * Substitute "in" for "out" in "*strptr" and update "*strptr".
2115 * If "gbal", do global substitution.
2117 * This returns a result from the heap. There seems to have
2118 * been some confusion on this point.
2123 subst(char **strptr
, char *in
, char *out
, int gbal
)
2125 char *str
= *strptr
, *substcut
, *sptr
;
2126 int off
, inlen
, outlen
;
2131 if (isset(HISTSUBSTPATTERN
)) {
2132 int fl
= SUB_LONG
|SUB_REST
|SUB_RETFAIL
;
2136 if (*in
== '#' || *in
== Pound
) {
2137 /* anchor at head, flag needed if SUB_END is also set */
2142 /* anchor at tail */
2147 /* no anchor, substring match */
2152 if (parse_subst_string(in
) || errflag
)
2154 if (parse_subst_string(out
) || errflag
)
2157 if (getmatch(strptr
, in
, fl
, 1, out
))
2160 if ((substcut
= (char *)strstr(str
, in
))) {
2162 sptr
= convamps(out
, in
, inlen
);
2163 outlen
= strlen(sptr
);
2167 off
= substcut
- *strptr
+ outlen
;
2169 *strptr
= zhtricat(*strptr
, sptr
, substcut
);
2170 str
= (char *)*strptr
+ off
;
2171 } while (gbal
&& (substcut
= (char *)strstr(str
, in
)));
2182 convamps(char *out
, char *in
, int inlen
)
2184 char *ptr
, *ret
, *pp
;
2187 for (ptr
= out
, slen
= 0; *ptr
; ptr
++, slen
++)
2190 else if (*ptr
== '&')
2191 slen
+= inlen
- 1, sdup
= 1;
2194 ret
= pp
= (char *) zhalloc(slen
+ 1);
2195 for (ptr
= out
; *ptr
; ptr
++)
2198 else if (*ptr
== '&') {
2209 checkcurline(Histent he
)
2211 if (he
->histnum
== curhist
&& (histactive
& HA_ACTIVE
)) {
2212 curline
.node
.nam
= chline
;
2213 curline
.nwords
= chwordpos
/2;
2214 curline
.words
= chwords
;
2220 quietgethist(int ev
)
2222 return gethistent(ev
, GETHIST_EXACT
);
2231 ret
= quietgethist(ev
);
2234 zerr("no such event: %d", ev
);
2241 getargs(Histent elist
, int arg1
, int arg2
)
2243 short *words
= elist
->words
;
2244 int pos1
, nwords
= elist
->nwords
;
2246 if (arg2
< arg1
|| arg1
>= nwords
|| arg2
>= nwords
) {
2247 /* remember, argN is indexed from 0, nwords is total no. of words */
2249 zerr("no such word in event");
2253 pos1
= words
[2*arg1
];
2254 return dupstrpfx(elist
->node
.nam
+ pos1
, words
[2*arg2
+1] - pos1
);
2261 char *ptr
, *rptr
, **str
= tr
;
2265 for (ptr
= *str
; *ptr
; ptr
++, len
++)
2272 } else if (inblank(*ptr
) && !inquotes
&& ptr
[-1] != '\\')
2275 *str
= rptr
= (char *) zhalloc(len
);
2287 } else if (inblank(*ptr
) && !inquotes
&& ptr
[-1] != '\\') {
2300 quotebreak(char **tr
)
2302 char *ptr
, *rptr
, **str
= tr
;
2305 for (ptr
= *str
; *ptr
; ptr
++, len
++)
2308 else if (inblank(*ptr
))
2311 *str
= rptr
= (char *) zhalloc(len
);
2320 } else if (inblank(*ptr
)) {
2331 /* read an arbitrary amount of data into a buffer until stop is found */
2337 int bsiz
= 256, ct
= 0, c
;
2338 char *buf
= (char *)zalloc(bsiz
), *ptr
;
2341 while ((c
= ingetc()) != stop
&& c
!= '\n' && !lexstop
) {
2346 buf
= realloc(buf
, bsiz
*= 2);
2353 zerr("delimiter expected");
2365 int bsiz
= 256, ct
= 0, c
;
2366 char *buf
= (char *)zalloc(bsiz
), *ptr
;
2369 while ((c
= ingetc()) != stop
&& c
!= '\n' && !lexstop
) {
2374 buf
= realloc(buf
, bsiz
*= 2);
2393 resizehistents(void)
2395 if (histlinect
> histsiz
) {
2396 /* The reason we don't just call freehistnode(hist_ring->down) is
2397 * so that we can honor the HISTEXPIREDUPSFIRST setting. */
2398 putoldhistentryontop(0);
2399 freehistnode(&hist_ring
->node
);
2400 while (histlinect
> histsiz
) {
2401 putoldhistentryontop(1);
2402 freehistnode(&hist_ring
->node
);
2408 readhistline(int start
, char **bufp
, int *bufsiz
, FILE *in
)
2411 if (fgets(buf
+ start
, *bufsiz
- start
, in
)) {
2412 int len
= start
+ strlen(buf
+ start
);
2415 if (buf
[len
- 1] != '\n') {
2417 if (len
< (*bufsiz
) - 1)
2419 *bufp
= zrealloc(buf
, 2 * (*bufsiz
));
2420 *bufsiz
= 2 * (*bufsiz
);
2421 return readhistline(len
, bufp
, bufsiz
, in
);
2425 buf
[len
- 1] = '\0';
2426 if (len
> 1 && buf
[len
- 2] == '\\') {
2427 buf
[--len
- 1] = '\n';
2429 return readhistline(len
, bufp
, bufsiz
, in
);
2439 readhistfile(char *fn
, int err
, int readflags
)
2441 char *buf
, *start
= NULL
;
2444 time_t stim
, ftim
, tim
= time(NULL
);
2448 int nwordpos
, nwords
, bufsiz
;
2449 int searching
, newflags
, l
, ret
, uselex
;
2451 if (!fn
&& !(fn
= getsparam("HISTFILE")))
2453 if (stat(unmeta(fn
), &sb
) < 0 ||
2456 if (readflags
& HFILE_FAST
) {
2457 if ((lasthist
.fsiz
== sb
.st_size
&& lasthist
.mtim
== sb
.st_mtime
)
2458 || lockhistfile(fn
, 0))
2460 lasthist
.fsiz
= sb
.st_size
;
2461 lasthist
.mtim
= sb
.st_mtime
;
2462 } else if ((ret
= lockhistfile(fn
, 1))) {
2464 zwarn("locking failed for %s: %e: reading anyway", fn
, errno
);
2466 zerr("locking failed for %s: %e", fn
, errno
);
2470 if ((in
= fopen(unmeta(fn
), "r"))) {
2472 words
= (short *)zalloc(nwords
*sizeof(short));
2474 buf
= zalloc(bufsiz
);
2477 if (readflags
& HFILE_FAST
&& lasthist
.text
) {
2478 if (lasthist
.fpos
< lasthist
.fsiz
) {
2479 fseek(in
, lasthist
.fpos
, 0);
2483 histfile_linect
= 0;
2489 newflags
= HIST_OLD
| HIST_READ
;
2490 if (readflags
& HFILE_FAST
)
2491 newflags
|= HIST_FOREIGN
;
2492 if (readflags
& HFILE_SKIPOLD
2493 || (hist_ignore_all_dups
&& newflags
& hist_skip_flags
))
2494 newflags
|= HIST_MAKEUNIQUE
;
2495 while (fpos
= ftell(in
), (l
= readhistline(0, &buf
, &bufsiz
, in
))) {
2500 zerr("corrupt history file %s", fn
);
2505 * Handle the special case that we're reading from an
2506 * old shell with fewer meta characters, so we need to
2507 * metafy some more. (It's not clear why the history
2508 * file is metafied at all; some would say this is plain
2509 * stupid. But we're stuck with it now without some
2510 * hairy workarounds for compatibility).
2512 * This is rare so doesn't need to be that efficient; just
2513 * allocate space off the heap.
2515 for (pt
= buf
; *pt
; pt
++) {
2516 if (*pt
== Meta
&& pt
[1])
2518 else if (imeta(*pt
)) {
2524 unmetafy(buf
, &remeta
);
2525 pt
= metafy(buf
, remeta
, META_USEHEAP
);
2532 stim
= zstrtol(pt
, NULL
, 0);
2533 for (; *pt
!= ':' && *pt
; pt
++);
2536 ftim
= zstrtol(pt
, NULL
, 0);
2537 for (; *pt
!= ';' && *pt
; pt
++);
2543 if (*pt
== '\\' && pt
[1] == ':')
2549 if (searching
> 0) {
2550 if (stim
== lasthist
.stim
2551 && histstrcmp(pt
, lasthist
.text
) == 0)
2555 histfile_linect
= 0;
2560 else if (stim
< lasthist
.stim
) {
2567 if (readflags
& HFILE_USE_OPTIONS
) {
2569 lasthist
.fpos
= fpos
;
2570 lasthist
.stim
= stim
;
2573 he
= prepnexthistent();
2574 he
->node
.nam
= ztrdup(pt
);
2575 he
->node
.flags
= newflags
;
2576 if ((he
->stim
= stim
) == 0)
2577 he
->stim
= he
->ftim
= tim
;
2578 else if (ftim
< stim
)
2579 he
->ftim
= stim
+ ftim
;
2584 * Divide up the words.
2587 uselex
= isset(HISTLEXWORDS
) && !(readflags
& HFILE_FAST
);
2588 histsplitwords(pt
, &words
, &nwords
, &nwordpos
, uselex
);
2590 he
->nwords
= nwordpos
/2;
2592 he
->words
= (short *)zalloc(nwordpos
*sizeof(short));
2593 memcpy(he
->words
, words
, nwordpos
*sizeof(short));
2595 he
->words
= (short *)NULL
;
2596 addhistnode(histtab
, he
->node
.nam
, he
);
2597 if (he
->node
.flags
& HIST_DUP
) {
2598 freehistnode(&he
->node
);
2602 * Do this last out of paranoia in case use of
2603 * heap is disguised...
2605 if (uselex
|| remeta
)
2607 if (errflag
& ERRFLAG_INT
)
2610 if (start
&& readflags
& HFILE_USE_OPTIONS
) {
2611 zsfree(lasthist
.text
);
2612 lasthist
.text
= ztrdup(start
);
2614 zfree(words
, nwords
*sizeof(short));
2620 zerr("can't read history file %s", fn
);
2625 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
2629 static int flock_fd
= -1;
2632 * Lock file using fcntl(). Return 0 on success, 1 on failure of
2633 * locking mechanism, 2 on permanent failure (e.g. permission).
2637 flockhistfile(char *fn
, int keep_trying
)
2640 long sleep_us
= 0x10000; /* about 67 ms */
2644 return 0; /* already locked */
2646 if ((flock_fd
= open(unmeta(fn
), O_RDWR
| O_NOCTTY
)) < 0)
2647 return errno
== ENOENT
? 0 : 2; /* "successfully" locked missing file */
2649 lck
.l_type
= F_WRLCK
;
2650 lck
.l_whence
= SEEK_SET
;
2652 lck
.l_len
= 0; /* lock the whole file */
2655 * Timeout is ten seconds.
2657 end_time
= time(NULL
) + (time_t)10;
2658 while (fcntl(flock_fd
, F_SETLKW
, &lck
) == -1) {
2659 if (!keep_trying
|| time(NULL
) >= end_time
||
2661 * Randomise wait to minimise clashes with shells exiting at
2664 !zsleep_random(sleep_us
, end_time
)) {
2678 savehistfile(char *fn
, int err
, int writeflags
)
2680 char *t
, *tmpfile
, *start
= NULL
;
2683 zlong xcurhist
= curhist
- !!(histactive
& HA_ACTIVE
);
2684 int extended_history
= isset(EXTENDEDHISTORY
);
2687 if (!interact
|| savehistsiz
<= 0 || !hist_ring
2688 || (!fn
&& !(fn
= getsparam("HISTFILE"))))
2690 if (writeflags
& HFILE_FAST
) {
2691 he
= gethistent(lasthist
.next_write_ev
, GETHIST_DOWNWARD
);
2692 while (he
&& he
->node
.flags
& HIST_OLD
) {
2693 lasthist
.next_write_ev
= he
->histnum
+ 1;
2694 he
= down_histent(he
);
2696 if (!he
|| lockhistfile(fn
, 0))
2698 if (histfile_linect
> savehistsiz
+ savehistsiz
/ 5)
2699 writeflags
&= ~HFILE_FAST
;
2702 if (lockhistfile(fn
, 1)) {
2703 zerr("locking failed for %s: %e", fn
, errno
);
2706 he
= hist_ring
->down
;
2708 if (writeflags
& HFILE_USE_OPTIONS
) {
2709 if (isset(APPENDHISTORY
) || isset(INCAPPENDHISTORY
)
2710 || isset(INCAPPENDHISTORYTIME
) || isset(SHAREHISTORY
))
2711 writeflags
|= HFILE_APPEND
| HFILE_SKIPOLD
;
2713 histfile_linect
= 0;
2714 if (isset(HISTSAVENODUPS
))
2715 writeflags
|= HFILE_SKIPDUPS
;
2716 if (isset(SHAREHISTORY
))
2717 extended_history
= 1;
2720 if (writeflags
& HFILE_APPEND
) {
2721 int fd
= open(unmeta(fn
), O_CREAT
| O_WRONLY
| O_APPEND
| O_NOCTTY
, 0600);
2723 out
= fd
>= 0 ? fdopen(fd
, "a") : NULL
;
2724 } else if (!isset(HISTSAVEBYCOPY
)) {
2725 int fd
= open(unmeta(fn
), O_CREAT
| O_WRONLY
| O_TRUNC
| O_NOCTTY
, 0600);
2727 out
= fd
>= 0 ? fdopen(fd
, "w") : NULL
;
2729 tmpfile
= bicat(unmeta(fn
), ".new");
2730 if (unlink(tmpfile
) < 0 && errno
!= ENOENT
)
2734 int old_exists
= stat(unmeta(fn
), &sb
) == 0;
2735 uid_t euid
= geteuid();
2738 #if defined HAVE_FCHMOD && defined HAVE_FCHOWN
2741 && sb
.st_uid
!= euid
) {
2745 if (isset(APPENDHISTORY
) || isset(INCAPPENDHISTORY
)
2746 || isset(INCAPPENDHISTORYTIME
) || isset(SHAREHISTORY
))
2747 zerr("rewriting %s would change its ownership -- skipped", fn
);
2749 zerr("rewriting %s would change its ownership -- history not saved", fn
);
2750 err
= 0; /* Don't report a generic error below. */
2754 int fd
= open(tmpfile
, O_CREAT
| O_WRONLY
| O_EXCL
, 0600);
2756 out
= fdopen(fd
, "w");
2764 if (old_exists
&& out
) {
2766 if (fchown(fileno(out
), sb
.st_uid
, sb
.st_gid
) < 0) {} /* IGNORE FAILURE */
2768 if (fchmod(fileno(out
), sb
.st_mode
) < 0) {} /* IGNORE FAILURE */
2774 char *history_ignore
;
2775 Patprog histpat
= NULL
;
2779 if ((history_ignore
= getsparam("HISTORY_IGNORE")) != NULL
) {
2780 tokenize(history_ignore
= dupstring(history_ignore
));
2781 remnulargs(history_ignore
);
2782 histpat
= patcompile(history_ignore
, 0, NULL
);
2786 for (; he
&& he
->histnum
<= xcurhist
; he
= down_histent(he
)) {
2787 int count_backslashes
= 0;
2789 if ((writeflags
& HFILE_SKIPDUPS
&& he
->node
.flags
& HIST_DUP
)
2790 || (writeflags
& HFILE_SKIPFOREIGN
&& he
->node
.flags
& HIST_FOREIGN
)
2791 || he
->node
.flags
& HIST_TMPSTORE
)
2794 pattry(histpat
, metafy(he
->node
.nam
, -1, META_HEAPDUP
))) {
2797 if (writeflags
& HFILE_SKIPOLD
) {
2798 if (he
->node
.flags
& (HIST_OLD
|HIST_NOWRITE
))
2800 he
->node
.flags
|= HIST_OLD
;
2801 if (writeflags
& HFILE_USE_OPTIONS
)
2802 lasthist
.next_write_ev
= he
->histnum
+ 1;
2804 if (writeflags
& HFILE_USE_OPTIONS
) {
2805 lasthist
.fpos
= ftell(out
);
2806 lasthist
.stim
= he
->stim
;
2809 t
= start
= he
->node
.nam
;
2810 if (extended_history
) {
2811 ret
= fprintf(out
, ": %ld:%ld;", (long)he
->stim
,
2812 he
->ftim
? (long)(he
->ftim
- he
->stim
) : 0L);
2813 } else if (*t
== ':')
2814 ret
= fputc('\\', out
);
2816 for (; ret
>= 0 && *t
; t
++) {
2818 if ((ret
= fputc('\\', out
)) < 0)
2821 count_backslashes
++;
2823 count_backslashes
= 0;
2824 if ((ret
= fputc(*t
, out
)) < 0)
2829 if (count_backslashes
&& (count_backslashes
% 2 == 0))
2830 if ((ret
= fputc(' ', out
)) < 0)
2832 if (ret
< 0 || (ret
= fputc('\n', out
)) < 0)
2835 if (ret
>= 0 && start
&& writeflags
& HFILE_USE_OPTIONS
) {
2837 if ((ret
= fflush(out
)) >= 0) {
2838 if (fstat(fileno(out
), &sb
) == 0) {
2839 lasthist
.fsiz
= sb
.st_size
;
2840 lasthist
.mtim
= sb
.st_mtime
;
2842 zsfree(lasthist
.text
);
2843 lasthist
.text
= ztrdup(start
);
2846 if (fclose(out
) < 0 && ret
>= 0)
2850 if (rename(tmpfile
, unmeta(fn
)) < 0) {
2851 zerr("can't rename %s.new to $HISTFILE", fn
);
2856 /* We renamed over the locked HISTFILE, so close fd.
2857 * If we do more writing, we'll get a lock then. */
2858 if (flock_fd
>= 0) {
2866 if (ret
>= 0 && writeflags
& HFILE_SKIPOLD
2867 && !(writeflags
& (HFILE_FAST
| HFILE_NO_REWRITE
))) {
2868 int remember_histactive
= histactive
;
2870 /* Zeroing histactive avoids unnecessary munging of curline. */
2872 /* The NULL leaves HISTFILE alone, preserving fn's value. */
2873 pushhiststack(NULL
, savehistsiz
, savehistsiz
, -1);
2875 hist_ignore_all_dups
|= isset(HISTSAVENODUPS
);
2876 readhistfile(fn
, err
, 0);
2877 hist_ignore_all_dups
= isset(HISTIGNOREALLDUPS
);
2879 savehistfile(fn
, err
, 0);
2882 histactive
= remember_histactive
;
2890 if (ret
< 0 && err
) {
2892 zerr("failed to write history file %s.new: %e", fn
, errno
);
2894 zerr("failed to write history file %s: %e", fn
, errno
);
2902 static int lockhistct
;
2905 checklocktime(char *lockfile
, long *sleep_usp
, time_t then
)
2907 time_t now
= time(NULL
);
2909 if (now
+ 10 < then
) {
2910 /* File is more than 10 seconds in the future? */
2915 if (now
- then
< 10) {
2917 * To give the effect of a gradually increasing backoff,
2918 * we'll sleep a period based on the time we've spent so far.
2920 DPUTS(now
< then
, "time flowing backwards through history");
2922 * Randomise to minimise clashes with shells exiting at the same
2925 (void)zsleep_random(*sleep_usp
, then
+ 10);
2934 * Lock history file. Return 0 on success, 1 on failure to lock this
2935 * time, 2 on permanent failure (e.g. permission).
2940 lockhistfile(char *fn
, int keep_trying
)
2942 int ct
= lockhistct
;
2944 long sleep_us
= 0x10000; /* about 67 ms */
2946 if (!fn
&& !(fn
= getsparam("HISTFILE")))
2949 if (!lockhistct
++) {
2954 # ifdef HAVE_SYMLINK
2955 char pidbuf
[32], *lnk
;
2962 if (isset(HISTFCNTLLOCK
))
2963 return flockhistfile(fn
, keep_trying
);
2966 lockfile
= bicat(unmeta(fn
), ".LOCK");
2967 /* NOTE: only use symlink locking on a link()-having host in order to
2968 * avoid a change from open()-based locking to symlink()-based. */
2970 # ifdef HAVE_SYMLINK
2971 sprintf(pidbuf
, "/pid-%ld/host-", (long)mypid
);
2972 lnk
= getsparam("HOST");
2973 lnk
= bicat(pidbuf
, lnk
? lnk
: "");
2974 /* We'll abuse fd as our success flag. */
2975 while ((fd
= symlink(lnk
, lockfile
)) < 0) {
2976 if (errno
!= EEXIST
) {
2979 } else if (!keep_trying
) {
2983 if (lstat(lockfile
, &sb
) < 0) {
2984 if (errno
== ENOENT
)
2988 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
2996 # else /* not HAVE_SYMLINK */
2997 if ((fd
= gettempfile(fn
, 0, &tmpfile
)) >= 0) {
2998 FILE *out
= fdopen(fd
, "w");
3000 fprintf(out
, "%ld %s\n", (long)getpid(), getsparam("HOST"));
3004 while (link(tmpfile
, lockfile
) < 0) {
3005 if (errno
!= EEXIST
) {
3008 } else if (!keep_trying
) {
3011 } else if (lstat(lockfile
, &sb
) < 0) {
3012 if (errno
== ENOENT
)
3016 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
3028 # endif /* not HAVE_SYMLINK */
3029 #else /* not HAVE_LINK */
3030 while ((fd
= open(lockfile
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644)) < 0) {
3031 if (errno
!= EEXIST
) {
3034 } else if (!keep_trying
) {
3038 if (lstat(lockfile
, &sb
) < 0) {
3039 if (errno
== ENOENT
)
3044 if (checklocktime(lockfile
, &sleep_us
, sb
.st_mtime
) < 0) {
3052 FILE *out
= fdopen(fd
, "w");
3054 fprintf(out
, "%ld %s\n", (long)mypid
, getsparam("HOST"));
3059 #endif /* not HAVE_LINK */
3063 if (ct
== lockhistct
) {
3065 if (flock_fd
>= 0) {
3070 DPUTS(ret
== 0, "BUG: return value non-zero on locking error");
3076 /* Unlock the history file if this corresponds to the last nested lock
3077 * request. If we don't have the file locked, just return.
3082 unlockhistfile(char *fn
)
3084 if (!fn
&& !(fn
= getsparam("HISTFILE")))
3093 lockfile
= zalloc(strlen(fn
) + 5 + 1);
3094 sprintf(lockfile
, "%s.LOCK", fn
);
3098 if (flock_fd
>= 0) {
3108 histfileIsLocked(void)
3110 return lockhistct
> 0;
3114 * Get the words in the current buffer. Using the lexer.
3116 * As far as I can make out, this is a gross hack based on a gross hack.
3117 * When analysing lines from within zle, we tweak the metafied line
3118 * positions (zlemetall and zlemetacs) directly in the lexer. That's
3119 * bad enough, but this function appears to be designed to be called
3120 * from outside zle, pretending to be in zle and calling out, so
3121 * we set zlemetall and zlemetacs locally and copy the current zle line,
3122 * which may not even be valid at this point.
3124 * However, I'm so confused it could simply be baking Bakewell tarts.
3126 * list may be an existing linked list (off the heap), in which case
3127 * it will be appended to; otherwise it will be created.
3129 * If buf is set we will take input from that string, else we will
3130 * attempt to use ZLE directly in a way they tell you not to do on all
3131 * programming courses.
3133 * If index is non-NULL, and input is from a string in ZLE, *index
3134 * is set to the position of the end of the current editor word.
3136 * flags is passed directly to lexflags, see lex.c, except that
3137 * we 'or' in the bit LEXFLAGS_ACTIVE to make sure the variable
3143 bufferwords(LinkList list
, char *buf
, int *index
, int flags
)
3145 int num
= 0, cur
= -1, got
= 0, ne
= noerrs
;
3146 int owb
= wb
, owe
= we
, oadx
= addedx
, onc
= nocomments
;
3147 int ona
= noaliases
, ocs
= zlemetacs
, oll
= zlemetall
;
3148 int forloop
= 0, rcquotes
= opts
[RCQUOTES
];
3149 char *p
, *addedspaceptr
;
3152 list
= newlinklist();
3155 * With RC_QUOTES, 'foo '' bar' comes back as 'foo ' bar'. That's
3156 * not very useful. As nothing in here requires the fully processed
3157 * string expression, we just turn the option off for this function.
3163 lexflags
= flags
| LEXFLAGS_ACTIVE
;
3165 * Are we handling comments?
3167 nocomments
= !(flags
& (LEXFLAGS_COMMENTS_KEEP
|
3168 LEXFLAGS_COMMENTS_STRIP
));
3170 int l
= strlen(buf
);
3172 p
= (char *) zhalloc(l
+ 2);
3175 * I'm sure this space is here for a reason, but it's
3176 * a pain in the neck: when we get back a string that's
3177 * not finished it's very hard to tell if a space at the
3178 * end is this one or not. We use two tricks below to
3181 addedspaceptr
= p
+ l
;
3182 *addedspaceptr
= ' ';
3183 addedspaceptr
[1] = '\0';
3185 zlemetall
= strlen(p
) ;
3186 zlemetacs
= zlemetall
+ 1;
3191 linein
= zleentry(ZLE_CMD_GET_LINE
, &ll
, &cs
);
3192 zlemetall
= ll
+ 1; /* length of line plus space added below */
3195 if (!isfirstln
&& chline
) {
3196 p
= (char *) zhalloc(hptr
- chline
+ ll
+ 2);
3197 memcpy(p
, chline
, hptr
- chline
);
3198 memcpy(p
+ (hptr
- chline
), linein
, ll
);
3199 addedspaceptr
= p
+ (hptr
- chline
) + ll
;
3200 *addedspaceptr
= ' ';
3201 addedspaceptr
[1] = '\0';
3205 * advance line length and character position over
3208 zlemetall
+= hptr
- chline
;
3209 zlemetacs
+= hptr
- chline
;
3211 p
= (char *) zhalloc(ll
+ 2);
3212 memcpy(p
, linein
, ll
);
3213 addedspaceptr
= p
+ ll
;
3214 *addedspaceptr
= ' ';
3215 p
[zlemetall
] = '\0';
3226 incond
= 1 + (tok
!= DINBRACK
&& tok
!= INPAR
&&
3227 tok
!= DBAR
&& tok
!= DAMPER
&&
3230 if (tok
== ENDINPUT
|| tok
== LEXERR
)
3234 * The way for (( expr1 ; expr2; expr3 )) is parsed is:
3236 * - a DINPAR with no tokstr
3237 * - two DINPARS with tokstr's expr1, expr2.
3238 * - a DOUTPAR with tokstr expr3.
3240 * We'll decrement the variable forloop as we verify
3241 * the various stages.
3243 * Don't ask me, ma'am, I'm just the programmer.
3268 p
= dyncat(tokstr
, "=(");
3274 p
= dyncat(tokstr
, ";");
3277 * Mathematical expressions analysed as a single
3278 * word. That's correct because it behaves like
3279 * double quotes. Whitespace in the middle is
3280 * similarly retained, so just add the parentheses back.
3282 p
= zhtricat("((", tokstr
, "))");
3287 p
= dupstring(tokstr
);
3292 if (ingetptr() == addedspaceptr
+ 1) {
3294 * Whoops, we've read past the space we added, probably
3295 * because we were expecting a terminator but when
3296 * it didn't turn up we shrugged our shoulders thinking
3297 * it might as well be a complete string anyway.
3298 * So remove the space. C.f. below for the case
3299 * where the missing terminator caused a lex error.
3300 * We use the same paranoid test.
3302 int plen
= strlen(p
);
3303 if (plen
&& p
[plen
-1] == ' ' &&
3304 (plen
== 1 || p
[plen
-2] != Meta
))
3307 addlinknode(list
, p
);
3311 if (IS_REDIROP(tok
) && tokfd
>= 0) {
3314 sprintf(b
, "%d%s", tokfd
, tokstrings
[tok
]);
3315 addlinknode(list
, dupstring(b
));
3317 } else if (tok
!= NEWLIN
) {
3318 addlinknode(list
, dupstring(tokstrings
[tok
]));
3325 * Final "))" of for loop to match opening,
3326 * since we've just added the preceding element.
3328 addlinknode(list
, dupstring("))"));
3332 if (!got
&& !lexflags
) {
3336 } while (tok
!= ENDINPUT
&& tok
!= LEXERR
&& !(errflag
& ERRFLAG_INT
));
3337 if (buf
&& tok
== LEXERR
&& tokstr
&& *tokstr
) {
3339 untokenize((p
= dupstring(tokstr
)));
3342 * Strip the space we added for lexing but which won't have
3343 * been swallowed by the lexer because we aborted early.
3344 * The test is paranoia.
3346 if (plen
&& p
[plen
-1] == ' ' && (plen
== 1 || p
[plen
-2] != Meta
))
3348 addlinknode(list
, p
);
3356 errflag
&= ~ERRFLAG_ERROR
;
3365 opts
[RCQUOTES
] = rcquotes
;
3374 * Split up a line into words for use in a history file.
3376 * lineptr is the line to be split.
3378 * *wordsp and *nwordsp are an array already allocated to hold words
3379 * and its length. The array holds both start and end positions,
3380 * so *nwordsp actually counts twice the number of words in the
3381 * original string. *nwordsp may be zero in which case the array
3382 * will be allocated.
3384 * *nwordposp returns the used length of *wordsp in the same units as
3385 * *nwordsp, i.e. twice the number of words in the input line.
3387 * If uselex is 1, attempt to do this using the lexical analyser.
3388 * This is more accurate, but slower; for reading history files it's
3389 * controlled by the option HISTLEXWORDS. If this failed (which
3390 * indicates a bug in the shell) it falls back to whitespace-separated
3391 * strings, printing a message if in debug mode.
3393 * If uselex is 0, just look for whitespace-separated words; the only
3394 * special handling is for a backslash-newline combination as used
3395 * by the history file format to save multiline buffers.
3399 histsplitwords(char *lineptr
, short **wordsp
, int *nwordsp
, int *nwordposp
,
3402 int nwords
= *nwordsp
, nwordpos
= 0;
3403 short *words
= *wordsp
;
3404 char *start
= lineptr
;
3411 wordlist
= bufferwords(NULL
, lineptr
, NULL
,
3412 LEXFLAGS_COMMENTS_KEEP
);
3415 nwords_max
= 2 * countlinknodes(wordlist
);
3416 if (nwords_max
> nwords
) {
3417 *nwordsp
= nwords
= nwords_max
;
3418 *wordsp
= words
= (short *)zrealloc(words
, nwords
*sizeof(short));
3420 for (wordnode
= firstnode(wordlist
);
3422 incnode(wordnode
)) {
3423 char *word
= getdata(wordnode
);
3424 char *lptr
, *wptr
= word
;
3425 int loop_next
= 0, skipping
;
3427 /* Skip stuff at the start of the word */
3430 * Not really an oddity: "\\\n" is
3431 * removed from input as if whitespace.
3433 if (inblank(*lineptr
))
3435 else if (lineptr
[0] == '\\' && lineptr
[1] == '\n') {
3437 * Optimisation: we handle this in the loop below,
3446 * Skip chunks of word with possible intervening
3447 * backslash-newline.
3449 * To get round C's annoying lack of ability to
3450 * reference the outer loop, we'll break from this
3452 * loop_next = 0: carry on as normal
3453 * loop_next = 1: break from outer loop
3454 * loop_next = 2: continue round outer loop.
3458 if (strpfx(wptr
, lptr
)) {
3460 * Normal case: word from lexer matches start of
3461 * string from line. Just advance over it.
3464 if (!strcmp(wptr
, ";") && strpfx(";;", lptr
)) {
3466 * Don't get confused between a semicolon that's
3467 * probably really a newline and a double
3468 * semicolon that's terminating a case.
3478 * Didn't get to the end of the word.
3483 * Oddity 1: newlines turn into semicolons.
3485 if (!strcmp(wptr
, ";"))
3493 * End of the word before the end of the
3501 * Oddity 2: !'s turn into |'s.
3503 if (*lptr
== *wptr
||
3504 (*lptr
== '!' && *wptr
== '|')) {
3508 } else if (lptr
[0] == '\\' &&
3511 * \\\n can occur in the middle of a word;
3512 * wptr is already pointing at this, we
3513 * just need to skip over the break
3514 * in lptr and look at the next chunk.
3527 dputs(ERRMSG("bad wordsplit reading history: "
3528 "%s\nat: %s\nword: %s"),
3529 start
, lineptr
, word
);
3543 /* Record position of current word... */
3544 words
[nwordpos
++] = lineptr
- start
;
3545 words
[nwordpos
++] = lptr
- start
;
3547 /* ready for start of next word. */
3554 if (inblank(*lineptr
))
3556 else if (lineptr
[0] == '\\' && lineptr
[1] == '\n')
3562 if (nwordpos
>= nwords
) {
3563 *nwordsp
= nwords
= nwords
+ 64;
3564 *wordsp
= words
= (short *)
3565 zrealloc(words
, nwords
*sizeof(*words
));
3567 words
[nwordpos
++] = lineptr
- start
;
3568 while (*lineptr
&& !inblank(*lineptr
))
3570 words
[nwordpos
++] = lineptr
- start
;
3575 *nwordposp
= nwordpos
;
3578 /* Move the current history list out of the way and prepare a fresh history
3579 * list using hf for HISTFILE, hs for HISTSIZE, and shs for SAVEHIST. If
3580 * the hf value is an empty string, HISTFILE will be unset from the new
3581 * environment; if it is NULL, HISTFILE will not be changed, not even by the
3582 * pop function (this functionality is used internally to rewrite the current
3583 * history file without affecting pointers into the environment).
3588 pushhiststack(char *hf
, zlong hs
, zlong shs
, int level
)
3591 int curline_in_ring
= (histactive
& HA_ACTIVE
) && hist_ring
== &curline
;
3593 if (histsave_stack_pos
== histsave_stack_size
) {
3594 histsave_stack_size
+= 5;
3595 histsave_stack
= zrealloc(histsave_stack
,
3596 histsave_stack_size
* sizeof (struct histsave
));
3599 if (curline_in_ring
)
3602 h
= &histsave_stack
[histsave_stack_pos
++];
3604 h
->lasthist
= lasthist
;
3606 if ((h
->histfile
= getsparam("HISTFILE")) != NULL
&& *h
->histfile
)
3607 h
->histfile
= ztrdup(h
->histfile
);
3612 h
->histtab
= histtab
;
3613 h
->hist_ring
= hist_ring
;
3614 h
->curhist
= curhist
;
3615 h
->histlinect
= histlinect
;
3616 h
->histsiz
= histsiz
;
3617 h
->savehistsiz
= savehistsiz
;
3618 h
->locallevel
= level
;
3620 memset(&lasthist
, 0, sizeof lasthist
);
3623 setsparam("HISTFILE", ztrdup(hf
));
3625 unsetparam("HISTFILE");
3628 curhist
= histlinect
= 0;
3630 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
3633 inithist(); /* sets histtab */
3635 if (curline_in_ring
)
3638 return histsave_stack_pos
;
3647 int curline_in_ring
= (histactive
& HA_ACTIVE
) && hist_ring
== &curline
;
3649 if (histsave_stack_pos
== 0)
3652 if (curline_in_ring
)
3655 deletehashtable(histtab
);
3656 zsfree(lasthist
.text
);
3658 h
= &histsave_stack
[--histsave_stack_pos
];
3660 lasthist
= h
->lasthist
;
3663 setsparam("HISTFILE", h
->histfile
);
3665 unsetparam("HISTFILE");
3667 histtab
= h
->histtab
;
3668 hist_ring
= h
->hist_ring
;
3669 curhist
= h
->curhist
;
3671 zleentry(ZLE_CMD_SET_HIST_LINE
, curhist
);
3672 histlinect
= h
->histlinect
;
3673 histsiz
= h
->histsiz
;
3674 savehistsiz
= h
->savehistsiz
;
3676 if (curline_in_ring
)
3679 return histsave_stack_pos
+ 1;
3682 /* If pop_through > 0, pop all array items >= the 1-relative index value.
3683 * If pop_through <= 0, pop (-1)*pop_through levels off the stack.
3684 * If the (new) top of stack is from a higher locallevel, auto-pop until
3690 saveandpophiststack(int pop_through
, int writeflags
)
3692 if (pop_through
<= 0) {
3693 pop_through
+= histsave_stack_pos
+ 1;
3694 if (pop_through
<= 0)
3697 while (pop_through
> 1
3698 && histsave_stack
[pop_through
-2].locallevel
> locallevel
)
3700 if (histsave_stack_pos
< pop_through
)
3704 savehistfile(NULL
, 1, writeflags
);
3706 } while (histsave_stack_pos
>= pop_through
);