Created
July 26, 2015 17:55
-
-
Save dunn/6d64e94f36a4e2416bab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/-i b/-i | |
deleted file mode 100644 | |
index e69de29..0000000 | |
diff --git a/.gitignore b/.gitignore | |
new file mode 100644 | |
index 0000000..e999b2f | |
--- /dev/null | |
+++ b/.gitignore | |
@@ -0,0 +1 @@ | |
+-i | |
diff --git a/arrayfunc.c b/arrayfunc.c | |
index b82767e..c4bae0a 100644 | |
--- a/arrayfunc.c | |
+++ b/arrayfunc.c | |
@@ -179,6 +179,7 @@ bind_array_var_internal (entry, ind, key, value, flags) | |
array_insert (array_cell (entry), ind, newval); | |
FREE (newval); | |
+ VUNSETATTR (entry, att_invisible); /* no longer invisible */ | |
return (entry); | |
} | |
@@ -403,6 +404,9 @@ assign_array_var_from_word_list (var, list, flags) | |
(*var->assign_func) (var, l->word->word, i, 0); | |
else | |
array_insert (a, i, l->word->word); | |
+ | |
+ VUNSETATTR (var, att_invisible); /* no longer invisible */ | |
+ | |
return var; | |
} | |
@@ -597,6 +601,11 @@ assign_compound_array_list (var, nlist, flags) | |
if (assoc_p (var)) | |
{ | |
val = expand_assignment_string_to_string (val, 0); | |
+ if (val == 0) | |
+ { | |
+ val = (char *)xmalloc (1); | |
+ val[0] = '\0'; /* like do_assignment_internal */ | |
+ } | |
free_val = 1; | |
} | |
@@ -628,6 +637,10 @@ assign_array_var_from_string (var, value, flags) | |
if (nlist) | |
dispose_words (nlist); | |
+ | |
+ if (var) | |
+ VUNSETATTR (var, att_invisible); /* no longer invisible */ | |
+ | |
return (var); | |
} | |
diff --git a/assoc.c b/assoc.c | |
index f9ed881..7298a1f 100644 | |
--- a/assoc.c | |
+++ b/assoc.c | |
@@ -436,6 +436,8 @@ assoc_to_assign (hash, quoted) | |
#if 1 | |
if (sh_contains_shell_metas (tlist->key)) | |
istr = sh_double_quote (tlist->key); | |
+ else if (ALL_ELEMENT_SUB (tlist->key[0]) && tlist->key[1] == '\0') | |
+ istr = sh_double_quote (tlist->key); | |
else | |
istr = tlist->key; | |
#else | |
diff --git a/bashline.c b/bashline.c | |
index 1f12764..c874151 100644 | |
--- a/bashline.c | |
+++ b/bashline.c | |
@@ -202,6 +202,7 @@ extern int current_command_line_count, saved_command_line_count; | |
extern int last_command_exit_value; | |
extern int array_needs_making; | |
extern int posixly_correct, no_symbolic_links; | |
+extern int sigalrm_seen; | |
extern char *current_prompt_string, *ps1_prompt; | |
extern STRING_INT_ALIST word_token_alist[]; | |
extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin; | |
@@ -4167,9 +4168,16 @@ bash_directory_completion_matches (text) | |
int qc; | |
qc = rl_dispatching ? rl_completion_quote_character : 0; | |
- dfn = bash_dequote_filename ((char *)text, qc); | |
+ /* If rl_completion_found_quote != 0, rl_completion_matches will call the | |
+ filename dequoting function, causing the directory name to be dequoted | |
+ twice. */ | |
+ if (rl_dispatching && rl_completion_found_quote == 0) | |
+ dfn = bash_dequote_filename ((char *)text, qc); | |
+ else | |
+ dfn = (char *)text; | |
m1 = rl_completion_matches (dfn, rl_filename_completion_function); | |
- free (dfn); | |
+ if (dfn != text) | |
+ free (dfn); | |
if (m1 == 0 || m1[0] == 0) | |
return m1; | |
@@ -4201,8 +4209,9 @@ bash_event_hook () | |
{ | |
/* If we're going to longjmp to top_level, make sure we clean up readline. | |
check_signals will call QUIT, which will eventually longjmp to top_level, | |
- calling run_interrupt_trap along the way. */ | |
- if (interrupt_state) | |
+ calling run_interrupt_trap along the way. The check for sigalrm_seen is | |
+ to clean up the read builtin's state. */ | |
+ if (terminating_signal || interrupt_state || sigalrm_seen) | |
rl_cleanup_after_signal (); | |
bashline_reset_event_hook (); | |
check_signals_and_traps (); /* XXX */ | |
diff --git a/builtins/common.h b/builtins/common.h | |
index b0c2f7d..a1298cb 100644 | |
--- a/builtins/common.h | |
+++ b/builtins/common.h | |
@@ -33,6 +33,8 @@ | |
#define SEVAL_RESETLINE 0x010 | |
#define SEVAL_PARSEONLY 0x020 | |
#define SEVAL_NOLONGJMP 0x040 | |
+#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */ | |
+#define SEVAL_ONECMD 0x100 /* only allow a single command */ | |
/* Flags for describe_command, shared between type.def and command.def */ | |
#define CDESC_ALL 0x001 /* type -a */ | |
@@ -120,6 +122,10 @@ extern void bash_logout __P((void)); | |
/* Functions from getopts.def */ | |
extern void getopts_reset __P((int)); | |
+/* Functions from read.def */ | |
+extern void read_tty_cleanup __P((void)); | |
+extern int read_tty_modified __P((void)); | |
+ | |
/* Functions from set.def */ | |
extern int minus_o_option_value __P((char *)); | |
extern void list_minus_o_opts __P((int, int)); | |
diff --git a/builtins/evalstring.c b/builtins/evalstring.c | |
index ce5b4d6..0758c43 100644 | |
--- a/builtins/evalstring.c | |
+++ b/builtins/evalstring.c | |
@@ -308,6 +308,27 @@ parse_and_execute (string, from_file, flags) | |
{ | |
struct fd_bitmap *bitmap; | |
+ if (flags & SEVAL_FUNCDEF) | |
+ { | |
+ char *x; | |
+ | |
+ /* If the command parses to something other than a straight | |
+ function definition, or if we have not consumed the entire | |
+ string, or if the parser has transformed the function | |
+ name (as parsing will if it begins or ends with shell | |
+ whitespace, for example), reject the attempt */ | |
+ if (command->type != cm_function_def || | |
+ ((x = parser_remaining_input ()) && *x) || | |
+ (STREQ (from_file, command->value.Function_def->name->word) == 0)) | |
+ { | |
+ internal_warning (_("%s: ignoring function definition attempt"), from_file); | |
+ should_jump_to_top_level = 0; | |
+ last_result = last_command_exit_value = EX_BADUSAGE; | |
+ reset_parser (); | |
+ break; | |
+ } | |
+ } | |
+ | |
bitmap = new_fd_bitmap (FD_BITMAP_SIZE); | |
begin_unwind_frame ("pe_dispose"); | |
add_unwind_protect (dispose_fd_bitmap, bitmap); | |
@@ -368,6 +389,12 @@ parse_and_execute (string, from_file, flags) | |
dispose_command (command); | |
dispose_fd_bitmap (bitmap); | |
discard_unwind_frame ("pe_dispose"); | |
+ | |
+ if (flags & SEVAL_ONECMD) | |
+ { | |
+ reset_parser (); | |
+ break; | |
+ } | |
} | |
} | |
else | |
diff --git a/builtins/read.def b/builtins/read.def | |
index 56945b9..56c2301 100644 | |
--- a/builtins/read.def | |
+++ b/builtins/read.def | |
@@ -140,10 +140,12 @@ static void reset_alarm __P((void)); | |
procenv_t alrmbuf; | |
int sigalrm_seen; | |
-static int reading; | |
+static int reading, tty_modified; | |
static SigHandler *old_alrm; | |
static unsigned char delim; | |
+static struct ttsave termsave; | |
+ | |
/* In all cases, SIGALRM just sets a flag that we check periodically. This | |
avoids problems with the semi-tricky stuff we do with the xfree of | |
input_string at the top of the unwind-protect list (see below). */ | |
@@ -188,7 +190,6 @@ read_builtin (list) | |
struct stat tsb; | |
SHELL_VAR *var; | |
TTYSTRUCT ttattrs, ttset; | |
- struct ttsave termsave; | |
#if defined (ARRAY_VARS) | |
WORD_LIST *alist; | |
#endif | |
@@ -221,7 +222,7 @@ read_builtin (list) | |
USE_VAR(ps2); | |
USE_VAR(lastsig); | |
- sigalrm_seen = reading = 0; | |
+ sigalrm_seen = reading = tty_modified = 0; | |
i = 0; /* Index into the string that we are reading. */ | |
raw = edit = 0; /* Not reading raw input by default. */ | |
@@ -438,11 +439,16 @@ read_builtin (list) | |
retval = 128+SIGALRM; | |
goto assign_vars; | |
} | |
+ if (interactive_shell == 0) | |
+ initialize_terminating_signals (); | |
old_alrm = set_signal_handler (SIGALRM, sigalrm); | |
add_unwind_protect (reset_alarm, (char *)NULL); | |
#if defined (READLINE) | |
if (edit) | |
- add_unwind_protect (reset_attempted_completion_function, (char *)NULL); | |
+ { | |
+ add_unwind_protect (reset_attempted_completion_function, (char *)NULL); | |
+ add_unwind_protect (bashline_reset_event_hook, (char *)NULL); | |
+ } | |
#endif | |
falarm (tmsec, tmusec); | |
} | |
@@ -479,7 +485,10 @@ read_builtin (list) | |
i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset); | |
if (i < 0) | |
sh_ttyerror (1); | |
+ tty_modified = 1; | |
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); | |
+ if (interactive_shell == 0) | |
+ initialize_terminating_signals (); | |
} | |
} | |
else if (silent) /* turn off echo but leave term in canonical mode */ | |
@@ -494,7 +503,10 @@ read_builtin (list) | |
if (i < 0) | |
sh_ttyerror (1); | |
+ tty_modified = 1; | |
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); | |
+ if (interactive_shell == 0) | |
+ initialize_terminating_signals (); | |
} | |
/* This *must* be the top unwind-protect on the stack, so the manipulation | |
@@ -585,6 +597,8 @@ read_builtin (list) | |
} | |
else | |
lastsig = 0; | |
+ if (terminating_signal && tty_modified) | |
+ ttyrestore (&termsave); /* fix terminal before exiting */ | |
CHECK_TERMSIG; | |
eof = 1; | |
break; | |
@@ -975,6 +989,20 @@ ttyrestore (ttp) | |
struct ttsave *ttp; | |
{ | |
ttsetattr (ttp->fd, ttp->attrs); | |
+ tty_modified = 0; | |
+} | |
+ | |
+void | |
+read_tty_cleanup () | |
+{ | |
+ if (tty_modified) | |
+ ttyrestore (&termsave); | |
+} | |
+ | |
+int | |
+read_tty_modified () | |
+{ | |
+ return (tty_modified); | |
} | |
#if defined (READLINE) | |
@@ -1021,6 +1049,7 @@ edit_line (p, itext) | |
old_attempted_completion_function = rl_attempted_completion_function; | |
rl_attempted_completion_function = (rl_completion_func_t *)NULL; | |
+ bashline_set_event_hook (); | |
if (itext) | |
{ | |
old_startup_hook = rl_startup_hook; | |
@@ -1032,6 +1061,7 @@ edit_line (p, itext) | |
rl_attempted_completion_function = old_attempted_completion_function; | |
old_attempted_completion_function = (rl_completion_func_t *)NULL; | |
+ bashline_reset_event_hook (); | |
if (ret == 0) | |
return ret; | |
diff --git a/builtins/set.def b/builtins/set.def | |
index c4a7001..9fbbca1 100644 | |
--- a/builtins/set.def | |
+++ b/builtins/set.def | |
@@ -751,9 +751,11 @@ unset_builtin (list) | |
WORD_LIST *list; | |
{ | |
int unset_function, unset_variable, unset_array, opt, nameref, any_failed; | |
+ int global_unset_func, global_unset_var; | |
char *name; | |
unset_function = unset_variable = unset_array = nameref = any_failed = 0; | |
+ global_unset_func = global_unset_var = 0; | |
reset_internal_getopt (); | |
while ((opt = internal_getopt (list, "fnv")) != -1) | |
@@ -761,10 +763,10 @@ unset_builtin (list) | |
switch (opt) | |
{ | |
case 'f': | |
- unset_function = 1; | |
+ global_unset_func = 1; | |
break; | |
case 'v': | |
- unset_variable = 1; | |
+ global_unset_var = 1; | |
break; | |
case 'n': | |
nameref = 1; | |
@@ -777,7 +779,7 @@ unset_builtin (list) | |
list = loptend; | |
- if (unset_function && unset_variable) | |
+ if (global_unset_func && global_unset_var) | |
{ | |
builtin_error (_("cannot simultaneously unset a function and a variable")); | |
return (EXECUTION_FAILURE); | |
@@ -795,6 +797,9 @@ unset_builtin (list) | |
name = list->word->word; | |
+ unset_function = global_unset_func; | |
+ unset_variable = global_unset_var; | |
+ | |
#if defined (ARRAY_VARS) | |
unset_array = 0; | |
if (!unset_function && valid_array_reference (name)) | |
diff --git a/copy_cmd.c b/copy_cmd.c | |
index 911d34f..826e0c3 100644 | |
--- a/copy_cmd.c | |
+++ b/copy_cmd.c | |
@@ -126,7 +126,7 @@ copy_redirect (redirect) | |
{ | |
case r_reading_until: | |
case r_deblank_reading_until: | |
- new_redirect->here_doc_eof = savestring (redirect->here_doc_eof); | |
+ new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0; | |
/*FALLTHROUGH*/ | |
case r_reading_string: | |
case r_appending_to: | |
diff --git a/execute_cmd.c b/execute_cmd.c | |
index f9a755d..9cebaef 100644 | |
--- a/execute_cmd.c | |
+++ b/execute_cmd.c | |
@@ -2409,7 +2409,16 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) | |
#endif | |
lstdin = wait_for (lastpid); | |
#if defined (JOB_CONTROL) | |
- exec_result = job_exit_status (lastpipe_jid); | |
+ /* If wait_for removes the job from the jobs table, use result of last | |
+ command as pipeline's exit status as usual. The jobs list can get | |
+ frozen and unfrozen at inconvenient times if there are multiple pipelines | |
+ running simultaneously. */ | |
+ if (INVALID_JOB (lastpipe_jid) == 0) | |
+ exec_result = job_exit_status (lastpipe_jid); | |
+ else if (pipefail_opt) | |
+ exec_result = exec_result | lstdin; /* XXX */ | |
+ /* otherwise we use exec_result */ | |
+ | |
#endif | |
unfreeze_jobs_list (); | |
} | |
diff --git a/externs.h b/externs.h | |
index 61fd0eb..8db43f2 100644 | |
--- a/externs.h | |
+++ b/externs.h | |
@@ -324,6 +324,7 @@ extern char *sh_un_double_quote __P((char *)); | |
extern char *sh_backslash_quote __P((char *, const char *, int)); | |
extern char *sh_backslash_quote_for_double_quotes __P((char *)); | |
extern int sh_contains_shell_metas __P((char *)); | |
+extern int sh_contains_quotes __P((char *)); | |
/* declarations for functions defined in lib/sh/spell.c */ | |
extern int spname __P((char *, char *)); | |
diff --git a/jobs.c b/jobs.c | |
index 2452779..b6e59eb 100644 | |
--- a/jobs.c | |
+++ b/jobs.c | |
@@ -3339,7 +3339,9 @@ itrace("waitchld: waitpid returns %d block = %d", pid, block); | |
if (posixly_correct && this_shell_builtin && this_shell_builtin == wait_builtin) | |
{ | |
interrupt_immediately = 0; | |
- trap_handler (SIGCHLD); /* set pending_traps[SIGCHLD] */ | |
+ /* This was trap_handler (SIGCHLD) but that can lose traps if | |
+ children_exited > 1 */ | |
+ queue_sigchld_trap (children_exited); | |
wait_signal_received = SIGCHLD; | |
/* If we're in a signal handler, let CHECK_WAIT_INTR pick it up; | |
run_pending_traps will call run_sigchld_trap later */ | |
@@ -3597,6 +3599,7 @@ run_sigchld_trap (nchild) | |
unwind_protect_int (jobs_list_frozen); | |
unwind_protect_pointer (the_pipeline); | |
unwind_protect_pointer (subst_assign_varlist); | |
+ unwind_protect_pointer (this_shell_builtin); | |
/* We have to add the commands this way because they will be run | |
in reverse order of adding. We don't want maybe_set_sigchld_trap () | |
@@ -4374,7 +4377,7 @@ without_job_control () | |
void | |
end_job_control () | |
{ | |
- if (interactive_shell) /* XXX - should it be interactive? */ | |
+ if (interactive_shell || job_control) /* XXX - should it be just job_control? */ | |
{ | |
terminate_stopped_jobs (); | |
diff --git a/lib/glob/glob.c b/lib/glob/glob.c | |
index f549436..ac59e8d 100644 | |
--- a/lib/glob/glob.c | |
+++ b/lib/glob/glob.c | |
@@ -123,6 +123,8 @@ static char **glob_dir_to_array __P((char *, char **, int)); | |
extern char *glob_patscan __P((char *, char *, int)); | |
extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); | |
+extern char *glob_dirscan __P((char *, int)); | |
+ | |
/* Compile `glob_loop.c' for single-byte characters. */ | |
#define CHAR unsigned char | |
#define INT int | |
@@ -179,42 +181,53 @@ extglob_skipname (pat, dname, flags) | |
char *pat, *dname; | |
int flags; | |
{ | |
- char *pp, *pe, *t; | |
- int n, r; | |
+ char *pp, *pe, *t, *se; | |
+ int n, r, negate; | |
+ negate = *pat == '!'; | |
pp = pat + 2; | |
- pe = pp + strlen (pp) - 1; /*(*/ | |
- if (*pe != ')') | |
+ se = pp + strlen (pp) - 1; /* end of string */ | |
+ pe = glob_patscan (pp, se, 0); /* end of extglob pattern (( */ | |
+ /* we should check for invalid extglob pattern here */ | |
+ if (pe == 0) | |
return 0; | |
- if ((t = strchr (pp, '|')) == 0) /* easy case first */ | |
+ | |
+ /* if pe != se we have more of the pattern at the end of the extglob | |
+ pattern. Check the easy case first ( */ | |
+ if (pe == se && *pe == ')' && (t = strchr (pp, '|')) == 0) | |
{ | |
*pe = '\0'; | |
+#if defined (HANDLE_MULTIBYTE) | |
+ r = mbskipname (pp, dname, flags); | |
+#else | |
r = skipname (pp, dname, flags); /*(*/ | |
+#endif | |
*pe = ')'; | |
return r; | |
} | |
+ | |
+ /* check every subpattern */ | |
while (t = glob_patscan (pp, pe, '|')) | |
{ | |
n = t[-1]; | |
t[-1] = '\0'; | |
+#if defined (HANDLE_MULTIBYTE) | |
+ r = mbskipname (pp, dname, flags); | |
+#else | |
r = skipname (pp, dname, flags); | |
+#endif | |
t[-1] = n; | |
if (r == 0) /* if any pattern says not skip, we don't skip */ | |
return r; | |
pp = t; | |
} /*(*/ | |
- if (pp == pe) /* glob_patscan might find end of pattern */ | |
+ /* glob_patscan might find end of pattern */ | |
+ if (pp == se) | |
return r; | |
- *pe = '\0'; | |
-# if defined (HANDLE_MULTIBYTE) | |
- r = mbskipname (pp, dname, flags); /*(*/ | |
-# else | |
- r = skipname (pp, dname, flags); /*(*/ | |
-# endif | |
- *pe = ')'; | |
- return r; | |
+ /* but if it doesn't then we didn't match a leading dot */ | |
+ return 0; | |
} | |
#endif | |
@@ -277,20 +290,23 @@ wextglob_skipname (pat, dname, flags) | |
int flags; | |
{ | |
#if EXTENDED_GLOB | |
- wchar_t *pp, *pe, *t, n; | |
- int r; | |
+ wchar_t *pp, *pe, *t, n, *se; | |
+ int r, negate; | |
+ negate = *pat == L'!'; | |
pp = pat + 2; | |
- pe = pp + wcslen (pp) - 1; /*(*/ | |
- if (*pe != L')') | |
- return 0; | |
- if ((t = wcschr (pp, L'|')) == 0) | |
+ se = pp + wcslen (pp) - 1; /*(*/ | |
+ pe = glob_patscan_wc (pp, se, 0); | |
+ | |
+ if (pe == se && *pe == ')' && (t = wcschr (pp, L'|')) == 0) | |
{ | |
*pe = L'\0'; | |
r = wchkname (pp, dname); /*(*/ | |
*pe = L')'; | |
return r; | |
} | |
+ | |
+ /* check every subpattern */ | |
while (t = glob_patscan_wc (pp, pe, '|')) | |
{ | |
n = t[-1]; | |
@@ -305,10 +321,8 @@ wextglob_skipname (pat, dname, flags) | |
if (pp == pe) /* glob_patscan_wc might find end of pattern */ | |
return r; | |
- *pe = L'\0'; | |
- r = wchkname (pp, dname); /*(*/ | |
- *pe = L')'; | |
- return r; | |
+ /* but if it doesn't then we didn't match a leading dot */ | |
+ return 0; | |
#else | |
return (wchkname (pat, dname)); | |
#endif | |
@@ -1006,7 +1020,7 @@ glob_filename (pathname, flags) | |
{ | |
char **result; | |
unsigned int result_size; | |
- char *directory_name, *filename, *dname; | |
+ char *directory_name, *filename, *dname, *fn; | |
unsigned int directory_len; | |
int free_dirname; /* flag */ | |
int dflags; | |
@@ -1022,6 +1036,18 @@ glob_filename (pathname, flags) | |
/* Find the filename. */ | |
filename = strrchr (pathname, '/'); | |
+#if defined (EXTENDED_GLOB) | |
+ if (filename && extended_glob) | |
+ { | |
+ fn = glob_dirscan (pathname, '/'); | |
+#if DEBUG_MATCHING | |
+ if (fn != filename) | |
+ fprintf (stderr, "glob_filename: glob_dirscan: fn (%s) != filename (%s)\n", fn ? fn : "(null)", filename); | |
+#endif | |
+ filename = fn; | |
+ } | |
+#endif | |
+ | |
if (filename == NULL) | |
{ | |
filename = pathname; | |
diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c | |
index 17e4265..96b1bc0 100644 | |
--- a/lib/glob/gmisc.c | |
+++ b/lib/glob/gmisc.c | |
@@ -42,6 +42,8 @@ | |
#define WLPAREN L'(' | |
#define WRPAREN L')' | |
+extern char *glob_patscan __P((char *, char *, int)); | |
+ | |
/* Return 1 of the first character of WSTRING could match the first | |
character of pattern WPAT. Wide character version. */ | |
int | |
@@ -210,6 +212,7 @@ extglob_pattern_p (pat) | |
case '+': | |
case '!': | |
case '@': | |
+ case '?': | |
return (pat[1] == LPAREN); | |
default: | |
return 0; | |
@@ -374,3 +377,34 @@ bad_bracket: | |
return matlen; | |
} | |
+ | |
+/* Skip characters in PAT and return the final occurrence of DIRSEP. This | |
+ is only called when extended_glob is set, so we have to skip over extglob | |
+ patterns x(...) */ | |
+char * | |
+glob_dirscan (pat, dirsep) | |
+ char *pat; | |
+ int dirsep; | |
+{ | |
+ char *p, *d, *pe, *se; | |
+ | |
+ d = pe = se = 0; | |
+ for (p = pat; p && *p; p++) | |
+ { | |
+ if (extglob_pattern_p (p)) | |
+ { | |
+ if (se == 0) | |
+ se = p + strlen (p) - 1; | |
+ pe = glob_patscan (p + 2, se, 0); | |
+ if (pe == 0) | |
+ continue; | |
+ else if (*pe == 0) | |
+ break; | |
+ p = pe - 1; /* will do increment above */ | |
+ continue; | |
+ } | |
+ if (*p == dirsep) | |
+ d = p; | |
+ } | |
+ return d; | |
+} | |
diff --git a/lib/readline/display.c b/lib/readline/display.c | |
index 913e0da..4df1f73 100644 | |
--- a/lib/readline/display.c | |
+++ b/lib/readline/display.c | |
@@ -1637,7 +1637,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) | |
/* If we are changing the number of invisible characters in a line, and | |
the spot of first difference is before the end of the invisible chars, | |
lendiff needs to be adjusted. */ | |
- if (current_line == 0 && !_rl_horizontal_scroll_mode && | |
+ if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */ | |
current_invis_chars != visible_wrap_offset) | |
{ | |
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) | |
@@ -1825,8 +1825,13 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) | |
else | |
_rl_last_c_pos += bytes_to_insert; | |
+ /* XXX - we only want to do this if we are at the end of the line | |
+ so we move there with _rl_move_cursor_relative */ | |
if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new))) | |
- goto clear_rest_of_line; | |
+ { | |
+ _rl_move_cursor_relative (ne-new, new); | |
+ goto clear_rest_of_line; | |
+ } | |
} | |
} | |
/* Otherwise, print over the existing material. */ | |
@@ -2677,7 +2682,8 @@ _rl_clean_up_for_exit () | |
{ | |
if (_rl_echoing_p) | |
{ | |
- _rl_move_vert (_rl_vis_botlin); | |
+ if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */ | |
+ _rl_move_vert (_rl_vis_botlin); | |
_rl_vis_botlin = 0; | |
fflush (rl_outstream); | |
rl_restart_output (1, 0); | |
diff --git a/lib/readline/input.c b/lib/readline/input.c | |
index 117dfe8..f3f6d59 100644 | |
--- a/lib/readline/input.c | |
+++ b/lib/readline/input.c | |
@@ -534,8 +534,16 @@ rl_getc (stream) | |
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); | |
else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM) | |
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); | |
+ /* keyboard-generated signals of interest */ | |
else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT) | |
RL_CHECK_SIGNALS (); | |
+ /* non-keyboard-generated signals of interest */ | |
+ else if (_rl_caught_signal == SIGALRM | |
+#if defined (SIGVTALRM) | |
+ || _rl_caught_signal == SIGVTALRM | |
+#endif | |
+ ) | |
+ RL_CHECK_SIGNALS (); | |
if (rl_signal_event_hook) | |
(*rl_signal_event_hook) (); | |
diff --git a/lib/readline/misc.c b/lib/readline/misc.c | |
index da5c696..a890cda 100644 | |
--- a/lib/readline/misc.c | |
+++ b/lib/readline/misc.c | |
@@ -461,6 +461,7 @@ _rl_revert_all_lines () | |
saved_undo_list = 0; | |
/* Set up rl_line_buffer and other variables from history entry */ | |
rl_replace_from_history (entry, 0); /* entry->line is now current */ | |
+ entry->data = 0; /* entry->data is now current undo list */ | |
/* Undo all changes to this history entry */ | |
while (rl_undo_list) | |
rl_do_undo (); | |
@@ -468,7 +469,6 @@ _rl_revert_all_lines () | |
the timestamp. */ | |
FREE (entry->line); | |
entry->line = savestring (rl_line_buffer); | |
- entry->data = 0; | |
} | |
entry = previous_history (); | |
} | |
diff --git a/lib/readline/readline.c b/lib/readline/readline.c | |
index 03eefa6..abb29a0 100644 | |
--- a/lib/readline/readline.c | |
+++ b/lib/readline/readline.c | |
@@ -744,7 +744,8 @@ _rl_dispatch_callback (cxt) | |
r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); | |
RL_CHECK_SIGNALS (); | |
- if (r == 0) /* success! */ | |
+ /* We only treat values < 0 specially to simulate recursion. */ | |
+ if (r >= 0 || (r == -1 && (cxt->flags & KSEQ_SUBSEQ) == 0)) /* success! or failure! */ | |
{ | |
_rl_keyseq_chain_dispose (); | |
RL_UNSETSTATE (RL_STATE_MULTIKEY); | |
@@ -964,7 +965,7 @@ _rl_dispatch_subseq (key, map, got_subseq) | |
#if defined (VI_MODE) | |
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && | |
key != ANYOTHERKEY && | |
- rl_key_sequence_length == 1 && /* XXX */ | |
+ _rl_dispatching_keymap == vi_movement_keymap && | |
_rl_vi_textmod_command (key)) | |
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); | |
#endif | |
diff --git a/lib/readline/readline.c.orig b/lib/readline/readline.c.orig | |
new file mode 100644 | |
index 0000000..55c0522 | |
--- /dev/null | |
+++ b/lib/readline/readline.c.orig | |
@@ -0,0 +1,1364 @@ | |
+/* readline.c -- a general facility for reading lines of input | |
+ with emacs style editing and completion. */ | |
+ | |
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc. | |
+ | |
+ This file is part of the GNU Readline Library (Readline), a library | |
+ for reading lines of text with interactive input and history editing. | |
+ | |
+ Readline is free software: you can redistribute it and/or modify | |
+ it under the terms of the GNU General Public License as published by | |
+ the Free Software Foundation, either version 3 of the License, or | |
+ (at your option) any later version. | |
+ | |
+ Readline is distributed in the hope that it will be useful, | |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ GNU General Public License for more details. | |
+ | |
+ You should have received a copy of the GNU General Public License | |
+ along with Readline. If not, see <http://www.gnu.org/licenses/>. | |
+*/ | |
+ | |
+#define READLINE_LIBRARY | |
+ | |
+#if defined (HAVE_CONFIG_H) | |
+# include <config.h> | |
+#endif | |
+ | |
+#include <sys/types.h> | |
+#include "posixstat.h" | |
+#include <fcntl.h> | |
+#if defined (HAVE_SYS_FILE_H) | |
+# include <sys/file.h> | |
+#endif /* HAVE_SYS_FILE_H */ | |
+ | |
+#if defined (HAVE_UNISTD_H) | |
+# include <unistd.h> | |
+#endif /* HAVE_UNISTD_H */ | |
+ | |
+#if defined (HAVE_STDLIB_H) | |
+# include <stdlib.h> | |
+#else | |
+# include "ansi_stdlib.h" | |
+#endif /* HAVE_STDLIB_H */ | |
+ | |
+#if defined (HAVE_LOCALE_H) | |
+# include <locale.h> | |
+#endif | |
+ | |
+#include <stdio.h> | |
+#include "posixjmp.h" | |
+#include <errno.h> | |
+ | |
+#if !defined (errno) | |
+extern int errno; | |
+#endif /* !errno */ | |
+ | |
+/* System-specific feature definitions and include files. */ | |
+#include "rldefs.h" | |
+#include "rlmbutil.h" | |
+ | |
+#if defined (__EMX__) | |
+# define INCL_DOSPROCESS | |
+# include <os2.h> | |
+#endif /* __EMX__ */ | |
+ | |
+/* Some standard library routines. */ | |
+#include "readline.h" | |
+#include "history.h" | |
+ | |
+#include "rlprivate.h" | |
+#include "rlshell.h" | |
+#include "xmalloc.h" | |
+ | |
+#ifndef RL_LIBRARY_VERSION | |
+# define RL_LIBRARY_VERSION "5.1" | |
+#endif | |
+ | |
+#ifndef RL_READLINE_VERSION | |
+# define RL_READLINE_VERSION 0x0501 | |
+#endif | |
+ | |
+extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); | |
+ | |
+#if defined (COLOR_SUPPORT) | |
+extern void _rl_parse_colors PARAMS((void)); /* XXX */ | |
+#endif | |
+ | |
+ | |
+/* Forward declarations used in this file. */ | |
+static char *readline_internal PARAMS((void)); | |
+static void readline_initialize_everything PARAMS((void)); | |
+ | |
+static void bind_arrow_keys_internal PARAMS((Keymap)); | |
+static void bind_arrow_keys PARAMS((void)); | |
+ | |
+static void readline_default_bindings PARAMS((void)); | |
+static void reset_default_bindings PARAMS((void)); | |
+ | |
+static int _rl_subseq_result PARAMS((int, Keymap, int, int)); | |
+static int _rl_subseq_getchar PARAMS((int)); | |
+ | |
+/* **************************************************************** */ | |
+/* */ | |
+/* Line editing input utility */ | |
+/* */ | |
+/* **************************************************************** */ | |
+ | |
+const char *rl_library_version = RL_LIBRARY_VERSION; | |
+ | |
+int rl_readline_version = RL_READLINE_VERSION; | |
+ | |
+/* True if this is `real' readline as opposed to some stub substitute. */ | |
+int rl_gnu_readline_p = 1; | |
+ | |
+/* A pointer to the keymap that is currently in use. | |
+ By default, it is the standard emacs keymap. */ | |
+Keymap _rl_keymap = emacs_standard_keymap; | |
+ | |
+/* The current style of editing. */ | |
+int rl_editing_mode = emacs_mode; | |
+ | |
+/* The current insert mode: input (the default) or overwrite */ | |
+int rl_insert_mode = RL_IM_DEFAULT; | |
+ | |
+/* Non-zero if we called this function from _rl_dispatch(). It's present | |
+ so functions can find out whether they were called from a key binding | |
+ or directly from an application. */ | |
+int rl_dispatching; | |
+ | |
+/* Non-zero if the previous command was a kill command. */ | |
+int _rl_last_command_was_kill = 0; | |
+ | |
+/* The current value of the numeric argument specified by the user. */ | |
+int rl_numeric_arg = 1; | |
+ | |
+/* Non-zero if an argument was typed. */ | |
+int rl_explicit_arg = 0; | |
+ | |
+/* Temporary value used while generating the argument. */ | |
+int rl_arg_sign = 1; | |
+ | |
+/* Non-zero means we have been called at least once before. */ | |
+static int rl_initialized; | |
+ | |
+#if 0 | |
+/* If non-zero, this program is running in an EMACS buffer. */ | |
+static int running_in_emacs; | |
+#endif | |
+ | |
+/* Flags word encapsulating the current readline state. */ | |
+int rl_readline_state = RL_STATE_NONE; | |
+ | |
+/* The current offset in the current input line. */ | |
+int rl_point; | |
+ | |
+/* Mark in the current input line. */ | |
+int rl_mark; | |
+ | |
+/* Length of the current input line. */ | |
+int rl_end; | |
+ | |
+/* Make this non-zero to return the current input_line. */ | |
+int rl_done; | |
+ | |
+/* The last function executed by readline. */ | |
+rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL; | |
+ | |
+/* Top level environment for readline_internal (). */ | |
+procenv_t _rl_top_level; | |
+ | |
+/* The streams we interact with. */ | |
+FILE *_rl_in_stream, *_rl_out_stream; | |
+ | |
+/* The names of the streams that we do input and output to. */ | |
+FILE *rl_instream = (FILE *)NULL; | |
+FILE *rl_outstream = (FILE *)NULL; | |
+ | |
+/* Non-zero means echo characters as they are read. Defaults to no echo; | |
+ set to 1 if there is a controlling terminal, we can get its attributes, | |
+ and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings | |
+ for the code that sets it. */ | |
+int _rl_echoing_p = 0; | |
+ | |
+/* Current prompt. */ | |
+char *rl_prompt = (char *)NULL; | |
+int rl_visible_prompt_length = 0; | |
+ | |
+/* Set to non-zero by calling application if it has already printed rl_prompt | |
+ and does not want readline to do it the first time. */ | |
+int rl_already_prompted = 0; | |
+ | |
+/* The number of characters read in order to type this complete command. */ | |
+int rl_key_sequence_length = 0; | |
+ | |
+/* If non-zero, then this is the address of a function to call just | |
+ before readline_internal_setup () prints the first prompt. */ | |
+rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL; | |
+ | |
+/* If non-zero, this is the address of a function to call just before | |
+ readline_internal_setup () returns and readline_internal starts | |
+ reading input characters. */ | |
+rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL; | |
+ | |
+/* What we use internally. You should always refer to RL_LINE_BUFFER. */ | |
+static char *the_line; | |
+ | |
+/* The character that can generate an EOF. Really read from | |
+ the terminal driver... just defaulted here. */ | |
+int _rl_eof_char = CTRL ('D'); | |
+ | |
+/* Non-zero makes this the next keystroke to read. */ | |
+int rl_pending_input = 0; | |
+ | |
+/* Pointer to a useful terminal name. */ | |
+const char *rl_terminal_name = (const char *)NULL; | |
+ | |
+/* Non-zero means to always use horizontal scrolling in line display. */ | |
+int _rl_horizontal_scroll_mode = 0; | |
+ | |
+/* Non-zero means to display an asterisk at the starts of history lines | |
+ which have been modified. */ | |
+int _rl_mark_modified_lines = 0; | |
+ | |
+/* The style of `bell' notification preferred. This can be set to NO_BELL, | |
+ AUDIBLE_BELL, or VISIBLE_BELL. */ | |
+int _rl_bell_preference = AUDIBLE_BELL; | |
+ | |
+/* String inserted into the line by rl_insert_comment (). */ | |
+char *_rl_comment_begin; | |
+ | |
+/* Keymap holding the function currently being executed. */ | |
+Keymap rl_executing_keymap; | |
+ | |
+/* Keymap we're currently using to dispatch. */ | |
+Keymap _rl_dispatching_keymap; | |
+ | |
+/* Non-zero means to erase entire line, including prompt, on empty input lines. */ | |
+int rl_erase_empty_line = 0; | |
+ | |
+/* Non-zero means to read only this many characters rather than up to a | |
+ character bound to accept-line. */ | |
+int rl_num_chars_to_read; | |
+ | |
+/* Line buffer and maintenance. */ | |
+char *rl_line_buffer = (char *)NULL; | |
+int rl_line_buffer_len = 0; | |
+ | |
+/* Key sequence `contexts' */ | |
+_rl_keyseq_cxt *_rl_kscxt = 0; | |
+ | |
+int rl_executing_key; | |
+char *rl_executing_keyseq = 0; | |
+int _rl_executing_keyseq_size = 0; | |
+ | |
+/* Timeout (specified in milliseconds) when reading characters making up an | |
+ ambiguous multiple-key sequence */ | |
+int _rl_keyseq_timeout = 500; | |
+ | |
+#define RESIZE_KEYSEQ_BUFFER() \ | |
+ do \ | |
+ { \ | |
+ if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \ | |
+ { \ | |
+ _rl_executing_keyseq_size += 16; \ | |
+ rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \ | |
+ } \ | |
+ } \ | |
+ while (0); | |
+ | |
+/* Forward declarations used by the display, termcap, and history code. */ | |
+ | |
+/* **************************************************************** */ | |
+/* */ | |
+/* `Forward' declarations */ | |
+/* */ | |
+/* **************************************************************** */ | |
+ | |
+/* Non-zero means do not parse any lines other than comments and | |
+ parser directives. */ | |
+unsigned char _rl_parsing_conditionalized_out = 0; | |
+ | |
+/* Non-zero means to convert characters with the meta bit set to | |
+ escape-prefixed characters so we can indirect through | |
+ emacs_meta_keymap or vi_escape_keymap. */ | |
+int _rl_convert_meta_chars_to_ascii = 1; | |
+ | |
+/* Non-zero means to output characters with the meta bit set directly | |
+ rather than as a meta-prefixed escape sequence. */ | |
+int _rl_output_meta_chars = 0; | |
+ | |
+/* Non-zero means to look at the termios special characters and bind | |
+ them to equivalent readline functions at startup. */ | |
+int _rl_bind_stty_chars = 1; | |
+ | |
+/* Non-zero means to go through the history list at every newline (or | |
+ whenever rl_done is set and readline returns) and revert each line to | |
+ its initial state. */ | |
+int _rl_revert_all_at_newline = 0; | |
+ | |
+/* Non-zero means to honor the termios ECHOCTL bit and echo control | |
+ characters corresponding to keyboard-generated signals. */ | |
+int _rl_echo_control_chars = 1; | |
+ | |
+/* Non-zero means to prefix the displayed prompt with a character indicating | |
+ the editing mode: @ for emacs, : for vi-command, + for vi-insert. */ | |
+int _rl_show_mode_in_prompt = 0; | |
+ | |
+/* **************************************************************** */ | |
+/* */ | |
+/* Top Level Functions */ | |
+/* */ | |
+/* **************************************************************** */ | |
+ | |
+/* Non-zero means treat 0200 bit in terminal input as Meta bit. */ | |
+int _rl_meta_flag = 0; /* Forward declaration */ | |
+ | |
+/* Set up the prompt and expand it. Called from readline() and | |
+ rl_callback_handler_install (). */ | |
+int | |
+rl_set_prompt (prompt) | |
+ const char *prompt; | |
+{ | |
+ FREE (rl_prompt); | |
+ rl_prompt = prompt ? savestring (prompt) : (char *)NULL; | |
+ rl_display_prompt = rl_prompt ? rl_prompt : ""; | |
+ | |
+ rl_visible_prompt_length = rl_expand_prompt (rl_prompt); | |
+ return 0; | |
+} | |
+ | |
+/* Read a line of input. Prompt with PROMPT. An empty PROMPT means | |
+ none. A return value of NULL means that EOF was encountered. */ | |
+char * | |
+readline (prompt) | |
+ const char *prompt; | |
+{ | |
+ char *value; | |
+#if 0 | |
+ int in_callback; | |
+#endif | |
+ | |
+ /* If we are at EOF return a NULL string. */ | |
+ if (rl_pending_input == EOF) | |
+ { | |
+ rl_clear_pending_input (); | |
+ return ((char *)NULL); | |
+ } | |
+ | |
+#if 0 | |
+ /* If readline() is called after installing a callback handler, temporarily | |
+ turn off the callback state to avoid ensuing messiness. Patch supplied | |
+ by the gdb folks. XXX -- disabled. This can be fooled and readline | |
+ left in a strange state by a poorly-timed longjmp. */ | |
+ if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK)) | |
+ RL_UNSETSTATE (RL_STATE_CALLBACK); | |
+#endif | |
+ | |
+ rl_set_prompt (prompt); | |
+ | |
+ rl_initialize (); | |
+ if (rl_prep_term_function) | |
+ (*rl_prep_term_function) (_rl_meta_flag); | |
+ | |
+#if defined (HANDLE_SIGNALS) | |
+ rl_set_signals (); | |
+#endif | |
+ | |
+ value = readline_internal (); | |
+ if (rl_deprep_term_function) | |
+ (*rl_deprep_term_function) (); | |
+ | |
+#if defined (HANDLE_SIGNALS) | |
+ rl_clear_signals (); | |
+#endif | |
+ | |
+#if 0 | |
+ if (in_callback) | |
+ RL_SETSTATE (RL_STATE_CALLBACK); | |
+#endif | |
+ | |
+#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT) | |
+ if (value) | |
+ _rl_audit_tty (value); | |
+#endif | |
+ | |
+ return (value); | |
+} | |
+ | |
+#if defined (READLINE_CALLBACKS) | |
+# define STATIC_CALLBACK | |
+#else | |
+# define STATIC_CALLBACK static | |
+#endif | |
+ | |
+STATIC_CALLBACK void | |
+readline_internal_setup () | |
+{ | |
+ char *nprompt; | |
+ | |
+ _rl_in_stream = rl_instream; | |
+ _rl_out_stream = rl_outstream; | |
+ | |
+ /* Enable the meta key only for the duration of readline(), if this | |
+ terminal has one and the terminal has been initialized */ | |
+ if (_rl_enable_meta & RL_ISSTATE (RL_STATE_TERMPREPPED)) | |
+ _rl_enable_meta_key (); | |
+ | |
+ if (rl_startup_hook) | |
+ (*rl_startup_hook) (); | |
+ | |
+#if defined (VI_MODE) | |
+ if (rl_editing_mode == vi_mode) | |
+ rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */ | |
+#endif /* VI_MODE */ | |
+ | |
+ /* If we're not echoing, we still want to at least print a prompt, because | |
+ rl_redisplay will not do it for us. If the calling application has a | |
+ custom redisplay function, though, let that function handle it. */ | |
+ if (_rl_echoing_p == 0 && rl_redisplay_function == rl_redisplay) | |
+ { | |
+ if (rl_prompt && rl_already_prompted == 0) | |
+ { | |
+ nprompt = _rl_strip_prompt (rl_prompt); | |
+ fprintf (_rl_out_stream, "%s", nprompt); | |
+ fflush (_rl_out_stream); | |
+ xfree (nprompt); | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if (rl_prompt && rl_already_prompted) | |
+ rl_on_new_line_with_prompt (); | |
+ else | |
+ rl_on_new_line (); | |
+ (*rl_redisplay_function) (); | |
+ } | |
+ | |
+ if (rl_pre_input_hook) | |
+ (*rl_pre_input_hook) (); | |
+ | |
+ RL_CHECK_SIGNALS (); | |
+} | |
+ | |
+STATIC_CALLBACK char * | |
+readline_internal_teardown (eof) | |
+ int eof; | |
+{ | |
+ char *temp; | |
+ HIST_ENTRY *entry; | |
+ | |
+ RL_CHECK_SIGNALS (); | |
+ | |
+ /* Restore the original of this history line, iff the line that we | |
+ are editing was originally in the history, AND the line has changed. */ | |
+ entry = current_history (); | |
+ | |
+ if (entry && rl_undo_list) | |
+ { | |
+ temp = savestring (the_line); | |
+ rl_revert_line (1, 0); | |
+ entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL); | |
+ _rl_free_history_entry (entry); | |
+ | |
+ strcpy (the_line, temp); | |
+ xfree (temp); | |
+ } | |
+ | |
+ if (_rl_revert_all_at_newline) | |
+ _rl_revert_all_lines (); | |
+ | |
+ /* At any rate, it is highly likely that this line has an undo list. Get | |
+ rid of it now. */ | |
+ if (rl_undo_list) | |
+ rl_free_undo_list (); | |
+ | |
+ /* Disable the meta key, if this terminal has one and we were told to use it. | |
+ The check whether or not we sent the enable string is in | |
+ _rl_disable_meta_key(); the flag is set in _rl_enable_meta_key */ | |
+ _rl_disable_meta_key (); | |
+ | |
+ /* Restore normal cursor, if available. */ | |
+ _rl_set_insert_mode (RL_IM_INSERT, 0); | |
+ | |
+ return (eof ? (char *)NULL : savestring (the_line)); | |
+} | |
+ | |
+void | |
+_rl_internal_char_cleanup () | |
+{ | |
+#if defined (VI_MODE) | |
+ /* In vi mode, when you exit insert mode, the cursor moves back | |
+ over the previous character. We explicitly check for that here. */ | |
+ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) | |
+ rl_vi_check (); | |
+#endif /* VI_MODE */ | |
+ | |
+ if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) | |
+ { | |
+ (*rl_redisplay_function) (); | |
+ _rl_want_redisplay = 0; | |
+ rl_newline (1, '\n'); | |
+ } | |
+ | |
+ if (rl_done == 0) | |
+ { | |
+ (*rl_redisplay_function) (); | |
+ _rl_want_redisplay = 0; | |
+ } | |
+ | |
+ /* If the application writer has told us to erase the entire line if | |
+ the only character typed was something bound to rl_newline, do so. */ | |
+ if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && | |
+ rl_point == 0 && rl_end == 0) | |
+ _rl_erase_entire_line (); | |
+} | |
+ | |
+STATIC_CALLBACK int | |
+#if defined (READLINE_CALLBACKS) | |
+readline_internal_char () | |
+#else | |
+readline_internal_charloop () | |
+#endif | |
+{ | |
+ static int lastc, eof_found; | |
+ int c, code, lk; | |
+ | |
+ lastc = -1; | |
+ eof_found = 0; | |
+ | |
+#if !defined (READLINE_CALLBACKS) | |
+ while (rl_done == 0) | |
+ { | |
+#endif | |
+ lk = _rl_last_command_was_kill; | |
+ | |
+#if defined (HAVE_POSIX_SIGSETJMP) | |
+ code = sigsetjmp (_rl_top_level, 0); | |
+#else | |
+ code = setjmp (_rl_top_level); | |
+#endif | |
+ | |
+ if (code) | |
+ { | |
+ (*rl_redisplay_function) (); | |
+ _rl_want_redisplay = 0; | |
+ /* If we get here, we're not being called from something dispatched | |
+ from _rl_callback_read_char(), which sets up its own value of | |
+ _rl_top_level (saving and restoring the old, of course), so | |
+ we can just return here. */ | |
+ if (RL_ISSTATE (RL_STATE_CALLBACK)) | |
+ return (0); | |
+ } | |
+ | |
+ if (rl_pending_input == 0) | |
+ { | |
+ /* Then initialize the argument and number of keys read. */ | |
+ _rl_reset_argument (); | |
+ rl_key_sequence_length = 0; | |
+ rl_executing_keyseq[0] = 0; | |
+ } | |
+ | |
+ RL_SETSTATE(RL_STATE_READCMD); | |
+ c = rl_read_key (); | |
+ RL_UNSETSTATE(RL_STATE_READCMD); | |
+ | |
+ /* look at input.c:rl_getc() for the circumstances under which this will | |
+ be returned; punt immediately on read error without converting it to | |
+ a newline; assume that rl_read_key has already called the signal | |
+ handler. */ | |
+ if (c == READERR) | |
+ { | |
+#if defined (READLINE_CALLBACKS) | |
+ RL_SETSTATE(RL_STATE_DONE); | |
+ return (rl_done = 1); | |
+#else | |
+ eof_found = 1; | |
+ break; | |
+#endif | |
+ } | |
+ | |
+ /* EOF typed to a non-blank line is a <NL>. If we want to change this, | |
+ to force any existing line to be ignored when read(2) reads EOF, | |
+ for example, this is the place to change. */ | |
+ if (c == EOF && rl_end) | |
+ c = NEWLINE; | |
+ | |
+ /* The character _rl_eof_char typed to blank line, and not as the | |
+ previous character is interpreted as EOF. */ | |
+ if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) | |
+ { | |
+#if defined (READLINE_CALLBACKS) | |
+ RL_SETSTATE(RL_STATE_DONE); | |
+ return (rl_done = 1); | |
+#else | |
+ eof_found = 1; | |
+ break; | |
+#endif | |
+ } | |
+ | |
+ lastc = c; | |
+ _rl_dispatch ((unsigned char)c, _rl_keymap); | |
+ RL_CHECK_SIGNALS (); | |
+ | |
+ /* If there was no change in _rl_last_command_was_kill, then no kill | |
+ has taken place. Note that if input is pending we are reading | |
+ a prefix command, so nothing has changed yet. */ | |
+ if (rl_pending_input == 0 && lk == _rl_last_command_was_kill) | |
+ _rl_last_command_was_kill = 0; | |
+ | |
+ _rl_internal_char_cleanup (); | |
+ | |
+#if defined (READLINE_CALLBACKS) | |
+ return 0; | |
+#else | |
+ } | |
+ | |
+ return (eof_found); | |
+#endif | |
+} | |
+ | |
+#if defined (READLINE_CALLBACKS) | |
+static int | |
+readline_internal_charloop () | |
+{ | |
+ int eof = 1; | |
+ | |
+ while (rl_done == 0) | |
+ eof = readline_internal_char (); | |
+ return (eof); | |
+} | |
+#endif /* READLINE_CALLBACKS */ | |
+ | |
+/* Read a line of input from the global rl_instream, doing output on | |
+ the global rl_outstream. | |
+ If rl_prompt is non-null, then that is our prompt. */ | |
+static char * | |
+readline_internal () | |
+{ | |
+ int eof; | |
+ | |
+ readline_internal_setup (); | |
+ eof = readline_internal_charloop (); | |
+ return (readline_internal_teardown (eof)); | |
+} | |
+ | |
+void | |
+_rl_init_line_state () | |
+{ | |
+ rl_point = rl_end = rl_mark = 0; | |
+ the_line = rl_line_buffer; | |
+ the_line[0] = 0; | |
+} | |
+ | |
+void | |
+_rl_set_the_line () | |
+{ | |
+ the_line = rl_line_buffer; | |
+} | |
+ | |
+#if defined (READLINE_CALLBACKS) | |
+_rl_keyseq_cxt * | |
+_rl_keyseq_cxt_alloc () | |
+{ | |
+ _rl_keyseq_cxt *cxt; | |
+ | |
+ cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt)); | |
+ | |
+ cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0; | |
+ | |
+ cxt->okey = 0; | |
+ cxt->ocxt = _rl_kscxt; | |
+ cxt->childval = 42; /* sentinel value */ | |
+ | |
+ return cxt; | |
+} | |
+ | |
+void | |
+_rl_keyseq_cxt_dispose (cxt) | |
+ _rl_keyseq_cxt *cxt; | |
+{ | |
+ xfree (cxt); | |
+} | |
+ | |
+void | |
+_rl_keyseq_chain_dispose () | |
+{ | |
+ _rl_keyseq_cxt *cxt; | |
+ | |
+ while (_rl_kscxt) | |
+ { | |
+ cxt = _rl_kscxt; | |
+ _rl_kscxt = _rl_kscxt->ocxt; | |
+ _rl_keyseq_cxt_dispose (cxt); | |
+ } | |
+} | |
+#endif | |
+ | |
+static int | |
+_rl_subseq_getchar (key) | |
+ int key; | |
+{ | |
+ int k; | |
+ | |
+ if (key == ESC) | |
+ RL_SETSTATE(RL_STATE_METANEXT); | |
+ RL_SETSTATE(RL_STATE_MOREINPUT); | |
+ k = rl_read_key (); | |
+ RL_UNSETSTATE(RL_STATE_MOREINPUT); | |
+ if (key == ESC) | |
+ RL_UNSETSTATE(RL_STATE_METANEXT); | |
+ | |
+ return k; | |
+} | |
+ | |
+#if defined (READLINE_CALLBACKS) | |
+int | |
+_rl_dispatch_callback (cxt) | |
+ _rl_keyseq_cxt *cxt; | |
+{ | |
+ int nkey, r; | |
+ | |
+ /* For now */ | |
+ /* The first time this context is used, we want to read input and dispatch | |
+ on it. When traversing the chain of contexts back `up', we want to use | |
+ the value from the next context down. We're simulating recursion using | |
+ a chain of contexts. */ | |
+ if ((cxt->flags & KSEQ_DISPATCHED) == 0) | |
+ { | |
+ nkey = _rl_subseq_getchar (cxt->okey); | |
+ if (nkey < 0) | |
+ { | |
+ _rl_abort_internal (); | |
+ return -1; | |
+ } | |
+ r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); | |
+ cxt->flags |= KSEQ_DISPATCHED; | |
+ } | |
+ else | |
+ r = cxt->childval; | |
+ | |
+ /* For now */ | |
+ if (r != -3) /* don't do this if we indicate there will be other matches */ | |
+ r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); | |
+ | |
+ RL_CHECK_SIGNALS (); | |
+ /* We only treat values < 0 specially to simulate recursion. */ | |
+ if (r >= 0 || (r == -1 && (cxt->flags & KSEQ_SUBSEQ) == 0)) /* success! or failure! */ | |
+ { | |
+ _rl_keyseq_chain_dispose (); | |
+ RL_UNSETSTATE (RL_STATE_MULTIKEY); | |
+ return r; | |
+ } | |
+ | |
+ if (r != -3) /* magic value that says we added to the chain */ | |
+ _rl_kscxt = cxt->ocxt; | |
+ if (_rl_kscxt) | |
+ _rl_kscxt->childval = r; | |
+ if (r != -3) | |
+ _rl_keyseq_cxt_dispose (cxt); | |
+ | |
+ return r; | |
+} | |
+#endif /* READLINE_CALLBACKS */ | |
+ | |
+/* Do the command associated with KEY in MAP. | |
+ If the associated command is really a keymap, then read | |
+ another key, and dispatch into that map. */ | |
+int | |
+_rl_dispatch (key, map) | |
+ register int key; | |
+ Keymap map; | |
+{ | |
+ _rl_dispatching_keymap = map; | |
+ return _rl_dispatch_subseq (key, map, 0); | |
+} | |
+ | |
+int | |
+_rl_dispatch_subseq (key, map, got_subseq) | |
+ register int key; | |
+ Keymap map; | |
+ int got_subseq; | |
+{ | |
+ int r, newkey; | |
+ char *macro; | |
+ rl_command_func_t *func; | |
+#if defined (READLINE_CALLBACKS) | |
+ _rl_keyseq_cxt *cxt; | |
+#endif | |
+ | |
+ if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) | |
+ { | |
+ if (map[ESC].type == ISKMAP) | |
+ { | |
+ if (RL_ISSTATE (RL_STATE_MACRODEF)) | |
+ _rl_add_macro_char (ESC); | |
+ RESIZE_KEYSEQ_BUFFER (); | |
+ rl_executing_keyseq[rl_key_sequence_length++] = ESC; | |
+ map = FUNCTION_TO_KEYMAP (map, ESC); | |
+ key = UNMETA (key); | |
+ return (_rl_dispatch (key, map)); | |
+ } | |
+ else | |
+ rl_ding (); | |
+ return 0; | |
+ } | |
+ | |
+ if (RL_ISSTATE (RL_STATE_MACRODEF)) | |
+ _rl_add_macro_char (key); | |
+ | |
+ r = 0; | |
+ switch (map[key].type) | |
+ { | |
+ case ISFUNC: | |
+ func = map[key].function; | |
+ if (func) | |
+ { | |
+ /* Special case rl_do_lowercase_version (). */ | |
+ if (func == rl_do_lowercase_version) | |
+ /* Should we do anything special if key == ANYOTHERKEY? */ | |
+ return (_rl_dispatch (_rl_to_lower (key), map)); | |
+ | |
+ rl_executing_keymap = map; | |
+ rl_executing_key = key; | |
+ | |
+ RESIZE_KEYSEQ_BUFFER(); | |
+ rl_executing_keyseq[rl_key_sequence_length++] = key; | |
+ rl_executing_keyseq[rl_key_sequence_length] = '\0'; | |
+ | |
+ rl_dispatching = 1; | |
+ RL_SETSTATE(RL_STATE_DISPATCHING); | |
+ r = (*func) (rl_numeric_arg * rl_arg_sign, key); | |
+ RL_UNSETSTATE(RL_STATE_DISPATCHING); | |
+ rl_dispatching = 0; | |
+ | |
+ /* If we have input pending, then the last command was a prefix | |
+ command. Don't change the state of rl_last_func. Otherwise, | |
+ remember the last command executed in this variable. */ | |
+ if (rl_pending_input == 0 && map[key].function != rl_digit_argument) | |
+ rl_last_func = map[key].function; | |
+ | |
+ RL_CHECK_SIGNALS (); | |
+ } | |
+ else if (map[ANYOTHERKEY].function) | |
+ { | |
+ /* OK, there's no function bound in this map, but there is a | |
+ shadow function that was overridden when the current keymap | |
+ was created. Return -2 to note that. */ | |
+ if (RL_ISSTATE (RL_STATE_MACROINPUT)) | |
+ _rl_prev_macro_key (); | |
+ else | |
+ _rl_unget_char (key); | |
+ return -2; | |
+ } | |
+ else if (got_subseq) | |
+ { | |
+ /* Return -1 to note that we're in a subsequence, but we don't | |
+ have a matching key, nor was one overridden. This means | |
+ we need to back up the recursion chain and find the last | |
+ subsequence that is bound to a function. */ | |
+ if (RL_ISSTATE (RL_STATE_MACROINPUT)) | |
+ _rl_prev_macro_key (); | |
+ else | |
+ _rl_unget_char (key); | |
+ return -1; | |
+ } | |
+ else | |
+ { | |
+#if defined (READLINE_CALLBACKS) | |
+ RL_UNSETSTATE (RL_STATE_MULTIKEY); | |
+ _rl_keyseq_chain_dispose (); | |
+#endif | |
+ _rl_abort_internal (); | |
+ return -1; | |
+ } | |
+ break; | |
+ | |
+ case ISKMAP: | |
+ if (map[key].function != 0) | |
+ { | |
+#if defined (VI_MODE) | |
+ /* The only way this test will be true is if a subsequence has been | |
+ bound starting with ESC, generally the arrow keys. What we do is | |
+ check whether there's input in the queue, which there generally | |
+ will be if an arrow key has been pressed, and, if there's not, | |
+ just dispatch to (what we assume is) rl_vi_movement_mode right | |
+ away. This is essentially an input test with a zero timeout (by | |
+ default) or a timeout determined by the value of `keyseq-timeout' */ | |
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued | |
+ takes microseconds, so multiply by 1000 */ | |
+ if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap | |
+ && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0) | |
+ return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); | |
+#endif | |
+ | |
+ RESIZE_KEYSEQ_BUFFER (); | |
+ rl_executing_keyseq[rl_key_sequence_length++] = key; | |
+ _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key); | |
+ | |
+ /* Allocate new context here. Use linked contexts (linked through | |
+ cxt->ocxt) to simulate recursion */ | |
+#if defined (READLINE_CALLBACKS) | |
+ if (RL_ISSTATE (RL_STATE_CALLBACK)) | |
+ { | |
+ /* Return 0 only the first time, to indicate success to | |
+ _rl_callback_read_char. The rest of the time, we're called | |
+ from _rl_dispatch_callback, so we return -3 to indicate | |
+ special handling is necessary. */ | |
+ r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0; | |
+ cxt = _rl_keyseq_cxt_alloc (); | |
+ | |
+ if (got_subseq) | |
+ cxt->flags |= KSEQ_SUBSEQ; | |
+ cxt->okey = key; | |
+ cxt->oldmap = map; | |
+ cxt->dmap = _rl_dispatching_keymap; | |
+ cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function; | |
+ | |
+ RL_SETSTATE (RL_STATE_MULTIKEY); | |
+ _rl_kscxt = cxt; | |
+ | |
+ return r; /* don't indicate immediate success */ | |
+ } | |
+#endif | |
+ | |
+ /* Tentative inter-character timeout for potential multi-key | |
+ sequences? If no input within timeout, abort sequence and | |
+ act as if we got non-matching input. */ | |
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued | |
+ takes microseconds, so multiply by 1000 */ | |
+ if (_rl_keyseq_timeout > 0 && | |
+ (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) && | |
+ _rl_pushed_input_available () == 0 && | |
+ _rl_dispatching_keymap[ANYOTHERKEY].function && | |
+ _rl_input_queued (_rl_keyseq_timeout*1000) == 0) | |
+ return (_rl_subseq_result (-2, map, key, got_subseq)); | |
+ | |
+ newkey = _rl_subseq_getchar (key); | |
+ if (newkey < 0) | |
+ { | |
+ _rl_abort_internal (); | |
+ return -1; | |
+ } | |
+ | |
+ r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function); | |
+ return _rl_subseq_result (r, map, key, got_subseq); | |
+ } | |
+ else | |
+ { | |
+ _rl_abort_internal (); | |
+ return -1; | |
+ } | |
+ break; | |
+ | |
+ case ISMACR: | |
+ if (map[key].function != 0) | |
+ { | |
+ rl_executing_keyseq[rl_key_sequence_length] = '\0'; | |
+ macro = savestring ((char *)map[key].function); | |
+ _rl_with_macro_input (macro); | |
+ return 0; | |
+ } | |
+ break; | |
+ } | |
+#if defined (VI_MODE) | |
+ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && | |
+ key != ANYOTHERKEY && | |
+ rl_key_sequence_length == 1 && /* XXX */ | |
+ _rl_vi_textmod_command (key)) | |
+ _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); | |
+#endif | |
+ | |
+ return (r); | |
+} | |
+ | |
+static int | |
+_rl_subseq_result (r, map, key, got_subseq) | |
+ int r; | |
+ Keymap map; | |
+ int key, got_subseq; | |
+{ | |
+ Keymap m; | |
+ int type, nt; | |
+ rl_command_func_t *func, *nf; | |
+ | |
+ if (r == -2) | |
+ /* We didn't match anything, and the keymap we're indexed into | |
+ shadowed a function previously bound to that prefix. Call | |
+ the function. The recursive call to _rl_dispatch_subseq has | |
+ already taken care of pushing any necessary input back onto | |
+ the input queue with _rl_unget_char. */ | |
+ { | |
+ m = _rl_dispatching_keymap; | |
+ type = m[ANYOTHERKEY].type; | |
+ func = m[ANYOTHERKEY].function; | |
+ if (type == ISFUNC && func == rl_do_lowercase_version) | |
+ r = _rl_dispatch (_rl_to_lower (key), map); | |
+ else if (type == ISFUNC && func == rl_insert) | |
+ { | |
+ /* If the function that was shadowed was self-insert, we | |
+ somehow need a keymap with map[key].func == self-insert. | |
+ Let's use this one. */ | |
+ nt = m[key].type; | |
+ nf = m[key].function; | |
+ | |
+ m[key].type = type; | |
+ m[key].function = func; | |
+ r = _rl_dispatch (key, m); | |
+ m[key].type = nt; | |
+ m[key].function = nf; | |
+ } | |
+ else | |
+ r = _rl_dispatch (ANYOTHERKEY, m); | |
+ } | |
+ else if (r && map[ANYOTHERKEY].function) | |
+ { | |
+ /* We didn't match (r is probably -1), so return something to | |
+ tell the caller that it should try ANYOTHERKEY for an | |
+ overridden function. */ | |
+ if (RL_ISSTATE (RL_STATE_MACROINPUT)) | |
+ _rl_prev_macro_key (); | |
+ else | |
+ _rl_unget_char (key); | |
+ _rl_dispatching_keymap = map; | |
+ return -2; | |
+ } | |
+ else if (r && got_subseq) | |
+ { | |
+ /* OK, back up the chain. */ | |
+ if (RL_ISSTATE (RL_STATE_MACROINPUT)) | |
+ _rl_prev_macro_key (); | |
+ else | |
+ _rl_unget_char (key); | |
+ _rl_dispatching_keymap = map; | |
+ return -1; | |
+ } | |
+ | |
+ return r; | |
+} | |
+ | |
+/* **************************************************************** */ | |
+/* */ | |
+/* Initializations */ | |
+/* */ | |
+/* **************************************************************** */ | |
+ | |
+/* Initialize readline (and terminal if not already). */ | |
+int | |
+rl_initialize () | |
+{ | |
+ /* If we have never been called before, initialize the | |
+ terminal and data structures. */ | |
+ if (!rl_initialized) | |
+ { | |
+ RL_SETSTATE(RL_STATE_INITIALIZING); | |
+ readline_initialize_everything (); | |
+ RL_UNSETSTATE(RL_STATE_INITIALIZING); | |
+ rl_initialized++; | |
+ RL_SETSTATE(RL_STATE_INITIALIZED); | |
+ } | |
+ | |
+ /* Initialize the current line information. */ | |
+ _rl_init_line_state (); | |
+ | |
+ /* We aren't done yet. We haven't even gotten started yet! */ | |
+ rl_done = 0; | |
+ RL_UNSETSTATE(RL_STATE_DONE); | |
+ | |
+ /* Tell the history routines what is going on. */ | |
+ _rl_start_using_history (); | |
+ | |
+ /* Make the display buffer match the state of the line. */ | |
+ rl_reset_line_state (); | |
+ | |
+ /* No such function typed yet. */ | |
+ rl_last_func = (rl_command_func_t *)NULL; | |
+ | |
+ /* Parsing of key-bindings begins in an enabled state. */ | |
+ _rl_parsing_conditionalized_out = 0; | |
+ | |
+#if defined (VI_MODE) | |
+ if (rl_editing_mode == vi_mode) | |
+ _rl_vi_initialize_line (); | |
+#endif | |
+ | |
+ /* Each line starts in insert mode (the default). */ | |
+ _rl_set_insert_mode (RL_IM_DEFAULT, 1); | |
+ | |
+ return 0; | |
+} | |
+ | |
+#if 0 | |
+#if defined (__EMX__) | |
+static void | |
+_emx_build_environ () | |
+{ | |
+ TIB *tibp; | |
+ PIB *pibp; | |
+ char *t, **tp; | |
+ int c; | |
+ | |
+ DosGetInfoBlocks (&tibp, &pibp); | |
+ t = pibp->pib_pchenv; | |
+ for (c = 1; *t; c++) | |
+ t += strlen (t) + 1; | |
+ tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *)); | |
+ t = pibp->pib_pchenv; | |
+ while (*t) | |
+ { | |
+ *tp++ = t; | |
+ t += strlen (t) + 1; | |
+ } | |
+ *tp = 0; | |
+} | |
+#endif /* __EMX__ */ | |
+#endif | |
+ | |
+/* Initialize the entire state of the world. */ | |
+static void | |
+readline_initialize_everything () | |
+{ | |
+#if 0 | |
+#if defined (__EMX__) | |
+ if (environ == 0) | |
+ _emx_build_environ (); | |
+#endif | |
+#endif | |
+ | |
+#if 0 | |
+ /* Find out if we are running in Emacs -- UNUSED. */ | |
+ running_in_emacs = sh_get_env_value ("EMACS") != (char *)0; | |
+#endif | |
+ | |
+ /* Set up input and output if they are not already set up. */ | |
+ if (!rl_instream) | |
+ rl_instream = stdin; | |
+ | |
+ if (!rl_outstream) | |
+ rl_outstream = stdout; | |
+ | |
+ /* Bind _rl_in_stream and _rl_out_stream immediately. These values | |
+ may change, but they may also be used before readline_internal () | |
+ is called. */ | |
+ _rl_in_stream = rl_instream; | |
+ _rl_out_stream = rl_outstream; | |
+ | |
+ /* Allocate data structures. */ | |
+ if (rl_line_buffer == 0) | |
+ rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); | |
+ | |
+ /* Initialize the terminal interface. */ | |
+ if (rl_terminal_name == 0) | |
+ rl_terminal_name = sh_get_env_value ("TERM"); | |
+ _rl_init_terminal_io (rl_terminal_name); | |
+ | |
+ /* Bind tty characters to readline functions. */ | |
+ readline_default_bindings (); | |
+ | |
+ /* Initialize the function names. */ | |
+ rl_initialize_funmap (); | |
+ | |
+ /* Decide whether we should automatically go into eight-bit mode. */ | |
+ _rl_init_eightbit (); | |
+ | |
+ /* Read in the init file. */ | |
+ rl_read_init_file ((char *)NULL); | |
+ | |
+ /* XXX */ | |
+ if (_rl_horizontal_scroll_mode && _rl_term_autowrap) | |
+ { | |
+ _rl_screenwidth--; | |
+ _rl_screenchars -= _rl_screenheight; | |
+ } | |
+ | |
+ /* Override the effect of any `set keymap' assignments in the | |
+ inputrc file. */ | |
+ rl_set_keymap_from_edit_mode (); | |
+ | |
+ /* Try to bind a common arrow key prefix, if not already bound. */ | |
+ bind_arrow_keys (); | |
+ | |
+ /* If the completion parser's default word break characters haven't | |
+ been set yet, then do so now. */ | |
+ if (rl_completer_word_break_characters == (char *)NULL) | |
+ rl_completer_word_break_characters = (char *)rl_basic_word_break_characters; | |
+ | |
+#if defined (COLOR_SUPPORT) | |
+ if (_rl_colored_stats) | |
+ _rl_parse_colors (); | |
+#endif | |
+ | |
+ rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16); | |
+ if (rl_executing_keyseq) | |
+ rl_executing_keyseq[0] = '\0'; | |
+} | |
+ | |
+/* If this system allows us to look at the values of the regular | |
+ input editing characters, then bind them to their readline | |
+ equivalents, iff the characters are not bound to keymaps. */ | |
+static void | |
+readline_default_bindings () | |
+{ | |
+ if (_rl_bind_stty_chars) | |
+ rl_tty_set_default_bindings (_rl_keymap); | |
+} | |
+ | |
+/* Reset the default bindings for the terminal special characters we're | |
+ interested in back to rl_insert and read the new ones. */ | |
+static void | |
+reset_default_bindings () | |
+{ | |
+ if (_rl_bind_stty_chars) | |
+ { | |
+ rl_tty_unset_default_bindings (_rl_keymap); | |
+ rl_tty_set_default_bindings (_rl_keymap); | |
+ } | |
+} | |
+ | |
+/* Bind some common arrow key sequences in MAP. */ | |
+static void | |
+bind_arrow_keys_internal (map) | |
+ Keymap map; | |
+{ | |
+ Keymap xkeymap; | |
+ | |
+ xkeymap = _rl_keymap; | |
+ _rl_keymap = map; | |
+ | |
+#if defined (__MSDOS__) | |
+ rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history); | |
+ rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char); | |
+ rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char); | |
+ rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history); | |
+#endif | |
+ | |
+ rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history); | |
+ rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history); | |
+ rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char); | |
+ rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char); | |
+ rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line); | |
+ rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line); | |
+ | |
+ rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history); | |
+ rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history); | |
+ rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char); | |
+ rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char); | |
+ rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line); | |
+ rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line); | |
+ | |
+#if defined (__MINGW32__) | |
+ rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history); | |
+ rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history); | |
+ rl_bind_keyseq_if_unbound ("\340M", rl_forward_char); | |
+ rl_bind_keyseq_if_unbound ("\340K", rl_backward_char); | |
+ rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line); | |
+ rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line); | |
+ rl_bind_keyseq_if_unbound ("\340S", rl_delete); | |
+ rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode); | |
+ | |
+ /* These may or may not work because of the embedded NUL. */ | |
+ rl_bind_keyseq_if_unbound ("\\000H", rl_get_previous_history); | |
+ rl_bind_keyseq_if_unbound ("\\000P", rl_get_next_history); | |
+ rl_bind_keyseq_if_unbound ("\\000M", rl_forward_char); | |
+ rl_bind_keyseq_if_unbound ("\\000K", rl_backward_char); | |
+ rl_bind_keyseq_if_unbound ("\\000G", rl_beg_of_line); | |
+ rl_bind_keyseq_if_unbound ("\\000O", rl_end_of_line); | |
+ rl_bind_keyseq_if_unbound ("\\000S", rl_delete); | |
+ rl_bind_keyseq_if_unbound ("\\000R", rl_overwrite_mode); | |
+#endif | |
+ | |
+ _rl_keymap = xkeymap; | |
+} | |
+ | |
+/* Try and bind the common arrow key prefixes after giving termcap and | |
+ the inputrc file a chance to bind them and create `real' keymaps | |
+ for the arrow key prefix. */ | |
+static void | |
+bind_arrow_keys () | |
+{ | |
+ bind_arrow_keys_internal (emacs_standard_keymap); | |
+ | |
+#if defined (VI_MODE) | |
+ bind_arrow_keys_internal (vi_movement_keymap); | |
+ /* Unbind vi_movement_keymap[ESC] to allow users to repeatedly hit ESC | |
+ in vi command mode while still allowing the arrow keys to work. */ | |
+ if (vi_movement_keymap[ESC].type == ISKMAP) | |
+ rl_bind_keyseq_in_map ("\033", (rl_command_func_t *)NULL, vi_movement_keymap); | |
+ bind_arrow_keys_internal (vi_insertion_keymap); | |
+#endif | |
+} | |
+ | |
+/* **************************************************************** */ | |
+/* */ | |
+/* Saving and Restoring Readline's state */ | |
+/* */ | |
+/* **************************************************************** */ | |
+ | |
+int | |
+rl_save_state (sp) | |
+ struct readline_state *sp; | |
+{ | |
+ if (sp == 0) | |
+ return -1; | |
+ | |
+ sp->point = rl_point; | |
+ sp->end = rl_end; | |
+ sp->mark = rl_mark; | |
+ sp->buffer = rl_line_buffer; | |
+ sp->buflen = rl_line_buffer_len; | |
+ sp->ul = rl_undo_list; | |
+ sp->prompt = rl_prompt; | |
+ | |
+ sp->rlstate = rl_readline_state; | |
+ sp->done = rl_done; | |
+ sp->kmap = _rl_keymap; | |
+ | |
+ sp->lastfunc = rl_last_func; | |
+ sp->insmode = rl_insert_mode; | |
+ sp->edmode = rl_editing_mode; | |
+ sp->kseqlen = rl_key_sequence_length; | |
+ sp->inf = rl_instream; | |
+ sp->outf = rl_outstream; | |
+ sp->pendingin = rl_pending_input; | |
+ sp->macro = rl_executing_macro; | |
+ | |
+ sp->catchsigs = rl_catch_signals; | |
+ sp->catchsigwinch = rl_catch_sigwinch; | |
+ | |
+ return (0); | |
+} | |
+ | |
+int | |
+rl_restore_state (sp) | |
+ struct readline_state *sp; | |
+{ | |
+ if (sp == 0) | |
+ return -1; | |
+ | |
+ rl_point = sp->point; | |
+ rl_end = sp->end; | |
+ rl_mark = sp->mark; | |
+ the_line = rl_line_buffer = sp->buffer; | |
+ rl_line_buffer_len = sp->buflen; | |
+ rl_undo_list = sp->ul; | |
+ rl_prompt = sp->prompt; | |
+ | |
+ rl_readline_state = sp->rlstate; | |
+ rl_done = sp->done; | |
+ _rl_keymap = sp->kmap; | |
+ | |
+ rl_last_func = sp->lastfunc; | |
+ rl_insert_mode = sp->insmode; | |
+ rl_editing_mode = sp->edmode; | |
+ rl_key_sequence_length = sp->kseqlen; | |
+ rl_instream = sp->inf; | |
+ rl_outstream = sp->outf; | |
+ rl_pending_input = sp->pendingin; | |
+ rl_executing_macro = sp->macro; | |
+ | |
+ rl_catch_signals = sp->catchsigs; | |
+ rl_catch_sigwinch = sp->catchsigwinch; | |
+ | |
+ return (0); | |
+} | |
diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c | |
index 31cce1c..fff4f81 100644 | |
--- a/lib/sh/shquote.c | |
+++ b/lib/sh/shquote.c | |
@@ -311,3 +311,17 @@ sh_contains_shell_metas (string) | |
return (0); | |
} | |
+ | |
+int | |
+sh_contains_quotes (string) | |
+ char *string; | |
+{ | |
+ char *s; | |
+ | |
+ for (s = string; s && *s; s++) | |
+ { | |
+ if (*s == '\'' || *s == '"' || *s == '\\') | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c | |
index 9ee7147..798260e 100644 | |
--- a/lib/sh/unicode.c | |
+++ b/lib/sh/unicode.c | |
@@ -78,13 +78,15 @@ stub_charset () | |
s = strrchr (locale, '.'); | |
if (s) | |
{ | |
- strcpy (charsetbuf, s+1); | |
+ strncpy (charsetbuf, s+1, sizeof (charsetbuf) - 1); | |
+ charsetbuf[sizeof (charsetbuf) - 1] = '\0'; | |
t = strchr (charsetbuf, '@'); | |
if (t) | |
*t = 0; | |
return charsetbuf; | |
} | |
- strcpy (charsetbuf, locale); | |
+ strncpy (charsetbuf, locale, sizeof (charsetbuf) - 1); | |
+ charsetbuf[sizeof (charsetbuf) - 1] = '\0'; | |
return charsetbuf; | |
} | |
#endif | |
diff --git a/make_cmd.c b/make_cmd.c | |
index 3bc5408..b01d084 100644 | |
--- a/make_cmd.c | |
+++ b/make_cmd.c | |
@@ -692,6 +692,7 @@ make_redirection (source, instruction, dest_and_filename, flags) | |
/* First do the common cases. */ | |
temp->redirector = source; | |
temp->redirectee = dest_and_filename; | |
+ temp->here_doc_eof = 0; | |
temp->instruction = instruction; | |
temp->flags = 0; | |
temp->rflags = flags; | |
diff --git a/parse.y b/parse.y | |
index 82595de..74b5927 100644 | |
--- a/parse.y | |
+++ b/parse.y | |
@@ -168,6 +168,9 @@ static char *read_a_line __P((int)); | |
static int reserved_word_acceptable __P((int)); | |
static int yylex __P((void)); | |
+ | |
+static void push_heredoc __P((REDIRECT *)); | |
+static char *mk_alexpansion __P((char *)); | |
static int alias_expand_token __P((char *)); | |
static int time_command_acceptable __P((void)); | |
static int special_case_tokens __P((char *)); | |
@@ -265,7 +268,9 @@ int parser_state; | |
/* Variables to manage the task of reading here documents, because we need to | |
defer the reading until after a complete command has been collected. */ | |
-static REDIRECT *redir_stack[10]; | |
+#define HEREDOC_MAX 16 | |
+ | |
+static REDIRECT *redir_stack[HEREDOC_MAX]; | |
int need_here_doc; | |
/* Where shell input comes from. History expansion is performed on each | |
@@ -307,7 +312,7 @@ static int global_extglob; | |
or `for WORD' begins. This is a nested command maximum, since the array | |
index is decremented after a case, select, or for command is parsed. */ | |
#define MAX_CASE_NEST 128 | |
-static int word_lineno[MAX_CASE_NEST]; | |
+static int word_lineno[MAX_CASE_NEST+1]; | |
static int word_top = -1; | |
/* If non-zero, it is the token that we want read_token to return | |
@@ -520,42 +525,42 @@ redirection: '>' WORD | |
source.dest = 0; | |
redir.filename = $2; | |
$$ = make_redirection (source, r_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| NUMBER LESS_LESS WORD | |
{ | |
source.dest = $1; | |
redir.filename = $3; | |
$$ = make_redirection (source, r_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| REDIR_WORD LESS_LESS WORD | |
{ | |
source.filename = $1; | |
redir.filename = $3; | |
$$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| LESS_LESS_MINUS WORD | |
{ | |
source.dest = 0; | |
redir.filename = $2; | |
$$ = make_redirection (source, r_deblank_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| NUMBER LESS_LESS_MINUS WORD | |
{ | |
source.dest = $1; | |
redir.filename = $3; | |
$$ = make_redirection (source, r_deblank_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| REDIR_WORD LESS_LESS_MINUS WORD | |
{ | |
source.filename = $1; | |
redir.filename = $3; | |
$$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN); | |
- redir_stack[need_here_doc++] = $$; | |
+ push_heredoc ($$); | |
} | |
| LESS_LESS_LESS WORD | |
{ | |
@@ -2424,7 +2429,7 @@ shell_getc (remove_quoted_newline) | |
not already end in an EOF character. */ | |
if (shell_input_line_terminator != EOF) | |
{ | |
- if (shell_input_line_size < SIZE_MAX && shell_input_line_len > shell_input_line_size - 3) | |
+ if (shell_input_line_size < SIZE_MAX-3 && (shell_input_line_len+3 > shell_input_line_size)) | |
shell_input_line = (char *)xrealloc (shell_input_line, | |
1 + (shell_input_line_size += 2)); | |
@@ -2533,6 +2538,16 @@ shell_ungetc (c) | |
eol_ungetc_lookahead = c; | |
} | |
+char * | |
+parser_remaining_input () | |
+{ | |
+ if (shell_input_line == 0) | |
+ return 0; | |
+ if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len) | |
+ return '\0'; /* XXX */ | |
+ return (shell_input_line + shell_input_line_index); | |
+} | |
+ | |
#ifdef INCLUDE_UNUSED | |
/* Back the input pointer up by one, effectively `ungetting' a character. */ | |
static void | |
@@ -2636,13 +2651,28 @@ yylex () | |
which allow ESAC to be the next one read. */ | |
static int esacs_needed_count; | |
+static void | |
+push_heredoc (r) | |
+ REDIRECT *r; | |
+{ | |
+ if (need_here_doc >= HEREDOC_MAX) | |
+ { | |
+ last_command_exit_value = EX_BADUSAGE; | |
+ need_here_doc = 0; | |
+ report_syntax_error (_("maximum here-document count exceeded")); | |
+ reset_parser (); | |
+ exit_shell (last_command_exit_value); | |
+ } | |
+ redir_stack[need_here_doc++] = r; | |
+} | |
+ | |
void | |
gather_here_documents () | |
{ | |
int r; | |
r = 0; | |
- while (need_here_doc) | |
+ while (need_here_doc > 0) | |
{ | |
parser_state |= PST_HEREDOC; | |
make_here_document (redir_stack[r++], line_number); | |
@@ -2788,11 +2818,16 @@ time_command_acceptable () | |
case AND_AND: | |
case OR_OR: | |
case '&': | |
+ case WHILE: | |
case DO: | |
+ case UNTIL: | |
+ case IF: | |
case THEN: | |
+ case ELIF: | |
case ELSE: | |
case '{': /* } */ | |
- case '(': /* ) */ | |
+ case '(': /* )( */ | |
+ case ')': /* only valid in case statement */ | |
case BANG: /* ! time pipeline */ | |
case TIME: /* time time pipeline */ | |
case TIMEOPT: /* time -p time pipeline */ | |
@@ -2953,6 +2988,8 @@ reset_parser () | |
FREE (word_desc_to_read); | |
word_desc_to_read = (WORD_DESC *)NULL; | |
+ eol_ungetc_lookahead = 0; | |
+ | |
current_token = '\n'; /* XXX */ | |
last_read_token = '\n'; | |
token_to_read = '\n'; | |
@@ -3398,7 +3435,7 @@ parse_matched_pair (qc, open, close, lenp, flags) | |
within a double-quoted ${...} construct "an even number of | |
unescaped double-quotes or single-quotes, if any, shall occur." */ | |
/* This was changed in Austin Group Interp 221 */ | |
- if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'') | |
+ if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && dolbrace_state != DOLBRACE_QUOTE2 && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'') | |
continue; | |
/* Could also check open == '`' if we want to parse grouping constructs | |
@@ -4005,8 +4042,8 @@ xparse_dolparen (base, string, indp, flags) | |
reset_parser (); | |
/* reset_parser clears shell_input_line and associated variables */ | |
restore_input_line_state (&ls); | |
- if (interactive) | |
- token_to_read = 0; | |
+ | |
+ token_to_read = 0; | |
/* Need to find how many characters parse_and_execute consumed, update | |
*indp, if flags != 0, copy the portion of the string parsed into RET | |
@@ -6075,6 +6112,7 @@ save_parser_state (ps) | |
ps->expand_aliases = expand_aliases; | |
ps->echo_input_at_read = echo_input_at_read; | |
+ ps->need_here_doc = need_here_doc; | |
ps->token = token; | |
ps->token_buffer_size = token_buffer_size; | |
@@ -6123,6 +6161,7 @@ restore_parser_state (ps) | |
expand_aliases = ps->expand_aliases; | |
echo_input_at_read = ps->echo_input_at_read; | |
+ need_here_doc = ps->need_here_doc; | |
FREE (token); | |
token = ps->token; | |
diff --git a/patchlevel.h b/patchlevel.h | |
index d3516b2..058e617 100644 | |
--- a/patchlevel.h | |
+++ b/patchlevel.h | |
@@ -25,6 +25,6 @@ | |
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh | |
looks for to find the patch level (for the sccs version string). */ | |
-#define PATCHLEVEL 0 | |
+#define PATCHLEVEL 39 | |
#endif /* _PATCHLEVEL_H_ */ | |
diff --git a/pcomplete.c b/pcomplete.c | |
index a3327ed..70cbc98 100644 | |
--- a/pcomplete.c | |
+++ b/pcomplete.c | |
@@ -183,6 +183,7 @@ ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 }; | |
COMPSPEC *pcomp_curcs; | |
const char *pcomp_curcmd; | |
+const char *pcomp_curtxt; | |
#ifdef DEBUG | |
/* Debugging code */ | |
@@ -753,6 +754,32 @@ pcomp_filename_completion_function (text, state) | |
quoted strings. */ | |
dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); | |
} | |
+ /* Intended to solve a mismatched assumption by bash-completion. If | |
+ the text to be completed is empty, but bash-completion turns it into | |
+ a quoted string ('') assuming that this code will dequote it before | |
+ calling readline, do the dequoting. */ | |
+ else if (iscompgen && iscompleting && | |
+ pcomp_curtxt && *pcomp_curtxt == 0 && | |
+ text && (*text == '\'' || *text == '"') && text[1] == text[0] && text[2] == 0 && | |
+ rl_filename_dequoting_function) | |
+ dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); | |
+ /* Another mismatched assumption by bash-completion. If compgen is being | |
+ run as part of bash-completion, and the argument to compgen is not | |
+ the same as the word originally passed to the programmable completion | |
+ code, dequote the argument if it has quote characters. It's an | |
+ attempt to detect when bash-completion is quoting its filename | |
+ argument before calling compgen. */ | |
+ /* We could check whether gen_shell_function_matches is in the call | |
+ stack by checking whether the gen-shell-function-matches tag is in | |
+ the unwind-protect stack, but there's no function to do that yet. | |
+ We could simply check whether we're executing in a function by | |
+ checking variable_context, and may end up doing that. */ | |
+ else if (iscompgen && iscompleting && rl_filename_dequoting_function && | |
+ pcomp_curtxt && text && | |
+ STREQ (pcomp_curtxt, text) == 0 && | |
+ variable_context && | |
+ sh_contains_quotes (text)) /* guess */ | |
+ dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); | |
else | |
dfn = savestring (text); | |
} | |
@@ -1522,7 +1549,7 @@ gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs) | |
COMPSPEC **lastcs; | |
{ | |
COMPSPEC *cs, *oldcs; | |
- const char *oldcmd; | |
+ const char *oldcmd, *oldtxt; | |
STRINGLIST *ret; | |
cs = progcomp_search (ocmd); | |
@@ -1545,14 +1572,17 @@ gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs) | |
oldcs = pcomp_curcs; | |
oldcmd = pcomp_curcmd; | |
+ oldtxt = pcomp_curtxt; | |
pcomp_curcs = cs; | |
pcomp_curcmd = cmd; | |
+ pcomp_curtxt = word; | |
ret = gen_compspec_completions (cs, cmd, word, start, end, foundp); | |
pcomp_curcs = oldcs; | |
pcomp_curcmd = oldcmd; | |
+ pcomp_curtxt = oldtxt; | |
/* We need to conditionally handle setting *retryp here */ | |
if (retryp) | |
diff --git a/shell.c b/shell.c | |
index bbc8a66..2fd8179 100644 | |
--- a/shell.c | |
+++ b/shell.c | |
@@ -73,6 +73,7 @@ | |
#endif | |
#if defined (READLINE) | |
+# include <readline/readline.h> | |
# include "bashline.h" | |
#endif | |
@@ -909,6 +910,14 @@ exit_shell (s) | |
fflush (stdout); /* XXX */ | |
fflush (stderr); | |
+ /* Clean up the terminal if we are in a state where it's been modified. */ | |
+#if defined (READLINE) | |
+ if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function) | |
+ (*rl_deprep_term_function) (); | |
+#endif | |
+ if (read_tty_modified ()) | |
+ read_tty_cleanup (); | |
+ | |
/* Do trap[0] if defined. Allow it to override the exit status | |
passed to us. */ | |
if (signal_is_trapped (0)) | |
diff --git a/shell.h b/shell.h | |
index 243e467..3cf25df 100644 | |
--- a/shell.h | |
+++ b/shell.h | |
@@ -168,7 +168,8 @@ typedef struct _sh_parser_state_t { | |
/* flags state affecting the parser */ | |
int expand_aliases; | |
int echo_input_at_read; | |
- | |
+ int need_here_doc; | |
+ | |
} sh_parser_state_t; | |
typedef struct _sh_input_line_state_t { | |
@@ -179,6 +180,8 @@ typedef struct _sh_input_line_state_t { | |
} sh_input_line_state_t; | |
/* Let's try declaring these here. */ | |
+extern char *parser_remaining_input __P((void)); | |
+ | |
extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *)); | |
extern void restore_parser_state __P((sh_parser_state_t *)); | |
diff --git a/sig.c b/sig.c | |
index 3b62ea5..8bc45c1 100644 | |
--- a/sig.c | |
+++ b/sig.c | |
@@ -532,8 +532,10 @@ termsig_sighandler (sig) | |
#if defined (READLINE) | |
/* Set the event hook so readline will call it after the signal handlers | |
finish executing, so if this interrupted character input we can get | |
- quick response. */ | |
- if (interactive_shell && interactive && no_line_editing == 0) | |
+ quick response. If readline is active or has modified the terminal we | |
+ need to set this no matter what the signal is, though the check for | |
+ RL_STATE_TERMPREPPED is possibly redundant. */ | |
+ if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED)) | |
bashline_set_event_hook (); | |
#endif | |
diff --git a/subst.c b/subst.c | |
index e131f4c..9e8447a 100644 | |
--- a/subst.c | |
+++ b/subst.c | |
@@ -1192,12 +1192,18 @@ extract_arithmetic_subst (string, sindex) | |
Start extracting at (SINDEX) as if we had just seen "<(". | |
Make (SINDEX) get the position of the matching ")". */ /*))*/ | |
char * | |
-extract_process_subst (string, starter, sindex) | |
+extract_process_subst (string, starter, sindex, xflags) | |
char *string; | |
char *starter; | |
int *sindex; | |
+ int xflags; | |
{ | |
+#if 0 | |
return (extract_delimited_string (string, sindex, starter, "(", ")", SX_COMMAND)); | |
+#else | |
+ xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0); | |
+ return (xparse_dolparen (string, string+*sindex, sindex, xflags)); | |
+#endif | |
} | |
#endif /* PROCESS_SUBSTITUTION */ | |
@@ -1785,7 +1791,7 @@ skip_to_delim (string, start, delims, flags) | |
si = i + 2; | |
if (string[si] == '\0') | |
CQ_RETURN(si); | |
- temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si); | |
+ temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si, 0); | |
free (temp); /* no SX_ALLOC here */ | |
i = si; | |
if (string[i] == '\0') | |
@@ -3248,8 +3254,10 @@ cond_expand_word (w, special) | |
if (w->word == 0 || w->word[0] == '\0') | |
return ((char *)NULL); | |
+ expand_no_split_dollar_star = 1; | |
w->flags |= W_NOSPLIT2; | |
l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0); | |
+ expand_no_split_dollar_star = 0; | |
if (l) | |
{ | |
if (special == 0) /* LHS */ | |
@@ -7366,7 +7374,13 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta | |
} | |
if (want_indir) | |
- tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at); | |
+ { | |
+ tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at); | |
+ /* Turn off the W_ARRAYIND flag because there is no way for this function | |
+ to return the index we're supposed to be using. */ | |
+ if (tdesc && tdesc->flags) | |
+ tdesc->flags &= ~W_ARRAYIND; | |
+ } | |
else | |
tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)), &ind); | |
@@ -7847,6 +7861,10 @@ param_expand (string, sindex, quoted, expanded_something, | |
We also want to make sure that splitting is done no matter what -- | |
according to POSIX.2, this expands to a list of the positional | |
parameters no matter what IFS is set to. */ | |
+ /* XXX - what to do when in a context where word splitting is not | |
+ performed? Even when IFS is not the default, posix seems to imply | |
+ that we behave like unquoted $* ? Maybe we should use PF_NOSPLIT2 | |
+ here. */ | |
temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted); | |
tflag |= W_DOLLARAT; | |
@@ -8029,7 +8047,9 @@ comsub: | |
goto return0; | |
} | |
- else if (var = find_variable_last_nameref (temp1)) | |
+ else if (var && (invisible_p (var) || var_isset (var) == 0)) | |
+ temp = (char *)NULL; | |
+ else if ((var = find_variable_last_nameref (temp1)) && var_isset (var) && invisible_p (var) == 0) | |
{ | |
temp = nameref_cell (var); | |
#if defined (ARRAY_VARS) | |
@@ -8243,7 +8263,7 @@ add_string: | |
else | |
t_index = sindex + 1; /* skip past both '<' and LPAREN */ | |
- temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/ | |
+ temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index, 0); /*))*/ | |
sindex = t_index; | |
/* If the process substitution specification is `<()', we want to | |
@@ -8816,6 +8836,7 @@ finished_with_string: | |
else | |
{ | |
char *ifs_chars; | |
+ char *tstring; | |
ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL; | |
@@ -8830,11 +8851,36 @@ finished_with_string: | |
regardless of what else has happened to IFS since the expansion. */ | |
if (split_on_spaces) | |
list = list_string (istring, " ", 1); /* XXX quoted == 1? */ | |
+ /* If we have $@ (has_dollar_at != 0) and we are in a context where we | |
+ don't want to split the result (W_NOSPLIT2), and we are not quoted, | |
+ we have already separated the arguments with the first character of | |
+ $IFS. In this case, we want to return a list with a single word | |
+ with the separator possibly replaced with a space (it's what other | |
+ shells seem to do). | |
+ quoted_dollar_at is internal to this function and is set if we are | |
+ passed an argument that is unquoted (quoted == 0) but we encounter a | |
+ double-quoted $@ while expanding it. */ | |
+ else if (has_dollar_at && quoted_dollar_at == 0 && ifs_chars && quoted == 0 && (word->flags & W_NOSPLIT2)) | |
+ { | |
+ /* Only split and rejoin if we have to */ | |
+ if (*ifs_chars && *ifs_chars != ' ') | |
+ { | |
+ list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); | |
+ tstring = string_list (list); | |
+ } | |
+ else | |
+ tstring = istring; | |
+ tword = make_bare_word (tstring); | |
+ if (tstring != istring) | |
+ free (tstring); | |
+ goto set_word_flags; | |
+ } | |
else if (has_dollar_at && ifs_chars) | |
list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); | |
else | |
{ | |
tword = make_bare_word (istring); | |
+set_word_flags: | |
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED)) | |
tword->flags |= W_QUOTED; | |
if (word->flags & W_ASSIGNMENT) | |
diff --git a/subst.h b/subst.h | |
index d123fcc..1c300ab 100644 | |
--- a/subst.h | |
+++ b/subst.h | |
@@ -47,6 +47,7 @@ | |
#define ASS_MKASSOC 0x0004 | |
#define ASS_MKGLOBAL 0x0008 /* force global assignment */ | |
#define ASS_NAMEREF 0x0010 /* assigning to nameref variable */ | |
+#define ASS_FROMREF 0x0020 /* assigning from value of nameref variable */ | |
/* Flags for the string extraction functions. */ | |
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */ | |
@@ -82,7 +83,7 @@ extern char *extract_arithmetic_subst __P((char *, int *)); | |
/* Extract the <( or >( construct in STRING, and return a new string. | |
Start extracting at (SINDEX) as if we had just seen "<(". | |
Make (SINDEX) get the position just after the matching ")". */ | |
-extern char *extract_process_subst __P((char *, char *, int *)); | |
+extern char *extract_process_subst __P((char *, char *, int *, int)); | |
#endif /* PROCESS_SUBSTITUTION */ | |
/* Extract the name of the variable to bind to from the assignment string. */ | |
diff --git a/test.c b/test.c | |
index 7f0b28d..ab7bec7 100644 | |
--- a/test.c | |
+++ b/test.c | |
@@ -646,8 +646,8 @@ unary_test (op, arg) | |
return (v && invisible_p (v) == 0 && var_isset (v) ? TRUE : FALSE); | |
case 'R': | |
- v = find_variable (arg); | |
- return (v && invisible_p (v) == 0 && var_isset (v) && nameref_p (v) ? TRUE : FALSE); | |
+ v = find_variable_noref (arg); | |
+ return ((v && invisible_p (v) == 0 && var_isset (v) && nameref_p (v)) ? TRUE : FALSE); | |
} | |
/* We can't actually get here, but this shuts up gcc. */ | |
@@ -723,6 +723,7 @@ test_unop (op) | |
case 'o': case 'p': case 'r': case 's': case 't': | |
case 'u': case 'v': case 'w': case 'x': case 'z': | |
case 'G': case 'L': case 'O': case 'S': case 'N': | |
+ case 'R': | |
return (1); | |
} | |
diff --git a/trap.c b/trap.c | |
index 15d3fc8..edce31a 100644 | |
--- a/trap.c | |
+++ b/trap.c | |
@@ -920,7 +920,8 @@ _run_trap_internal (sig, tag) | |
subst_assign_varlist = 0; | |
#if defined (JOB_CONTROL) | |
- save_pipeline (1); /* XXX only provides one save level */ | |
+ if (sig != DEBUG_TRAP) /* run_debug_trap does this */ | |
+ save_pipeline (1); /* XXX only provides one save level */ | |
#endif | |
/* If we're in a function, make sure return longjmps come here, too. */ | |
@@ -940,7 +941,8 @@ _run_trap_internal (sig, tag) | |
trap_exit_value = last_command_exit_value; | |
#if defined (JOB_CONTROL) | |
- restore_pipeline (1); | |
+ if (sig != DEBUG_TRAP) /* run_debug_trap does this */ | |
+ restore_pipeline (1); | |
#endif | |
subst_assign_varlist = save_subst_varlist; | |
diff --git a/variables.c b/variables.c | |
index 70fac3b..51aaf9c 100644 | |
--- a/variables.c | |
+++ b/variables.c | |
@@ -83,6 +83,11 @@ | |
#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0') | |
+#define BASHFUNC_PREFIX "BASH_FUNC_" | |
+#define BASHFUNC_PREFLEN 10 /* == strlen(BASHFUNC_PREFIX */ | |
+#define BASHFUNC_SUFFIX "%%" | |
+#define BASHFUNC_SUFFLEN 2 /* == strlen(BASHFUNC_SUFFIX) */ | |
+ | |
extern char **environ; | |
/* Variables used here and defined in other files. */ | |
@@ -279,7 +284,7 @@ static void push_temp_var __P((PTR_T)); | |
static void propagate_temp_var __P((PTR_T)); | |
static void dispose_temporary_env __P((sh_free_func_t *)); | |
-static inline char *mk_env_string __P((const char *, const char *)); | |
+static inline char *mk_env_string __P((const char *, const char *, int)); | |
static char **make_env_array_from_var_list __P((SHELL_VAR **)); | |
static char **make_var_export_array __P((VAR_CONTEXT *)); | |
static char **make_func_export_array __P((void)); | |
@@ -349,24 +354,33 @@ initialize_shell_variables (env, privmode) | |
/* If exported function, define it now. Don't import functions from | |
the environment in privileged mode. */ | |
- if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4)) | |
+ if (privmode == 0 && read_but_dont_execute == 0 && | |
+ STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) && | |
+ STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) && | |
+ STREQN ("() {", string, 4)) | |
{ | |
- string_length = strlen (string); | |
- temp_string = (char *)xmalloc (3 + string_length + char_index); | |
+ size_t namelen; | |
+ char *tname; /* desired imported function name */ | |
+ | |
+ namelen = char_index - BASHFUNC_PREFLEN - BASHFUNC_SUFFLEN; | |
- strcpy (temp_string, name); | |
- temp_string[char_index] = ' '; | |
- strcpy (temp_string + char_index + 1, string); | |
+ tname = name + BASHFUNC_PREFLEN; /* start of func name */ | |
+ tname[namelen] = '\0'; /* now tname == func name */ | |
+ | |
+ string_length = strlen (string); | |
+ temp_string = (char *)xmalloc (namelen + string_length + 2); | |
- if (posixly_correct == 0 || legal_identifier (name)) | |
- parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST); | |
+ memcpy (temp_string, tname, namelen); | |
+ temp_string[namelen] = ' '; | |
+ memcpy (temp_string + namelen + 1, string, string_length + 1); | |
- /* Ancient backwards compatibility. Old versions of bash exported | |
- functions like name()=() {...} */ | |
- if (name[char_index - 1] == ')' && name[char_index - 2] == '(') | |
- name[char_index - 2] = '\0'; | |
+ /* Don't import function names that are invalid identifiers from the | |
+ environment, though we still allow them to be defined as shell | |
+ variables. */ | |
+ if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname))) | |
+ parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD); | |
- if (temp_var = find_function (name)) | |
+ if (temp_var = find_function (tname)) | |
{ | |
VSETATTR (temp_var, (att_exported|att_imported)); | |
array_needs_making = 1; | |
@@ -379,12 +393,11 @@ initialize_shell_variables (env, privmode) | |
array_needs_making = 1; | |
} | |
last_command_exit_value = 1; | |
- report_error (_("error importing function definition for `%s'"), name); | |
+ report_error (_("error importing function definition for `%s'"), tname); | |
} | |
- /* ( */ | |
- if (name[char_index - 1] == ')' && name[char_index - 2] == '\0') | |
- name[char_index - 2] = '('; /* ) */ | |
+ /* Restore original suffix */ | |
+ tname[namelen] = BASHFUNC_SUFFIX[0]; | |
} | |
#if defined (ARRAY_VARS) | |
# if ARRAY_EXPORT | |
@@ -2197,10 +2210,7 @@ make_local_variable (name) | |
/* local foo; local foo; is a no-op. */ | |
old_var = find_variable (name); | |
if (old_var && local_p (old_var) && old_var->context == variable_context) | |
- { | |
- VUNSETATTR (old_var, att_invisible); /* XXX */ | |
- return (old_var); | |
- } | |
+ return (old_var); | |
was_tmpvar = old_var && tempvar_p (old_var); | |
/* If we're making a local variable in a shell function, the temporary env | |
@@ -2506,10 +2516,27 @@ bind_variable_internal (name, value, table, hflags, aflags) | |
HASH_TABLE *table; | |
int hflags, aflags; | |
{ | |
- char *newval; | |
+ char *newname, *newval; | |
SHELL_VAR *entry; | |
+#if defined (ARRAY_VARS) | |
+ arrayind_t ind; | |
+ char *subp; | |
+ int sublen; | |
+#endif | |
+ newname = 0; | |
+#if defined (ARRAY_VARS) | |
+ if ((aflags & ASS_FROMREF) && (hflags & HASH_NOSRCH) == 0 && valid_array_reference (name)) | |
+ { | |
+ newname = array_variable_name (name, &subp, &sublen); | |
+ if (newname == 0) | |
+ return (SHELL_VAR *)NULL; /* XXX */ | |
+ entry = hash_lookup (newname, table); | |
+ } | |
+ else | |
+#endif | |
entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table); | |
+ | |
/* Follow the nameref chain here if this is the global variables table */ | |
if (entry && nameref_p (entry) && (invisible_p (entry) == 0) && table == global_variables->table) | |
{ | |
@@ -2540,6 +2567,16 @@ bind_variable_internal (name, value, table, hflags, aflags) | |
var_setvalue (entry, make_variable_value (entry, value, 0)); | |
} | |
} | |
+#if defined (ARRAY_VARS) | |
+ else if (entry == 0 && newname) | |
+ { | |
+ entry = make_new_array_variable (newname); /* indexed array by default */ | |
+ if (entry == 0) | |
+ return entry; | |
+ ind = array_expand_index (name, subp, sublen); | |
+ bind_array_element (entry, ind, value, aflags); | |
+ } | |
+#endif | |
else if (entry == 0) | |
{ | |
entry = make_new_variable (name, table); | |
@@ -2660,7 +2697,8 @@ bind_variable (name, value, flags) | |
normal. */ | |
if (nameref_cell (nv) == 0) | |
return (bind_variable_internal (nv->name, value, nvc->table, 0, flags)); | |
- return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags)); | |
+ /* XXX - bug here with ref=array[index] */ | |
+ return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags|ASS_FROMREF)); | |
} | |
else | |
v = nv; | |
@@ -2795,10 +2833,12 @@ bind_int_variable (lhs, rhs) | |
#endif | |
v = bind_variable (lhs, rhs, 0); | |
- if (v && isint) | |
- VSETATTR (v, att_integer); | |
- | |
- VUNSETATTR (v, att_invisible); | |
+ if (v) | |
+ { | |
+ if (isint) | |
+ VSETATTR (v, att_integer); | |
+ VUNSETATTR (v, att_invisible); | |
+ } | |
return (v); | |
} | |
@@ -2963,7 +3003,7 @@ assign_in_env (word, flags) | |
var->context = variable_context; /* XXX */ | |
INVALIDATE_EXPORTSTR (var); | |
- var->exportstr = mk_env_string (name, value); | |
+ var->exportstr = mk_env_string (name, value, 0); | |
array_needs_making = 1; | |
@@ -3861,21 +3901,42 @@ merge_temporary_env () | |
/* **************************************************************** */ | |
static inline char * | |
-mk_env_string (name, value) | |
+mk_env_string (name, value, isfunc) | |
const char *name, *value; | |
+ int isfunc; | |
{ | |
- int name_len, value_len; | |
- char *p; | |
+ size_t name_len, value_len; | |
+ char *p, *q; | |
name_len = strlen (name); | |
value_len = STRLEN (value); | |
- p = (char *)xmalloc (2 + name_len + value_len); | |
- strcpy (p, name); | |
- p[name_len] = '='; | |
+ | |
+ /* If we are exporting a shell function, construct the encoded function | |
+ name. */ | |
+ if (isfunc && value) | |
+ { | |
+ p = (char *)xmalloc (BASHFUNC_PREFLEN + name_len + BASHFUNC_SUFFLEN + value_len + 2); | |
+ q = p; | |
+ memcpy (q, BASHFUNC_PREFIX, BASHFUNC_PREFLEN); | |
+ q += BASHFUNC_PREFLEN; | |
+ memcpy (q, name, name_len); | |
+ q += name_len; | |
+ memcpy (q, BASHFUNC_SUFFIX, BASHFUNC_SUFFLEN); | |
+ q += BASHFUNC_SUFFLEN; | |
+ } | |
+ else | |
+ { | |
+ p = (char *)xmalloc (2 + name_len + value_len); | |
+ memcpy (p, name, name_len); | |
+ q = p + name_len; | |
+ } | |
+ | |
+ q[0] = '='; | |
if (value && *value) | |
- strcpy (p + name_len + 1, value); | |
+ memcpy (q + 1, value, value_len + 1); | |
else | |
- p[name_len + 1] = '\0'; | |
+ q[1] = '\0'; | |
+ | |
return (p); | |
} | |
@@ -3961,7 +4022,7 @@ make_env_array_from_var_list (vars) | |
/* Gee, I'd like to get away with not using savestring() if we're | |
using the cached exportstr... */ | |
list[list_index] = USE_EXPORTSTR ? savestring (value) | |
- : mk_env_string (var->name, value); | |
+ : mk_env_string (var->name, value, function_p (var)); | |
if (USE_EXPORTSTR == 0) | |
SAVE_EXPORTSTR (var, list[list_index]); | |
diff --git a/y.tab.c b/y.tab.c | |
index f77131b..4141e5d 100644 | |
--- a/y.tab.c | |
+++ b/y.tab.c | |
@@ -168,7 +168,7 @@ | |
/* Copy the first part of user declarations. */ | |
-#line 21 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 21 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
#include "config.h" | |
@@ -319,6 +319,9 @@ static char *read_a_line __P((int)); | |
static int reserved_word_acceptable __P((int)); | |
static int yylex __P((void)); | |
+ | |
+static void push_heredoc __P((REDIRECT *)); | |
+static char *mk_alexpansion __P((char *)); | |
static int alias_expand_token __P((char *)); | |
static int time_command_acceptable __P((void)); | |
static int special_case_tokens __P((char *)); | |
@@ -416,7 +419,9 @@ int parser_state; | |
/* Variables to manage the task of reading here documents, because we need to | |
defer the reading until after a complete command has been collected. */ | |
-static REDIRECT *redir_stack[10]; | |
+#define HEREDOC_MAX 16 | |
+ | |
+static REDIRECT *redir_stack[HEREDOC_MAX]; | |
int need_here_doc; | |
/* Where shell input comes from. History expansion is performed on each | |
@@ -458,7 +463,7 @@ static int global_extglob; | |
or `for WORD' begins. This is a nested command maximum, since the array | |
index is decremented after a case, select, or for command is parsed. */ | |
#define MAX_CASE_NEST 128 | |
-static int word_lineno[MAX_CASE_NEST]; | |
+static int word_lineno[MAX_CASE_NEST+1]; | |
static int word_top = -1; | |
/* If non-zero, it is the token that we want read_token to return | |
@@ -492,7 +497,7 @@ static REDIRECTEE redir; | |
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED | |
typedef union YYSTYPE | |
-#line 324 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 329 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
WORD_DESC *word; /* the word that we read. */ | |
int number; /* the number that we read. */ | |
@@ -503,7 +508,7 @@ typedef union YYSTYPE | |
PATTERN_LIST *pattern; | |
} | |
/* Line 193 of yacc.c. */ | |
-#line 507 "y.tab.c" | |
+#line 512 "y.tab.c" | |
YYSTYPE; | |
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ | |
# define YYSTYPE_IS_DECLARED 1 | |
@@ -516,7 +521,7 @@ typedef union YYSTYPE | |
/* Line 216 of yacc.c. */ | |
-#line 520 "y.tab.c" | |
+#line 525 "y.tab.c" | |
#ifdef short | |
# undef short | |
@@ -886,23 +891,23 @@ static const yytype_int8 yyrhs[] = | |
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ | |
static const yytype_uint16 yyrline[] = | |
{ | |
- 0, 377, 377, 388, 397, 412, 422, 424, 428, 434, | |
- 440, 446, 452, 458, 464, 470, 476, 482, 488, 494, | |
- 500, 506, 512, 518, 525, 532, 539, 546, 553, 560, | |
- 566, 572, 578, 584, 590, 596, 602, 608, 614, 620, | |
- 626, 632, 638, 644, 650, 656, 662, 668, 674, 680, | |
- 686, 692, 700, 702, 704, 708, 712, 723, 725, 729, | |
- 731, 733, 749, 751, 755, 757, 759, 761, 763, 765, | |
- 767, 769, 771, 773, 775, 779, 784, 789, 794, 799, | |
- 804, 809, 814, 821, 826, 831, 836, 843, 848, 853, | |
- 858, 863, 868, 875, 880, 885, 892, 895, 898, 902, | |
- 904, 935, 942, 947, 964, 969, 986, 993, 995, 997, | |
- 1002, 1006, 1010, 1014, 1016, 1018, 1022, 1023, 1027, 1029, | |
- 1031, 1033, 1037, 1039, 1041, 1043, 1045, 1047, 1051, 1053, | |
- 1062, 1070, 1071, 1077, 1078, 1085, 1089, 1091, 1093, 1100, | |
- 1102, 1104, 1108, 1109, 1112, 1114, 1116, 1120, 1121, 1130, | |
- 1143, 1159, 1174, 1176, 1178, 1185, 1188, 1192, 1194, 1200, | |
- 1206, 1223, 1243, 1245, 1268, 1272, 1274, 1276 | |
+ 0, 382, 382, 393, 402, 417, 427, 429, 433, 439, | |
+ 445, 451, 457, 463, 469, 475, 481, 487, 493, 499, | |
+ 505, 511, 517, 523, 530, 537, 544, 551, 558, 565, | |
+ 571, 577, 583, 589, 595, 601, 607, 613, 619, 625, | |
+ 631, 637, 643, 649, 655, 661, 667, 673, 679, 685, | |
+ 691, 697, 705, 707, 709, 713, 717, 728, 730, 734, | |
+ 736, 738, 754, 756, 760, 762, 764, 766, 768, 770, | |
+ 772, 774, 776, 778, 780, 784, 789, 794, 799, 804, | |
+ 809, 814, 819, 826, 831, 836, 841, 848, 853, 858, | |
+ 863, 868, 873, 880, 885, 890, 897, 900, 903, 907, | |
+ 909, 940, 947, 952, 969, 974, 991, 998, 1000, 1002, | |
+ 1007, 1011, 1015, 1019, 1021, 1023, 1027, 1028, 1032, 1034, | |
+ 1036, 1038, 1042, 1044, 1046, 1048, 1050, 1052, 1056, 1058, | |
+ 1067, 1075, 1076, 1082, 1083, 1090, 1094, 1096, 1098, 1105, | |
+ 1107, 1109, 1113, 1114, 1117, 1119, 1121, 1125, 1126, 1135, | |
+ 1148, 1164, 1179, 1181, 1183, 1190, 1193, 1197, 1199, 1205, | |
+ 1211, 1228, 1248, 1250, 1273, 1277, 1279, 1281 | |
}; | |
#endif | |
@@ -2093,7 +2098,7 @@ yyreduce: | |
switch (yyn) | |
{ | |
case 2: | |
-#line 378 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 383 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
/* Case of regular command. Discard the error | |
safety net,and return the command just parsed. */ | |
@@ -2107,7 +2112,7 @@ yyreduce: | |
break; | |
case 3: | |
-#line 389 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 394 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
/* Case of regular command, but not a very | |
interesting one. Return a NULL command. */ | |
@@ -2119,7 +2124,7 @@ yyreduce: | |
break; | |
case 4: | |
-#line 398 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 403 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
/* Error during parsing. Return NULL command. */ | |
global_command = (COMMAND *)NULL; | |
@@ -2137,7 +2142,7 @@ yyreduce: | |
break; | |
case 5: | |
-#line 413 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 418 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
/* Case of EOF seen by itself. Do ignoreeof or | |
not. */ | |
@@ -2148,17 +2153,17 @@ yyreduce: | |
break; | |
case 6: | |
-#line 423 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 428 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.word_list) = make_word_list ((yyvsp[(1) - (1)].word), (WORD_LIST *)NULL); } | |
break; | |
case 7: | |
-#line 425 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 430 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.word_list) = make_word_list ((yyvsp[(2) - (2)].word), (yyvsp[(1) - (2)].word_list)); } | |
break; | |
case 8: | |
-#line 429 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 434 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2167,7 +2172,7 @@ yyreduce: | |
break; | |
case 9: | |
-#line 435 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 440 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2176,7 +2181,7 @@ yyreduce: | |
break; | |
case 10: | |
-#line 441 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 446 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2185,7 +2190,7 @@ yyreduce: | |
break; | |
case 11: | |
-#line 447 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 452 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2194,7 +2199,7 @@ yyreduce: | |
break; | |
case 12: | |
-#line 453 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 458 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2203,7 +2208,7 @@ yyreduce: | |
break; | |
case 13: | |
-#line 459 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 464 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2212,7 +2217,7 @@ yyreduce: | |
break; | |
case 14: | |
-#line 465 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 470 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2221,7 +2226,7 @@ yyreduce: | |
break; | |
case 15: | |
-#line 471 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 476 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2230,7 +2235,7 @@ yyreduce: | |
break; | |
case 16: | |
-#line 477 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 482 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2239,7 +2244,7 @@ yyreduce: | |
break; | |
case 17: | |
-#line 483 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 488 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2248,7 +2253,7 @@ yyreduce: | |
break; | |
case 18: | |
-#line 489 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 494 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2257,7 +2262,7 @@ yyreduce: | |
break; | |
case 19: | |
-#line 495 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 500 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2266,7 +2271,7 @@ yyreduce: | |
break; | |
case 20: | |
-#line 501 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 506 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2275,7 +2280,7 @@ yyreduce: | |
break; | |
case 21: | |
-#line 507 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 512 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2284,7 +2289,7 @@ yyreduce: | |
break; | |
case 22: | |
-#line 513 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 518 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2293,67 +2298,67 @@ yyreduce: | |
break; | |
case 23: | |
-#line 519 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 524 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
(yyval.redirect) = make_redirection (source, r_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 24: | |
-#line 526 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 531 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
(yyval.redirect) = make_redirection (source, r_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 25: | |
-#line 533 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 538 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
(yyval.redirect) = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 26: | |
-#line 540 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 545 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
(yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 27: | |
-#line 547 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 552 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
(yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, 0); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 28: | |
-#line 554 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 559 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
(yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN); | |
- redir_stack[need_here_doc++] = (yyval.redirect); | |
+ push_heredoc ((yyval.redirect)); | |
} | |
break; | |
case 29: | |
-#line 561 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 566 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2362,7 +2367,7 @@ yyreduce: | |
break; | |
case 30: | |
-#line 567 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 572 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2371,7 +2376,7 @@ yyreduce: | |
break; | |
case 31: | |
-#line 573 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 578 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2380,7 +2385,7 @@ yyreduce: | |
break; | |
case 32: | |
-#line 579 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 584 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.dest = (yyvsp[(2) - (2)].number); | |
@@ -2389,7 +2394,7 @@ yyreduce: | |
break; | |
case 33: | |
-#line 585 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 590 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.dest = (yyvsp[(3) - (3)].number); | |
@@ -2398,7 +2403,7 @@ yyreduce: | |
break; | |
case 34: | |
-#line 591 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 596 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.dest = (yyvsp[(3) - (3)].number); | |
@@ -2407,7 +2412,7 @@ yyreduce: | |
break; | |
case 35: | |
-#line 597 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 602 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.dest = (yyvsp[(2) - (2)].number); | |
@@ -2416,7 +2421,7 @@ yyreduce: | |
break; | |
case 36: | |
-#line 603 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 608 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.dest = (yyvsp[(3) - (3)].number); | |
@@ -2425,7 +2430,7 @@ yyreduce: | |
break; | |
case 37: | |
-#line 609 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 614 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.dest = (yyvsp[(3) - (3)].number); | |
@@ -2434,7 +2439,7 @@ yyreduce: | |
break; | |
case 38: | |
-#line 615 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 620 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2443,7 +2448,7 @@ yyreduce: | |
break; | |
case 39: | |
-#line 621 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 626 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2452,7 +2457,7 @@ yyreduce: | |
break; | |
case 40: | |
-#line 627 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 632 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2461,7 +2466,7 @@ yyreduce: | |
break; | |
case 41: | |
-#line 633 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 638 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2470,7 +2475,7 @@ yyreduce: | |
break; | |
case 42: | |
-#line 639 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 644 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2479,7 +2484,7 @@ yyreduce: | |
break; | |
case 43: | |
-#line 645 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 650 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.filename = (yyvsp[(3) - (3)].word); | |
@@ -2488,7 +2493,7 @@ yyreduce: | |
break; | |
case 44: | |
-#line 651 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 656 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.dest = 0; | |
@@ -2497,7 +2502,7 @@ yyreduce: | |
break; | |
case 45: | |
-#line 657 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 662 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.dest = 0; | |
@@ -2506,7 +2511,7 @@ yyreduce: | |
break; | |
case 46: | |
-#line 663 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 668 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.dest = 0; | |
@@ -2515,7 +2520,7 @@ yyreduce: | |
break; | |
case 47: | |
-#line 669 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 674 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 0; | |
redir.dest = 0; | |
@@ -2524,7 +2529,7 @@ yyreduce: | |
break; | |
case 48: | |
-#line 675 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 680 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = (yyvsp[(1) - (3)].number); | |
redir.dest = 0; | |
@@ -2533,7 +2538,7 @@ yyreduce: | |
break; | |
case 49: | |
-#line 681 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 686 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.filename = (yyvsp[(1) - (3)].word); | |
redir.dest = 0; | |
@@ -2542,7 +2547,7 @@ yyreduce: | |
break; | |
case 50: | |
-#line 687 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 692 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2551,7 +2556,7 @@ yyreduce: | |
break; | |
case 51: | |
-#line 693 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 698 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
source.dest = 1; | |
redir.filename = (yyvsp[(2) - (2)].word); | |
@@ -2560,29 +2565,29 @@ yyreduce: | |
break; | |
case 52: | |
-#line 701 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 706 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.element).word = (yyvsp[(1) - (1)].word); (yyval.element).redirect = 0; } | |
break; | |
case 53: | |
-#line 703 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 708 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.element).word = (yyvsp[(1) - (1)].word); (yyval.element).redirect = 0; } | |
break; | |
case 54: | |
-#line 705 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 710 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.element).redirect = (yyvsp[(1) - (1)].redirect); (yyval.element).word = 0; } | |
break; | |
case 55: | |
-#line 709 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 714 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.redirect) = (yyvsp[(1) - (1)].redirect); | |
} | |
break; | |
case 56: | |
-#line 713 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 718 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
register REDIRECT *t; | |
@@ -2594,27 +2599,27 @@ yyreduce: | |
break; | |
case 57: | |
-#line 724 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 729 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_simple_command ((yyvsp[(1) - (1)].element), (COMMAND *)NULL); } | |
break; | |
case 58: | |
-#line 726 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 731 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_simple_command ((yyvsp[(2) - (2)].element), (yyvsp[(1) - (2)].command)); } | |
break; | |
case 59: | |
-#line 730 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 735 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = clean_simple_command ((yyvsp[(1) - (1)].command)); } | |
break; | |
case 60: | |
-#line 732 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 737 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 61: | |
-#line 734 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 739 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
COMMAND *tc; | |
@@ -2633,72 +2638,72 @@ yyreduce: | |
break; | |
case 62: | |
-#line 750 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 755 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 63: | |
-#line 752 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 757 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 64: | |
-#line 756 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 761 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 65: | |
-#line 758 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 763 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 66: | |
-#line 760 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 765 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_while_command ((yyvsp[(2) - (5)].command), (yyvsp[(4) - (5)].command)); } | |
break; | |
case 67: | |
-#line 762 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 767 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_until_command ((yyvsp[(2) - (5)].command), (yyvsp[(4) - (5)].command)); } | |
break; | |
case 68: | |
-#line 764 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 769 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 69: | |
-#line 766 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 771 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 70: | |
-#line 768 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 773 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 71: | |
-#line 770 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 775 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 72: | |
-#line 772 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 777 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 73: | |
-#line 774 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 779 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 74: | |
-#line 776 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 781 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 75: | |
-#line 780 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 785 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (6)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(5) - (6)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2706,7 +2711,7 @@ yyreduce: | |
break; | |
case 76: | |
-#line 785 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 790 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (6)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(5) - (6)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2714,7 +2719,7 @@ yyreduce: | |
break; | |
case 77: | |
-#line 790 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 795 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (7)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(6) - (7)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2722,7 +2727,7 @@ yyreduce: | |
break; | |
case 78: | |
-#line 795 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 800 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (7)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(6) - (7)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2730,7 +2735,7 @@ yyreduce: | |
break; | |
case 79: | |
-#line 800 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 805 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (10)].word), REVERSE_LIST ((yyvsp[(5) - (10)].word_list), WORD_LIST *), (yyvsp[(9) - (10)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2738,7 +2743,7 @@ yyreduce: | |
break; | |
case 80: | |
-#line 805 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 810 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (10)].word), REVERSE_LIST ((yyvsp[(5) - (10)].word_list), WORD_LIST *), (yyvsp[(9) - (10)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2746,7 +2751,7 @@ yyreduce: | |
break; | |
case 81: | |
-#line 810 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 815 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (9)].word), (WORD_LIST *)NULL, (yyvsp[(8) - (9)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2754,7 +2759,7 @@ yyreduce: | |
break; | |
case 82: | |
-#line 815 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 820 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_for_command ((yyvsp[(2) - (9)].word), (WORD_LIST *)NULL, (yyvsp[(8) - (9)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2762,7 +2767,7 @@ yyreduce: | |
break; | |
case 83: | |
-#line 822 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 827 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_arith_for_command ((yyvsp[(2) - (7)].word_list), (yyvsp[(6) - (7)].command), arith_for_lineno); | |
if (word_top > 0) word_top--; | |
@@ -2770,7 +2775,7 @@ yyreduce: | |
break; | |
case 84: | |
-#line 827 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 832 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_arith_for_command ((yyvsp[(2) - (7)].word_list), (yyvsp[(6) - (7)].command), arith_for_lineno); | |
if (word_top > 0) word_top--; | |
@@ -2778,7 +2783,7 @@ yyreduce: | |
break; | |
case 85: | |
-#line 832 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 837 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_arith_for_command ((yyvsp[(2) - (5)].word_list), (yyvsp[(4) - (5)].command), arith_for_lineno); | |
if (word_top > 0) word_top--; | |
@@ -2786,7 +2791,7 @@ yyreduce: | |
break; | |
case 86: | |
-#line 837 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 842 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_arith_for_command ((yyvsp[(2) - (5)].word_list), (yyvsp[(4) - (5)].command), arith_for_lineno); | |
if (word_top > 0) word_top--; | |
@@ -2794,7 +2799,7 @@ yyreduce: | |
break; | |
case 87: | |
-#line 844 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 849 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (6)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(5) - (6)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2802,7 +2807,7 @@ yyreduce: | |
break; | |
case 88: | |
-#line 849 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 854 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (6)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(5) - (6)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2810,7 +2815,7 @@ yyreduce: | |
break; | |
case 89: | |
-#line 854 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 859 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (7)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(6) - (7)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2818,7 +2823,7 @@ yyreduce: | |
break; | |
case 90: | |
-#line 859 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 864 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (7)].word), add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), (yyvsp[(6) - (7)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2826,7 +2831,7 @@ yyreduce: | |
break; | |
case 91: | |
-#line 864 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 869 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (10)].word), REVERSE_LIST ((yyvsp[(5) - (10)].word_list), WORD_LIST *), (yyvsp[(9) - (10)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2834,7 +2839,7 @@ yyreduce: | |
break; | |
case 92: | |
-#line 869 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 874 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_select_command ((yyvsp[(2) - (10)].word), REVERSE_LIST ((yyvsp[(5) - (10)].word_list), WORD_LIST *), (yyvsp[(9) - (10)].command), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2842,7 +2847,7 @@ yyreduce: | |
break; | |
case 93: | |
-#line 876 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 881 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_case_command ((yyvsp[(2) - (6)].word), (PATTERN_LIST *)NULL, word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2850,7 +2855,7 @@ yyreduce: | |
break; | |
case 94: | |
-#line 881 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 886 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_case_command ((yyvsp[(2) - (7)].word), (yyvsp[(5) - (7)].pattern), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2858,7 +2863,7 @@ yyreduce: | |
break; | |
case 95: | |
-#line 886 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 891 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_case_command ((yyvsp[(2) - (6)].word), (yyvsp[(5) - (6)].pattern), word_lineno[word_top]); | |
if (word_top > 0) word_top--; | |
@@ -2866,27 +2871,27 @@ yyreduce: | |
break; | |
case 96: | |
-#line 893 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 898 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_function_def ((yyvsp[(1) - (5)].word), (yyvsp[(5) - (5)].command), function_dstart, function_bstart); } | |
break; | |
case 97: | |
-#line 896 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 901 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_function_def ((yyvsp[(2) - (6)].word), (yyvsp[(6) - (6)].command), function_dstart, function_bstart); } | |
break; | |
case 98: | |
-#line 899 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 904 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_function_def ((yyvsp[(2) - (4)].word), (yyvsp[(4) - (4)].command), function_dstart, function_bstart); } | |
break; | |
case 99: | |
-#line 903 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 908 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 100: | |
-#line 905 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 910 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
COMMAND *tc; | |
@@ -2918,7 +2923,7 @@ yyreduce: | |
break; | |
case 101: | |
-#line 936 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 941 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_subshell_command ((yyvsp[(2) - (3)].command)); | |
(yyval.command)->flags |= CMD_WANT_SUBSHELL; | |
@@ -2926,7 +2931,7 @@ yyreduce: | |
break; | |
case 102: | |
-#line 943 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 948 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_coproc_command ("COPROC", (yyvsp[(2) - (2)].command)); | |
(yyval.command)->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL; | |
@@ -2934,7 +2939,7 @@ yyreduce: | |
break; | |
case 103: | |
-#line 948 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 953 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
COMMAND *tc; | |
@@ -2954,7 +2959,7 @@ yyreduce: | |
break; | |
case 104: | |
-#line 965 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 970 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_coproc_command ((yyvsp[(2) - (3)].word)->word, (yyvsp[(3) - (3)].command)); | |
(yyval.command)->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL; | |
@@ -2962,7 +2967,7 @@ yyreduce: | |
break; | |
case 105: | |
-#line 970 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 975 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
COMMAND *tc; | |
@@ -2982,7 +2987,7 @@ yyreduce: | |
break; | |
case 106: | |
-#line 987 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 992 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = make_coproc_command ("COPROC", clean_simple_command ((yyvsp[(2) - (2)].command))); | |
(yyval.command)->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL; | |
@@ -2990,117 +2995,117 @@ yyreduce: | |
break; | |
case 107: | |
-#line 994 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 999 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (5)].command), (yyvsp[(4) - (5)].command), (COMMAND *)NULL); } | |
break; | |
case 108: | |
-#line 996 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1001 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (7)].command), (yyvsp[(4) - (7)].command), (yyvsp[(6) - (7)].command)); } | |
break; | |
case 109: | |
-#line 998 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1003 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (6)].command), (yyvsp[(4) - (6)].command), (yyvsp[(5) - (6)].command)); } | |
break; | |
case 110: | |
-#line 1003 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1008 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_group_command ((yyvsp[(2) - (3)].command)); } | |
break; | |
case 111: | |
-#line 1007 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1012 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_arith_command ((yyvsp[(1) - (1)].word_list)); } | |
break; | |
case 112: | |
-#line 1011 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1016 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(2) - (3)].command); } | |
break; | |
case 113: | |
-#line 1015 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1020 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (4)].command), (yyvsp[(4) - (4)].command), (COMMAND *)NULL); } | |
break; | |
case 114: | |
-#line 1017 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1022 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (6)].command), (yyvsp[(4) - (6)].command), (yyvsp[(6) - (6)].command)); } | |
break; | |
case 115: | |
-#line 1019 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1024 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = make_if_command ((yyvsp[(2) - (5)].command), (yyvsp[(4) - (5)].command), (yyvsp[(5) - (5)].command)); } | |
break; | |
case 117: | |
-#line 1024 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1029 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(2) - (2)].pattern)->next = (yyvsp[(1) - (2)].pattern); (yyval.pattern) = (yyvsp[(2) - (2)].pattern); } | |
break; | |
case 118: | |
-#line 1028 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1033 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.pattern) = make_pattern_list ((yyvsp[(2) - (4)].word_list), (yyvsp[(4) - (4)].command)); } | |
break; | |
case 119: | |
-#line 1030 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1035 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.pattern) = make_pattern_list ((yyvsp[(2) - (4)].word_list), (COMMAND *)NULL); } | |
break; | |
case 120: | |
-#line 1032 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1037 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.pattern) = make_pattern_list ((yyvsp[(3) - (5)].word_list), (yyvsp[(5) - (5)].command)); } | |
break; | |
case 121: | |
-#line 1034 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1039 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.pattern) = make_pattern_list ((yyvsp[(3) - (5)].word_list), (COMMAND *)NULL); } | |
break; | |
case 122: | |
-#line 1038 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1043 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.pattern) = (yyvsp[(1) - (2)].pattern); } | |
break; | |
case 123: | |
-#line 1040 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1045 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(2) - (3)].pattern)->next = (yyvsp[(1) - (3)].pattern); (yyval.pattern) = (yyvsp[(2) - (3)].pattern); } | |
break; | |
case 124: | |
-#line 1042 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1047 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(1) - (2)].pattern)->flags |= CASEPAT_FALLTHROUGH; (yyval.pattern) = (yyvsp[(1) - (2)].pattern); } | |
break; | |
case 125: | |
-#line 1044 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1049 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(2) - (3)].pattern)->flags |= CASEPAT_FALLTHROUGH; (yyvsp[(2) - (3)].pattern)->next = (yyvsp[(1) - (3)].pattern); (yyval.pattern) = (yyvsp[(2) - (3)].pattern); } | |
break; | |
case 126: | |
-#line 1046 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1051 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(1) - (2)].pattern)->flags |= CASEPAT_TESTNEXT; (yyval.pattern) = (yyvsp[(1) - (2)].pattern); } | |
break; | |
case 127: | |
-#line 1048 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1053 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyvsp[(2) - (3)].pattern)->flags |= CASEPAT_TESTNEXT; (yyvsp[(2) - (3)].pattern)->next = (yyvsp[(1) - (3)].pattern); (yyval.pattern) = (yyvsp[(2) - (3)].pattern); } | |
break; | |
case 128: | |
-#line 1052 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1057 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.word_list) = make_word_list ((yyvsp[(1) - (1)].word), (WORD_LIST *)NULL); } | |
break; | |
case 129: | |
-#line 1054 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1059 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.word_list) = make_word_list ((yyvsp[(3) - (3)].word), (yyvsp[(1) - (3)].word_list)); } | |
break; | |
case 130: | |
-#line 1063 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1068 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = (yyvsp[(2) - (2)].command); | |
if (need_here_doc) | |
@@ -3109,14 +3114,14 @@ yyreduce: | |
break; | |
case 132: | |
-#line 1072 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1077 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = (yyvsp[(2) - (2)].command); | |
} | |
break; | |
case 134: | |
-#line 1079 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1084 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(1) - (3)].command)->type == cm_connection) | |
(yyval.command) = connect_async_list ((yyvsp[(1) - (3)].command), (COMMAND *)NULL, '&'); | |
@@ -3126,17 +3131,17 @@ yyreduce: | |
break; | |
case 136: | |
-#line 1090 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1095 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), AND_AND); } | |
break; | |
case 137: | |
-#line 1092 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1097 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), OR_OR); } | |
break; | |
case 138: | |
-#line 1094 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1099 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(1) - (4)].command)->type == cm_connection) | |
(yyval.command) = connect_async_list ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), '&'); | |
@@ -3146,37 +3151,37 @@ yyreduce: | |
break; | |
case 139: | |
-#line 1101 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1106 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), ';'); } | |
break; | |
case 140: | |
-#line 1103 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1108 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), ';'); } | |
break; | |
case 141: | |
-#line 1105 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1110 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 144: | |
-#line 1113 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1118 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = '\n'; } | |
break; | |
case 145: | |
-#line 1115 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1120 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = ';'; } | |
break; | |
case 146: | |
-#line 1117 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1122 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = yacc_EOF; } | |
break; | |
case 149: | |
-#line 1131 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1136 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = (yyvsp[(1) - (1)].command); | |
if (need_here_doc) | |
@@ -3192,7 +3197,7 @@ yyreduce: | |
break; | |
case 150: | |
-#line 1144 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1149 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(1) - (2)].command)->type == cm_connection) | |
(yyval.command) = connect_async_list ((yyvsp[(1) - (2)].command), (COMMAND *)NULL, '&'); | |
@@ -3211,7 +3216,7 @@ yyreduce: | |
break; | |
case 151: | |
-#line 1160 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1165 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
(yyval.command) = (yyvsp[(1) - (2)].command); | |
if (need_here_doc) | |
@@ -3227,17 +3232,17 @@ yyreduce: | |
break; | |
case 152: | |
-#line 1175 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1180 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), AND_AND); } | |
break; | |
case 153: | |
-#line 1177 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1182 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), OR_OR); } | |
break; | |
case 154: | |
-#line 1179 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1184 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(1) - (3)].command)->type == cm_connection) | |
(yyval.command) = connect_async_list ((yyvsp[(1) - (3)].command), (yyvsp[(3) - (3)].command), '&'); | |
@@ -3247,22 +3252,22 @@ yyreduce: | |
break; | |
case 155: | |
-#line 1186 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1191 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (3)].command), (yyvsp[(3) - (3)].command), ';'); } | |
break; | |
case 156: | |
-#line 1189 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1194 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 157: | |
-#line 1193 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1198 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 158: | |
-#line 1195 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1200 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(2) - (2)].command)) | |
(yyvsp[(2) - (2)].command)->flags ^= CMD_INVERT_RETURN; /* toggle */ | |
@@ -3271,7 +3276,7 @@ yyreduce: | |
break; | |
case 159: | |
-#line 1201 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1206 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
if ((yyvsp[(2) - (2)].command)) | |
(yyvsp[(2) - (2)].command)->flags |= (yyvsp[(1) - (2)].number); | |
@@ -3280,7 +3285,7 @@ yyreduce: | |
break; | |
case 160: | |
-#line 1207 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1212 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
ELEMENT x; | |
@@ -3300,7 +3305,7 @@ yyreduce: | |
break; | |
case 161: | |
-#line 1224 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1229 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
ELEMENT x; | |
@@ -3321,12 +3326,12 @@ yyreduce: | |
break; | |
case 162: | |
-#line 1244 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1249 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = command_connect ((yyvsp[(1) - (4)].command), (yyvsp[(4) - (4)].command), '|'); } | |
break; | |
case 163: | |
-#line 1246 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1251 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ | |
/* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */ | |
COMMAND *tc; | |
@@ -3352,28 +3357,28 @@ yyreduce: | |
break; | |
case 164: | |
-#line 1269 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1274 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.command) = (yyvsp[(1) - (1)].command); } | |
break; | |
case 165: | |
-#line 1273 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1278 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = CMD_TIME_PIPELINE; } | |
break; | |
case 166: | |
-#line 1275 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1280 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = CMD_TIME_PIPELINE|CMD_TIME_POSIX; } | |
break; | |
case 167: | |
-#line 1277 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1282 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
{ (yyval.number) = CMD_TIME_PIPELINE|CMD_TIME_POSIX; } | |
break; | |
/* Line 1267 of yacc.c. */ | |
-#line 3377 "y.tab.c" | |
+#line 3382 "y.tab.c" | |
default: break; | |
} | |
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); | |
@@ -3587,7 +3592,7 @@ yyreturn: | |
} | |
-#line 1279 "/usr/homes/chet/src/bash/src/parse.y" | |
+#line 1284 "/usr/src/local/bash/bash-4.3-patched/parse.y" | |
/* Initial size to allocate for tokens, and the | |
@@ -4736,7 +4741,7 @@ shell_getc (remove_quoted_newline) | |
not already end in an EOF character. */ | |
if (shell_input_line_terminator != EOF) | |
{ | |
- if (shell_input_line_size < SIZE_MAX && shell_input_line_len > shell_input_line_size - 3) | |
+ if (shell_input_line_size < SIZE_MAX-3 && (shell_input_line_len+3 > shell_input_line_size)) | |
shell_input_line = (char *)xrealloc (shell_input_line, | |
1 + (shell_input_line_size += 2)); | |
@@ -4845,6 +4850,16 @@ shell_ungetc (c) | |
eol_ungetc_lookahead = c; | |
} | |
+char * | |
+parser_remaining_input () | |
+{ | |
+ if (shell_input_line == 0) | |
+ return 0; | |
+ if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len) | |
+ return '\0'; /* XXX */ | |
+ return (shell_input_line + shell_input_line_index); | |
+} | |
+ | |
#ifdef INCLUDE_UNUSED | |
/* Back the input pointer up by one, effectively `ungetting' a character. */ | |
static void | |
@@ -4948,13 +4963,28 @@ yylex () | |
which allow ESAC to be the next one read. */ | |
static int esacs_needed_count; | |
+static void | |
+push_heredoc (r) | |
+ REDIRECT *r; | |
+{ | |
+ if (need_here_doc >= HEREDOC_MAX) | |
+ { | |
+ last_command_exit_value = EX_BADUSAGE; | |
+ need_here_doc = 0; | |
+ report_syntax_error (_("maximum here-document count exceeded")); | |
+ reset_parser (); | |
+ exit_shell (last_command_exit_value); | |
+ } | |
+ redir_stack[need_here_doc++] = r; | |
+} | |
+ | |
void | |
gather_here_documents () | |
{ | |
int r; | |
r = 0; | |
- while (need_here_doc) | |
+ while (need_here_doc > 0) | |
{ | |
parser_state |= PST_HEREDOC; | |
make_here_document (redir_stack[r++], line_number); | |
@@ -5100,11 +5130,16 @@ time_command_acceptable () | |
case AND_AND: | |
case OR_OR: | |
case '&': | |
+ case WHILE: | |
case DO: | |
+ case UNTIL: | |
+ case IF: | |
case THEN: | |
+ case ELIF: | |
case ELSE: | |
case '{': /* } */ | |
- case '(': /* ) */ | |
+ case '(': /* )( */ | |
+ case ')': /* only valid in case statement */ | |
case BANG: /* ! time pipeline */ | |
case TIME: /* time time pipeline */ | |
case TIMEOPT: /* time -p time pipeline */ | |
@@ -5265,6 +5300,8 @@ reset_parser () | |
FREE (word_desc_to_read); | |
word_desc_to_read = (WORD_DESC *)NULL; | |
+ eol_ungetc_lookahead = 0; | |
+ | |
current_token = '\n'; /* XXX */ | |
last_read_token = '\n'; | |
token_to_read = '\n'; | |
@@ -5710,7 +5747,7 @@ parse_matched_pair (qc, open, close, lenp, flags) | |
within a double-quoted ${...} construct "an even number of | |
unescaped double-quotes or single-quotes, if any, shall occur." */ | |
/* This was changed in Austin Group Interp 221 */ | |
- if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'') | |
+ if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && dolbrace_state != DOLBRACE_QUOTE2 && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'') | |
continue; | |
/* Could also check open == '`' if we want to parse grouping constructs | |
@@ -6317,8 +6354,8 @@ xparse_dolparen (base, string, indp, flags) | |
reset_parser (); | |
/* reset_parser clears shell_input_line and associated variables */ | |
restore_input_line_state (&ls); | |
- if (interactive) | |
- token_to_read = 0; | |
+ | |
+ token_to_read = 0; | |
/* Need to find how many characters parse_and_execute consumed, update | |
*indp, if flags != 0, copy the portion of the string parsed into RET | |
@@ -8387,6 +8424,7 @@ save_parser_state (ps) | |
ps->expand_aliases = expand_aliases; | |
ps->echo_input_at_read = echo_input_at_read; | |
+ ps->need_here_doc = need_here_doc; | |
ps->token = token; | |
ps->token_buffer_size = token_buffer_size; | |
@@ -8435,6 +8473,7 @@ restore_parser_state (ps) | |
expand_aliases = ps->expand_aliases; | |
echo_input_at_read = ps->echo_input_at_read; | |
+ need_here_doc = ps->need_here_doc; | |
FREE (token); | |
token = ps->token; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment