diff options
author | Chet Ramey <chet.ramey@case.edu> | 2020-09-09 15:25:32 -0400 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2020-09-09 15:25:32 -0400 |
commit | 3eb0018e75b74bb886df7fba4b1712529ce7258f (patch) | |
tree | 13b53713ef8f483a82295324e314da48b59c9346 /builtins | |
parent | 712f80b0a49c3a0227d0b52bff5e0b763747697e (diff) | |
download | bash-5.1-beta.tar.gz |
bash-5.1 beta releasebash-5.1-beta
Diffstat (limited to 'builtins')
-rw-r--r-- | builtins/command.def | 4 | ||||
-rw-r--r-- | builtins/common.h | 1 | ||||
-rw-r--r-- | builtins/complete.def | 220 | ||||
-rw-r--r-- | builtins/declare.def | 6 | ||||
-rw-r--r-- | builtins/evalstring.c | 22 | ||||
-rw-r--r-- | builtins/fc.def | 82 | ||||
-rw-r--r-- | builtins/hash.def | 3 | ||||
-rw-r--r-- | builtins/set.def | 18 | ||||
-rw-r--r-- | builtins/setattr.def | 2 |
9 files changed, 198 insertions, 160 deletions
diff --git a/builtins/command.def b/builtins/command.def index cea55b8e..acd46cc1 100644 --- a/builtins/command.def +++ b/builtins/command.def @@ -124,6 +124,10 @@ command_builtin (list) #define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN | (use_standard_path ? CMD_STDPATH : 0)) +#ifdef DEBUG + itrace("command_builtin: running execute_command for `%s'", list->word->word); +#endif + /* We don't want this to be reparsed (consider command echo 'foo &'), so just make a simple_command structure and call execute_command with it. */ command = make_bare_simple_command (); diff --git a/builtins/common.h b/builtins/common.h index 0aecc9ce..a4f9275d 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -210,6 +210,7 @@ extern int should_suppress_fork PARAMS((COMMAND *)); extern int can_optimize_connection PARAMS((COMMAND *)); extern void optimize_fork PARAMS((COMMAND *)); extern void optimize_subshell_command PARAMS((COMMAND *)); +extern void optimize_shell_function PARAMS((COMMAND *)); /* Functions from evalfile.c */ extern int maybe_execute_file PARAMS((const char *, int)); diff --git a/builtins/complete.def b/builtins/complete.def index f33328e8..28a9ec2f 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -42,7 +42,7 @@ Options: command) word When completion is attempted, the actions are applied in the order the -uppercase-letter options are listed above. If multiple options are supplied, +uppercase-letter options are listed above. If multiple options are supplied, the -D option takes precedence over -E, and both take precedence over -I. Exit Status: @@ -97,11 +97,16 @@ static void print_compopts PARAMS((const char *, COMPSPEC *, int)); static void print_all_completions PARAMS((void)); static int print_cmd_completions PARAMS((WORD_LIST *)); +static void print_compoptions PARAMS((unsigned long, int)); +static void print_compactions PARAMS((unsigned long)); +static void print_arg PARAMS((const char *, const char *, int)); +static void print_cmd_name PARAMS((const char *)); + static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg; static const struct _compacts { const char * const actname; - int actflag; + unsigned long actflag; int actopt; } compacts[] = { { "alias", CA_ALIAS, 'a' }, @@ -134,7 +139,7 @@ static const struct _compacts { /* This should be a STRING_INT_ALIST */ static const struct _compopt { const char * const optname; - int optflag; + unsigned long optflag; } compopts[] = { { "bashdefault", COPT_BASHDEFAULT }, { "default", COPT_DEFAULT }, @@ -485,122 +490,95 @@ remove_cmd_completions (list) return ret; } -#define SQPRINTARG(a, f) \ - do { \ - if (a) \ - { \ - x = sh_single_quote (a); \ - printf ("%s %s ", f, x); \ - free (x); \ - } \ - } while (0) - -#define PRINTARG(a, f) \ - do { \ - if (a) \ - printf ("%s %s ", f, a); \ - } while (0) - -#define PRINTOPT(a, f) \ - do { \ - if (acts & a) \ - printf ("%s ", f); \ - } while (0) - -#define PRINTACT(a, f) \ - do { \ - if (acts & a) \ - printf ("-A %s ", f); \ - } while (0) - -#define PRINTCOMPOPT(a, f) \ - do { \ - if (copts & a) \ - printf ("-o %s ", f); \ - } while (0) - -#define XPRINTCOMPOPT(a, f) \ - do { \ - if (copts & a) \ - printf ("-o %s ", f); \ - else \ - printf ("+o %s ", f); \ - } while (0) +static void +print_compoptions (copts, full) + unsigned long copts; + int full; +{ + const struct _compopt *co; + + for (co = compopts; co->optname; co++) + if (copts & co->optflag) + printf ("-o %s ", co->optname); + else if (full) + printf ("+o %s ", co->optname); +} + +static void +print_compactions (acts) + unsigned long acts; +{ + const struct _compacts *ca; + + /* simple flags first */ + for (ca = compacts; ca->actname; ca++) + if (ca->actopt && (acts & ca->actflag)) + printf ("-%c ", ca->actopt); + + /* then the rest of the actions */ + for (ca = compacts; ca->actname; ca++) + if (ca->actopt == 0 && (acts & ca->actflag)) + printf ("-A %s ", ca->actname); +} + +static void +print_arg (arg, flag, quote) + const char *arg, *flag; + int quote; +{ + char *x; + + if (arg) + { + x = quote ? sh_single_quote (arg) : (char *)arg; + printf ("%s %s ", flag, x); + if (x != arg) + free (x); + } +} + +static void +print_cmd_name (cmd) + const char *cmd; +{ + if (STREQ (cmd, DEFAULTCMD)) + printf ("-D"); + else if (STREQ (cmd, EMPTYCMD)) + printf ("-E"); + else if (STREQ (cmd, INITIALWORD)) + printf ("-I"); + else if (*cmd == 0) /* XXX - can this happen? */ + printf ("''"); + else + printf ("%s", cmd); +} static int print_one_completion (cmd, cs) char *cmd; COMPSPEC *cs; { - unsigned long acts, copts; - char *x; - printf ("complete "); - copts = cs->options; - - /* First, print the -o options. */ - PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); - PRINTCOMPOPT (COPT_DEFAULT, "default"); - PRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); - PRINTCOMPOPT (COPT_FILENAMES, "filenames"); - PRINTCOMPOPT (COPT_NOQUOTE, "noquote"); - PRINTCOMPOPT (COPT_NOSORT, "nosort"); - PRINTCOMPOPT (COPT_NOSPACE, "nospace"); - PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); - - acts = cs->actions; - - /* simple flags next */ - PRINTOPT (CA_ALIAS, "-a"); - PRINTOPT (CA_BUILTIN, "-b"); - PRINTOPT (CA_COMMAND, "-c"); - PRINTOPT (CA_DIRECTORY, "-d"); - PRINTOPT (CA_EXPORT, "-e"); - PRINTOPT (CA_FILE, "-f"); - PRINTOPT (CA_GROUP, "-g"); - PRINTOPT (CA_JOB, "-j"); - PRINTOPT (CA_KEYWORD, "-k"); - PRINTOPT (CA_SERVICE, "-s"); - PRINTOPT (CA_USER, "-u"); - PRINTOPT (CA_VARIABLE, "-v"); - - /* now the rest of the actions */ - PRINTACT (CA_ARRAYVAR, "arrayvar"); - PRINTACT (CA_BINDING, "binding"); - PRINTACT (CA_DISABLED, "disabled"); - PRINTACT (CA_ENABLED, "enabled"); - PRINTACT (CA_FUNCTION, "function"); - PRINTACT (CA_HELPTOPIC, "helptopic"); - PRINTACT (CA_HOSTNAME, "hostname"); - PRINTACT (CA_RUNNING, "running"); - PRINTACT (CA_SETOPT, "setopt"); - PRINTACT (CA_SHOPT, "shopt"); - PRINTACT (CA_SIGNAL, "signal"); - PRINTACT (CA_STOPPED, "stopped"); + print_compoptions (cs->options, 0); + print_compactions (cs->actions); /* now the rest of the arguments */ /* arguments that require quoting */ - SQPRINTARG (cs->globpat, "-G"); - SQPRINTARG (cs->words, "-W"); - SQPRINTARG (cs->prefix, "-P"); - SQPRINTARG (cs->suffix, "-S"); - SQPRINTARG (cs->filterpat, "-X"); + print_arg (cs->globpat, "-G", 1); + print_arg (cs->words, "-W", 1); + print_arg (cs->prefix, "-P", 1); + print_arg (cs->suffix, "-S", 1); + print_arg (cs->filterpat, "-X", 1); - SQPRINTARG (cs->command, "-C"); + print_arg (cs->command, "-C", 1); /* simple arguments that don't require quoting */ - PRINTARG (cs->funcname, "-F"); + print_arg (cs->funcname, "-F", 0); - if (STREQ (cmd, DEFAULTCMD)) - printf ("-D\n"); - else if (STREQ (cmd, EMPTYCMD)) - printf ("-E\n"); - else if (STREQ (cmd, INITIALWORD)) - printf ("-I\n"); - else - printf ("%s\n", cmd); + print_cmd_name (cmd); + printf ("\n"); return (0); } @@ -611,42 +589,12 @@ print_compopts (cmd, cs, full) COMPSPEC *cs; int full; { - int copts; - printf ("compopt "); - copts = cs->options; - if (full) - { - XPRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); - XPRINTCOMPOPT (COPT_DEFAULT, "default"); - XPRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); - XPRINTCOMPOPT (COPT_FILENAMES, "filenames"); - XPRINTCOMPOPT (COPT_NOQUOTE, "noquote"); - XPRINTCOMPOPT (COPT_NOSORT, "nosort"); - XPRINTCOMPOPT (COPT_NOSPACE, "nospace"); - XPRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); - } - else - { - PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); - PRINTCOMPOPT (COPT_DEFAULT, "default"); - PRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); - PRINTCOMPOPT (COPT_FILENAMES, "filenames"); - PRINTCOMPOPT (COPT_NOQUOTE, "noquote"); - PRINTCOMPOPT (COPT_NOSORT, "nosort"); - PRINTCOMPOPT (COPT_NOSPACE, "nospace"); - PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); - } + print_compoptions (cs->options, full); + print_cmd_name (cmd); - if (STREQ (cmd, DEFAULTCMD)) - printf ("-D\n"); - else if (STREQ (cmd, EMPTYCMD)) - printf ("-E\n"); - else if (STREQ (cmd, INITIALWORD)) - printf ("-I\n"); - else - printf ("%s\n", cmd); + printf ("\n"); } static int diff --git a/builtins/declare.def b/builtins/declare.def index 98878243..21e4516d 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -727,20 +727,20 @@ restart_new_var_name: if (flags_on & att_assoc) { var = make_new_assoc_variable (name); - if (var && offset == 0 && no_invisible_vars == 0) + if (var && offset == 0) VSETATTR (var, att_invisible); } else if ((flags_on & att_array) || making_array_special) { var = make_new_array_variable (name); - if (var && offset == 0 && no_invisible_vars == 0) + if (var && offset == 0) VSETATTR (var, att_invisible); } else #endif { var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE); - if (var && offset == 0 && no_invisible_vars == 0) + if (var && offset == 0) VSETATTR (var, att_invisible); } if (var == 0) diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 4240277e..3a6801dd 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -145,7 +145,27 @@ optimize_subshell_command (command) (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR)) optimize_subshell_command (command->value.Connection->second); } - + +void +optimize_shell_function (command) + COMMAND *command; +{ + COMMAND *fc; + + fc = (command->type == cm_group) ? command->value.Group->command : command; + + if (fc->type == cm_simple && should_suppress_fork (fc)) + { + fc->flags |= CMD_NO_FORK; + fc->value.Simple->flags |= CMD_NO_FORK; + } + else if (fc->type == cm_connection && can_optimize_connection (fc) && should_suppress_fork (fc->value.Connection->second)) + { + fc->value.Connection->second->flags |= CMD_NO_FORK; + fc->value.Connection->second->value.Simple->flags |= CMD_NO_FORK; + } +} + /* How to force parse_and_execute () to clean up after itself. */ void parse_and_execute_cleanup (old_running_trap) diff --git a/builtins/fc.def b/builtins/fc.def index c266ac2c..467dbcbc 100644 --- a/builtins/fc.def +++ b/builtins/fc.def @@ -86,6 +86,14 @@ $END extern int errno; #endif /* !errno */ +#define HIST_INVALID INT_MIN +#define HIST_ERANGE INT_MIN+1 +#define HIST_NOTFOUND INT_MIN+2 + +/* Values for the flags argument to fc_gethnum */ +#define HN_LISTING 0x01 +#define HN_FIRST 0x02 + extern int unlink PARAMS((const char *)); extern FILE *sh_mktmpfp PARAMS((char *, int, char **)); @@ -201,7 +209,7 @@ fc_builtin (list) break; case 'l': - listing = 1; + listing = HN_LISTING; /* for fc_gethnum */ break; case 'r': @@ -321,14 +329,11 @@ fc_builtin (list) while (last_hist >= 0 && hlist[last_hist] == 0) last_hist--; if (last_hist < 0) - { - sh_erange ((char *)NULL, _("history specification")); - return (EXECUTION_FAILURE); - } + last_hist = 0; /* per POSIX */ if (list) { - histbeg = fc_gethnum (list->word->word, hlist, listing); + histbeg = fc_gethnum (list->word->word, hlist, listing|HN_FIRST); list = list->next; if (list) @@ -353,12 +358,27 @@ fc_builtin (list) histbeg = histend = last_hist; } - /* We print error messages for line specifications out of range. */ - if ((histbeg < 0) || (histend < 0)) + if (histbeg == HIST_INVALID || histend == HIST_INVALID) + { + sh_erange ((char *)NULL, _("history specification")); + return (EXECUTION_FAILURE); + } + else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE) { sh_erange ((char *)NULL, _("history specification")); return (EXECUTION_FAILURE); } + else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND) + { + builtin_error (_("no command found")); + return (EXECUTION_FAILURE); + } + + /* We don't throw an error for line specifications out of range, per POSIX */ + if (histbeg < 0) + histbeg = 0; + if (histend < 0) + histend = 0; /* "When not listing, the fc command that caused the editing shall not be entered into the history list." */ @@ -382,12 +402,27 @@ fc_builtin (list) histbeg = last_hist; } - /* We print error messages for line specifications out of range. */ - if ((histbeg < 0) || (histend < 0)) + if (histbeg == HIST_INVALID || histend == HIST_INVALID) + { + sh_erange ((char *)NULL, _("history specification")); + return (EXECUTION_FAILURE); + } + else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE) { sh_erange ((char *)NULL, _("history specification")); return (EXECUTION_FAILURE); } + else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND) + { + builtin_error (_("no command found")); + return (EXECUTION_FAILURE); + } + + /* We don't throw an error for line specifications out of range, per POSIX */ + if (histbeg < 0) + histbeg = 0; + if (histend < 0) + histend = 0; if (histend < histbeg) { @@ -507,7 +542,9 @@ fc_number (list) /* Return an absolute index into HLIST which corresponds to COMMAND. If COMMAND is a number, then it was specified in relative terms. If it is a string, then it is the start of a command line present in HLIST. - MODE is 1 if we are listing commands, 0 if we are executing them. */ + MODE includes HN_LISTING if we are listing commands, and does not if we + are executing them. If MODE includes HN_FIRST we are looking for the + first history number specification. */ static int fc_gethnum (command, hlist, mode) char *command; @@ -515,9 +552,10 @@ fc_gethnum (command, hlist, mode) int mode; { int sign, n, clen, rh; - register int i, j, last_hist, real_last; + register int i, j, last_hist, real_last, listing; register char *s; + listing = mode & HN_LISTING; sign = 1; /* Count history elements. */ for (i = 0; hlist[i]; i++); @@ -570,19 +608,33 @@ fc_gethnum (command, hlist, mode) n = atoi (s); n *= sign; + /* We want to return something that is an offset to HISTORY_BASE. */ + /* If the value is negative or zero, then it is an offset from the current history item. */ + /* We don't use HN_FIRST here, so we don't return different values + depending on whether we're looking for the first or last in a + pair of range arguments, but nobody else does, either. */ if (n < 0) { n += i + 1; return (n < 0 ? 0 : n); } else if (n == 0) - return ((sign == -1) ? (mode ? real_last : -1) : i); + return ((sign == -1) ? (listing ? real_last : HIST_INVALID) : i); else { + /* If we're out of range (greater than I (last history entry) or + less than HISTORY_BASE, we want to return different values + based on whether or not we are looking for the first or last + value in a desired range of history entries. */ n -= history_base; - return (i < n ? i : n); + if (n < 0) + return (mode & HN_FIRST ? 0 : i); + else if (n >= i) + return (mode & HN_FIRST ? 0 : i); + else + return n; } } @@ -592,7 +644,7 @@ fc_gethnum (command, hlist, mode) if (STREQN (command, histline (j), clen)) return (j); } - return (-1); + return (HIST_NOTFOUND); } /* Locate the most recent history line which begins with diff --git a/builtins/hash.def b/builtins/hash.def index 8eddc999..c58e91c4 100644 --- a/builtins/hash.def +++ b/builtins/hash.def @@ -134,7 +134,8 @@ hash_builtin (list) if (list == 0 && expunge_hash_table == 0) { opt = print_hashed_commands (list_portably); - if (opt == 0 && posixly_correct == 0) + if (opt == 0 && posixly_correct == 0 && + (list_portably == 0 || shell_compatibility_level <= 50)) printf (_("%s: hash table empty\n"), this_command_name); return (EXECUTION_SUCCESS); diff --git a/builtins/set.def b/builtins/set.def index 48927679..8ee01657 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -358,17 +358,29 @@ void set_current_options (bitmap) const char *bitmap; { - int i; + int i, v, cv, *on_or_off; if (bitmap == 0) return; for (i = 0; o_options[i].name; i++) { + v = bitmap[i] ? FLAG_ON : FLAG_OFF; if (o_options[i].letter) - change_flag (o_options[i].letter, bitmap[i] ? FLAG_ON : FLAG_OFF); + { + /* We should not get FLAG_UNKNOWN here */ + on_or_off = find_flag (o_options[i].letter); + cv = *on_or_off ? FLAG_ON : FLAG_OFF; + if (v != cv) + change_flag (o_options[i].letter, v); + } else - SET_BINARY_O_OPTION_VALUE (i, bitmap[i] ? FLAG_ON : FLAG_OFF, o_options[i].name); + { + cv = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name); + cv = cv ? FLAG_ON : FLAG_OFF; + if (v != cv) + SET_BINARY_O_OPTION_VALUE (i, v, o_options[i].name); + } } /* Now reset the variables changed by posix mode */ diff --git a/builtins/setattr.def b/builtins/setattr.def index e43f7091..a193462d 100644 --- a/builtins/setattr.def +++ b/builtins/setattr.def @@ -645,7 +645,7 @@ set_var_attribute (name, attribute, undo) if (var == 0) { var = bind_variable (name, (char *)NULL, 0); - if (var && no_invisible_vars == 0) + if (var) VSETATTR (var, att_invisible); } else if (var->context != 0) |