]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/fc.def
bash-5.0-alpha release
[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
a0c0a00f 4Copyright (C) 1987-2015 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"
9a51695b 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
f73dda09 89extern int unlink __P((const char *));
726f6388 90
28ef6c31 91extern FILE *sh_mktmpfp __P((char *, int, char **));
d166f048 92
726f6388
JA
93/* **************************************************************** */
94/* */
95/* The K*rn shell style fc command (Fix Command) */
96/* */
97/* **************************************************************** */
98
99/* fc builtin command (fix command) for Bash for those who
100 like K*rn-style history better than csh-style.
101
102 fc [-e ename] [-nlr] [first] [last]
103
104 FIRST and LAST can be numbers specifying the range, or FIRST can be
105 a string, which means the most recent command beginning with that
106 string.
107
108 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
109 then the editor which corresponds to the current readline editing
110 mode, then vi.
111
112 -l means list lines instead of editing.
113 -n means no line numbers listed.
114 -r means reverse the order of the lines (making it newest listed first).
115
116 fc -e - [pat=rep ...] [command]
117 fc -s [pat=rep ...] [command]
118
119 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
120*/
121
726f6388
JA
122/* Data structure describing a list of global replacements to perform. */
123typedef struct repl {
124 struct repl *next;
125 char *pat;
126 char *rep;
127} REPL;
128
726f6388
JA
129/* Accessors for HIST_ENTRY lists that are called HLIST. */
130#define histline(i) (hlist[(i)]->line)
131#define histdata(i) (hlist[(i)]->data)
132
133#define FREE_RLIST() \
134 do { \
135 for (rl = rlist; rl; ) { \
136 REPL *r; \
137 r = rl->next; \
138 if (rl->pat) \
139 free (rl->pat); \
140 if (rl->rep) \
141 free (rl->rep); \
142 free (rl); \
143 rl = r; \
144 } \
145 } while (0)
146
f73dda09
JA
147static char *fc_dosubs __P((char *, REPL *));
148static char *fc_gethist __P((char *, HIST_ENTRY **));
149static int fc_gethnum __P((char *, HIST_ENTRY **));
150static int fc_number __P((WORD_LIST *));
151static void fc_replhist __P((char *));
152#ifdef INCLUDE_UNUSED
153static char *fc_readline __P((FILE *));
154static void fc_addhist __P((char *));
155#endif
156
a0c0a00f
CR
157static void
158set_verbose_flag ()
159{
160 echo_input_at_read = verbose_flag;
161}
162
726f6388
JA
163/* String to execute on a file that we want to edit. */
164#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
95732b49
JA
165#if defined (STRICT_POSIX)
166# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
167#else
168# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
169#endif
726f6388
JA
170
171int
172fc_builtin (list)
173 WORD_LIST *list;
174{
175 register int i;
176 register char *sep;
177 int numbering, reverse, listing, execute;
ac50fbac 178 int histbeg, histend, last_hist, retval, opt, rh, real_last;
726f6388 179 FILE *stream;
ccc6cda3 180 REPL *rlist, *rl;
95732b49 181 char *ename, *command, *newcom, *fcedit;
726f6388 182 HIST_ENTRY **hlist;
28ef6c31 183 char *fn;
726f6388
JA
184
185 numbering = 1;
186 reverse = listing = execute = 0;
ccc6cda3 187 ename = (char *)NULL;
726f6388
JA
188
189 /* Parse out the options and set which of the two forms we're in. */
ccc6cda3
JA
190 reset_internal_getopt ();
191 lcurrent = list; /* XXX */
192 while (fc_number (loptend = lcurrent) == 0 &&
193 (opt = internal_getopt (list, ":e:lnrs")) != -1)
726f6388 194 {
ccc6cda3
JA
195 switch (opt)
196 {
197 case 'n':
198 numbering = 0;
199 break;
726f6388 200
ccc6cda3
JA
201 case 'l':
202 listing = 1;
203 break;
726f6388 204
ccc6cda3
JA
205 case 'r':
206 reverse = 1;
207 break;
208
209 case 's':
210 execute = 1;
211 break;
212
213 case 'e':
214 ename = list_optarg;
215 break;
216
a0c0a00f 217 CASE_HELPOPT;
ccc6cda3
JA
218 default:
219 builtin_usage ();
220 return (EX_USAGE);
726f6388 221 }
726f6388
JA
222 }
223
ccc6cda3
JA
224 list = loptend;
225
726f6388
JA
226 if (ename && (*ename == '-') && (ename[1] == '\0'))
227 execute = 1;
228
229 /* The "execute" form of the command (re-run, with possible string
230 substitutions). */
231 if (execute)
232 {
ccc6cda3 233 rlist = (REPL *)NULL;
726f6388
JA
234 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
235 {
236 *sep++ = '\0';
237 rl = (REPL *)xmalloc (sizeof (REPL));
238 rl->next = (REPL *)NULL;
239 rl->pat = savestring (list->word->word);
240 rl->rep = savestring (sep);
241
242 if (rlist == NULL)
243 rlist = rl;
244 else
245 {
246 rl->next = rlist;
247 rlist = rl;
248 }
249 list = list->next;
250 }
251
252 /* If we have a list of substitutions to do, then reverse it
253 to get the replacements in the proper order. */
254
7117c2d2 255 rlist = REVERSE_LIST (rlist, REPL *);
726f6388
JA
256
257 hlist = history_list ();
258
259 /* If we still have something in list, it is a command spec.
260 Otherwise, we use the most recent command in time. */
ccc6cda3 261 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
726f6388
JA
262
263 if (command == NULL)
264 {
b80f6443 265 builtin_error (_("no command found"));
726f6388
JA
266 if (rlist)
267 FREE_RLIST ();
268
269 return (EXECUTION_FAILURE);
270 }
271
272 if (rlist)
273 {
274 newcom = fc_dosubs (command, rlist);
275 free (command);
276 FREE_RLIST ();
277 command = newcom;
278 }
279
ccc6cda3
JA
280 fprintf (stderr, "%s\n", command);
281 fc_replhist (command); /* replace `fc -s' with command */
89a92869
CR
282 /* Posix says that the re-executed commands should be entered into the
283 history. */
d166f048 284 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
726f6388
JA
285 }
286
287 /* This is the second form of the command (the list-or-edit-and-rerun
288 form). */
289 hlist = history_list ();
290 if (hlist == 0)
291 return (EXECUTION_SUCCESS);
292 for (i = 0; hlist[i]; i++);
293
294 /* With the Bash implementation of history, the current command line
295 ("fc blah..." and so on) is already part of the history list by
296 the time we get to this point. This just skips over that command
297 and makes the last command that this deals with be the last command
d166f048
JA
298 the user entered before the fc. We need to check whether the
299 line was actually added (HISTIGNORE may have caused it to not be),
300 so we check hist_last_line_added. */
726f6388 301
89a92869
CR
302 /* Even though command substitution through parse_and_execute turns off
303 remember_on_history, command substitution in a shell when set -o history
304 has been enabled (interactive or not) should use it in the last_hist
305 calculation as if it were on. */
306 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
307 last_hist = i - rh - hist_last_line_added;
726f6388 308
ac50fbac
CR
309 /* Make sure that real_last is calculated the same way here and in
310 fc_gethnum. The return value from fc_gethnum is treated specially if
311 it is == real_last and we are listing commands. */
312 real_last = i;
313 /* back up from the end to the last non-null history entry */
314 while (hlist[real_last] == 0 && real_last > 0)
315 real_last--;
316
30d188c2 317 /* XXX */
7aaa661d 318 if (i == last_hist && hlist[last_hist] == 0)
30d188c2
CR
319 while (last_hist >= 0 && hlist[last_hist] == 0)
320 last_hist--;
321 if (last_hist < 0)
322 {
323 sh_erange ((char *)NULL, _("history specification"));
324 return (EXECUTION_FAILURE);
325 }
326
726f6388
JA
327 if (list)
328 {
329 histbeg = fc_gethnum (list->word->word, hlist);
330 list = list->next;
331
332 if (list)
333 histend = fc_gethnum (list->word->word, hlist);
ac50fbac
CR
334 else if (histbeg == real_last)
335 histend = listing ? real_last : histbeg;
726f6388 336 else
ccc6cda3 337 histend = listing ? last_hist : histbeg;
726f6388
JA
338 }
339 else
340 {
341 /* The default for listing is the last 16 history items. */
342 if (listing)
343 {
344 histend = last_hist;
95732b49 345 histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
726f6388
JA
346 if (histbeg < 0)
347 histbeg = 0;
348 }
349 else
ccc6cda3
JA
350 /* For editing, it is the last history command. */
351 histbeg = histend = last_hist;
726f6388
JA
352 }
353
3185942a
JA
354 /* "When not listing, the fc command that caused the editing shall not be
355 entered into the history list." */
356 if (listing == 0 && hist_last_line_added)
357 {
358 bash_delete_last_history ();
359 /* If we're editing a single command -- the last command in the
360 history -- and we just removed the dummy command added by
361 edit_and_execute_command (), we need to check whether or not we
362 just removed the last command in the history and need to back
363 the pointer up. remember_on_history is off because we're running
364 in parse_and_execute(). */
365 if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
366 last_hist = histbeg = --histend;
367 }
368
726f6388 369 /* We print error messages for line specifications out of range. */
7117c2d2 370 if ((histbeg < 0) || (histend < 0))
726f6388 371 {
b80f6443 372 sh_erange ((char *)NULL, _("history specification"));
726f6388
JA
373 return (EXECUTION_FAILURE);
374 }
375
376 if (histend < histbeg)
377 {
ccc6cda3 378 i = histend;
726f6388 379 histend = histbeg;
ccc6cda3
JA
380 histbeg = i;
381
726f6388
JA
382 reverse = 1;
383 }
384
385 if (listing)
386 stream = stdout;
387 else
388 {
389 numbering = 0;
28ef6c31 390 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
ccc6cda3 391 if (stream == 0)
726f6388 392 {
b80f6443 393 builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
28ef6c31 394 FREE (fn);
726f6388
JA
395 return (EXECUTION_FAILURE);
396 }
397 }
398
ccc6cda3 399 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
726f6388 400 {
ccc6cda3
JA
401 QUIT;
402 if (numbering)
403 fprintf (stream, "%d", i + history_base);
404 if (listing)
95732b49
JA
405 {
406 if (posixly_correct)
407 fputs ("\t", stream);
408 else
409 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
410 }
ccc6cda3 411 fprintf (stream, "%s\n", histline (i));
726f6388
JA
412 }
413
414 if (listing)
3185942a 415 return (sh_chkwrite (EXECUTION_SUCCESS));
726f6388 416
3185942a
JA
417 fflush (stream);
418 if (ferror (stream))
419 {
420 sh_wrerror ();
421 fclose (stream);
422 return (EXECUTION_FAILURE);
423 }
726f6388
JA
424 fclose (stream);
425
426 /* Now edit the file of commands. */
427 if (ename)
428 {
429 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
430 sprintf (command, "%s %s", ename, fn);
431 }
432 else
433 {
95732b49
JA
434 fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
435 command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
436 sprintf (command, "%s %s", fcedit, fn);
726f6388 437 }
d166f048 438 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
ccc6cda3
JA
439 if (retval != EXECUTION_SUCCESS)
440 {
441 unlink (fn);
28ef6c31 442 free (fn);
ccc6cda3
JA
443 return (EXECUTION_FAILURE);
444 }
726f6388 445
a0c0a00f
CR
446#if defined (READLINE)
447 /* If we're executing as part of a dispatched readline commnand like
448 {emacs,vi}_edit_and_execute_command, the readline state will indicate it.
449 We could remove the partial command from the history, but ksh93 doesn't
450 so we stay compatible. */
451#endif
452
d166f048
JA
453 /* Make sure parse_and_execute doesn't turn this off, even though a
454 call to parse_and_execute farther up the function call stack (e.g.,
455 if this is called by vi_edit_and_execute_command) may have already
456 called bash_history_disable. */
457 remember_on_history = 1;
726f6388 458
d166f048 459 /* Turn on the `v' flag while fc_execute_file runs so the commands
726f6388
JA
460 will be echoed as they are read by the parser. */
461 begin_unwind_frame ("fc builtin");
9a51695b 462 add_unwind_protect (xfree, fn);
726f6388 463 add_unwind_protect (unlink, fn);
a0c0a00f 464 add_unwind_protect (set_verbose_flag, (char *)NULL);
726f6388 465 echo_input_at_read = 1;
726f6388 466
a0c0a00f 467 retval = fc_execute_file (fn);
726f6388
JA
468 run_unwind_frame ("fc builtin");
469
470 return (retval);
471}
472
ccc6cda3
JA
473/* Return 1 if LIST->word->word is a legal number for fc's use. */
474static int
475fc_number (list)
476 WORD_LIST *list;
477{
478 char *s;
479
480 if (list == 0)
481 return 0;
482 s = list->word->word;
483 if (*s == '-')
484 s++;
7117c2d2 485 return (legal_number (s, (intmax_t *)NULL));
ccc6cda3
JA
486}
487
726f6388
JA
488/* Return an absolute index into HLIST which corresponds to COMMAND. If
489 COMMAND is a number, then it was specified in relative terms. If it
490 is a string, then it is the start of a command line present in HLIST. */
491static int
492fc_gethnum (command, hlist)
493 char *command;
494 HIST_ENTRY **hlist;
495{
89a92869 496 int sign, n, clen, rh;
ac50fbac 497 register int i, j, last_hist, real_last;
726f6388
JA
498 register char *s;
499
3185942a 500 sign = 1;
726f6388
JA
501 /* Count history elements. */
502 for (i = 0; hlist[i]; i++);
503
504 /* With the Bash implementation of history, the current command line
505 ("fc blah..." and so on) is already part of the history list by
506 the time we get to this point. This just skips over that command
507 and makes the last command that this deals with be the last command
d166f048
JA
508 the user entered before the fc. We need to check whether the
509 line was actually added (HISTIGNORE may have caused it to not be),
3185942a
JA
510 so we check hist_last_line_added. This needs to agree with the
511 calculation of last_hist in fc_builtin above. */
89a92869
CR
512 /* Even though command substitution through parse_and_execute turns off
513 remember_on_history, command substitution in a shell when set -o history
514 has been enabled (interactive or not) should use it in the last_hist
515 calculation as if it were on. */
516 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
7aaa661d
CR
517 last_hist = i - rh - hist_last_line_added;
518
519 if (i == last_hist && hlist[last_hist] == 0)
520 while (last_hist >= 0 && hlist[last_hist] == 0)
521 last_hist--;
522 if (last_hist < 0)
523 return (-1);
524
ac50fbac 525 real_last = i;
7aaa661d 526 i = last_hist;
726f6388
JA
527
528 /* No specification defaults to most recent command. */
529 if (command == NULL)
530 return (i);
531
ac50fbac
CR
532 /* back up from the end to the last non-null history entry */
533 while (hlist[real_last] == 0 && real_last > 0)
534 real_last--;
535
726f6388
JA
536 /* Otherwise, there is a specification. It can be a number relative to
537 the current position, or an absolute history number. */
538 s = command;
539
540 /* Handle possible leading minus sign. */
541 if (s && (*s == '-'))
542 {
543 sign = -1;
544 s++;
545 }
546
f73dda09 547 if (s && DIGIT(*s))
726f6388
JA
548 {
549 n = atoi (s);
550 n *= sign;
551
726f6388
JA
552 /* If the value is negative or zero, then it is an offset from
553 the current history item. */
554 if (n < 0)
7117c2d2
JA
555 {
556 n += i + 1;
557 return (n < 0 ? 0 : n);
558 }
726f6388 559 else if (n == 0)
ac50fbac 560 return ((sign == -1) ? real_last : i);
726f6388 561 else
7117c2d2
JA
562 {
563 n -= history_base;
564 return (i < n ? i : n);
565 }
726f6388
JA
566 }
567
568 clen = strlen (command);
569 for (j = i; j >= 0; j--)
570 {
571 if (STREQN (command, histline (j), clen))
572 return (j);
573 }
574 return (-1);
575}
576
577/* Locate the most recent history line which begins with
578 COMMAND in HLIST, and return a malloc()'ed copy of it. */
579static char *
580fc_gethist (command, hlist)
581 char *command;
582 HIST_ENTRY **hlist;
583{
584 int i;
585
95732b49 586 if (hlist == 0)
726f6388
JA
587 return ((char *)NULL);
588
589 i = fc_gethnum (command, hlist);
590
591 if (i >= 0)
592 return (savestring (histline (i)));
593 else
594 return ((char *)NULL);
595}
596
f73dda09 597#ifdef INCLUDE_UNUSED
726f6388
JA
598/* Read the edited history lines from STREAM and return them
599 one at a time. This can read unlimited length lines. The
600 caller should free the storage. */
601static char *
602fc_readline (stream)
603 FILE *stream;
604{
605 register int c;
606 int line_len = 0, lindex = 0;
607 char *line = (char *)NULL;
608
609 while ((c = getc (stream)) != EOF)
610 {
611 if ((lindex + 2) >= line_len)
f73dda09 612 line = (char *)xrealloc (line, (line_len += 128));
726f6388
JA
613
614 if (c == '\n')
615 {
616 line[lindex++] = '\n';
617 line[lindex++] = '\0';
618 return (line);
619 }
620 else
621 line[lindex++] = c;
622 }
623
624 if (!lindex)
625 {
626 if (line)
627 free (line);
628
629 return ((char *)NULL);
630 }
631
632 if (lindex + 2 >= line_len)
633 line = (char *)xrealloc (line, lindex + 3);
634
635 line[lindex++] = '\n'; /* Finish with newline if none in file */
636 line[lindex++] = '\0';
637 return (line);
638}
f73dda09 639#endif
726f6388
JA
640
641/* Perform the SUBS on COMMAND.
642 SUBS is a list of substitutions, and COMMAND is a simple string.
643 Return a pointer to a malloc'ed string which contains the substituted
644 command. */
645static char *
646fc_dosubs (command, subs)
647 char *command;
648 REPL *subs;
649{
ccc6cda3 650 register char *new, *t;
726f6388
JA
651 register REPL *r;
652
ccc6cda3 653 for (new = savestring (command), r = subs; r; r = r->next)
726f6388 654 {
ccc6cda3 655 t = strsub (new, r->pat, r->rep, 1);
726f6388
JA
656 free (new);
657 new = t;
658 }
659 return (new);
660}
661
726f6388
JA
662/* Use `command' to replace the last entry in the history list, which,
663 by this time, is `fc blah...'. The intent is that the new command
664 become the history entry, and that `fc' should never appear in the
665 history list. This way you can do `r' to your heart's content. */
666static void
667fc_replhist (command)
668 char *command;
669{
726f6388
JA
670 int n;
671
ccc6cda3 672 if (command == 0 || *command == '\0')
726f6388
JA
673 return;
674
726f6388 675 n = strlen (command);
726f6388
JA
676 if (command[n - 1] == '\n')
677 command[n - 1] = '\0';
678
679 if (command && *command)
680 {
3185942a 681 bash_delete_last_history ();
726f6388
JA
682 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
683 }
684}
685
f73dda09 686#ifdef INCLUDE_UNUSED
726f6388
JA
687/* Add LINE to the history, after removing a single trailing newline. */
688static void
689fc_addhist (line)
690 char *line;
691{
692 register int n;
693
95732b49
JA
694 if (line == 0 || *line == 0)
695 return;
696
726f6388
JA
697 n = strlen (line);
698
699 if (line[n - 1] == '\n')
700 line[n - 1] = '\0';
701
702 if (line && *line)
95732b49 703 maybe_add_history (line); /* Obeys HISTCONTROL setting. */
726f6388 704}
f73dda09
JA
705#endif
706
726f6388 707#endif /* HISTORY */