]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/fc.def
Bash-5.2 patch 26: fix typo when specifying readline's custom color prefix
[thirdparty/bash.git] / builtins / fc.def
CommitLineData
726f6388
JA
1This file is fc.def, from which is created fc.c.
2It implements the builtin "fc" in Bash.
3
74091dd4 4Copyright (C) 1987-2021 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES fc.c
22
23$BUILTIN fc
24$FUNCTION fc_builtin
25$DEPENDS_ON HISTORY
3185942a
JA
26$SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]
27Display or execute commands from the history list.
28
b72432fd 29fc is used to list or edit and re-execute commands from the history list.
726f6388
JA
30FIRST and LAST can be numbers specifying the range, or FIRST can be a
31string, which means the most recent command beginning with that
32string.
33
3185942a
JA
34Options:
35 -e ENAME select which editor to use. Default is FCEDIT, then EDITOR,
36 then vi
37 -l list lines instead of editing
38 -n omit line numbers when listing
39 -r reverse the order of the lines (newest listed first)
726f6388 40
3185942a 41With the `fc -s [pat=rep ...] [command]' format, COMMAND is
726f6388
JA
42re-executed after the substitution OLD=NEW is performed.
43
44A useful alias to use with this is r='fc -s', so that typing `r cc'
45runs the last command beginning with `cc' and typing `r' re-executes
46the last command.
3185942a
JA
47
48Exit Status:
49Returns success or status of executed command; non-zero if an error occurs.
726f6388
JA
50$END
51
ccc6cda3
JA
52#include <config.h>
53
726f6388 54#if defined (HISTORY)
ac50fbac 55#if defined (HAVE_SYS_PARAM_H)
cce855bc
JA
56# include <sys/param.h>
57#endif
d166f048 58#include "../bashtypes.h"
bb70624e 59#include "posixstat.h"
b80f6443 60#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
cce855bc
JA
61# include <sys/file.h>
62#endif
ccc6cda3
JA
63
64#if defined (HAVE_UNISTD_H)
65# include <unistd.h>
66#endif
67
68#include <stdio.h>
f73dda09 69#include <chartypes.h>
ccc6cda3
JA
70
71#include "../bashansi.h"
b80f6443 72#include "../bashintl.h"
726f6388 73#include <errno.h>
ccc6cda3
JA
74
75#include "../shell.h"
726f6388
JA
76#include "../builtins.h"
77#include "../flags.h"
d233b485 78#include "../parser.h"
726f6388 79#include "../bashhist.h"
bb70624e 80#include "maxpath.h"
726f6388
JA
81#include <readline/history.h>
82#include "bashgetopt.h"
ccc6cda3 83#include "common.h"
726f6388 84
726f6388
JA
85#if !defined (errno)
86extern int errno;
87#endif /* !errno */
88
8868edaf
CR
89#define HIST_INVALID INT_MIN
90#define HIST_ERANGE INT_MIN+1
91#define HIST_NOTFOUND INT_MIN+2
726f6388 92
8868edaf
CR
93/* Values for the flags argument to fc_gethnum */
94#define HN_LISTING 0x01
95#define HN_FIRST 0x02
96
97extern int unlink PARAMS((const char *));
98
99extern FILE *sh_mktmpfp PARAMS((char *, int, char **));
100
101extern int suppress_debug_trap_verbose;
d166f048 102
726f6388
JA
103/* **************************************************************** */
104/* */
105/* The K*rn shell style fc command (Fix Command) */
106/* */
107/* **************************************************************** */
108
109/* fc builtin command (fix command) for Bash for those who
110 like K*rn-style history better than csh-style.
111
112 fc [-e ename] [-nlr] [first] [last]
113
114 FIRST and LAST can be numbers specifying the range, or FIRST can be
115 a string, which means the most recent command beginning with that
116 string.
117
118 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
119 then the editor which corresponds to the current readline editing
120 mode, then vi.
121
122 -l means list lines instead of editing.
123 -n means no line numbers listed.
124 -r means reverse the order of the lines (making it newest listed first).
125
126 fc -e - [pat=rep ...] [command]
127 fc -s [pat=rep ...] [command]
128
129 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
130*/
131
726f6388
JA
132/* Data structure describing a list of global replacements to perform. */
133typedef struct repl {
134 struct repl *next;
135 char *pat;
136 char *rep;
137} REPL;
138
726f6388
JA
139/* Accessors for HIST_ENTRY lists that are called HLIST. */
140#define histline(i) (hlist[(i)]->line)
141#define histdata(i) (hlist[(i)]->data)
142
143#define FREE_RLIST() \
144 do { \
145 for (rl = rlist; rl; ) { \
146 REPL *r; \
147 r = rl->next; \
148 if (rl->pat) \
149 free (rl->pat); \
150 if (rl->rep) \
151 free (rl->rep); \
152 free (rl); \
153 rl = r; \
154 } \
155 } while (0)
156
8868edaf
CR
157static char *fc_dosubs PARAMS((char *, REPL *));
158static char *fc_gethist PARAMS((char *, HIST_ENTRY **, int));
159static int fc_gethnum PARAMS((char *, HIST_ENTRY **, int));
160static int fc_number PARAMS((WORD_LIST *));
161static void fc_replhist PARAMS((char *));
f73dda09 162#ifdef INCLUDE_UNUSED
8868edaf
CR
163static char *fc_readline PARAMS((FILE *));
164static void fc_addhist PARAMS((char *));
f73dda09
JA
165#endif
166
a0c0a00f
CR
167static void
168set_verbose_flag ()
169{
170 echo_input_at_read = verbose_flag;
171}
172
726f6388
JA
173/* String to execute on a file that we want to edit. */
174#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
95732b49
JA
175#if defined (STRICT_POSIX)
176# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
177#else
178# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
179#endif
726f6388
JA
180
181int
182fc_builtin (list)
183 WORD_LIST *list;
184{
185 register int i;
186 register char *sep;
187 int numbering, reverse, listing, execute;
ac50fbac 188 int histbeg, histend, last_hist, retval, opt, rh, real_last;
726f6388 189 FILE *stream;
ccc6cda3 190 REPL *rlist, *rl;
95732b49 191 char *ename, *command, *newcom, *fcedit;
726f6388 192 HIST_ENTRY **hlist;
28ef6c31 193 char *fn;
726f6388
JA
194
195 numbering = 1;
196 reverse = listing = execute = 0;
ccc6cda3 197 ename = (char *)NULL;
726f6388
JA
198
199 /* Parse out the options and set which of the two forms we're in. */
ccc6cda3
JA
200 reset_internal_getopt ();
201 lcurrent = list; /* XXX */
202 while (fc_number (loptend = lcurrent) == 0 &&
203 (opt = internal_getopt (list, ":e:lnrs")) != -1)
726f6388 204 {
ccc6cda3
JA
205 switch (opt)
206 {
207 case 'n':
208 numbering = 0;
209 break;
726f6388 210
ccc6cda3 211 case 'l':
8868edaf 212 listing = HN_LISTING; /* for fc_gethnum */
ccc6cda3 213 break;
726f6388 214
ccc6cda3
JA
215 case 'r':
216 reverse = 1;
217 break;
218
219 case 's':
220 execute = 1;
221 break;
222
223 case 'e':
224 ename = list_optarg;
225 break;
226
a0c0a00f 227 CASE_HELPOPT;
ccc6cda3
JA
228 default:
229 builtin_usage ();
230 return (EX_USAGE);
726f6388 231 }
726f6388
JA
232 }
233
ccc6cda3
JA
234 list = loptend;
235
726f6388
JA
236 if (ename && (*ename == '-') && (ename[1] == '\0'))
237 execute = 1;
238
239 /* The "execute" form of the command (re-run, with possible string
240 substitutions). */
241 if (execute)
242 {
ccc6cda3 243 rlist = (REPL *)NULL;
726f6388
JA
244 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
245 {
246 *sep++ = '\0';
247 rl = (REPL *)xmalloc (sizeof (REPL));
248 rl->next = (REPL *)NULL;
249 rl->pat = savestring (list->word->word);
250 rl->rep = savestring (sep);
251
252 if (rlist == NULL)
253 rlist = rl;
254 else
255 {
256 rl->next = rlist;
257 rlist = rl;
258 }
259 list = list->next;
260 }
261
262 /* If we have a list of substitutions to do, then reverse it
263 to get the replacements in the proper order. */
264
7117c2d2 265 rlist = REVERSE_LIST (rlist, REPL *);
726f6388
JA
266
267 hlist = history_list ();
268
269 /* If we still have something in list, it is a command spec.
270 Otherwise, we use the most recent command in time. */
8868edaf 271 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist, 0);
726f6388
JA
272
273 if (command == NULL)
274 {
b80f6443 275 builtin_error (_("no command found"));
726f6388
JA
276 if (rlist)
277 FREE_RLIST ();
278
279 return (EXECUTION_FAILURE);
280 }
281
282 if (rlist)
283 {
284 newcom = fc_dosubs (command, rlist);
285 free (command);
286 FREE_RLIST ();
287 command = newcom;
288 }
289
ccc6cda3
JA
290 fprintf (stderr, "%s\n", command);
291 fc_replhist (command); /* replace `fc -s' with command */
89a92869
CR
292 /* Posix says that the re-executed commands should be entered into the
293 history. */
d166f048 294 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
726f6388
JA
295 }
296
297 /* This is the second form of the command (the list-or-edit-and-rerun
298 form). */
299 hlist = history_list ();
300 if (hlist == 0)
301 return (EXECUTION_SUCCESS);
302 for (i = 0; hlist[i]; i++);
303
304 /* With the Bash implementation of history, the current command line
305 ("fc blah..." and so on) is already part of the history list by
306 the time we get to this point. This just skips over that command
307 and makes the last command that this deals with be the last command
d166f048
JA
308 the user entered before the fc. We need to check whether the
309 line was actually added (HISTIGNORE may have caused it to not be),
310 so we check hist_last_line_added. */
726f6388 311
89a92869
CR
312 /* Even though command substitution through parse_and_execute turns off
313 remember_on_history, command substitution in a shell when set -o history
314 has been enabled (interactive or not) should use it in the last_hist
315 calculation as if it were on. */
316 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
317 last_hist = i - rh - hist_last_line_added;
726f6388 318
ac50fbac
CR
319 /* Make sure that real_last is calculated the same way here and in
320 fc_gethnum. The return value from fc_gethnum is treated specially if
321 it is == real_last and we are listing commands. */
322 real_last = i;
323 /* back up from the end to the last non-null history entry */
324 while (hlist[real_last] == 0 && real_last > 0)
325 real_last--;
326
30d188c2 327 /* XXX */
7aaa661d 328 if (i == last_hist && hlist[last_hist] == 0)
30d188c2
CR
329 while (last_hist >= 0 && hlist[last_hist] == 0)
330 last_hist--;
331 if (last_hist < 0)
8868edaf 332 last_hist = 0; /* per POSIX */
30d188c2 333
726f6388
JA
334 if (list)
335 {
8868edaf 336 histbeg = fc_gethnum (list->word->word, hlist, listing|HN_FIRST);
726f6388
JA
337 list = list->next;
338
339 if (list)
8868edaf 340 histend = fc_gethnum (list->word->word, hlist, listing);
ac50fbac
CR
341 else if (histbeg == real_last)
342 histend = listing ? real_last : histbeg;
726f6388 343 else
ccc6cda3 344 histend = listing ? last_hist : histbeg;
726f6388
JA
345 }
346 else
347 {
348 /* The default for listing is the last 16 history items. */
349 if (listing)
350 {
351 histend = last_hist;
95732b49 352 histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
726f6388
JA
353 if (histbeg < 0)
354 histbeg = 0;
355 }
356 else
ccc6cda3
JA
357 /* For editing, it is the last history command. */
358 histbeg = histend = last_hist;
726f6388
JA
359 }
360
8868edaf
CR
361 if (histbeg == HIST_INVALID || histend == HIST_INVALID)
362 {
363 sh_erange ((char *)NULL, _("history specification"));
364 return (EXECUTION_FAILURE);
365 }
366 else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE)
367 {
368 sh_erange ((char *)NULL, _("history specification"));
369 return (EXECUTION_FAILURE);
370 }
371 else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND)
372 {
373 builtin_error (_("no command found"));
374 return (EXECUTION_FAILURE);
375 }
376
377 /* We don't throw an error for line specifications out of range, per POSIX */
378 if (histbeg < 0)
379 histbeg = 0;
380 if (histend < 0)
381 histend = 0;
382
3185942a
JA
383 /* "When not listing, the fc command that caused the editing shall not be
384 entered into the history list." */
385 if (listing == 0 && hist_last_line_added)
386 {
387 bash_delete_last_history ();
388 /* If we're editing a single command -- the last command in the
389 history -- and we just removed the dummy command added by
390 edit_and_execute_command (), we need to check whether or not we
391 just removed the last command in the history and need to back
392 the pointer up. remember_on_history is off because we're running
393 in parse_and_execute(). */
394 if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
395 last_hist = histbeg = --histend;
8868edaf
CR
396
397 if (hlist[last_hist] == 0)
398 last_hist--;
399 if (histend >= last_hist)
400 histend = last_hist;
401 else if (histbeg >= last_hist)
402 histbeg = last_hist;
3185942a
JA
403 }
404
8868edaf
CR
405 if (histbeg == HIST_INVALID || histend == HIST_INVALID)
406 {
407 sh_erange ((char *)NULL, _("history specification"));
408 return (EXECUTION_FAILURE);
409 }
410 else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE)
726f6388 411 {
b80f6443 412 sh_erange ((char *)NULL, _("history specification"));
726f6388
JA
413 return (EXECUTION_FAILURE);
414 }
8868edaf
CR
415 else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND)
416 {
417 builtin_error (_("no command found"));
418 return (EXECUTION_FAILURE);
419 }
420
421 /* We don't throw an error for line specifications out of range, per POSIX */
422 if (histbeg < 0)
423 histbeg = 0;
424 if (histend < 0)
425 histend = 0;
726f6388
JA
426
427 if (histend < histbeg)
428 {
ccc6cda3 429 i = histend;
726f6388 430 histend = histbeg;
ccc6cda3
JA
431 histbeg = i;
432
726f6388
JA
433 reverse = 1;
434 }
435
436 if (listing)
437 stream = stdout;
438 else
439 {
440 numbering = 0;
28ef6c31 441 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
ccc6cda3 442 if (stream == 0)
726f6388 443 {
b80f6443 444 builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
28ef6c31 445 FREE (fn);
726f6388
JA
446 return (EXECUTION_FAILURE);
447 }
448 }
449
ccc6cda3 450 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
726f6388 451 {
ccc6cda3 452 QUIT;
74091dd4
CR
453 if (hlist[i] == 0)
454 continue;
ccc6cda3
JA
455 if (numbering)
456 fprintf (stream, "%d", i + history_base);
457 if (listing)
95732b49
JA
458 {
459 if (posixly_correct)
460 fputs ("\t", stream);
461 else
462 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
463 }
74091dd4
CR
464 if (histline (i))
465 fprintf (stream, "%s\n", histline (i));
726f6388
JA
466 }
467
468 if (listing)
3185942a 469 return (sh_chkwrite (EXECUTION_SUCCESS));
726f6388 470
3185942a
JA
471 fflush (stream);
472 if (ferror (stream))
473 {
474 sh_wrerror ();
475 fclose (stream);
d233b485 476 FREE (fn);
3185942a
JA
477 return (EXECUTION_FAILURE);
478 }
726f6388
JA
479 fclose (stream);
480
481 /* Now edit the file of commands. */
482 if (ename)
483 {
484 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
485 sprintf (command, "%s %s", ename, fn);
486 }
487 else
488 {
95732b49
JA
489 fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
490 command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
491 sprintf (command, "%s %s", fcedit, fn);
726f6388 492 }
d166f048 493 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
ccc6cda3
JA
494 if (retval != EXECUTION_SUCCESS)
495 {
496 unlink (fn);
28ef6c31 497 free (fn);
ccc6cda3
JA
498 return (EXECUTION_FAILURE);
499 }
726f6388 500
a0c0a00f 501#if defined (READLINE)
8868edaf 502 /* If we're executing as part of a dispatched readline command like
a0c0a00f
CR
503 {emacs,vi}_edit_and_execute_command, the readline state will indicate it.
504 We could remove the partial command from the history, but ksh93 doesn't
505 so we stay compatible. */
506#endif
507
d166f048
JA
508 /* Make sure parse_and_execute doesn't turn this off, even though a
509 call to parse_and_execute farther up the function call stack (e.g.,
510 if this is called by vi_edit_and_execute_command) may have already
511 called bash_history_disable. */
512 remember_on_history = 1;
726f6388 513
d166f048 514 /* Turn on the `v' flag while fc_execute_file runs so the commands
726f6388
JA
515 will be echoed as they are read by the parser. */
516 begin_unwind_frame ("fc builtin");
d233b485 517 add_unwind_protect (xfree, fn);
726f6388 518 add_unwind_protect (unlink, fn);
a0c0a00f 519 add_unwind_protect (set_verbose_flag, (char *)NULL);
8868edaf 520 unwind_protect_int (suppress_debug_trap_verbose);
726f6388 521 echo_input_at_read = 1;
8868edaf 522 suppress_debug_trap_verbose = 1;
726f6388 523
a0c0a00f 524 retval = fc_execute_file (fn);
726f6388
JA
525 run_unwind_frame ("fc builtin");
526
527 return (retval);
528}
529
ccc6cda3
JA
530/* Return 1 if LIST->word->word is a legal number for fc's use. */
531static int
532fc_number (list)
533 WORD_LIST *list;
534{
535 char *s;
536
537 if (list == 0)
538 return 0;
539 s = list->word->word;
540 if (*s == '-')
541 s++;
7117c2d2 542 return (legal_number (s, (intmax_t *)NULL));
ccc6cda3
JA
543}
544
726f6388
JA
545/* Return an absolute index into HLIST which corresponds to COMMAND. If
546 COMMAND is a number, then it was specified in relative terms. If it
8868edaf
CR
547 is a string, then it is the start of a command line present in HLIST.
548 MODE includes HN_LISTING if we are listing commands, and does not if we
549 are executing them. If MODE includes HN_FIRST we are looking for the
550 first history number specification. */
726f6388 551static int
8868edaf 552fc_gethnum (command, hlist, mode)
726f6388
JA
553 char *command;
554 HIST_ENTRY **hlist;
8868edaf 555 int mode;
726f6388 556{
89a92869 557 int sign, n, clen, rh;
8868edaf 558 register int i, j, last_hist, real_last, listing;
726f6388
JA
559 register char *s;
560
8868edaf 561 listing = mode & HN_LISTING;
3185942a 562 sign = 1;
726f6388
JA
563 /* Count history elements. */
564 for (i = 0; hlist[i]; i++);
565
566 /* With the Bash implementation of history, the current command line
567 ("fc blah..." and so on) is already part of the history list by
568 the time we get to this point. This just skips over that command
569 and makes the last command that this deals with be the last command
d166f048
JA
570 the user entered before the fc. We need to check whether the
571 line was actually added (HISTIGNORE may have caused it to not be),
3185942a
JA
572 so we check hist_last_line_added. This needs to agree with the
573 calculation of last_hist in fc_builtin above. */
89a92869
CR
574 /* Even though command substitution through parse_and_execute turns off
575 remember_on_history, command substitution in a shell when set -o history
576 has been enabled (interactive or not) should use it in the last_hist
577 calculation as if it were on. */
578 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
7aaa661d
CR
579 last_hist = i - rh - hist_last_line_added;
580
581 if (i == last_hist && hlist[last_hist] == 0)
582 while (last_hist >= 0 && hlist[last_hist] == 0)
583 last_hist--;
584 if (last_hist < 0)
585 return (-1);
586
ac50fbac 587 real_last = i;
7aaa661d 588 i = last_hist;
726f6388
JA
589
590 /* No specification defaults to most recent command. */
591 if (command == NULL)
592 return (i);
593
ac50fbac
CR
594 /* back up from the end to the last non-null history entry */
595 while (hlist[real_last] == 0 && real_last > 0)
596 real_last--;
597
726f6388
JA
598 /* Otherwise, there is a specification. It can be a number relative to
599 the current position, or an absolute history number. */
600 s = command;
601
602 /* Handle possible leading minus sign. */
603 if (s && (*s == '-'))
604 {
605 sign = -1;
606 s++;
607 }
608
f73dda09 609 if (s && DIGIT(*s))
726f6388
JA
610 {
611 n = atoi (s);
612 n *= sign;
613
8868edaf
CR
614 /* We want to return something that is an offset to HISTORY_BASE. */
615
726f6388
JA
616 /* If the value is negative or zero, then it is an offset from
617 the current history item. */
8868edaf
CR
618 /* We don't use HN_FIRST here, so we don't return different values
619 depending on whether we're looking for the first or last in a
620 pair of range arguments, but nobody else does, either. */
726f6388 621 if (n < 0)
7117c2d2
JA
622 {
623 n += i + 1;
624 return (n < 0 ? 0 : n);
625 }
726f6388 626 else if (n == 0)
8868edaf 627 return ((sign == -1) ? (listing ? real_last : HIST_INVALID) : i);
726f6388 628 else
7117c2d2 629 {
8868edaf
CR
630 /* If we're out of range (greater than I (last history entry) or
631 less than HISTORY_BASE, we want to return different values
632 based on whether or not we are looking for the first or last
633 value in a desired range of history entries. */
7117c2d2 634 n -= history_base;
8868edaf
CR
635 if (n < 0)
636 return (mode & HN_FIRST ? 0 : i);
637 else if (n >= i)
638 return (mode & HN_FIRST ? 0 : i);
639 else
640 return n;
7117c2d2 641 }
726f6388
JA
642 }
643
644 clen = strlen (command);
645 for (j = i; j >= 0; j--)
646 {
647 if (STREQN (command, histline (j), clen))
648 return (j);
649 }
8868edaf 650 return (HIST_NOTFOUND);
726f6388
JA
651}
652
653/* Locate the most recent history line which begins with
8868edaf
CR
654 COMMAND in HLIST, and return a malloc()'ed copy of it.
655 MODE is 1 if we are listing commands, 0 if we are executing them. */
726f6388 656static char *
8868edaf 657fc_gethist (command, hlist, mode)
726f6388
JA
658 char *command;
659 HIST_ENTRY **hlist;
8868edaf 660 int mode;
726f6388
JA
661{
662 int i;
663
95732b49 664 if (hlist == 0)
726f6388
JA
665 return ((char *)NULL);
666
8868edaf 667 i = fc_gethnum (command, hlist, mode);
726f6388
JA
668
669 if (i >= 0)
670 return (savestring (histline (i)));
671 else
672 return ((char *)NULL);
673}
674
f73dda09 675#ifdef INCLUDE_UNUSED
726f6388
JA
676/* Read the edited history lines from STREAM and return them
677 one at a time. This can read unlimited length lines. The
678 caller should free the storage. */
679static char *
680fc_readline (stream)
681 FILE *stream;
682{
683 register int c;
684 int line_len = 0, lindex = 0;
685 char *line = (char *)NULL;
686
687 while ((c = getc (stream)) != EOF)
688 {
689 if ((lindex + 2) >= line_len)
f73dda09 690 line = (char *)xrealloc (line, (line_len += 128));
726f6388
JA
691
692 if (c == '\n')
693 {
694 line[lindex++] = '\n';
695 line[lindex++] = '\0';
696 return (line);
697 }
698 else
699 line[lindex++] = c;
700 }
701
702 if (!lindex)
703 {
704 if (line)
705 free (line);
706
707 return ((char *)NULL);
708 }
709
710 if (lindex + 2 >= line_len)
711 line = (char *)xrealloc (line, lindex + 3);
712
713 line[lindex++] = '\n'; /* Finish with newline if none in file */
714 line[lindex++] = '\0';
715 return (line);
716}
f73dda09 717#endif
726f6388
JA
718
719/* Perform the SUBS on COMMAND.
720 SUBS is a list of substitutions, and COMMAND is a simple string.
721 Return a pointer to a malloc'ed string which contains the substituted
722 command. */
723static char *
724fc_dosubs (command, subs)
725 char *command;
726 REPL *subs;
727{
ccc6cda3 728 register char *new, *t;
726f6388
JA
729 register REPL *r;
730
ccc6cda3 731 for (new = savestring (command), r = subs; r; r = r->next)
726f6388 732 {
ccc6cda3 733 t = strsub (new, r->pat, r->rep, 1);
726f6388
JA
734 free (new);
735 new = t;
736 }
737 return (new);
738}
739
726f6388
JA
740/* Use `command' to replace the last entry in the history list, which,
741 by this time, is `fc blah...'. The intent is that the new command
742 become the history entry, and that `fc' should never appear in the
743 history list. This way you can do `r' to your heart's content. */
744static void
745fc_replhist (command)
746 char *command;
747{
726f6388
JA
748 int n;
749
ccc6cda3 750 if (command == 0 || *command == '\0')
726f6388
JA
751 return;
752
726f6388 753 n = strlen (command);
726f6388
JA
754 if (command[n - 1] == '\n')
755 command[n - 1] = '\0';
756
757 if (command && *command)
758 {
3185942a 759 bash_delete_last_history ();
726f6388
JA
760 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
761 }
762}
763
f73dda09 764#ifdef INCLUDE_UNUSED
726f6388
JA
765/* Add LINE to the history, after removing a single trailing newline. */
766static void
767fc_addhist (line)
768 char *line;
769{
770 register int n;
771
95732b49
JA
772 if (line == 0 || *line == 0)
773 return;
774
726f6388
JA
775 n = strlen (line);
776
777 if (line[n - 1] == '\n')
778 line[n - 1] = '\0';
779
780 if (line && *line)
95732b49 781 maybe_add_history (line); /* Obeys HISTCONTROL setting. */
726f6388 782}
f73dda09
JA
783#endif
784
726f6388 785#endif /* HISTORY */