commit bash-20121005 snapshot

This commit is contained in:
Chet Ramey
2012-11-02 09:04:00 -04:00
parent 15be7e1e2f
commit 1562376007
44 changed files with 47536 additions and 1737 deletions
+53
View File
@@ -3633,3 +3633,56 @@ lib/glob/sm_loop.c:
the pattern, and the rest of the pattern is something that can
match the NUL at the end of the search string, we should successfully
match. Fixes `a*!(x)' bug reported by <hans1worst@gmail.com>
10/2
----
command.h
- add c_lock member to coproc structure for future use to tell who is
manipulating it
execute_cmd.c
- execute_coproc: block SIGCHLD while parent is forking coproc
process and adding pid to sh_coproc struct to avoid race condition
where child is reaped before the pid is assigned and the coproc is
never marked as having died. Fixes race condition identified by
Davide Baldini <baldiniebaldini@gmail.com>
- add assignments to c_lock member of struct coproc in various
functions that manipulate it; was used to identify race condition
- coproc_pidchk: don't call coproc_dispose to avoid using malloc and
other functions in a signal handler context
- coproc_dispose: call BLOCK_SIGNAL/UNBLOCK_SIGNAL for SIGCHLD while
manipulating the sh_coproc struct
10/6
----
lib/readline/complete.c
- rl_display_match_list: if printing completions horizontally, don't
bother with spacing calculations if limit == 1, which means we are
printing one completion per line no matter what. Fixes bug
reported by David Kaasen <kaasen@nvg.ntnu.no>
10/7
----
builtins/declare.def
- declare_internal: add error checking for nameref attribute and
variable assignments: self-references, attempts to make an array
variable a nameref
subst.c
- parameter_brace_expand: handle parameter_brace_expand_word returning
&expand_param_fatal or &expand_param_error and return the appropriate
error value
- parameter_brace_expand_word: if a nameref variable's value is not a
valid identifier, return an error
- param_expand: if a nameref variable's value is not a valid identifier,
return an error
test.c
- unary_operator: add new -R variable, returns true if variable is set
and has the nameref attribute. From ksh93
builtins/test.def
- add -R to description of conditional commands for help test
doc/{bash.1,bashref.texi}
- document new -R unary conditional operator
+3685
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
Starting bash with the `--posix' command-line option or executing
`set -o posix' while bash is running will cause bash to conform more
closely to the Posix.2 standard by changing the behavior to match that
specified by Posix.2 in areas where the bash default differs.
The following list is what's changed when `posix mode' is in effect:
1. When a command in the hash table no longer exists, bash will re-search
$PATH to find the new location. This is also available with
`shopt -s checkhash'.
2. The >& redirection does not redirect stdout and stderr.
3. The message printed by the job control code and builtins when a job
exits with a non-zero status is `Done(status)'.
4. Reserved words may not be aliased.
5. The Posix.2 PS1 and PS2 expansions of `!' -> history number and
`!!' -> `!' are enabled, and parameter expansion is performed on
the value regardless of the setting of the `promptvars' option.
6. Interactive comments are enabled by default. (Note that bash has
them on by default anyway.)
7. The Posix.2 startup files are executed ($ENV) rather than the normal
bash files.
8. Tilde expansion is only performed on assignments preceding a command
name, rather than on all assignment statements on the line.
9. The default history file is ~/.sh_history (default value of $HISTFILE).
10. The output of `kill -l' prints all the signal names on a single line,
separated by spaces.
11. Non-interactive shells exit if `file' in `. file' is not found.
12. Redirection operators do not perform pathname expansion on the word
in the redirection unless the shell is interactive
13. Function names must be valid shell identifiers. That is, they may not
contain characters other than letters, digits, and underscores, and
may not start with a digit. Declaring a function with an illegal name
causes a fatal syntax error in non-interactive shells.
14. Posix.2 `special' builtins are found before shell functions during command
lookup.
15. If a Posix.2 special builtin returns an error status, a non-interactive
shell exits. The fatal errors are those listed in the POSIX.2 standard,
and include things like passing incorrect options, redirection errors,
variable assignment errors for assignments preceding the command name,
and so on.
16. The environment passed to executed commands is not sorted. Neither is
the output of `set'. This is not strictly Posix.2 behavior, but sh
does it this way. Ksh does not. It's not necessary to sort the
environment; no program should rely on it being sorted.
17. If the `cd' builtin finds a directory to change to using $CDPATH, the
value it assigns to $PWD does not contain any symbolic links, as if
`cd -P' had been executed.
18. A non-interactive shell exits with an error status if a variable
assignment error occurs when no command name follows the assignment
statements. A variable assignment error occurs, for example, when
trying to assign a value to a read-only variable.
19. A non-interactive shell exits with an error status if the iteration
variable in a for statement or the selection variable in a select
statement is a read-only variable.
20. Process substitution is not available.
21. Assignment statements preceding POSIX.2 `special' builtins persist in
the shell environment after the builtin completes.
There is other Posix.2 behavior that bash does not implement. Specifically:
1. Assignment statements affect the execution environment of all builtins,
not just special ones.
+544
View File
@@ -0,0 +1,544 @@
This file is set.def, from which is created set.c.
It implements the "set" and "unset" builtins in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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 1, or (at your option) any later
version.
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES set.c
#include <stdio.h>
#include "../shell.h"
#include "../flags.h"
#include "bashgetopt.h"
extern int interactive;
extern int noclobber, posixly_correct;
#if defined (READLINE)
extern int rl_editing_mode, no_line_editing;
#endif /* READLINE */
$BUILTIN set
$FUNCTION set_builtin
$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...]
-a Mark variables which are modified or created for export.
-b Notify of job termination immediately.
-e Exit immediately if a command exits with a non-zero status.
-f Disable file name generation (globbing).
-h Locate and remember function commands as functions are
defined. Function commands are normally looked up when
the function is executed.
-i Force the shell to be an "interactive" one. Interactive shells
always read `~/.bashrc' on startup.
-k All keyword arguments are placed in the environment for a
command, not just those that precede the command name.
-m Job control is enabled.
-n Read commands but do not execute them.
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand same as -B
#if defined (READLINE)
emacs use an emacs-style line editing interface
#endif /* READLINE */
errexit same as -e
histexpand same as -H
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
monitor same as -m
noclobber disallow redirection to existing files
noexec same as -n
noglob same as -f
nohash same as -d
notify save as -b
nounset same as -u
physical same as -P
posix change the behavior of bash where the default
operation differs from the 1003.2 standard to
match the standard
privileged same as -p
verbose same as -v
#if defined (READLINE)
vi use a vi-style line editing interface
#endif /* READLINE */
xtrace same as -x
-p Turned on whenever the real and effective user ids do not match.
Disables processing of the $ENV file and importing of shell
functions. Turning this option off causes the effective uid and
gid to be set to the real uid and gid.
-t Exit after reading and executing one command.
-u Treat unset variables as an error when substituting.
-v Print shell input lines as they are read.
-x Print commands and their arguments as they are executed.
-l Save and restore the binding of the NAME in a FOR command.
-d Disable the hashing of commands that are looked up for execution.
Normally, commands are remembered in a hash table, and once
found, do not have to be looked up again.
#if defined (BRACE_EXPANSION)
-B the shell will perform brace expansion
#endif /* BRACE_EXPANSION */
#if defined (BANG_HISTORY)
-H Enable ! style history substitution. This flag is on
by default.
#endif /* BANG_HISTORY */
-C If set, disallow existing regular files to be overwritten
by redirection of output.
-P If set, do not follow symbolic links when executing commands
such as cd which change the current directory.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
$END
/* An a-list used to match long options for set -o to the corresponding
option letter. */
struct {
char *name;
int letter;
} o_options[] = {
{ "allexport", 'a' },
#if defined (BRACE_EXPANSION)
{ "braceexpand",'B' },
#endif
{ "errexit", 'e' },
{ "histexpand", 'H' },
{ "monitor", 'm' },
{ "noexec", 'n' },
{ "noglob", 'f' },
{ "nohash", 'd' },
#if defined (JOB_CONTROL)
{ "notify", 'b' },
#endif /* JOB_CONTROL */
{"nounset", 'u' },
{"physical", 'P' },
{"privileged", 'p' },
{"verbose", 'v' },
{"xtrace", 'x' },
{(char *)NULL, 0},
};
#define MINUS_O_FORMAT "%-15s\t%s\n"
void
list_minus_o_opts ()
{
register int i;
char *on = "on", *off = "off";
printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
printf (MINUS_O_FORMAT, "ignoreeof", on);
else
printf (MINUS_O_FORMAT, "ignoreeof", off);
printf (MINUS_O_FORMAT, "interactive-comments",
interactive_comments ? on : off);
printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
#if defined (READLINE)
if (no_line_editing)
{
printf (MINUS_O_FORMAT, "emacs", off);
printf (MINUS_O_FORMAT, "vi", off);
}
else
{
/* Magic. This code `knows' how readline handles rl_editing_mode. */
printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
}
#endif /* READLINE */
for (i = 0; o_options[i].name; i++)
{
int *on_or_off, zero = 0;
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &zero;
printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
}
}
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int option_char = -1;
if (STREQ (option_name, "noclobber"))
{
if (on_or_off == FLAG_ON)
bind_variable ("noclobber", "");
else
unbind_variable ("noclobber");
stupidly_hack_special_variables ("noclobber");
}
else if (STREQ (option_name, "ignoreeof"))
{
unbind_variable ("ignoreeof");
unbind_variable ("IGNOREEOF");
if (on_or_off == FLAG_ON)
bind_variable ("IGNOREEOF", "10");
stupidly_hack_special_variables ("IGNOREEOF");
}
#if defined (READLINE)
else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
{
if (on_or_off == FLAG_ON)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
int isemacs = (rl_editing_mode == 1);
if ((isemacs && STREQ (option_name, "emacs")) ||
(!isemacs && STREQ (option_name, "vi")))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
else
builtin_error ("not in %s editing mode", option_name);
}
}
#endif /* READLINE */
else if (STREQ (option_name, "interactive-comments"))
interactive_comments = (on_or_off == FLAG_ON);
else if (STREQ (option_name, "posix"))
{
posixly_correct = (on_or_off == FLAG_ON);
unbind_variable ("POSIXLY_CORRECT");
unbind_variable ("POSIX_PEDANTIC");
if (on_or_off == FLAG_ON)
{
bind_variable ("POSIXLY_CORRECT", "");
stupidly_hack_special_variables ("POSIXLY_CORRECT");
}
}
else
{
register int i;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (option_name, o_options[i].name))
{
option_char = o_options[i].letter;
break;
}
}
if (option_char == -1)
{
builtin_error ("%s: unknown option name", option_name);
return (EXECUTION_FAILURE);
}
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
{
bad_option (option_name);
return (EXECUTION_FAILURE);
}
}
return (EXECUTION_SUCCESS);
}
/* Set some flags from the word values in the input list. If LIST is empty,
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
set_builtin (list)
WORD_LIST *list;
{
int on_or_off, flag_name, force_assignment = 0;
if (!list)
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
vars = all_shell_functions ();
if (vars)
{
print_var_list (vars);
free (vars);
}
return (EXECUTION_SUCCESS);
}
/* Check validity of flag arguments. */
if (*list->word->word == '-' || *list->word->word == '+')
{
register char *arg;
WORD_LIST *save_list = list;
while (list && (arg = list->word->word))
{
char c;
if (arg[0] != '-' && arg[0] != '+')
break;
/* `-' or `--' signifies end of flag arguments. */
if (arg[0] == '-' &&
(!arg[1] || (arg[1] == '-' && !arg[2])))
break;
while (c = *++arg)
{
if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
{
char s[2];
s[0] = c; s[1] = '\0';
bad_option (s);
if (c == '?')
builtin_usage ();
return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
}
list = list->next;
}
list = save_list;
}
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
while (list)
{
char *string = list->word->word;
/* If the argument is `--' or `-' then signal the end of the list
and remember the remaining arguments. */
if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
{
list = list->next;
/* `set --' unsets the positional parameters. */
if (string[1] == '-')
force_assignment = 1;
/* Until told differently, the old shell behaviour of
`set - [arg ...]' being equivalent to `set +xv [arg ...]'
stands. Posix.2 says the behaviour is marked as obsolescent. */
else
{
change_flag ('x', '+');
change_flag ('v', '+');
}
break;
}
if ((on_or_off = *string) &&
(on_or_off == '-' || on_or_off == '+'))
{
int i = 1;
while (flag_name = string[i++])
{
if (flag_name == '?')
{
builtin_usage ();
return (EXECUTION_SUCCESS);
}
else if (flag_name == 'o') /* -+o option-name */
{
char *option_name;
WORD_LIST *opt;
opt = list->next;
if (!opt)
{
list_minus_o_opts ();
continue;
}
option_name = opt->word->word;
if (!option_name || !*option_name || (*option_name == '-'))
{
list_minus_o_opts ();
continue;
}
list = list->next; /* Skip over option name. */
if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
return (EXECUTION_FAILURE);
}
else
{
if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
char opt[3];
opt[0] = on_or_off;
opt[1] = flag_name;
opt[2] = '\0';
bad_option (opt);
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
}
}
else
{
break;
}
list = list->next;
}
/* Assigning $1 ... $n */
if (list || force_assignment)
remember_args (list, 1);
return (EXECUTION_SUCCESS);
}
$BUILTIN unset
$FUNCTION unset_builtin
$SHORT_DOC unset [-f] [-v] [name ...]
For each NAME, remove the corresponding variable or function. Given
the `-v', unset will only act on variables. Given the `-f' flag,
unset will only act on functions. With neither flag, unset first
tries to unset a variable, and if that fails, then tries to unset a
function. Some variables (such as PATH and IFS) cannot be unset; also
see readonly.
$END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
unset_builtin (list)
WORD_LIST *list;
{
int unset_function, unset_variable, unset_array, opt, any_failed;
char *name;
unset_function = unset_variable = unset_array = any_failed = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fv")) != -1)
{
switch (opt)
{
case 'f':
unset_function = 1;
break;
case 'v':
unset_variable = 1;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
if (unset_function && unset_variable)
{
builtin_error ("cannot simultaneously unset a function and a variable");
return (EXECUTION_FAILURE);
}
while (list)
{
SHELL_VAR *var;
int tem;
#if defined (ARRAY_VARS)
char *t;
#endif
name = list->word->word;
#if defined (ARRAY_VARS)
if (!unset_function && valid_array_reference (name))
{
t = strchr (name, '[');
*t++ = '\0';
unset_array++;
}
#endif
var = unset_function ? find_function (name) : find_variable (name);
if (var && !unset_function && non_unsettable_p (var))
{
builtin_error ("%s: cannot unset", name);
NEXT_VARIABLE ();
}
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error ("%s: cannot unset: readonly %s",
name, unset_function ? "function" : "variable");
NEXT_VARIABLE ();
}
/* Unless the -f option is supplied, the name refers to a variable. */
#if defined (ARRAY_VARS)
if (var && unset_array)
{
if (array_p (var) == 0)
{
builtin_error ("%s: not an array variable", name);
NEXT_VARIABLE ();
}
else
tem = unbind_array_element (var, t);
}
else
#endif /* ARRAY_VARS */
tem = makunbound (name, unset_function ? shell_functions : shell_variables);
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if ((tem == -1) && !unset_function && !unset_variable)
tem = makunbound (name, shell_functions);
if (tem == -1)
any_failed++;
else if (!unset_function)
stupidly_hack_special_variables (name);
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}
+50
View File
@@ -0,0 +1,50 @@
/* unwind_prot.h - Macros and functions for hacking unwind protection. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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 2, or (at your option) any later
version.
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_UNWIND_PROT_H)
#define _UNWIND_PROT_H
/* Run a function without interrupts. */
extern void begin_unwind_frame ();
extern void discard_unwind_frame ();
extern void run_unwind_frame ();
extern void add_unwind_protect ();
extern void remove_unwind_protect ();
extern void run_unwind_protects ();
extern void unwind_protect_var ();
/* Define for people who like their code to look a certain way. */
#define end_unwind_frame()
/* How to protect an integer. */
#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
/* How to protect a pointer to a string. */
#define unwind_protect_string(X) \
unwind_protect_var ((int *)&(X), (X), sizeof (char *))
/* How to protect any old pointer. */
#define unwind_protect_pointer(X) unwind_protect_string (X)
/* How to protect the contents of a jmp_buf. */
#define unwind_protect_jmp_buf(X) \
unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t))
#endif /* _UNWIND_PROT_H */
+2
View File
@@ -894,6 +894,7 @@ tests/exp6.sub f
tests/extglob.tests f
tests/extglob.right f
tests/extglob1.sub f
tests/extglob1a.sub f
tests/extglob2.tests f
tests/extglob2.right f
tests/extglob3.tests f
@@ -970,6 +971,7 @@ tests/nameref2.sub f
tests/nameref3.sub f
tests/nameref4.sub f
tests/nameref5.sub f
tests/nameref6.sub f
tests/nameref.right f
tests/new-exp.tests f
tests/new-exp1.sub f
+1226
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -301,6 +301,24 @@ declare_internal (list, local_var)
else
value = "";
/* Do some lexical error checking on the LHS and RHS of the assignment
that is specific to nameref variables. */
if (flags_on & att_nameref)
{
if (valid_array_reference (name))
{
builtin_error (_("%s: reference variable cannot be an array"), name);
assign_error++;
NEXT_VARIABLE ();
}
else if (STREQ (name, value))
{
builtin_error (_("%s: nameref variable self references not allowed"), name);
assign_error++;
NEXT_VARIABLE ();
}
}
#if defined (ARRAY_VARS)
compound_array_assign = simple_array_assign = 0;
subscript_start = (char *)NULL;
@@ -493,6 +511,13 @@ declare_internal (list, local_var)
VSETATTR (var, att_invisible);
}
}
/* Can't take an existing array variable and make it a nameref */
else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
{
builtin_error (_("%s: reference variable cannot be an array"), name);
assign_error++;
NEXT_VARIABLE ();
}
/* Cannot use declare +r to turn off readonly attribute. */
if (readonly_p (var) && (flags_off & att_readonly))
+686
View File
@@ -0,0 +1,686 @@
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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.
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES declare.c
$BUILTIN declare
$FUNCTION declare_builtin
$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
Set variable values and attributes.
Declare variables and give them attributes. If no NAMEs are given,
display the attributes and values of all variables.
Options:
-f restrict action or display to function names and definitions
-F restrict display to function names only (plus line number and
source file when debugging)
-g create global variables when used in a shell function; otherwise
ignored
-p display the attributes and value of each NAME
Options which set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
-i to make NAMEs have the `integer' attribute
-l to convert NAMEs to lower case on assignment
-n make NAME a reference to the variable named by its value
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute
-u to convert NAMEs to upper case on assignment
-x to make NAMEs export
Using `+' instead of `-' turns off the given attribute.
Variables with the integer attribute have arithmetic evaluation (see
the `let' command) performed when the variable is assigned a value.
When used in a function, `declare' makes NAMEs local, as with the `local'
command. The `-g' option suppresses this behavior.
Exit Status:
Returns success unless an invalid option is supplied or an error occurs.
$END
$BUILTIN typeset
$FUNCTION declare_builtin
$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
Set variable values and attributes.
Obsolete. See `help declare'.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "common.h"
#include "builtext.h"
#include "bashgetopt.h"
extern int array_needs_making;
extern int posixly_correct;
static int declare_internal __P((register WORD_LIST *, int));
/* Declare or change variable attributes. */
int
declare_builtin (list)
register WORD_LIST *list;
{
return (declare_internal (list, 0));
}
$BUILTIN local
$FUNCTION local_builtin
$SHORT_DOC local [option] name[=value] ...
Define local variables.
Create a local variable called NAME, and give it VALUE. OPTION can
be any option accepted by `declare'.
Local variables can only be used within a function; they are visible
only to the function where they are defined and its children.
Exit Status:
Returns success unless an invalid option is supplied, an error occurs,
or the shell is not executing a function.
$END
int
local_builtin (list)
register WORD_LIST *list;
{
if (variable_context)
return (declare_internal (list, 1));
else
{
builtin_error (_("can only be used in a function"));
return (EXECUTION_FAILURE);
}
}
#if defined (ARRAY_VARS)
# define DECLARE_OPTS "+acfgilnprtuxAF"
#else
# define DECLARE_OPTS "+cfgilnprtuxF"
#endif
/* The workhorse function. */
static int
declare_internal (list, local_var)
register WORD_LIST *list;
int local_var;
{
int flags_on, flags_off, *flags;
int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
char *t, *subscript_start;
SHELL_VAR *var, *refvar;
FUNCTION_DEF *shell_fn;
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
refvar = (SHELL_VAR *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
{
flags = list_opttype == '+' ? &flags_off : &flags_on;
switch (opt)
{
case 'a':
#if defined (ARRAY_VARS)
*flags |= att_array;
break;
#else
builtin_usage ();
return (EX_USAGE);
#endif
case 'A':
#if defined (ARRAY_VARS)
*flags |= att_assoc;
break;
#else
builtin_usage ();
return (EX_USAGE);
#endif
case 'p':
if (local_var == 0)
pflag++;
break;
case 'F':
nodefs++;
*flags |= att_function;
break;
case 'f':
*flags |= att_function;
break;
case 'g':
if (flags == &flags_on)
mkglobal = 1;
break;
case 'i':
*flags |= att_integer;
break;
case 'n':
*flags |= att_nameref;
break;
case 'r':
*flags |= att_readonly;
break;
case 't':
*flags |= att_trace;
break;
case 'x':
*flags |= att_exported;
array_needs_making = 1;
break;
#if defined (CASEMOD_ATTRS)
# if defined (CASEMOD_CAPCASE)
case 'c':
*flags |= att_capcase;
if (flags == &flags_on)
flags_off |= att_uppercase|att_lowercase;
break;
# endif
case 'l':
*flags |= att_lowercase;
if (flags == &flags_on)
flags_off |= att_capcase|att_uppercase;
break;
case 'u':
*flags |= att_uppercase;
if (flags == &flags_on)
flags_off |= att_capcase|att_lowercase;
break;
#endif /* CASEMOD_ATTRS */
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* If there are no more arguments left, then we just want to show
some variables. */
if (list == 0) /* declare -[aAfFirtx] */
{
/* Show local variables defined at this context level if this is
the `local' builtin. */
if (local_var)
{
register SHELL_VAR **vlist;
register int i;
vlist = all_local_variables ();
if (vlist)
{
for (i = 0; vlist[i]; i++)
print_assignment (vlist[i]);
free (vlist);
}
}
else if (pflag && (flags_on == 0 || flags_on == att_function))
show_all_var_attributes (flags_on == 0, nodefs);
else if (flags_on == 0)
return (set_builtin ((WORD_LIST *)NULL));
else
set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
return (sh_chkwrite (EXECUTION_SUCCESS));
}
if (pflag) /* declare -p [-aAfFirtx] name [name...] */
{
for (any_failed = 0; list; list = list->next)
{
pflag = show_name_attributes (list->word->word, nodefs);
if (pflag)
{
sh_notfound (list->word->word);
any_failed++;
}
}
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
while (list) /* declare [-aAfFirx] name [name ...] */
{
char *value, *name;
int offset, aflags;
#if defined (ARRAY_VARS)
int making_array_special, compound_array_assign, simple_array_assign;
#endif
name = savestring (list->word->word);
offset = assignment (name, 0);
aflags = 0;
if (offset) /* declare [-aAfFirx] name=value */
{
name[offset] = '\0';
value = name + offset + 1;
if (name[offset - 1] == '+')
{
aflags |= ASS_APPEND;
name[offset - 1] = '\0';
}
}
else
value = "";
/* Do some lexical error checking on the LHS and RHS of the assignment
that is specific to nameref variables. */
if (flags_on & att_nameref)
{
if (valid_array_reference (name))
{
builtin_error (_("%s: reference variable cannot be an array"), name);
assign_error++;
NEXT_VARIABLE ();
}
else if (STREQ (name, value))
{
builtin_error (_("%s: nameref variable self references not allowed"), name);
assign_error++;
NEXT_VARIABLE ();
}
}
#if defined (ARRAY_VARS)
compound_array_assign = simple_array_assign = 0;
subscript_start = (char *)NULL;
if (t = strchr (name, '[')) /* ] */
{
/* If offset != 0 we have already validated any array reference */
if (offset == 0 && valid_array_reference (name) == 0)
{
sh_invalidid (name);
assign_error++;
NEXT_VARIABLE ();
}
subscript_start = t;
*t = '\0';
making_array_special = 1;
}
else
making_array_special = 0;
#endif
/* If we're in posix mode or not looking for a shell function (since
shell function names don't have to be valid identifiers when the
shell's not in posix mode), check whether or not the argument is a
valid, well-formed shell identifier. */
if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
{
sh_invalidid (name);
assign_error++;
NEXT_VARIABLE ();
}
/* If VARIABLE_CONTEXT has a non-zero value, then we are executing
inside of a function. This means we should make local variables,
not global ones. */
/* XXX - this has consequences when we're making a local copy of a
variable that was in the temporary environment. Watch out
for this. */
refvar = (SHELL_VAR *)NULL;
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
{
#if defined (ARRAY_VARS)
if (flags_on & att_assoc)
var = make_local_assoc_variable (name);
else if ((flags_on & att_array) || making_array_special)
var = make_local_array_variable (name, making_array_special);
else
#endif
#if 0
/* XXX - this doesn't work right yet. */
/* See below for rationale for doing this. */
if (flags_on & att_nameref)
{
/* See if we are trying to modify an existing nameref variable */
var = find_variable_last_nameref (name);
if (var && nameref_p (var) == 0)
var = make_local_variable (name);
}
else if (flags_off & att_nameref)
{
var = (SHELL_VAR *)NULL;
/* See if we are trying to modify an existing nameref variable */
refvar = find_variable_last_nameref (name);
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
if (refvar)
var = make_local_variable (nameref_cell (refvar));
if (var == 0)
var = make_local_variable (name);
}
else
#endif
var = make_local_variable (name);
if (var == 0)
{
any_failed++;
NEXT_VARIABLE ();
}
}
else
var = (SHELL_VAR *)NULL;
/* If we are declaring a function, then complain about it in some way.
We don't let people make functions by saying `typeset -f foo=bar'. */
/* There should be a way, however, to let people look at a particular
function definition by saying `typeset -f foo'. */
if (flags_on & att_function)
{
if (offset) /* declare -f [-rix] foo=bar */
{
builtin_error (_("cannot use `-f' to make functions"));
free (name);
return (EXECUTION_FAILURE);
}
else /* declare -f [-rx] name [name...] */
{
var = find_function (name);
if (var)
{
if (readonly_p (var) && (flags_off & att_readonly))
{
builtin_error (_("%s: readonly function"), name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -[Ff] name [name...] */
if (flags_on == att_function && flags_off == 0)
{
#if defined (DEBUGGER)
if (nodefs && debugging_mode)
{
shell_fn = find_function_def (var->name);
if (shell_fn)
printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
else
printf ("%s\n", var->name);
}
else
#endif /* DEBUGGER */
{
t = nodefs ? var->name
: named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
printf ("%s\n", t);
any_failed = sh_chkwrite (any_failed);
}
}
else /* declare -[fF] -[rx] name [name...] */
{
VSETATTR (var, flags_on);
VUNSETATTR (var, flags_off);
}
}
else
any_failed++;
NEXT_VARIABLE ();
}
}
else /* declare -[aAirx] name [name...] */
{
/* Non-null if we just created or fetched a local variable. */
/* Here's what ksh93 seems to do. If we are modifying an existing
nameref variable, we don't follow the nameref chain past the last
nameref, and we set the nameref variable's value so future
references to that variable will return the value of the variable
we're assigning right now. */
if (var == 0 && (flags_on & att_nameref))
{
/* See if we are trying to modify an existing nameref variable */
var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
if (var && nameref_p (var) == 0)
var = 0;
}
/* However, if we're turning off the nameref attribute on an existing
nameref variable, we first follow the nameref chain to the end,
modify the value of the variable this nameref variable references,
*CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
else if (var == 0 && (flags_off & att_nameref))
{
/* See if we are trying to modify an existing nameref variable */
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
if (refvar)
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
}
#if defined (ARRAY_VARS)
else if (var && (array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
{
builtin_error (_("%s: reference variable cannot be an array"), var->name);
assign_error++;
NEXT_VARIABLE ();
}
#endif
if (var == 0)
var = mkglobal ? find_global_variable (name) : find_variable (name);
if (var == 0)
{
#if defined (ARRAY_VARS)
if (flags_on & att_assoc)
var = make_new_assoc_variable (name);
else if ((flags_on & att_array) || making_array_special)
var = make_new_array_variable (name);
else
#endif
if (offset)
var = bind_variable (name, "", 0);
else
{
var = bind_variable (name, (char *)NULL, 0);
VSETATTR (var, att_invisible);
}
}
/* Cannot use declare +r to turn off readonly attribute. */
if (readonly_p (var) && (flags_off & att_readonly))
{
sh_readonly (name);
any_failed++;
NEXT_VARIABLE ();
}
/* Cannot use declare to assign value to readonly or noassign
variable. */
if ((readonly_p (var) || noassign_p (var)) && offset)
{
if (readonly_p (var))
sh_readonly (name);
assign_error++;
NEXT_VARIABLE ();
}
#if defined (ARRAY_VARS)
if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
{
int vlen;
vlen = STRLEN (value);
if (value[0] == '(' && value[vlen-1] == ')')
compound_array_assign = 1;
else
simple_array_assign = 1;
}
/* Cannot use declare +a name or declare +A name to remove an
array variable. */
if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
{
builtin_error (_("%s: cannot destroy array variables in this way"), name);
any_failed++;
NEXT_VARIABLE ();
}
if ((flags_on & att_array) && assoc_p (var))
{
builtin_error (_("%s: cannot convert associative to indexed array"), name);
any_failed++;
NEXT_VARIABLE ();
}
if ((flags_on & att_assoc) && array_p (var))
{
builtin_error (_("%s: cannot convert indexed to associative array"), name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -A name[[n]] makes name an associative array variable. */
if (flags_on & att_assoc)
{
if (assoc_p (var) == 0)
var = convert_var_to_assoc (var);
}
/* declare -a name[[n]] or declare name[n] makes name an indexed
array variable. */
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
var = convert_var_to_array (var);
#endif /* ARRAY_VARS */
/* XXX - we note that we are turning on nameref attribute and defer
setting it until the assignment has been made so we don't do an
inadvertent nameref lookup. Might have to do the same thing for
flags_off&att_nameref. */
/* XXX - ksh93 makes it an error to set a readonly nameref variable
using a single typeset command. */
onref = (flags_on & att_nameref);
flags_on &= ~att_nameref;
if (array_p (var) || assoc_p (var)
|| (offset && compound_array_assign)
|| simple_array_assign)
onref = 0; /* array variables may not be namerefs */
/* ksh93 seems to do this */
offref = (flags_off & att_nameref);
flags_off &= ~att_nameref;
VSETATTR (var, flags_on);
VUNSETATTR (var, flags_off);
#if defined (ARRAY_VARS)
if (offset && compound_array_assign)
assign_array_var_from_string (var, value, aflags);
else if (simple_array_assign && subscript_start)
{
/* declare [-aA] name[N]=value */
*subscript_start = '['; /* ] */
var = assign_array_element (name, value, 0); /* XXX - not aflags */
*subscript_start = '\0';
if (var == 0) /* some kind of assignment error */
{
assign_error++;
flags_on |= onref;
flags_off |= offref;
NEXT_VARIABLE ();
}
}
else if (simple_array_assign)
{
/* let bind_{array,assoc}_variable take care of this. */
if (assoc_p (var))
bind_assoc_variable (var, name, savestring ("0"), value, aflags);
else
bind_array_variable (name, 0, value, aflags);
}
else
#endif
/* bind_variable_value duplicates the essential internals of
bind_variable() */
if (offset)
bind_variable_value (var, value, aflags);
/* If we found this variable in the temporary environment, as with
`var=value declare -x var', make sure it is treated identically
to `var=value export var'. Do the same for `declare -r' and
`readonly'. Preserve the attributes, except for att_tempvar. */
/* XXX -- should this create a variable in the global scope, or
modify the local variable flags? ksh93 has it modify the
global scope.
Need to handle case like in set_var_attribute where a temporary
variable is in the same table as the function local vars. */
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
{
SHELL_VAR *tv;
char *tvalue;
tv = find_tempenv_variable (var->name);
if (tv)
{
tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
tv = bind_variable (var->name, tvalue, 0);
tv->attributes |= var->attributes & ~att_tempvar;
if (tv->context > 0)
VSETATTR (tv, att_propagate);
free (tvalue);
}
VSETATTR (var, att_propagate);
}
}
/* Turn on nameref attribute we deferred above. */
/* XXX - should we turn on the noassign attribute for consistency with
ksh93 when we turn on the nameref attribute? */
VSETATTR (var, onref);
flags_on |= onref;
VUNSETATTR (var, offref);
flags_off |= offref;
/* Yuck. ksh93 compatibility */
if (refvar)
VUNSETATTR (refvar, flags_off);
stupidly_hack_special_variables (name);
NEXT_VARIABLE ();
}
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}
+1
View File
@@ -84,6 +84,7 @@ Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set
-R VAR True if the shell variable VAR is set and is a name reference.
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
+158
View File
@@ -0,0 +1,158 @@
This file is test.def, from which is created test.c.
It implements the builtin "test" in Bash.
Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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.
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES test.c
$BUILTIN test
$FUNCTION test_builtin
$SHORT_DOC test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
-a FILE True if file exists.
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-O FILE True if the file is effectively owned by you.
-G FILE True if the file is effectively owned by your group.
-N FILE True if the file has been modified since it was last read.
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
modification date).
FILE1 -ot FILE2 True if file1 is older than file2.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
Arithmetic binary operators return true if ARG1 is equal, not-equal,
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
than ARG2.
Exit Status:
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
false or an invalid argument is given.
$END
$BUILTIN [
$DOCNAME test_bracket
$FUNCTION test_builtin
$SHORT_DOC [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "../test.h"
#include "common.h"
extern char *this_command_name;
/* TEST/[ builtin. */
int
test_builtin (list)
WORD_LIST *list;
{
char **argv;
int argc, result;
/* We let Matthew Bradburn and Kevin Braunsdorf's code do the
actual test command. So turn the list of args into an array
of strings, since that is what their code wants. */
if (list == 0)
{
if (this_command_name[0] == '[' && !this_command_name[1])
{
builtin_error (_("missing `]'"));
return (EX_BADUSAGE);
}
return (EXECUTION_FAILURE);
}
argv = make_builtin_argv (list, &argc);
result = test_command (argc, argv);
free ((char *)argv);
return (result);
}
+1
View File
@@ -356,6 +356,7 @@ typedef struct coproc {
int c_wsave;
int c_flags;
int c_status;
int c_lock;
} Coproc;
typedef struct coproc_com {
+42
View File
@@ -0,0 +1,42 @@
# This file is a shell script that caches the results of configure
# tests for CYGWIN32 so they don't need to be done when cross-compiling.
# AC_FUNC_GETPGRP should also define GETPGRP_VOID
ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
# AC_FUNC_SETVBUF_REVERSED should not define anything else
ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
# on CYGWIN32, system calls do not restart
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
# these may be necessary, but they are currently commented out
#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
# end of cross-build/cygwin32.cache
+1745
View File
File diff suppressed because it is too large Load Diff
+7 -2
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
.\" Last Change: Mon Sep 17 09:26:34 EDT 2012
.\" Last Change: Sun Oct 7 17:59:28 EDT 2012
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2012 September 17" "GNU Bash 4.2"
.TH BASH 1 "2012 October 7" "GNU Bash 4.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -4237,6 +4237,11 @@ True if the shell variable
.I varname
is set (has been assigned a value).
.TP
.B \-R \fIvarname\fP
True if the shell variable
.I varname
is set and is a name reference.
.TP
.B \-z \fIstring\fP
True if the length of \fIstring\fP is zero.
.TP
+10224
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -6424,6 +6424,9 @@ option to the @code{set} builtin (@pxref{The Set Builtin}).
@item -v @var{varname}
True if the shell variable @var{varname} is set (has been assigned a value).
@item -R @var{varname}
True if the shell variable @var{varname} is set and is a name reference.
@item -z @var{string}
True if the length of @var{string} is zero.
+8617
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -2,9 +2,9 @@
Copyright (C) 1988-2012 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Mon Sep 17 09:26:53 EDT 2012
@set LASTCHANGE Sun Oct 7 17:58:01 EDT 2012
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 17 September 2012
@set UPDATED-MONTH September 2012
@set UPDATED 7 October 2012
@set UPDATED-MONTH October 2012
+10
View File
@@ -0,0 +1,10 @@
@ignore
Copyright (C) 1988-2012 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Mon Sep 17 09:26:53 EDT 2012
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 17 September 2012
@set UPDATED-MONTH September 2012
+238
View File
@@ -0,0 +1,238 @@
#
# Simple makefile for the sample loadable builtins
#
# Copyright (C) 1996 Free Software Foundation, Inc.
# This program 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 2, or (at your option)
# any later version.
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
# Include some boilerplate Gnu makefile definitions.
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
infodir = @infodir@
includedir = @includedir@
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
srcdir = @srcdir@
VPATH = .:@srcdir@
@SET_MAKE@
CC = @CC@
RM = rm -f
SHELL = @MAKE_SHELL@
host_os = @host_os@
host_cpu = @host_cpu@
host_vendor = @host_vendor@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
DEFS = @DEFS@
LOCAL_DEFS = @LOCAL_DEFS@
CPPFLAGS = @CPPFLAGS@
BASHINCDIR = ${topdir}/include
LIBBUILD = ${BUILD_DIR}/lib
INTL_LIBSRC = ${topdir}/lib/intl
INTL_BUILDDIR = ${LIBBUILD}/intl
INTL_INC = @INTL_INC@
LIBINTL_H = @LIBINTL_H@
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
#
# These values are generated for configure by ${topdir}/support/shobj-conf.
# If your system is not supported by that script, but includes facilities for
# dynamic loading of shared objects, please update the script and send the
# changes to bash-maintainers@gnu.org.
#
SHOBJ_CC = @SHOBJ_CC@
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
SHOBJ_LD = @SHOBJ_LD@
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
SHOBJ_LIBS = @SHOBJ_LIBS@
SHOBJ_STATUS = @SHOBJ_STATUS@
INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
-I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
-I$(BUILD_DIR)/builtins $(INTL_INC)
.c.o:
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
tty pathchk tee head mkdir rmdir printenv id whoami \
uname sync push ln unlink cut realpath getconf strftime
OTHERPROG = necho hello cat
all: $(SHOBJ_STATUS)
supported: $(ALLPROG)
others: $(OTHERPROG)
unsupported:
@echo "Your system (${host_os}) is not supported by the"
@echo "${topdir}/support/shobj-conf script."
@echo "If your operating system provides facilities for dynamic"
@echo "loading of shared objects using the dlopen(3) interface,"
@echo "please update the script and re-run configure.
@echo "Please send the changes you made to bash-maintainers@gnu.org"
@echo "for inclusion in future bash releases."
everything: supported others
print: print.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
necho: necho.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
getconf: getconf.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
hello: hello.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
truefalse: truefalse.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
sleep: sleep.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
finfo: finfo.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
cat: cat.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
logname: logname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
basename: basename.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
dirname: dirname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
tty: tty.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
pathchk: pathchk.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
tee: tee.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
mkdir: mkdir.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
rmdir: rmdir.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
head: head.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
printenv: printenv.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
id: id.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
whoami: whoami.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
uname: uname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
sync: sync.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
push: push.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
ln: ln.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
unlink: unlink.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
cut: cut.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
realpath: realpath.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
strftime: strftime.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
# pushd is a special case. We use the same source that the builtin version
# uses, with special compilation options.
#
pushd.c: ${topdir}/builtins/pushd.def
$(RM) $@
${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
pushd.o: pushd.c
$(RM) $@
$(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
pushd: pushd.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
clean:
$(RM) $(ALLPROG) $(OTHERPROG) *.o
-( cd perl && ${MAKE} ${MFLAGS} $@ )
mostlyclean: clean
-( cd perl && ${MAKE} ${MFLAGS} $@ )
distclean maintainer-clean: clean
$(RM) Makefile pushd.c
-( cd perl && ${MAKE} ${MFLAGS} $@ )
print.o: print.c
truefalse.o: truefalse.c
sleep.o: sleep.c
finfo.o: finfo.c
logname.o: logname.c
basename.o: basename.c
dirname.o: dirname.c
tty.o: tty.c
pathchk.o: pathchk.c
tee.o: tee.c
head.o: head.c
rmdir.o: rmdir.c
necho.o: necho.c
getconf.o: getconf.c
hello.o: hello.c
cat.o: cat.c
printenv.o: printenv.c
id.o: id.c
whoami.o: whoami.c
uname.o: uname.c
sync.o: sync.c
push.o: push.c
mkdir.o: mkdir.c
realpath.o: realpath.c
strftime.o: strftime.c
+549
View File
@@ -0,0 +1,549 @@
#!/bin/bash
# ash -- "Adventure shell"
# last edit: 86/04/21 D A Gwyn
# SCCS ID: @(#)ash.sh 1.4
OPATH=$PATH
ask()
{
echo -n "$@" '[y/n] '
read ans
case "$ans" in
y*|Y*)
return 0
;;
*)
return 1
;;
esac
}
CAT=${PAGER:-more}
ash_inst()
{
cat <<- EOF
Instructions for the Adventure shell
Welcome to the Adventure shell! In this exploration of the UNIX file
system, I will act as your eyes and hands. As you move around, I will
describe whatever is visible and will carry out your commands. The
general form of a command is
Verb Object Extra_stuff.
Most commands pay no attention to the "Extra_stuff", and many do not
need an "Object". A typical command is
get all
which picks up all files in the current "room" (directory). You can
find out what you are carrying by typing the command
inventory
The command "help" results in a full description of all commands that I
understand. To quit the Adventure shell, type
quit
There are UNIX monsters lurking in the background. These are also
known as "commands with arguments".
Good luck!
EOF
}
ash_help()
{
echo "I understand the following commands (synonyms in parentheses):"
echo ""
echo "change OBJECT to NEW_NAME changes the name of the object"
echo "clone OBJECT as NEW_NAME duplicates the object"
echo "drop OBJECTS leaves the objects in the room"
echo "enter (go) PASSAGE takes the labeled passage"
echo "examine OBJECTS describes the objects in detail"
echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster"
echo "get (take) OBJECTS picks up the specified objects"
echo "gripe (bug) report a problem with the Adventure shell"
echo "help prints this summary"
echo "inventory (i) tells what you are carrying"
echo "kill (destroy) OBJECTS destroys the objects"
echo "look (l) describes the room, including hidden objects"
echo "open (read) OBJECT shows the contents of an object"
echo "quit (exit) leaves the Adventure shell"
echo "resurrect OBJECTS attempts to restore dead objects"
echo "steal OBJECT from MONSTER obtains the object from a UNIX monster"
echo "throw OBJECT at daemon feeds the object to the printer daemon"
echo "up takes the overhead passage"
echo "wake MONSTER awakens a UNIX monster"
echo "where (w) tells you where you are"
echo "xyzzy moves you to your home"
}
MAINT=chet@ins.cwru.edu
PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
export PATH
trap 'echo Ouch!' 2 3
#trap '' 18 # disable Berkeley job control
ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
# enable history, bang history expansion, and emacs editing
set -o history
set -o histexpand
set -o emacs
cd
LIM=.limbo # $HOME/$LIM contains "destroyed" objects
mkdir $LIM >&- 2>&-
KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
if [ ! -d $KNAP ]
then mkdir $KNAP >&- 2>&-
if [ $? = 0 ]
then echo 'You found a discarded empty knapsack.'
else echo 'You have no knapsack to carry things in.'
exit 1
fi
else echo 'One moment while I peek in your old knapsack...'
fi
kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
if ask 'Welcome to the Adventure shell! Do you need instructions?'
then
ash_inst
echo -n 'Type a newline to continue: '
read
fi
wiz=false
cha=false
prev=$LIM
while :
do room=`pwd`
if [ $room != $prev ]
then if [ $room = $HOME ]
then echo 'You are in your own home.'
else echo "You have entered $room."
fi
exs=
obs=
hexs=
hobs=
f=false
for i in `ls -a`
do case $i in
.|..) ;;
.*) if [ -f $i ]
then hobs="$hobs $i"
elif [ -d $i ]
then hexs="$hexs $i"
else f=true
fi
;;
*) if [ -f $i ]
then obs="$obs $i"
elif [ -d $i ]
then exs="$exs $i"
else f=true
fi
;;
esac
done
if [ "$obs" ]
then echo 'This room contains:'
ash_pr $obs
else echo 'The room looks empty.'
fi
if [ "$exs" ]
then echo 'There are exits labeled:'
ash_pr $exs
echo 'as well as a passage overhead.'
else echo 'There is a passage overhead.'
fi
if sh -c $f
then echo 'There are shadowy figures in the corner.'
fi
prev=$room
fi
read -e -p '-advsh> ' verb obj x # prompt is '-advsh> '
if [ $? != 0 ]
then verb=quit # EOF
fi
case $verb in
change) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
to) if [ "$2" ]
then if [ -f $2 ]
then echo "You must destroy $2 first."
set --
fi
if [ "$2" ]
then if mv $obj $2 >&- 2>&-
then echo "The $obj shimmers and turns into $2."
obs=`ash_rm "$2 $obs" "$obj"`
else echo "There is a cloud of smoke but the $obj is unchanged."
fi
fi
else echo 'To what?'
fi
;;
*) echo "Change $obj to what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Change what?'
fi
;;
clone) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then if [ ! -r $obj ]
then echo "The $obj does not wish to be cloned."
else set -- $x
case "$1" in
as) if [ "$2" ]
then if [ -f $2 ]
then echo "You must destroy $2 first."
else if cp $obj $2 >&- 2>&-
then echo "Poof! When the smoke clears, you see the new $2."
obs="$obs $2"
else echo 'You hear a dull thud but no clone appears.'
fi
fi
else echo 'As what?'
fi
;;
*) echo "Clone $obj as what?"
;;
esac
fi
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Clone what?'
fi
;;
drop) if [ "$obj" ]
then for it in $obj $x
do if ash_lk "$kn" "$it"
then if [ -w $it ]
then echo "You must destroy $it first."
else if mv $HOME/$KNAP/$it $it >&- 2>&-
then echo "$it: dropped."
kn=`ash_rm "$kn" "$it"`
obs=`echo $it $obs`
else echo "The $it is caught in your knapsack."
fi
fi
else echo "You're not carrying the $it!"
fi
done
else echo 'Drop what?'
fi
;;
enter|go) if [ "$obj" ]
then if [ $obj != up ]
then if ash_lk "$exs $hexs" "$obj"
then if [ -x $obj ]
then if cd $obj
then echo 'You squeeze through the passage.'
else echo "You can't go that direction."
fi
else echo 'An invisible force blocks your way.'
fi
else echo 'I see no such passage.'
fi
else if cd ..
then echo 'You struggle upwards.'
else echo "You can't reach that high."
fi
fi
else echo 'Which passage?'
fi
;;
examine) if [ "$obj" ]
then if [ $obj = all ]
then $obj=`echo $obs $exs`
x=
fi
for it in $obj $x
do if ash_lk "$obs $hobs $exs $hexs" "$it"
then echo "Upon close inspection of the $it, you see:"
ls -ld $it 2>&-
if [ $? != 0 ]
then echo "-- when you look directly at the $it, it vanishes."
fi
else if ash_lk "$kn" "$it"
then echo 'You must drop it first.'
else echo "I see no $it here."
fi
fi
done
else echo 'Examine what?'
fi
;;
feed) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
to) if [ "$2" ]
then shift
if PATH=$OPATH $* <$obj 2>&-
then echo "The $1 monster devours your $obj."
if rm -f $obj >&- 2>&-
then obs=`ash_rm "$obs" "$obj"`
else echo 'But he spits it back up.'
fi
else echo "The $1 monster holds his nose in disdain."
fi
else echo 'To what?'
fi
;;
*) echo "Feed $obj to what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Feed what?'
fi
;;
get|take) if [ "$obj" ]
then if [ $obj = all ]
then obj="$obs"
x=
fi
for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then if ash_lk "$kn" "$it"
then echo 'You already have one.'
else if mv $it $HOME/$KNAP/$it >&- 2>&-
then echo "$it: taken."
kn="$it $kn"
obs=`ash_rm "$obs" "$it"`
else echo "The $it is too heavy."
fi
fi
else echo "I see no $it here."
fi
done
else echo 'Get what?'
fi
;;
gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
cat | mail $MAINT -s 'ash bug'
echo 'Thank you!'
;;
help) ash_help
;;
inventory|i) if [ "$kn" ]
then echo 'Your knapsack contains:'
ash_pr $kn
else echo 'You are poverty-stricken.'
fi
;;
kill|destroy) if [ "$obj" ]
then if [ $obj = all ]
then x=
if ask "Do you really want to attempt to $verb them all?"
then obj=`echo $obs`
else echo 'Chicken!'
obj=
fi
fi
for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then if mv $it $HOME/$LIM <&- >&- 2>&-
then if [ $verb = kill ]
then echo "The $it cannot defend himself; he dies."
else echo "You have destroyed the $it; it vanishes."
fi
obs=`ash_rm "$obs" "$it"`
else if [ $verb = kill ]
then echo "Your feeble blows are no match for the $it."
else echo "The $it is indestructible."
fi
fi
else if ash_lk "$kn" "$it"
then echo "You must drop the $it first."
found=false
else echo "I see no $it here."
fi
fi
done
else echo 'Kill what?'
fi
;;
look|l) obs=`echo $obs $hobs`
hobs=
if [ "$obs" ]
then echo 'The room contains:'
ash_pr $obs
else echo 'The room is empty.'
fi
exs=`echo $exs $hexs`
hexs=
if [ "$exs" ]
then echo 'There are exits plainly labeled:'
ash_pr $exs
echo 'and a passage directly overhead.'
else echo 'The only exit is directly overhead.'
fi
;;
magic) if [ "$obj" = mode ]
then if sh -c $cha
then echo 'You had your chance and you blew it.'
else if ask 'Are you a wizard?'
then echo -n 'Prove it! Say the magic word: '
read obj
if [ "$obj" = armadillo ]
then echo 'Yes, master!!'
wiz=true
else echo "Homie says: I don't think so"
cha=true
fi
else echo "I didn't think so."
fi
fi
else echo 'Nice try.'
fi
;;
open|read) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then if [ -r $obj ]
then if [ -s $obj ]
then echo "Opening the $obj reveals:"
$CAT < $obj
if [ $? != 0 ]
then echo '-- oops, you lost the contents!'
fi
else echo "There is nothing inside the $obj."
fi
else echo "You do not have the proper tools to open the $obj."
fi
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
found=false
else echo "I see no $obj here."
fi
fi
else echo 'Open what?'
fi
;;
quit|exit) if ask 'Do you really want to quit now?'
then if [ "$kn" ]
then echo 'The contents of your knapsack will still be there next time.'
fi
rm -rf $HOME/$LIM
echo 'See you later!'
exit 0
fi
;;
resurrect) if [ "$obj" ]
then for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then echo "The $it is already alive and well."
else if mv $HOME/$LIM/$it $it <&- >&- 2>&-
then echo "The $it staggers to his feet."
obs=`echo $it $obs`
else echo "There are sparks but no $it appears."
fi
fi
done
else echo 'Resurrect what?'
fi
;;
steal) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then echo 'There is already one here.'
else set -- $x
case "$1" in
from) if [ "$2" ]
then shift
if PATH=$OPATH $* >$obj 2>&-
then echo "The $1 monster drops the $obj."
obs=`echo $obj $obs`
else echo "The $1 monster runs away as you approach."
rm -f $obj >&- 2>&-
fi
else echo 'From what?'
fi
;;
*) echo "Steal $obj from what?"
;;
esac
fi
else echo 'Steal what?'
fi
;;
throw) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
at) case "$2" in
daemon) if sh -c "lpr -r $obj"
then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
obs=`ash_rm "$obs" "$obj"`
else echo "The daemon is nowhere to be found."
fi
;;
*) echo 'At what?'
;;
esac
;;
*) echo "Throw $obj at what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'It is in your knapsack.'
found=false
else echo "I see no $obj here."
fi
fi
else echo 'Throw what?'
fi
;;
u|up) if cd ..
then echo 'You pull yourself up a level.'
else echo "You can't reach that high."
fi
;;
wake) if [ "$obj" ]
then echo "You awaken the $obj monster:"
PATH=$OPATH $obj $x
echo 'The monster slithers back into the darkness.'
else echo 'Wake what?'
fi
;;
w|where) echo "You are in $room."
;;
xyzzy) if cd
then echo 'A strange feeling comes over you.'
else echo 'Your spell fizzles out.'
fi
;;
*) if [ "$verb" ]
then if sh -c $wiz
then PATH=$OPATH $verb $obj $x
else echo "I don't know how to \"$verb\"."
echo 'Type "help" for assistance.'
fi
else echo 'Say something!'
fi
;;
esac
done
+24 -13
View File
@@ -1592,6 +1592,7 @@ typedef struct cplist
struct cpelement *head;
struct cpelement *tail;
int ncoproc;
int lock;
}
cplist_t;
@@ -1609,7 +1610,7 @@ static void cpl_prune __P((void));
static void coproc_free __P((struct coproc *));
/* Will go away when there is fully-implemented support for multiple coprocs. */
Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0 };
Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0, 0 };
cplist_t coproc_list = {0, 0, 0};
@@ -1859,7 +1860,7 @@ coproc_init (cp)
cp->c_pid = NO_PID;
cp->c_rfd = cp->c_wfd = -1;
cp->c_rsave = cp->c_wsave = -1;
cp->c_flags = cp->c_status = 0;
cp->c_flags = cp->c_status = cp->c_lock = 0;
}
struct coproc *
@@ -1875,14 +1876,14 @@ coproc_alloc (name, pid)
cp = &sh_coproc;
#endif
coproc_init (cp);
cp->c_lock = 2;
cp->c_name = savestring (name);
cp->c_pid = pid;
cp->c_name = savestring (name);
#if MULTIPLE_COPROCS
cpl_add (cp);
#endif
cp->c_lock = 0;
return (cp);
}
@@ -1897,9 +1898,13 @@ void
coproc_dispose (cp)
struct coproc *cp;
{
sigset_t set, oset;
if (cp == 0)
return;
BLOCK_SIGNAL (SIGCHLD, set, oset);
cp->c_lock = 3;
coproc_unsetvars (cp);
FREE (cp->c_name);
coproc_close (cp);
@@ -1907,7 +1912,9 @@ coproc_dispose (cp)
coproc_free (cp);
#else
coproc_init (cp);
cp->c_lock = 0;
#endif
UNBLOCK_SIGNAL (oset);
}
/* Placeholder for now. Will require changes for multiple coprocs */
@@ -2055,17 +2062,14 @@ coproc_pidchk (pid, status)
#endif
if (cp)
{
#if 0
itrace("coproc_pidchk: pid %d has died", pid);
#endif
cp->c_lock = 4;
cp->c_status = status;
cp->c_flags |= COPROC_DEAD;
cp->c_flags &= ~COPROC_RUNNING;
#if MULTIPLE_COPROCS
coproc_dispose (cp);
#else
coproc_unsetvars (cp);
#endif
/* Don't dispose the coproc or unset the COPROC_XXX variables because
this is executed in a signal handler context. Wait until coproc_reap
takes care of it. */
cp->c_lock = 0;
}
}
@@ -2159,6 +2163,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
pid_t coproc_pid;
Coproc *cp;
char *tcmd;
sigset_t set, oset;
/* XXX -- can be removed after changes to handle multiple coprocs */
#if !MULTIPLE_COPROCS
@@ -2173,12 +2178,16 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */
sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */
BLOCK_SIGNAL (SIGCHLD, set, oset);
coproc_pid = make_child (savestring (tcmd), 1);
if (coproc_pid == 0)
{
close (rpipe[0]);
close (wpipe[1]);
UNBLOCK_SIGNAL (oset);
estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close);
fflush (stdout);
@@ -2199,6 +2208,8 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
coproc_setvars (cp);
UNBLOCK_SIGNAL (oset);
#if 0
itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);
#endif
+1 -1
View File
@@ -1582,7 +1582,7 @@ rl_display_match_list (matches, len, max)
/* Have we reached the end of this line? */
if (matches[i+1])
{
if (i && (limit > 1) && (i % limit) == 0)
if (limit == 1 || (i && (limit > 1) && (i % limit) == 0))
{
rl_crlf ();
lines++;
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
# This makefile for Readline library documentation is in -*- text -*- mode.
# Emacs likes it that way.
RM = rm -f
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
TEXI2HTML = texi2html
QUIETPS = #set this to -q to shut up dvips
DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky
INSTALL_DATA = cp
infodir = /usr/local/info
RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
DVIOBJ = readline.dvi history.dvi
INFOOBJ = readline.info history.info
PSOBJ = readline.ps history.ps
HTMLOBJ = readline.html history.html
all: info dvi html ps
nodvi: info html
readline.dvi: $(RLSRC)
$(TEXI2DVI) rlman.texinfo
mv rlman.dvi readline.dvi
readline.info: $(RLSRC)
$(MAKEINFO) --no-split -o $@ rlman.texinfo
history.dvi: ${HISTSRC}
$(TEXI2DVI) hist.texinfo
mv hist.dvi history.dvi
history.info: ${HISTSRC}
$(MAKEINFO) --no-split -o $@ hist.texinfo
readline.ps: readline.dvi
$(RM) $@
$(DVIPS) readline.dvi
history.ps: history.dvi
$(RM) $@
$(DVIPS) history.dvi
readline.html: ${RLSRC}
$(TEXI2HTML) rlman.texinfo
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html
$(RM) rlman.html rlman_toc.html
history.html: ${HISTSRC}
$(TEXI2HTML) hist.texinfo
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html
$(RM) hist.html hist_toc.html
info: $(INFOOBJ)
dvi: $(DVIOBJ)
ps: $(PSOBJ)
html: $(HTMLOBJ)
clean:
$(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
*.fns *.kys *.tps *.vrs *.o core
distclean: clean
mostlyclean: clean
maintainer-clean: clean
$(RM) *.dvi *.info *.info-* *.ps *.html
install: info
${INSTALL_DATA} readline.info $(infodir)/readline.info
${INSTALL_DATA} history.info $(infodir)/history.info
+16 -1711
View File
File diff suppressed because it is too large Load Diff
+5521
View File
File diff suppressed because it is too large Load Diff
+32 -6
View File
@@ -5728,19 +5728,27 @@ expand_arrayref:
else
temp = (char *)NULL;
}
#if defined (ARRAY_VARS)
/* Handle expanding nameref whose value is x[n] */
else if (var = find_variable_last_nameref (name))
{
temp = nameref_cell (var);
#if defined (ARRAY_VARS)
/* Handle expanding nameref whose value is x[n] */
if (temp && *temp && valid_array_reference (temp))
{
name = temp;
goto expand_arrayref;
}
temp = (char *)NULL;
}
#endif
/* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
else if (temp && *temp && legal_identifier (temp) == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
report_error (_("%s: invalid variable name for name reference"), temp);
temp = &expand_param_error;
}
else
temp = (char *)NULL;
}
else
temp = (char *)NULL;
@@ -5781,6 +5789,9 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
}
}
/* If var_is_special == 0, and name is not an array reference, this does
more expansion than necessary. It should really look up the variable's
value and not try to expand it. */
w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
t = w->word;
/* Have to dequote here if necessary */
@@ -7240,6 +7251,13 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
else
temp = (char *)0;
if (temp == &expand_param_error || temp == &expand_param_fatal)
{
FREE (name);
FREE (value);
return (temp == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
}
#if defined (ARRAY_VARS)
if (valid_array_reference (name))
chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
@@ -7869,10 +7887,10 @@ comsub:
goto return0;
}
#if defined (ARRAY_VARS)
else if (var = find_variable_last_nameref (temp1))
{
temp = nameref_cell (var);
#if defined (ARRAY_VARS)
if (temp && *temp && valid_array_reference (temp))
{
tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
@@ -7882,9 +7900,17 @@ comsub:
goto return0;
}
else
#endif
/* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
if (temp && *temp && legal_identifier (temp) == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
report_error (_("%s: invalid variable name for name reference"), temp);
return (&expand_wdesc_error); /* XXX */
}
else
temp = (char *)NULL;
}
#endif
temp = (char *)NULL;
+9540
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -621,6 +621,10 @@ unary_test (op, arg)
case 'v':
v = find_variable (arg);
return (v && var_isset (v) ? TRUE : FALSE);
case 'R':
v = find_variable (arg);
return (v && var_isset (v) && nameref_p (v) ? TRUE : FALSE);
}
/* We can't actually get here, but this shuts up gcc. */
+852
View File
@@ -0,0 +1,852 @@
/* test.c - GNU test program (ksb and mjb) */
/* Modified to run with the GNU shell Apr 25, 1988 by bfox. */
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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.
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Define PATTERN_MATCHING to get the csh-like =~ and !~ pattern-matching
binary operators. */
/* #define PATTERN_MATCHING */
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdio.h>
#include "bashtypes.h"
#if !defined (HAVE_LIMITS_H) && defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif /* !_POSIX_VERSION */
#include "posixstat.h"
#include "filecntl.h"
#include "stat-time.h"
#include "bashintl.h"
#include "shell.h"
#include "pathexp.h"
#include "test.h"
#include "builtins/common.h"
#include <glob/strmatch.h>
#if !defined (STRLEN)
# define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
#endif
#if !defined (STREQ)
# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
#endif /* !STREQ */
#define STRCOLLEQ(a, b) ((a)[0] == (b)[0] && strcoll ((a), (b)) == 0)
#if !defined (R_OK)
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif /* R_OK */
#define EQ 0
#define NE 1
#define LT 2
#define GT 3
#define LE 4
#define GE 5
#define NT 0
#define OT 1
#define EF 2
/* The following few defines control the truth and false output of each stage.
TRUE and FALSE are what we use to compute the final output value.
SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
Default is TRUE = 1, FALSE = 0, SHELL_BOOLEAN = (!value). */
#define TRUE 1
#define FALSE 0
#define SHELL_BOOLEAN(value) (!(value))
#define TEST_ERREXIT_STATUS 2
static procenv_t test_exit_buf;
static int test_error_return;
#define test_exit(val) \
do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0)
extern int sh_stat __P((const char *, struct stat *));
static int pos; /* The offset of the current argument in ARGV. */
static int argc; /* The number of arguments present in ARGV. */
static char **argv; /* The argument list. */
static int noeval;
static void test_syntax_error __P((char *, char *)) __attribute__((__noreturn__));
static void beyond __P((void)) __attribute__((__noreturn__));
static void integer_expected_error __P((char *)) __attribute__((__noreturn__));
static int unary_operator __P((void));
static int binary_operator __P((void));
static int two_arguments __P((void));
static int three_arguments __P((void));
static int posixtest __P((void));
static int expr __P((void));
static int term __P((void));
static int and __P((void));
static int or __P((void));
static int filecomp __P((char *, char *, int));
static int arithcomp __P((char *, char *, int, int));
static int patcomp __P((char *, char *, int));
static void
test_syntax_error (format, arg)
char *format, *arg;
{
builtin_error (format, arg);
test_exit (TEST_ERREXIT_STATUS);
}
/*
* beyond - call when we're beyond the end of the argument list (an
* error condition)
*/
static void
beyond ()
{
test_syntax_error (_("argument expected"), (char *)NULL);
}
/* Syntax error for when an integer argument was expected, but
something else was found. */
static void
integer_expected_error (pch)
char *pch;
{
test_syntax_error (_("%s: integer expression expected"), pch);
}
/* Increment our position in the argument list. Check that we're not
past the end of the argument list. This check is supressed if the
argument is FALSE. Made a macro for efficiency. */
#define advance(f) do { ++pos; if (f && pos >= argc) beyond (); } while (0)
#define unary_advance() do { advance (1); ++pos; } while (0)
/*
* expr:
* or
*/
static int
expr ()
{
if (pos >= argc)
beyond ();
return (FALSE ^ or ()); /* Same with this. */
}
/*
* or:
* and
* and '-o' or
*/
static int
or ()
{
int value, v2;
value = and ();
if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2])
{
advance (0);
v2 = or ();
return (value || v2);
}
return (value);
}
/*
* and:
* term
* term '-a' and
*/
static int
and ()
{
int value, v2;
value = term ();
if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2])
{
advance (0);
v2 = and ();
return (value && v2);
}
return (value);
}
/*
* term - parse a term and return 1 or 0 depending on whether the term
* evaluates to true or false, respectively.
*
* term ::=
* '-'('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'k'|'p'|'r'|'s'|'u'|'w'|'x') filename
* '-'('G'|'L'|'O'|'S'|'N') filename
* '-t' [int]
* '-'('z'|'n') string
* '-o' option
* string
* string ('!='|'='|'==') string
* <int> '-'(eq|ne|le|lt|ge|gt) <int>
* file '-'(nt|ot|ef) file
* '(' <expr> ')'
* int ::=
* positive and negative integers
*/
static int
term ()
{
int value;
if (pos >= argc)
beyond ();
/* Deal with leading `not's. */
if (argv[pos][0] == '!' && argv[pos][1] == '\0')
{
value = 0;
while (pos < argc && argv[pos][0] == '!' && argv[pos][1] == '\0')
{
advance (1);
value = 1 - value;
}
return (value ? !term() : term());
}
/* A paren-bracketed argument. */
if (argv[pos][0] == '(' && argv[pos][1] == '\0') /* ) */
{
advance (1);
value = expr ();
if (argv[pos] == 0) /* ( */
test_syntax_error (_("`)' expected"), (char *)NULL);
else if (argv[pos][0] != ')' || argv[pos][1]) /* ( */
test_syntax_error (_("`)' expected, found %s"), argv[pos]);
advance (0);
return (value);
}
/* are there enough arguments left that this could be dyadic? */
if ((pos + 3 <= argc) && test_binop (argv[pos + 1]))
value = binary_operator ();
/* Might be a switch type argument */
else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
{
if (test_unop (argv[pos]))
value = unary_operator ();
else
test_syntax_error (_("%s: unary operator expected"), argv[pos]);
}
else
{
value = argv[pos][0] != '\0';
advance (0);
}
return (value);
}
static int
stat_mtime (fn, st, ts)
char *fn;
struct stat *st;
struct timespec *ts;
{
int r;
r = sh_stat (fn, st);
if (r < 0)
return r;
*ts = get_stat_mtime (st);
return 0;
}
static int
filecomp (s, t, op)
char *s, *t;
int op;
{
struct stat st1, st2;
struct timespec ts1, ts2;
int r1, r2;
if ((r1 = stat_mtime (s, &st1, &ts1)) < 0)
{
if (op == EF)
return (FALSE);
}
if ((r2 = stat_mtime (t, &st2, &ts2)) < 0)
{
if (op == EF)
return (FALSE);
}
switch (op)
{
case OT: return (r1 < r2 || (r2 == 0 && timespec_cmp (ts1, ts2) < 0));
case NT: return (r1 > r2 || (r1 == 0 && timespec_cmp (ts1, ts2) > 0));
case EF: return (same_file (s, t, &st1, &st2));
}
return (FALSE);
}
static int
arithcomp (s, t, op, flags)
char *s, *t;
int op, flags;
{
intmax_t l, r;
int expok;
if (flags & TEST_ARITHEXP)
{
l = evalexp (s, &expok);
if (expok == 0)
return (FALSE); /* should probably longjmp here */
r = evalexp (t, &expok);
if (expok == 0)
return (FALSE); /* ditto */
}
else
{
if (legal_number (s, &l) == 0)
integer_expected_error (s);
if (legal_number (t, &r) == 0)
integer_expected_error (t);
}
switch (op)
{
case EQ: return (l == r);
case NE: return (l != r);
case LT: return (l < r);
case GT: return (l > r);
case LE: return (l <= r);
case GE: return (l >= r);
}
return (FALSE);
}
static int
patcomp (string, pat, op)
char *string, *pat;
int op;
{
int m;
m = strmatch (pat, string, FNMATCH_EXTFLAG|FNMATCH_IGNCASE);
return ((op == EQ) ? (m == 0) : (m != 0));
}
int
binary_test (op, arg1, arg2, flags)
char *op, *arg1, *arg2;
int flags;
{
int patmatch;
patmatch = (flags & TEST_PATMATCH);
if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0')))
return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2));
else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
{
if (shell_compatibility_level > 40 && flags & TEST_LOCALE)
return ((op[0] == '>') ? (strcoll (arg1, arg2) > 0) : (strcoll (arg1, arg2) < 0));
else
return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
}
else if (op[0] == '!' && op[1] == '=' && op[2] == '\0')
return (patmatch ? patcomp (arg1, arg2, NE) : (STREQ (arg1, arg2) == 0));
else if (op[2] == 't')
{
switch (op[1])
{
case 'n': return (filecomp (arg1, arg2, NT)); /* -nt */
case 'o': return (filecomp (arg1, arg2, OT)); /* -ot */
case 'l': return (arithcomp (arg1, arg2, LT, flags)); /* -lt */
case 'g': return (arithcomp (arg1, arg2, GT, flags)); /* -gt */
}
}
else if (op[1] == 'e')
{
switch (op[2])
{
case 'f': return (filecomp (arg1, arg2, EF)); /* -ef */
case 'q': return (arithcomp (arg1, arg2, EQ, flags)); /* -eq */
}
}
else if (op[2] == 'e')
{
switch (op[1])
{
case 'n': return (arithcomp (arg1, arg2, NE, flags)); /* -ne */
case 'g': return (arithcomp (arg1, arg2, GE, flags)); /* -ge */
case 'l': return (arithcomp (arg1, arg2, LE, flags)); /* -le */
}
}
return (FALSE); /* should never get here */
}
static int
binary_operator ()
{
int value;
char *w;
w = argv[pos + 1];
if ((w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) || /* =, == */
((w[0] == '>' || w[0] == '<') && w[1] == '\0') || /* <, > */
(w[0] == '!' && w[1] == '=' && w[2] == '\0')) /* != */
{
value = binary_test (w, argv[pos], argv[pos + 2], 0);
pos += 3;
return (value);
}
#if defined (PATTERN_MATCHING)
if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0')
{
value = patcomp (argv[pos], argv[pos + 2], w[0] == '=' ? EQ : NE);
pos += 3;
return (value);
}
#endif
if ((w[0] != '-' || w[3] != '\0') || test_binop (w) == 0)
{
test_syntax_error (_("%s: binary operator expected"), w);
/* NOTREACHED */
return (FALSE);
}
value = binary_test (w, argv[pos], argv[pos + 2], 0);
pos += 3;
return value;
}
static int
unary_operator ()
{
char *op;
intmax_t r;
op = argv[pos];
if (test_unop (op) == 0)
return (FALSE);
/* the only tricky case is `-t', which may or may not take an argument. */
if (op[1] == 't')
{
advance (0);
if (pos < argc)
{
if (legal_number (argv[pos], &r))
{
advance (0);
return (unary_test (op, argv[pos - 1]));
}
else
return (FALSE);
}
else
return (unary_test (op, "1"));
}
/* All of the unary operators take an argument, so we first call
unary_advance (), which checks to make sure that there is an
argument, and then advances pos right past it. This means that
pos - 1 is the location of the argument. */
unary_advance ();
return (unary_test (op, argv[pos - 1]));
}
int
unary_test (op, arg)
char *op, *arg;
{
intmax_t r;
struct stat stat_buf;
SHELL_VAR *v;
switch (op[1])
{
case 'a': /* file exists in the file system? */
case 'e':
return (sh_stat (arg, &stat_buf) == 0);
case 'r': /* file is readable? */
return (sh_eaccess (arg, R_OK) == 0);
case 'w': /* File is writeable? */
return (sh_eaccess (arg, W_OK) == 0);
case 'x': /* File is executable? */
return (sh_eaccess (arg, X_OK) == 0);
case 'O': /* File is owned by you? */
return (sh_stat (arg, &stat_buf) == 0 &&
(uid_t) current_user.euid == (uid_t) stat_buf.st_uid);
case 'G': /* File is owned by your group? */
return (sh_stat (arg, &stat_buf) == 0 &&
(gid_t) current_user.egid == (gid_t) stat_buf.st_gid);
case 'N':
return (sh_stat (arg, &stat_buf) == 0 &&
stat_buf.st_atime <= stat_buf.st_mtime);
case 'f': /* File is a file? */
if (sh_stat (arg, &stat_buf) < 0)
return (FALSE);
/* -f is true if the given file exists and is a regular file. */
#if defined (S_IFMT)
return (S_ISREG (stat_buf.st_mode) || (stat_buf.st_mode & S_IFMT) == 0);
#else
return (S_ISREG (stat_buf.st_mode));
#endif /* !S_IFMT */
case 'd': /* File is a directory? */
return (sh_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode)));
case 's': /* File has something in it? */
return (sh_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0);
case 'S': /* File is a socket? */
#if !defined (S_ISSOCK)
return (FALSE);
#else
return (sh_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));
#endif /* S_ISSOCK */
case 'c': /* File is character special? */
return (sh_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode));
case 'b': /* File is block special? */
return (sh_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode));
case 'p': /* File is a named pipe? */
#ifndef S_ISFIFO
return (FALSE);
#else
return (sh_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));
#endif /* S_ISFIFO */
case 'L': /* Same as -h */
case 'h': /* File is a symbolic link? */
#if !defined (S_ISLNK) || !defined (HAVE_LSTAT)
return (FALSE);
#else
return ((arg[0] != '\0') &&
(lstat (arg, &stat_buf) == 0) && S_ISLNK (stat_buf.st_mode));
#endif /* S_IFLNK && HAVE_LSTAT */
case 'u': /* File is setuid? */
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0);
case 'g': /* File is setgid? */
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0);
case 'k': /* File has sticky bit set? */
#if !defined (S_ISVTX)
/* This is not Posix, and is not defined on some Posix systems. */
return (FALSE);
#else
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);
#endif
case 't': /* File fd is a terminal? */
if (legal_number (arg, &r) == 0)
return (FALSE);
return ((r == (int)r) && isatty ((int)r));
case 'n': /* True if arg has some length. */
return (arg[0] != '\0');
case 'z': /* True if arg has no length. */
return (arg[0] == '\0');
case 'o': /* True if option `arg' is set. */
return (minus_o_option_value (arg) == 1);
case 'v':
v = find_variable (arg);
return (v && var_isset (v) ? TRUE : FALSE);
}
/* We can't actually get here, but this shuts up gcc. */
return (FALSE);
}
/* Return TRUE if OP is one of the test command's binary operators. */
int
test_binop (op)
char *op;
{
if (op[0] == '=' && op[1] == '\0')
return (1); /* '=' */
else if ((op[0] == '<' || op[0] == '>') && op[1] == '\0') /* string <, > */
return (1);
else if ((op[0] == '=' || op[0] == '!') && op[1] == '=' && op[2] == '\0')
return (1); /* `==' and `!=' */
#if defined (PATTERN_MATCHING)
else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!'))
return (1);
#endif
else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0')
return (0);
else
{
if (op[2] == 't')
switch (op[1])
{
case 'n': /* -nt */
case 'o': /* -ot */
case 'l': /* -lt */
case 'g': /* -gt */
return (1);
default:
return (0);
}
else if (op[1] == 'e')
switch (op[2])
{
case 'q': /* -eq */
case 'f': /* -ef */
return (1);
default:
return (0);
}
else if (op[2] == 'e')
switch (op[1])
{
case 'n': /* -ne */
case 'g': /* -ge */
case 'l': /* -le */
return (1);
default:
return (0);
}
else
return (0);
}
}
/* Return non-zero if OP is one of the test command's unary operators. */
int
test_unop (op)
char *op;
{
if (op[0] != '-' || op[2] != 0)
return (0);
switch (op[1])
{
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'k': case 'n':
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':
return (1);
}
return (0);
}
static int
two_arguments ()
{
if (argv[pos][0] == '!' && argv[pos][1] == '\0')
return (argv[pos + 1][0] == '\0');
else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
{
if (test_unop (argv[pos]))
return (unary_operator ());
else
test_syntax_error (_("%s: unary operator expected"), argv[pos]);
}
else
test_syntax_error (_("%s: unary operator expected"), argv[pos]);
return (0);
}
#define ANDOR(s) (s[0] == '-' && !s[2] && (s[1] == 'a' || s[1] == 'o'))
/* This could be augmented to handle `-t' as equivalent to `-t 1', but
POSIX requires that `-t' be given an argument. */
#define ONE_ARG_TEST(s) ((s)[0] != '\0')
static int
three_arguments ()
{
int value;
if (test_binop (argv[pos+1]))
{
value = binary_operator ();
pos = argc;
}
else if (ANDOR (argv[pos+1]))
{
if (argv[pos+1][1] == 'a')
value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
else
value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
pos = argc;
}
else if (argv[pos][0] == '!' && argv[pos][1] == '\0')
{
advance (1);
value = !two_arguments ();
}
else if (argv[pos][0] == '(' && argv[pos+2][0] == ')')
{
value = ONE_ARG_TEST(argv[pos+1]);
pos = argc;
}
else
test_syntax_error (_("%s: binary operator expected"), argv[pos+1]);
return (value);
}
/* This is an implementation of a Posix.2 proposal by David Korn. */
static int
posixtest ()
{
int value;
switch (argc - 1) /* one extra passed in */
{
case 0:
value = FALSE;
pos = argc;
break;
case 1:
value = ONE_ARG_TEST(argv[1]);
pos = argc;
break;
case 2:
value = two_arguments ();
pos = argc;
break;
case 3:
value = three_arguments ();
break;
case 4:
if (argv[pos][0] == '!' && argv[pos][1] == '\0')
{
advance (1);
value = !three_arguments ();
break;
}
/* FALLTHROUGH */
default:
value = expr ();
}
return (value);
}
/*
* [:
* '[' expr ']'
* test:
* test expr
*/
int
test_command (margc, margv)
int margc;
char **margv;
{
int value;
int code;
USE_VAR(margc);
code = setjmp (test_exit_buf);
if (code)
return (test_error_return);
argv = margv;
if (margv[0] && margv[0][0] == '[' && margv[0][1] == '\0')
{
--margc;
if (margv[margc] && (margv[margc][0] != ']' || margv[margc][1]))
test_syntax_error (_("missing `]'"), (char *)NULL);
if (margc < 2)
test_exit (SHELL_BOOLEAN (FALSE));
}
argc = margc;
pos = 1;
if (pos >= argc)
test_exit (SHELL_BOOLEAN (FALSE));
noeval = 0;
value = posixtest ();
if (pos != argc)
test_syntax_error (_("too many arguments"), (char *)NULL);
test_exit (SHELL_BOOLEAN (value));
}
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+9
View File
@@ -0,0 +1,9 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
export THIS_SH PATH
rm -f /tmp/xx
/bin/sh "$@"
+4
View File
@@ -88,3 +88,7 @@ a.c
ok 1
ok 2
ok 3
a ab
a ab
a ab
a
+2
View File
@@ -368,4 +368,6 @@ builtin cd "$MYDIR"
${THIS_SH} ./extglob1.sub
${THIS_SH} ./extglob1a.sub
exit 0
+371
View File
@@ -0,0 +1,371 @@
# test the ksh-like extended globbing features: [!@*?+](patlist)
shopt -s extglob
expect()
{
echo expect "$@"
}
case "/dev/udp/129.22.8.102/45" in
/dev/@(tcp|udp)/*/*) echo ok 1;;
*) echo bad 1;;
esac
# valid numbers
case 12 in
0|[1-9]*([0-9])) echo ok 2;;
*) echo bad 2;;
esac
case 12abc in
0|[1-9]*([0-9])) echo bad 3;;
*) echo ok 3;;
esac
case 1 in
0|[1-9]*([0-9])) echo ok 4;;
*) echo bad 4;;
esac
# octal numbers
case 07 in
+([0-7])) echo ok 5;;
*) echo bad 5;;
esac
case 0377 in
+([0-7])) echo ok 6;;
*) echo bad 6;;
esac
case 09 in
+([0-7])) echo bad 7;;
*) echo ok 7;;
esac
# stuff from korn's book
case paragraph in
para@(chute|graph)) echo ok 8;;
*) echo bad 8;;
esac
case paramour in
para@(chute|graph)) echo bad 9;;
*) echo ok 9;;
esac
case para991 in
para?([345]|99)1) echo ok 10;;
*) echo bad 10;;
esac
case para381 in
para?([345]|99)1) echo bad 11;;
*) echo ok 11;;
esac
case paragraph in
para*([0-9])) echo bad 12;;
*) echo ok 12;;
esac
case para in
para*([0-9])) echo ok 13;;
*) echo bad 13;;
esac
case para13829383746592 in
para*([0-9])) echo ok 14;;
*) echo bad 14;;
esac
case paragraph in
para*([0-9])) echo bad 15;;
*) echo ok 15;;
esac
case para in
para+([0-9])) echo bad 16;;
*) echo ok 16;;
esac
case para987346523 in
para+([0-9])) echo ok 17;;
*) echo bad 17;;
esac
case paragraph in
para!(*.[0-9])) echo ok 18;;
*) echo bad 18;;
esac
case para.38 in
para!(*.[0-9])) echo ok 19;;
*) echo bad 19;;
esac
case para.graph in
para!(*.[0-9])) echo ok 20;;
*) echo bad 20;;
esac
case para39 in
para!(*.[0-9])) echo ok 21;;
*) echo bad 21;;
esac
# tests derived from those in rosenblatt's korn shell book
case "" in
*(0|1|3|5|7|9)) echo ok 22;;
*) echo bad 22;
esac
case 137577991 in
*(0|1|3|5|7|9)) echo ok 23;;
*) echo bad 23;
esac
case 2468 in
*(0|1|3|5|7|9)) echo bad 24;;
*) echo ok 24;
esac
case file.c in
*.c?(c)) echo ok 25;;
*) echo bad 25;;
esac
case file.C in
*.c?(c)) echo bad 26;;
*) echo ok 26;;
esac
case file.cc in
*.c?(c)) echo ok 27;;
*) echo bad 27;;
esac
case file.ccc in
*.c?(c)) echo bad 28;;
*) echo ok 28;;
esac
case parse.y in
!(*.c|*.h|Makefile.in|config*|README)) echo ok 29;;
*) echo bad 29;;
esac
case shell.c in
!(*.c|*.h|Makefile.in|config*|README)) echo bad 30;;
*) echo ok 30;;
esac
case Makefile in
!(*.c|*.h|Makefile.in|config*|README)) echo ok 31;;
*) echo bad 31;;
esac
case "VMS.FILE;1" in
*\;[1-9]*([0-9])) echo ok 32;;
*) echo bad 32;;
esac
case "VMS.FILE;0" in
*\;[1-9]*([0-9])) echo bad 33;;
*) echo ok 33;;
esac
case "VMS.FILE;" in
*\;[1-9]*([0-9])) echo bad 34;;
*) echo ok 34;;
esac
case "VMS.FILE;139" in
*\;[1-9]*([0-9])) echo ok 35;;
*) echo bad 35;;
esac
case "VMS.FILE;1N" in
*\;[1-9]*([0-9])) echo bad 36;;
*) echo ok 36;;
esac
# tests derived from the pd-ksh test suite
MYDIR=$PWD # save where we are
: ${TMPDIR:=/var/tmp}
TESTDIR=$TMPDIR/eglob-test-$$
mkdir $TESTDIR
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
rm -rf *
touch abcx abcz bbc
expect '!([*)*'
echo !([*)*
expect '+(a|b[)*'
echo +(a|b[)*
expect '[a*(]*z'
echo [a*(]*)z
rm -f abcx abcz bbc
touch abc
expect '+()c'
echo +()c
expect '+()x'
echo +()x
expect abc
echo +(*)c
expect '+(*)x'
echo +(*)x
# extended globbing should not be performed on the output of substitutions
x='@(*)'
expect '@(*)'
echo $x
expect 'no-file+(a|b)stuff'
echo no-file+(a|b)stuff
expect 'no-file+(a*(c)|b)stuff'
echo no-file+(a*(c)|b)stuff
touch abd acd
expect 'abd acd'
echo a+(b|c)d
expect 'acd'
echo a!(@(b|B))d
expect 'abd'
echo a[b*(foo|bar)]d
# simple kleene star tests
expect no
case foo in *(a|b[)) echo yes;; *) echo no;; esac
expect yes
case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac
# this doesn't work right yet; it is an incorrectly formed pattern
expect yes
case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac
# check extended globbing in pattern removal -- these don't work right yet
x=abcdef
expect '1: bcdef'
echo 1: ${x#+(a|abc)}
expect '2: def'
echo 2: ${x##+(a|abc)}
expect '3: abcde'
echo 3: ${x%+(def|f)}
expect '4: abc'
echo 4: ${x%%+(f|def)}
# these work ok
expect '5: ef'
echo 5: ${x#*(a|b)cd}
expect '6: ef'
echo 6: "${x#*(a|b)cd}"
expect '7: abcdef'
echo 7: ${x#"*(a|b)cd"}
# More tests derived from a bug report concerning extended glob patterns
# following a *
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
rm -rf *
touch ab abcdef abef abcfef
expect 'ab abef'
echo ab*(e|f)
expect 'abcfef abef'
echo ab?*(e|f)
expect abcdef
echo ab*d+(e|f)
expect 'ab abcdef abcfef abef'
echo ab**(e|f)
expect 'abcdef abcfef abef'
echo ab*+(e|f)
case 'abcfefg' in
ab**(e|f)) echo ok 37;;
*) echo bad 37;;
esac
case 'abcfefg' in
ab**(e|f)g) echo ok 38;;
*a) echo bad 38;;
esac
case ab in
ab*+(e|f)) echo bad 39;;
*) echo ok 39;;
esac
case abef in
ab***ef) echo ok 40;;
*) echo bad 40;;
esac
case abef in
ab**) echo ok 41;;
*) echo bad 41;;
esac
# bug in all versions up to and including bash-2.05b
case "123abc" in
*?(a)bc) echo ok 42;;
*) echo bad 42;;
esac
# clean up and do the next one
builtin cd /
rm -rf $TESTDIR
mkdir $TESTDIR
builtin cd $TESTDIR
LC_COLLATE=C # have to set this; it affects the sorting
touch a.b a,b a:b a-b a\;b a\ b a_b
echo a[^[:alnum:]]b
echo a[-.,:\;\ _]b
echo a@([^[:alnum:]])b
echo a@([-.,:; _])b
echo a@([.])b
echo a@([^.])b
echo a@([^x])b
echo a+([^[:alnum:]])b
echo a@(.|[^[:alnum:]])b
builtin cd /
rm -rf $TESTDIR
x=abcdef
recho "${x#*(a|b)cd}"
TEST='a , b'
shopt -s globstar
echo ${TEST//*([[:space:]]),*([[:space:]])/,}
shopt -u globstar
# this is for the benefit of pure coverage, so it writes the pcv file
# in the right place
builtin cd "$MYDIR"
${THIS_SH} ./extglob1.sub
exit 0
+16
View File
@@ -0,0 +1,16 @@
shopt -s extglob
TESTDIR=${TMPDIR:-/tmp}/eglob-test-$$
mkdir $TESTDIR
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
rm -rf *
touch a ab ba
echo a*!(x)
echo a!(x)
echo a*?(x)
echo a?(x)
builtin cd /
rm -rf $TESTDIR
+50
View File
@@ -0,0 +1,50 @@
:; ./shx
sh:
<&$fd ok
nlbq Mon Aug 3 02:45:00 EDT 1992
bang geoff
quote 712824302
setbq defmsgid=<1992Aug3.024502.6176@host>
bgwait sleep done... wait 6187
bash:
<&$fd ok
nlbq Mon Aug 3 02:45:09 EDT 1992
bang geoff
quote 712824311
setbq defmsgid=<1992Aug3.024512.6212@host>
bgwait sleep done... wait 6223
ash:
<&$fd shx1: 4: Syntax error: Bad fd number
nlbq Mon Aug 3 02:45:19 EDT 1992
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.` echo 024521
bgwait sleep done... wait 6241
ksh:
<&$fd ok
nlbq ./shx: 6248 Memory fault - core dumped
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.024530.6257@host>
bgwait no such job: 6265
wait 6265
sleep done...
zsh:
<&$fd ok
nlbq Mon Aug 3 02:45:36 EDT 1992
bang shx3: event not found: /s/ [4]
quote 712824337
setbq defmsgid=<..6290@host>
bgwait shx7: unmatched " [9]
sleep done...
:;
+10
View File
@@ -0,0 +1,10 @@
#! /bin/sh
for cmd in sh bash ash ksh zsh
do
echo
echo $cmd:
for demo in shx?
do
$cmd $demo
done
done
+9
View File
@@ -108,3 +108,12 @@ ref -> one, value: 1
ref -> two, value: 2
ref -> three, value: 3
final state: ref -> three, value: 3
./nameref6.sub: line 2: typeset: x: nameref variable self references not allowed
./nameref6.sub: line 5: typeset: x[3]: reference variable cannot be an array
./nameref6.sub: line 12: typeset: x: reference variable cannot be an array
the -- 1
./nameref6.sub: line 25: 42: invalid variable name for name reference
42 -- 0
./nameref6.sub: line 40: 2: invalid variable name for name reference
./nameref6.sub: line 41: 2: invalid variable name for name reference
2 -- 0
+1
View File
@@ -113,3 +113,4 @@ ${THIS_SH} ./nameref2.sub
${THIS_SH} ./nameref3.sub
${THIS_SH} ./nameref4.sub
${THIS_SH} ./nameref5.sub
${THIS_SH} ./nameref6.sub
+115
View File
@@ -0,0 +1,115 @@
# basic nameref tests
bar=one
flow=two
flip=three
foo=bar
typeset -n foo
typeset -n fee=flow
echo ${foo}
echo ${fee}
typeset -n fee=flip
echo ${fee}
typeset -n
echo turning off nameref attribute on foo
typeset +n foo=other
echo ${foo}
echo after +n foo bar = $bar
unset foo bar fee
bar=one
foo=bar
typeset -n foo
foo=two printf "%s\n" $foo
foo=two eval 'printf "%s\n" $foo'
foo=two echo $foo
unset foo bar
# other basic assignment tests
bar=one
echo "expect <one>"
recho ${bar}
typeset -n foo=bar
foo=two
echo "expect <two>"
recho ${bar}
# this appears to be a ksh93 bug; it doesn't unset foo here and messes up
# later
unset foo bar
# initial tests of working inside shell functions
echoval()
{
typeset -n ref=$1
printf "%s\n" $ref
}
foo=bar
bar=one
echo "expect <$foo>"
echoval foo
echo "expect <$bar>"
echoval bar
unset foo bar
changevar()
{
typeset -n v=$1
shift
v="$@"
echo "changevar: expect <$@>"
recho "$v"
}
bar=one
echo "expect <one>"
recho ${bar}
changevar bar two
echo "expect <two>"
recho $bar
changevar bar three four five
echo "expect <three four five>"
recho "$bar"
unset foo bar
unset -n foo bar
readonly foo=one
typeset -n bar=foo
bar=4
foo=4
echo $foo
echo $bar
assignvar()
{
typeset -n ref=$1
shift
ref="$@"
}
readonly foo=one
assignvar foo two three four
echo $foo
${THIS_SH} ./nameref1.sub
${THIS_SH} ./nameref2.sub
${THIS_SH} ./nameref3.sub
${THIS_SH} ./nameref4.sub
${THIS_SH} ./nameref5.sub
+44
View File
@@ -0,0 +1,44 @@
# these should be errors
typeset -n x=x
#echo $x -- $?
typeset -n x[3]=x
#echo $x -- $?
x=(the browns suck)
y=(one two three)
# should be an error but not disturb the current contents of x
# maybe rethink that later
typeset -n x=y
echo $x -- $?
typeset -n
unset x y
y=42
typeset -i x=1
# the integer attribute causes arithmetic eval to be done
# we should not allow namerefs to non-identifiers
typeset -n x=y
echo $x -- $?
typeset +n x
echo $x -- $?
# same kind of thing
unset -n x
unset y
set -- first second third
y=2
typeset -i x=1
typeset -n x=y
echo $x -- $?
echo ${x} -- $?
typeset +n x
echo $x -- $?