mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-18 21:38:03 +02:00
zsh-3.1.5-pws-2
This commit is contained in:
parent
a61dc2074a
commit
f13624e0f8
27 changed files with 852 additions and 375 deletions
|
@ -139,9 +139,13 @@ install.info: zsh.info
|
|||
elif test -f $(sdir)/$$file; then \
|
||||
$(INSTALL_DATA) $(sdir)/$$file $(infodir); \
|
||||
else :; \
|
||||
fi || exit 1; \
|
||||
fi || exit 1; \
|
||||
done
|
||||
|
||||
install.html: zsh_toc.html
|
||||
$(sdir_top)/mkinstalldirs $(htmldir)
|
||||
$(INSTALL_DATA) *.html $(htmldir)
|
||||
|
||||
# uninstall man pages
|
||||
uninstall.man:
|
||||
for file in $(MAN); do \
|
||||
|
|
|
@ -98,12 +98,13 @@ Change the current directory. In the first form, change the
|
|||
current directory to var(arg), or to the value of tt($HOME) if
|
||||
var(arg) is not specified. If var(arg) is `tt(-)', change to the
|
||||
value of tt($OLDPWD), the previous directory.
|
||||
If a directory named var(arg) is not found in the current directory
|
||||
and var(arg) does not begin with a slash,
|
||||
search each component of the shell parameter tt(cdpath).
|
||||
If the option tt(CDABLE_VARS) is set, and a parameter named var(arg)
|
||||
exists whose value begins with a slash, treat its value as
|
||||
the directory.
|
||||
Otherwise, if a directory named var(arg) is not found in the current
|
||||
directory and var(arg) does not begin with a slash, search each
|
||||
component of the shell parameter tt(cdpath). If no directory is found
|
||||
and the option tt(CDABLE_VARS) is set, and a parameter named var(arg)
|
||||
exists whose value begins with a slash, treat its value as the
|
||||
directory. In that case, the parameter is added to the named
|
||||
directory hash table.
|
||||
|
||||
The second form of tt(cd) substitutes the string var(new)
|
||||
for the string var(old) in the name of the current directory,
|
||||
|
@ -357,11 +358,20 @@ is stored in tt(OPTARG).
|
|||
vindex(OPTIND, use of)
|
||||
vindex(OPTARG, use of)
|
||||
|
||||
The first option to be examined may be changed by explicitly assigning
|
||||
to tt(OPTIND). tt(OPTIND) has an initial value of tt(1), and is
|
||||
normally reset to tt(1) upon exit from a shell function. tt(OPTARG)
|
||||
is not reset and retains its value from the most recent call to
|
||||
tt(getopts). If either of tt(OPTIND) or tt(OPTARG) is explicitly
|
||||
unset, it remains unset, and the index or option argument is not
|
||||
stored. The option itself is still stored in var(name) in this case.
|
||||
|
||||
A leading `tt(:)' in var(optstring) causes tt(getopts) to store the
|
||||
letter of the invalid option in tt(OPTARG), and to set var(name)
|
||||
to `tt(?)' for an unknown option and to `tt(:)' when a required option
|
||||
is missing. Otherwise, tt(getopts) prints an error
|
||||
message. The exit status is nonzero when there are no more options.
|
||||
letter of any invalid option in tt(OPTARG), and to set var(name) to
|
||||
`tt(?)' for an unknown option and to `tt(:)' when a required option is
|
||||
missing. Otherwise, tt(getopts) sets var(name) to `tt(?)' and prints
|
||||
an error message when an option is invalid. The exit status is
|
||||
nonzero when there are no more options.
|
||||
)
|
||||
findex(hash)
|
||||
item(tt(hash) [ tt(-dfmrv) ] [ var(name)[tt(=)var(value)] ] ...)(
|
||||
|
@ -521,8 +531,8 @@ Same as tt(exit), except that it only works in a login shell.
|
|||
prefix(noglob)
|
||||
findex(popd)
|
||||
item(tt(popd) [ {tt(PLUS())|tt(-)}var(n) ])(
|
||||
Removes a entry from the directory stack, and perform a tt(cd) to
|
||||
the new top directory. With no argument, the current top entry is
|
||||
Remove an entry from the directory stack, and perform a tt(cd) to
|
||||
the new top directory. With no argument, the current top entry is
|
||||
removed. An argument of the form `tt(PLUS())var(n)' identifies a stack
|
||||
entry by counting from the left of the list shown by the tt(dirs) command,
|
||||
starting with zero. An argument of the form tt(-n) counts from the right.
|
||||
|
@ -615,21 +625,9 @@ If var(arg) is not specified, change to the second directory
|
|||
on the stack (that is, exchange the top two entries), or
|
||||
change to tt($HOME) if the tt(PUSHD_TO_HOME)
|
||||
option is set or if there is only one entry on the stack.
|
||||
|
||||
If var(arg) is `tt(-)', change to tt($OLDPWD), the previous directory.
|
||||
If a directory named var(arg) is not found in the current directory
|
||||
and var(arg) does not contain a slash,
|
||||
search each component of the shell parameter tt(cdpath).
|
||||
If the option tt(CDABLE_VARS) is set, and a parameter named var(arg)
|
||||
exists whose value begins with a slash, treat its value as
|
||||
the directory.
|
||||
|
||||
If the option tt(PUSHD_SILENT) is not set, the directory
|
||||
stack will be printed after a tt(pushd) is performed.
|
||||
|
||||
The second form of tt(pushd) substitutes the string var(new)
|
||||
for the string var(old) in the name of the current directory,
|
||||
and tries to change to this new directory.
|
||||
Otherwise, var(arg) is interpreted as it would be by tt(cd).
|
||||
The meaning of var(old) and var(new) in the second form is also
|
||||
the same as for tt(cd).
|
||||
|
||||
The third form of tt(pushd) changes directory by rotating the
|
||||
directory list. An argument of the form `tt(PLUS())var(n)' identifies a stack
|
||||
|
@ -637,6 +635,9 @@ entry by counting from the left of the list shown by the tt(dirs)
|
|||
command, starting with zero. An argument of the form `tt(-)var(n)' counts
|
||||
from the right. If the tt(PUSHD_MINUS) option is set, the meanings
|
||||
of `tt(PLUS())' and `tt(-)' in this context are swapped.
|
||||
|
||||
If the option tt(PUSHD_SILENT) is not set, the directory
|
||||
stack will be printed after a tt(pushd) is performed.
|
||||
)
|
||||
findex(pushln)
|
||||
item(tt(pushln) [ var(arg) ... ])(
|
||||
|
@ -727,7 +728,8 @@ is interactive.
|
|||
|
||||
The value (exit status) of tt(read) is 1 when an end-of-file is
|
||||
encountered, or when tt(-c) or tt(-l) is present and the command is
|
||||
not called from a tt(compctl) function. Otherwise the value is 0.
|
||||
not called from a tt(compctl) function, or as described for tt(-q).
|
||||
Otherwise the value is 0.
|
||||
|
||||
The behavior of some combinations of the tt(-k), tt(-p), tt(-q), tt(-u)
|
||||
and tt(-z) flags is undefined. Presently tt(-q) cancels all the others,
|
||||
|
@ -835,7 +837,7 @@ var(arg) is a command to be read and executed when the shell
|
|||
receives var(sig). Each var(sig) can be given as a number
|
||||
or as the name of a signal.
|
||||
If var(arg) is `tt(-)', then all traps var(sig) are reset to their
|
||||
default values. If var(arg) is the null string, then this signal
|
||||
default values. If var(arg) is the empty string, then this signal
|
||||
is ignored by the shell and by the commands it invokes.
|
||||
|
||||
If var(sig) is tt(ZERR) then var(arg) will be executed
|
||||
|
@ -958,7 +960,7 @@ or functions (with the tt(-f) flag) with matching names are printed.
|
|||
findex(ulimit)
|
||||
cindex(resource limits)
|
||||
cindex(limits, resource)
|
||||
item(tt(ulimit) [ tt(-SHacdflmnpstv) [ tt(limit) ] ... ])(
|
||||
item(tt(ulimit) [ tt(-SHacdflmnpstv) [ var(limit) ] ... ])(
|
||||
Set or display resource limits of the shell and the processes started by
|
||||
the shell. The value of var(limit) can be a number in the unit specified
|
||||
below or the value `tt(unlimited)'. If the tt(-H) flag is given use
|
||||
|
|
|
@ -573,11 +573,11 @@ enditem()
|
|||
subsect(Example)
|
||||
The flag tt(f) is useful to split a double-quoted substitution line by
|
||||
line. For example, `tt("${(f)$LPAR()<)var(file)tt(RPAR()}")'
|
||||
will substitue the contents of var(file) divided so that one line is
|
||||
supplied per argument to var(cmd). Compare this with the effect of
|
||||
substitutes the contents of var(file) divided so that each line is
|
||||
an element of the resulting array. Compare this with the effect of
|
||||
`tt($)tt(LPAR()<)var(file)tt(RPAR())' alone, which divides the file
|
||||
up by words, or the same inside double quotes, where the entire
|
||||
contents of the file are passed as a single argument.
|
||||
up by words, or the same inside double quotes, which makes the entire
|
||||
content of the file a single string.
|
||||
texinode(Command Substitution)(Arithmetic Expansion)(Parameter Expansion)(Expansion)
|
||||
sect(Command Substitution)
|
||||
cindex(command substitution)
|
||||
|
|
|
@ -614,7 +614,7 @@ Thus if `tt(/usr/local/bin)' is in the user's path, and he types
|
|||
Commands explicitly beginning with `tt(/)', `tt(./)' or `tt(../)'
|
||||
are not subject to the path search.
|
||||
This also applies to the tt(.) builtin,
|
||||
and searches for modules performed by the tt(zmodload) builtin.
|
||||
and to searches for modules performed by the tt(zmodload) builtin.
|
||||
)
|
||||
pindex(POSIX_BUILTINS)
|
||||
item(tt(POSIX_BUILTINS))(
|
||||
|
|
|
@ -175,6 +175,8 @@ sitem(tt(w))(True if the day of the week is equal to var(n) (Sunday = 0).)
|
|||
sitem(tt(?))(True if the exit status of the last command was var(n).)
|
||||
sitem(tt(#))(True if the effective uid of the current process is var(n).)
|
||||
sitem(tt(g))(True if the effective gid of the current process is var(n).)
|
||||
sitem(tt(l))(True if at least var(n) characters have already been
|
||||
printed on the current line.)
|
||||
sitem(tt(L))(True if the tt(SHLVL) parameter is at least var(n).)
|
||||
sitem(tt(S))(True if the tt(SECONDS) parameter is at least var(n).)
|
||||
sitem(tt(v))(True if the array tt(psvar) has at least var(n) elements.)
|
||||
|
@ -185,25 +187,40 @@ endsitem()
|
|||
xitem(tt(%<)var(string)tt(<))
|
||||
xitem(tt(%>)var(string)tt(>))
|
||||
item(tt(%[)var(xstring)tt(]))(
|
||||
Specifies truncation behaviour.
|
||||
Specifies truncation behaviour for the remainder of the prompt string.
|
||||
The third, deprecated, form is equivalent to `tt(%)var(xstringx)',
|
||||
i.e. var(x) may be `tt(<)' or `tt(>)'.
|
||||
The numeric argument, which in the third form may appear immediately
|
||||
after the `tt([)', specifies the maximum permitted length of
|
||||
the various strings that can be displayed in the prompt. If this
|
||||
integer is zero, or missing, truncation is disabled. Truncation is
|
||||
initially disabled.
|
||||
the various strings that can be displayed in the prompt.
|
||||
The var(string) will be displayed in
|
||||
place of the truncated portion of any string.
|
||||
place of the truncated portion of any string; note this does not
|
||||
undergo prompt expansion.
|
||||
|
||||
The forms with `tt(<)' truncate at the left of the string,
|
||||
and the forms with `tt(>)' truncate at the right of the string.
|
||||
For example, if the current directory is `tt(/home/pike)',
|
||||
the prompt `tt(%8<..<%/)' will expand to `tt(..e/pike)'.
|
||||
In this string, the terminating character (`tt(<)', `tt(>)' or `tt(])'),
|
||||
or in fact any character, may be quoted by a preceding `tt(\)'.
|
||||
% escapes are em(not) recognised.
|
||||
or in fact any character, may be quoted by a preceding `tt(\)'; note
|
||||
when using tt(print -P), however, that this must be doubled as the
|
||||
string is also subject to standard tt(print) processing, in addition
|
||||
to any backslashes removed by a double quoted string: the worst case
|
||||
is therefore `tt(print -P "%<\\\\<<...")'.
|
||||
|
||||
If the var(string) is longer than the specified truncation length,
|
||||
it will appear in full, completely replacing the truncated string.
|
||||
|
||||
The part of the prompt string to be truncated runs to the end of the
|
||||
string, or to the end of the next enclosing group of the `tt(%LPAR())'
|
||||
construct, or to the next truncation encountered at the same grouping
|
||||
level (i.e. truncations inside a `tt(%LPAR())' are separate), which
|
||||
ever comes first. In particular, a truncation with argument zero
|
||||
(e.g. `tt(%<<)') marks the end of the range of the string to be
|
||||
truncated while turning off truncation from there on. For example, the
|
||||
prompt '%10<...<%~%<<%# ' will print a truncated representation of the
|
||||
current directory, followed by a `tt(%)' or `tt(#)', followed by a
|
||||
space. Without the `tt(%<<)', those two characters would be included
|
||||
in the string to be truncated.
|
||||
)
|
||||
enditem()
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
# Usage: e.g.
|
||||
# compctl -D -f + -U -Q -S '' -K multicomp
|
||||
#
|
||||
# Note that exactly matched directories are not expanded, e.g.
|
||||
# s/zsh-2.4/s<TAB> will not expand to src/zsh-2.4old/src.
|
||||
# Will expand glob patterns already in the word, but use complete-word,
|
||||
# not TAB (expand-or-complete), or you will get ordinary glob expansion.
|
||||
# Requires the -U option to compctl.
|
||||
|
@ -42,32 +40,32 @@ while [[ -n "$pref" ]]; do
|
|||
[[ "$pref" = /* ]] && sofar=(${sofar}/) && pref="${pref#/}"
|
||||
head="${pref%%/*}"
|
||||
pref="${pref#$head}"
|
||||
if [[ -n "$pref" && -z $sofar[2] && -d "${sofar}$head" ]]; then
|
||||
# Exactly matched directory: don't try to glob
|
||||
reply=("${sofar}$head")
|
||||
[[ -z "$pref" ]] && globdir=
|
||||
# if path segment contains wildcards, don't add another.
|
||||
if [[ "$head" = *[\[\(\*\?\$\~]* ]]; then
|
||||
wild=$head
|
||||
else
|
||||
[[ -z "$pref" ]] && globdir=
|
||||
# if path segment contains wildcards, don't add another.
|
||||
if [[ "$head" = *[\[\(\*\?\$\~]* || -z "$head" ]]; then
|
||||
wild=$head
|
||||
else
|
||||
# Simulate case-insensitive globbing for ASCII characters
|
||||
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
||||
# The following could all be one expansion, but for readability:
|
||||
wild=$wild:gs/a/aA/:gs/b/bB/:gs/c/cC/:gs/d/dD/:gs/e/eE/:gs/f/fF/
|
||||
wild=$wild:gs/g/gG/:gs/h/hH/:gs/i/iI/:gs/j/jJ/:gs/k/kK/:gs/l/lL/
|
||||
wild=$wild:gs/m/mM/:gs/n/nN/:gs/o/oO/:gs/p/pP/:gs/q/qQ/:gs/r/rR/
|
||||
wild=$wild:gs/s/sS/:gs/t/tT/:gs/u/uU/:gs/v/vV/:gs/w/wW/:gs/x/xX/
|
||||
wild=$wild:gs/y/yY/:gs/z/zZ/:gs/-/_/:gs/_/-_/:gs/[]//
|
||||
# Simulate case-insensitive globbing for ASCII characters
|
||||
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
||||
# The following could all be one expansion, but for readability:
|
||||
wild=$wild:gs/a/aA/:gs/b/bB/:gs/c/cC/:gs/d/dD/:gs/e/eE/:gs/f/fF/
|
||||
wild=$wild:gs/g/gG/:gs/h/hH/:gs/i/iI/:gs/j/jJ/:gs/k/kK/:gs/l/lL/
|
||||
wild=$wild:gs/m/mM/:gs/n/nN/:gs/o/oO/:gs/p/pP/:gs/q/qQ/:gs/r/rR/
|
||||
wild=$wild:gs/s/sS/:gs/t/tT/:gs/u/uU/:gs/v/vV/:gs/w/wW/:gs/x/xX/
|
||||
wild=$wild:gs/y/yY/:gs/z/zZ/:gs/-/_/:gs/_/-_/:gs/[]//
|
||||
|
||||
# Expand on both sides of '.' (except when leading) as for '/'
|
||||
wild="${${wild:gs/[.]/*.*/}#\*}"
|
||||
fi
|
||||
|
||||
reply=(${sofar}"${wild}${globdir}")
|
||||
reply=(${~reply})
|
||||
# Expand on both sides of '.' (except when leading) as for '/'
|
||||
wild="${${wild:gs/[.]/*.*/}#\*}"
|
||||
fi
|
||||
|
||||
reply=(${sofar}"${wild}${globdir}")
|
||||
reply=(${~reply})
|
||||
|
||||
[[ -z $reply[1] ]] && reply=() && break
|
||||
[[ -n $pref ]] && sofar=($reply)
|
||||
done
|
||||
|
@ -77,4 +75,3 @@ done
|
|||
[[ -n "$origtop" ]] && reply=("$origtop"${reply#$newtop})
|
||||
|
||||
# }
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# get a random line from a file
|
||||
integer z=$(wc -l <$1)
|
||||
integer z="$(wc -l <$1)"
|
||||
sed -n $[RANDOM%z+1]p $1
|
||||
|
|
|
@ -51,6 +51,10 @@ META-FAQ: FORCE
|
|||
|
||||
# ========== DEPENDENCIES FOR INSTALLING ==========
|
||||
|
||||
# install stripped
|
||||
install-strip:
|
||||
$(MAKE) install STRIPFLAGS="-s"
|
||||
|
||||
# install/uninstall everything
|
||||
install: install.bin install.modules install.man install.info
|
||||
uninstall: uninstall.bin uninstall.modules uninstall.man uninstall.info
|
||||
|
@ -71,6 +75,10 @@ install.man uninstall.man:
|
|||
install.info uninstall.info:
|
||||
@cd Doc && $(MAKE) $(MAKEDEFS) $@
|
||||
|
||||
# install/uninstall just the html pages
|
||||
install.html uninstall.html:
|
||||
@cd Doc && $(MAKE) $(MAKEDEFS) $@
|
||||
|
||||
# ========== DEPENDENCIES FOR CLEANUP ==========
|
||||
|
||||
@@clean.mk@@
|
||||
|
|
10
Misc/c2z
10
Misc/c2z
|
@ -3,6 +3,7 @@
|
|||
# c2z - environment conversion tool
|
||||
# Contributed by Bart Schaefer
|
||||
# (Tweaked a bit by Paul Falstad)
|
||||
# (Tweaked again by Bart Schaefer)
|
||||
#
|
||||
# This is a quick script to convert csh aliases to zsh aliases/functions.
|
||||
# It also converts the csh environment and local variables to zsh. c2z
|
||||
|
@ -81,7 +82,13 @@ grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
|
|||
sed -e "s/'/'"\\\\"''"/g \
|
||||
-e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/alias -- \1='"'\2'/" \
|
||||
/tmp/cz$$.3
|
||||
sed -e 's/![:#]*/$/g' \
|
||||
sed -e 's/>\(&*\)!/>\1|/g' \
|
||||
-e 's/!\*:q/"$@"/g' \
|
||||
-e 's/\(![:#]*[^'"$T"']*\):q/"\1"/g' \
|
||||
-e 's/!\([-0-9][0-9]*\)\(:x\)*/$\2(fc -nl \1)/g' \
|
||||
-e 's/\$:x(fc/$=(fc/g' \
|
||||
-e 's/![:#]*\([^'"$T"']\)/$==\1/g' \
|
||||
-e 's/\$=\(=[^'"$T"']*\):x/$\1/g' \
|
||||
-e 's/\$cwd/$PWD/' \
|
||||
-e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/\1 () { \2 }/' \
|
||||
/tmp/cz$$.2
|
||||
|
@ -92,6 +99,7 @@ exec < /tmp/cz$$.e
|
|||
# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ...
|
||||
sed -e '/^SHLVL/d' \
|
||||
-e '/^PWD/d' \
|
||||
-e '/^_=/d' \
|
||||
-e "s/'/'"\\\\"''"/g \
|
||||
-e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \
|
||||
-e "s/$/'/"
|
||||
|
|
|
@ -149,7 +149,7 @@ uninstall.bin: uninstall.bin-here
|
|||
# install binary, creating install directory if necessary
|
||||
install.bin-here: zsh install.bin-@L@
|
||||
$(sdir_top)/mkinstalldirs $(bindir)
|
||||
$(INSTALL_PROGRAM) zsh $(bindir)/zsh-$(VERSION)
|
||||
$(INSTALL_PROGRAM) $(STRIPFLAGS) zsh $(bindir)/zsh-$(VERSION)
|
||||
if test -f $(bindir)/zsh; then \
|
||||
rm -f $(bindir)/zsh.old; \
|
||||
ln $(bindir)/zsh $(bindir)/zsh.old; \
|
||||
|
|
|
@ -119,8 +119,9 @@ uninstall.modules: uninstall.modules-here
|
|||
install.bin-here uninstall.bin-here:
|
||||
|
||||
install.modules-here:
|
||||
$(sdir_top)/mkinstalldirs $(MODDIR)
|
||||
modules='$(MODULES)'; for mod in $$modules; do \
|
||||
modules='$(MODULES)'; \
|
||||
if test -n "$$modules"; then $(sdir_top)/mkinstalldirs $(MODDIR); fi; \
|
||||
for mod in $$modules; do \
|
||||
$(INSTALL_PROGRAM) $$mod $(MODDIR)/$$mod; \
|
||||
done
|
||||
|
||||
|
|
|
@ -2945,7 +2945,7 @@ docompletion(char *s, int lst, int incmd)
|
|||
ainfo = fainfo = NULL;
|
||||
|
||||
/* Make sure we have the completion list and compctl. */
|
||||
if (makecomplist(s, incmd)) {
|
||||
if (makecomplist(s, incmd, lst)) {
|
||||
/* Error condition: feeeeeeeeeeeeep(). */
|
||||
feep();
|
||||
goto compend;
|
||||
|
@ -3029,7 +3029,7 @@ static unsigned long ccont;
|
|||
|
||||
/**/
|
||||
static int
|
||||
makecomplist(char *s, int incmd)
|
||||
makecomplist(char *s, int incmd, int lst)
|
||||
{
|
||||
struct cmlist ms;
|
||||
Cmlist m = cmatcher;
|
||||
|
@ -3062,7 +3062,7 @@ makecomplist(char *s, int incmd)
|
|||
ccused = newlinklist();
|
||||
ccstack = newlinklist();
|
||||
|
||||
makecomplistglobal(s, incmd);
|
||||
makecomplistglobal(s, incmd, lst);
|
||||
|
||||
endcmgroup(NULL);
|
||||
|
||||
|
@ -3098,12 +3098,14 @@ makecomplist(char *s, int incmd)
|
|||
|
||||
/**/
|
||||
static void
|
||||
makecomplistglobal(char *os, int incmd)
|
||||
makecomplistglobal(char *os, int incmd, int lst)
|
||||
{
|
||||
Compctl cc;
|
||||
char *s;
|
||||
|
||||
if (inwhat == IN_ENV)
|
||||
if (lst == COMP_WIDGET) {
|
||||
cc = compwidget->u.cc;
|
||||
} else if (inwhat == IN_ENV)
|
||||
/* Default completion for parameter values. */
|
||||
cc = &cc_default;
|
||||
else if (inwhat == IN_MATH) {
|
||||
|
@ -4413,7 +4415,8 @@ get_user_var(char *nam)
|
|||
} else {
|
||||
/* Otherwise it should be a parameter name. */
|
||||
char **arr = NULL, *val;
|
||||
if (!(arr = getaparam(nam)) && (val = getsparam(nam))) {
|
||||
if (!(arr = getaparam(nam)) && !(arr = gethparam(nam)) &&
|
||||
(val = getsparam(nam))) {
|
||||
arr = (char **)ncalloc(2*sizeof(char *));
|
||||
arr[0] = val;
|
||||
arr[1] = NULL;
|
||||
|
@ -5026,6 +5029,7 @@ do_single(Cmatch m)
|
|||
else {
|
||||
p = (char *) ncalloc(strlen(ppre) + strlen(str) +
|
||||
strlen(psuf) + 1);
|
||||
sprintf(p, "%s%s%s", ppre, str, psuf);
|
||||
}
|
||||
parsestr(p);
|
||||
if (ic)
|
||||
|
|
|
@ -50,7 +50,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
|
||||
BUILTIN("chdir", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
|
||||
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
|
||||
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "LRUZfilrtux", NULL),
|
||||
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtux", NULL),
|
||||
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "v", NULL),
|
||||
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL),
|
||||
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
|
||||
|
@ -60,7 +60,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL),
|
||||
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
|
||||
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
|
||||
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRUZfilrtu", "x"),
|
||||
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRUZafilrtu", "x"),
|
||||
BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL),
|
||||
BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
|
||||
|
@ -78,7 +78,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
|
||||
BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "LRUZilrtu", NULL),
|
||||
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZailrtu", NULL),
|
||||
BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL),
|
||||
BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL),
|
||||
|
||||
|
@ -93,7 +93,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
|
||||
BUILTIN("r", BINF_R, bin_fc, 0, -1, BIN_FC, "nrl", NULL),
|
||||
BUILTIN("read", 0, bin_read, 0, -1, 0, "rzu0123456789pkqecnAlE", NULL),
|
||||
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "LRUZfiltux", "r"),
|
||||
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafiltux", "r"),
|
||||
BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "dfv", "r"),
|
||||
BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL),
|
||||
BUILTIN("set", BINF_PSPECIAL, bin_set, 0, -1, 0, NULL, NULL),
|
||||
|
@ -107,7 +107,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("trap", BINF_PSPECIAL, bin_trap, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
|
||||
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "LRUZfilrtuxm", NULL),
|
||||
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtuxm", NULL),
|
||||
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
|
||||
BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"),
|
||||
BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"),
|
||||
|
@ -618,6 +618,8 @@ set_pwd_env(void)
|
|||
{
|
||||
Param pm;
|
||||
|
||||
/* update the PWD and OLDPWD shell parameters */
|
||||
|
||||
pm = (Param) paramtab->getnode(paramtab, "PWD");
|
||||
if (pm && PM_TYPE(pm->flags) != PM_SCALAR) {
|
||||
pm->flags &= ~PM_READONLY;
|
||||
|
@ -704,7 +706,6 @@ bin_cd(char *nam, char **argv, char *ops, int func)
|
|||
chdir(unmeta(pwd));
|
||||
}
|
||||
}
|
||||
set_pwd_env();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -946,7 +947,6 @@ cd_try_chdir(char *pfix, char *dest, int hard)
|
|||
static void
|
||||
cd_new_pwd(int func, LinkNode dir, int chaselinks)
|
||||
{
|
||||
Param pm;
|
||||
List l;
|
||||
char *new_pwd, *s;
|
||||
int dirstacksize;
|
||||
|
@ -981,13 +981,8 @@ cd_new_pwd(int func, LinkNode dir, int chaselinks)
|
|||
zsfree(oldpwd);
|
||||
oldpwd = pwd;
|
||||
pwd = new_pwd;
|
||||
/* update the PWD and OLDPWD shell parameters */
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, "PWD")) &&
|
||||
(pm->flags & PM_EXPORTED) && pm->env)
|
||||
pm->env = replenv(pm->env, pwd);
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, "OLDPWD")) &&
|
||||
(pm->flags & PM_EXPORTED) && pm->env)
|
||||
pm->env = replenv(pm->env, oldpwd);
|
||||
set_pwd_env();
|
||||
|
||||
if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE))
|
||||
printdirstack();
|
||||
else if (doprintdir) {
|
||||
|
@ -1474,8 +1469,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
Param pm;
|
||||
Asgment asg;
|
||||
Comp com;
|
||||
char *optstr = "iLRZlurtxU";
|
||||
int on = 0, off = 0, roff, bit = PM_INTEGER;
|
||||
char *optstr = "aiLRZlurtxU----A";
|
||||
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
||||
int initon, initoff, of, i;
|
||||
int returnval = 0, printflags = 0;
|
||||
|
||||
|
@ -1506,6 +1501,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
off |= PM_LOWER;
|
||||
if (on & PM_LOWER)
|
||||
off |= PM_UPPER;
|
||||
if (on & PM_HASHED)
|
||||
off |= PM_ARRAY;
|
||||
on &= ~off;
|
||||
|
||||
/* Given no arguments, list whatever the options specify. */
|
||||
|
@ -1548,8 +1545,15 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
|
||||
!(pm->flags & PM_READONLY & ~off))
|
||||
uniqarray((*pm->gets.afn) (pm));
|
||||
if ((on & ~pm->flags) & PM_HASHED) {
|
||||
char *nam = ztrdup(pm->nam);
|
||||
unsetparam(nam);
|
||||
pm = createparam(nam, on & ~PM_READONLY);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
}
|
||||
pm->flags = (pm->flags | on) & ~off;
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY) {
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY &&
|
||||
PM_TYPE(pm->flags) != PM_HASHED) {
|
||||
if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) && auxlen)
|
||||
pm->ct = auxlen;
|
||||
/* did we just export this? */
|
||||
|
@ -1598,7 +1602,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
(((pm->flags & PM_SPECIAL) && pm->level == locallevel) ||
|
||||
(!(pm->flags & PM_UNSET) &&
|
||||
((locallevel == pm->level) || func == BIN_EXPORT) &&
|
||||
!(bit = ((off & pm->flags) | (on & ~pm->flags)) & PM_INTEGER)))) {
|
||||
!(bit = (((off & pm->flags) | (on & ~pm->flags)) &
|
||||
(PM_INTEGER|PM_HASHED)))))) {
|
||||
/* if no flags or values are given, just print this parameter */
|
||||
if (!on && !roff && !asg->value) {
|
||||
paramtab->printnode((HashNode) pm, 0);
|
||||
|
@ -1623,7 +1628,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) &&
|
||||
auxlen)
|
||||
pm->ct = auxlen;
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY) {
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY &&
|
||||
PM_TYPE(pm->flags) != PM_HASHED) {
|
||||
if (pm->flags & PM_EXPORTED) {
|
||||
if (!(pm->flags & PM_UNSET) && !pm->env && !asg->value)
|
||||
pm->env = addenv(asg->name, getsparam(asg->name));
|
||||
|
|
22
Src/exec.c
22
Src/exec.c
|
@ -1004,11 +1004,12 @@ void
|
|||
untokenize(char *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
if (itok(*s))
|
||||
if (itok(*s)) {
|
||||
if (*s == Nularg)
|
||||
chuck(s--);
|
||||
else
|
||||
*s = ztokens[*s - Pound];
|
||||
}
|
||||
}
|
||||
|
||||
/* Open a file for writing redicection */
|
||||
|
@ -1923,22 +1924,8 @@ save_params(Cmd cmd, LinkList *restore_p, LinkList *remove_p)
|
|||
} else if (!(pm->flags & PM_READONLY) &&
|
||||
(unset(RESTRICTED) || !(pm->flags & PM_RESTRICTED))) {
|
||||
Param tpm = (Param) alloc(sizeof *tpm);
|
||||
|
||||
tpm->nam = s;
|
||||
tpm->flags = pm->flags;
|
||||
switch (PM_TYPE(pm->flags)) {
|
||||
case PM_SCALAR:
|
||||
tpm->u.str = ztrdup(pm->gets.cfn(pm));
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
tpm->u.val = pm->gets.ifn(pm);
|
||||
break;
|
||||
case PM_ARRAY:
|
||||
PERMALLOC {
|
||||
tpm->u.arr = arrdup(pm->gets.afn(pm));
|
||||
} LASTALLOC;
|
||||
break;
|
||||
}
|
||||
copyparam(tpm, pm, 1);
|
||||
pm = tpm;
|
||||
}
|
||||
addlinknode(*remove_p, s);
|
||||
|
@ -1989,6 +1976,9 @@ restore_params(LinkList restorelist, LinkList removelist)
|
|||
case PM_ARRAY:
|
||||
tpm->sets.afn(tpm, pm->u.arr);
|
||||
break;
|
||||
case PM_HASHED:
|
||||
tpm->sets.hfn(tpm, pm->u.hash);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
paramtab->addnode(paramtab, pm->nam, pm);
|
||||
|
|
19
Src/glob.c
19
Src/glob.c
|
@ -355,21 +355,12 @@ scanner(Complist q)
|
|||
insert(c->str, 0);
|
||||
} else {
|
||||
/* Do pattern matching on current path section. */
|
||||
char *fn;
|
||||
char *fn = pathbuf[pathbufcwd] ? unmeta(pathbuf + pathbufcwd) : ".";
|
||||
int dirs = !!q->next;
|
||||
DIR *lock;
|
||||
DIR *lock = opendir(fn);
|
||||
char *subdirs = NULL;
|
||||
int subdirlen = 0;
|
||||
|
||||
fn = pathbuf[pathbufcwd] ? unmeta(pathbuf + pathbufcwd) : ".";
|
||||
if (dirs) {
|
||||
struct stat st;
|
||||
stat(fn, &st);
|
||||
/* a directory with subdirectories has link count greater than 2 */
|
||||
if (!S_ISDIR(st.st_mode) || st.st_nlink == 2)
|
||||
return;
|
||||
}
|
||||
lock = opendir(fn);
|
||||
if (lock == NULL)
|
||||
return;
|
||||
while ((fn = zreaddir(lock, 1)) && !errflag) {
|
||||
|
@ -594,7 +585,8 @@ parsecomp(int gflag)
|
|||
pptr[1] && pptr[1] != Outpar && pptr[1] != Bar) ||
|
||||
*pptr == Outpar) {
|
||||
if (*pptr == '/' || !*pptr ||
|
||||
(isset(EXTENDEDGLOB) && *pptr == Tilde &&
|
||||
((*pptr == Bar ||
|
||||
(isset(EXTENDEDGLOB) && *pptr == Tilde)) &&
|
||||
(gflag & GF_TOPLEV)))
|
||||
c->stat |= C_LAST;
|
||||
return c;
|
||||
|
@ -746,7 +738,8 @@ parsecomp(int gflag)
|
|||
}
|
||||
/* mark if last pattern component in path component or pattern */
|
||||
if (*pptr == '/' || !*pptr ||
|
||||
(isset(EXTENDEDGLOB) && *pptr == Tilde && (gflag & GF_TOPLEV)))
|
||||
((*pptr == Bar ||
|
||||
(isset(EXTENDEDGLOB) && *pptr == Tilde)) && (gflag & GF_TOPLEV)))
|
||||
c->stat |= C_LAST;
|
||||
c->str = dupstrpfx(cstr, pptr - cstr);
|
||||
return c;
|
||||
|
|
|
@ -1061,93 +1061,6 @@ printaliasnode(HashNode hn, int printflags)
|
|||
putchar('\n');
|
||||
}
|
||||
|
||||
/**********************************/
|
||||
/* Parameter Hash Table Functions */
|
||||
/**********************************/
|
||||
|
||||
/**/
|
||||
void
|
||||
freeparamnode(HashNode hn)
|
||||
{
|
||||
Param pm = (Param) hn;
|
||||
|
||||
zsfree(pm->nam);
|
||||
zfree(pm, sizeof(struct param));
|
||||
}
|
||||
|
||||
/* Print a parameter */
|
||||
|
||||
/**/
|
||||
void
|
||||
printparamnode(HashNode hn, int printflags)
|
||||
{
|
||||
Param p = (Param) hn;
|
||||
char *t, **u;
|
||||
|
||||
if (p->flags & PM_UNSET)
|
||||
return;
|
||||
|
||||
/* Print the attributes of the parameter */
|
||||
if (printflags & PRINT_TYPE) {
|
||||
if (p->flags & PM_INTEGER)
|
||||
printf("integer ");
|
||||
if (p->flags & PM_ARRAY)
|
||||
printf("array ");
|
||||
if (p->flags & PM_LEFT)
|
||||
printf("left justified %d ", p->ct);
|
||||
if (p->flags & PM_RIGHT_B)
|
||||
printf("right justified %d ", p->ct);
|
||||
if (p->flags & PM_RIGHT_Z)
|
||||
printf("zero filled %d ", p->ct);
|
||||
if (p->flags & PM_LOWER)
|
||||
printf("lowercase ");
|
||||
if (p->flags & PM_UPPER)
|
||||
printf("uppercase ");
|
||||
if (p->flags & PM_READONLY)
|
||||
printf("readonly ");
|
||||
if (p->flags & PM_TAGGED)
|
||||
printf("tagged ");
|
||||
if (p->flags & PM_EXPORTED)
|
||||
printf("exported ");
|
||||
}
|
||||
|
||||
if (printflags & PRINT_NAMEONLY) {
|
||||
zputs(p->nam, stdout);
|
||||
putchar('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
/* How the value is displayed depends *
|
||||
* on the type of the parameter */
|
||||
quotedzputs(p->nam, stdout);
|
||||
putchar('=');
|
||||
switch (PM_TYPE(p->flags)) {
|
||||
case PM_SCALAR:
|
||||
/* string: simple output */
|
||||
if (p->gets.cfn && (t = p->gets.cfn(p)))
|
||||
quotedzputs(t, stdout);
|
||||
putchar('\n');
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
/* integer */
|
||||
printf("%ld\n", p->gets.ifn(p));
|
||||
break;
|
||||
case PM_ARRAY:
|
||||
/* array */
|
||||
putchar('(');
|
||||
u = p->gets.afn(p);
|
||||
if(*u) {
|
||||
quotedzputs(*u++, stdout);
|
||||
while (*u) {
|
||||
putchar(' ');
|
||||
quotedzputs(*u++, stdout);
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
/* Named Directory Hash Table Functions */
|
||||
/****************************************/
|
||||
|
|
|
@ -176,7 +176,7 @@ shingetline(void)
|
|||
int
|
||||
ingetc(void)
|
||||
{
|
||||
char lastc;
|
||||
int lastc;
|
||||
|
||||
if (lexstop)
|
||||
return ' ';
|
||||
|
|
471
Src/params.c
471
Src/params.c
|
@ -232,6 +232,11 @@ IPDEF9("manpath", &manpath, "MANPATH"),
|
|||
IPDEF9("psvar", &psvar, "PSVAR"),
|
||||
IPDEF9("watch", &watch, "WATCH"),
|
||||
|
||||
/*TEST BEGIN*/
|
||||
#define IPDEF10(A) {NULL,A,PM_HASHED|PM_SPECIAL|PM_DONTIMPORT,BR((void *)0),SFN(hashsetfn),GFN(hashgetfn),stdunsetfn,0,NULL,NULL,NULL,0}
|
||||
IPDEF10("testhash"),
|
||||
/*TEST END*/
|
||||
|
||||
#ifdef DYNAMIC
|
||||
IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED),
|
||||
#endif
|
||||
|
@ -247,7 +252,137 @@ static Param argvparam;
|
|||
|
||||
/**/
|
||||
HashTable paramtab;
|
||||
|
||||
|
||||
/**/
|
||||
HashTable
|
||||
newparamtable(int size, char const *name)
|
||||
{
|
||||
HashTable ht = newhashtable(size, name, NULL);
|
||||
|
||||
ht->hash = hasher;
|
||||
ht->emptytable = emptyhashtable;
|
||||
ht->filltable = NULL;
|
||||
ht->addnode = addhashnode;
|
||||
ht->getnode = gethashnode2;
|
||||
ht->getnode2 = gethashnode2;
|
||||
ht->removenode = removehashnode;
|
||||
ht->disablenode = NULL;
|
||||
ht->enablenode = NULL;
|
||||
ht->freenode = freeparamnode;
|
||||
ht->printnode = printparamnode;
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
/* Copy a parameter hash table */
|
||||
|
||||
static HashTable outtable;
|
||||
|
||||
/**/
|
||||
static void
|
||||
scancopyparams(HashNode hn, int flags)
|
||||
{
|
||||
/* Going into a real parameter, so always use permanent storage */
|
||||
Param pm = (Param)hn;
|
||||
Param tpm = (Param) zcalloc(sizeof *tpm);
|
||||
tpm->nam = ztrdup(pm->nam);
|
||||
copyparam(tpm, pm, 0);
|
||||
addhashnode(outtable, tpm->nam, tpm);
|
||||
}
|
||||
|
||||
/**/
|
||||
HashTable
|
||||
copyparamtable(HashTable ht, char *name)
|
||||
{
|
||||
HashTable nht = newparamtable(ht->hsize, name);
|
||||
outtable = nht;
|
||||
scanhashtable(ht, 0, 0, 0, scancopyparams, 0);
|
||||
outtable = NULL;
|
||||
return nht;
|
||||
}
|
||||
|
||||
#define SCANPM_WANTVALS (1<<0)
|
||||
#define SCANPM_WANTKEYS (1<<1)
|
||||
#define SCANPM_WANTINDEX (1<<2)
|
||||
|
||||
static unsigned numparamvals;
|
||||
|
||||
/**/
|
||||
static void
|
||||
scancountparams(HashNode hn, int flags)
|
||||
{
|
||||
if (!(((Param)hn)->flags & PM_UNSET)) {
|
||||
++numparamvals;
|
||||
if ((flags & SCANPM_WANTKEYS) && (flags & SCANPM_WANTVALS))
|
||||
++numparamvals;
|
||||
}
|
||||
}
|
||||
|
||||
static char **paramvals;
|
||||
|
||||
/**/
|
||||
static void
|
||||
scanparamvals(HashNode hn, int flags)
|
||||
{
|
||||
struct value v;
|
||||
v.pm = (Param)hn;
|
||||
if (!(v.pm->flags & PM_UNSET)) {
|
||||
if (flags & SCANPM_WANTKEYS) {
|
||||
paramvals[numparamvals++] = v.pm->nam;
|
||||
if (!(flags & SCANPM_WANTVALS))
|
||||
return;
|
||||
}
|
||||
v.isarr = (PM_TYPE(v.pm->flags) & (PM_ARRAY|PM_HASHED));
|
||||
v.inv = (flags & SCANPM_WANTINDEX);
|
||||
v.a = 0;
|
||||
v.b = -1;
|
||||
paramvals[numparamvals++] = getstrvalue(&v);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
char **
|
||||
paramvalarr(HashTable ht, unsigned flags)
|
||||
{
|
||||
MUSTUSEHEAP("paramvalarr");
|
||||
numparamvals = 0;
|
||||
if (ht)
|
||||
scanhashtable(ht, 0, 0, 0, scancountparams, flags);
|
||||
paramvals = (char **) alloc((numparamvals + 1) * sizeof(char *));
|
||||
if (ht) {
|
||||
numparamvals = 0;
|
||||
scanhashtable(ht, 0, 0, 0, scanparamvals, flags);
|
||||
}
|
||||
paramvals[numparamvals] = 0;
|
||||
return paramvals;
|
||||
}
|
||||
|
||||
/* Return the full array (no indexing) referred to by a Value. *
|
||||
* The array value is cached for the lifetime of the Value. */
|
||||
|
||||
/**/
|
||||
static char **
|
||||
getvaluearr(Value v)
|
||||
{
|
||||
if (v->arr)
|
||||
return v->arr;
|
||||
else if (PM_TYPE(v->pm->flags) == PM_ARRAY)
|
||||
return v->arr = v->pm->gets.afn(v->pm);
|
||||
else if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
unsigned flags = 0;
|
||||
if (v->a)
|
||||
flags |= SCANPM_WANTKEYS;
|
||||
if (v->b > v->a)
|
||||
flags |= SCANPM_WANTVALS;
|
||||
v->arr = paramvalarr(v->pm->gets.hfn(v->pm), flags);
|
||||
/* Can't take numeric slices of associative arrays */
|
||||
v->a = 0;
|
||||
v->b = -1;
|
||||
return v->arr;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up parameter hash table. This will add predefined *
|
||||
* parameter entries as well as setting up parameter table *
|
||||
* entries for environment variables we inherit. */
|
||||
|
@ -261,19 +396,7 @@ createparamtable(void)
|
|||
char buf[50], *str, *iname;
|
||||
int num_env;
|
||||
|
||||
paramtab = newhashtable(151, "paramtab", NULL);
|
||||
|
||||
paramtab->hash = hasher;
|
||||
paramtab->emptytable = NULL;
|
||||
paramtab->filltable = NULL;
|
||||
paramtab->addnode = addhashnode;
|
||||
paramtab->getnode = gethashnode2;
|
||||
paramtab->getnode2 = gethashnode2;
|
||||
paramtab->removenode = removehashnode;
|
||||
paramtab->disablenode = NULL;
|
||||
paramtab->enablenode = NULL;
|
||||
paramtab->freenode = freeparamnode;
|
||||
paramtab->printnode = printparamnode;
|
||||
paramtab = newparamtable(151, "paramtab");
|
||||
|
||||
/* Add the special parameters to the hash table */
|
||||
for (ip = special_params; ip->nam; ip++)
|
||||
|
@ -368,6 +491,36 @@ createparamtable(void)
|
|||
noerrs = 0;
|
||||
}
|
||||
|
||||
/* assign various functions used for non-special parameters */
|
||||
|
||||
/**/
|
||||
static void
|
||||
assigngetset(Param pm)
|
||||
{
|
||||
switch (PM_TYPE(pm->flags)) {
|
||||
case PM_SCALAR:
|
||||
pm->sets.cfn = strsetfn;
|
||||
pm->gets.cfn = strgetfn;
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
pm->sets.ifn = intsetfn;
|
||||
pm->gets.ifn = intgetfn;
|
||||
break;
|
||||
case PM_ARRAY:
|
||||
pm->sets.afn = arrsetfn;
|
||||
pm->gets.afn = arrgetfn;
|
||||
break;
|
||||
case PM_HASHED:
|
||||
pm->sets.hfn = hashsetfn;
|
||||
pm->gets.hfn = hashgetfn;
|
||||
break;
|
||||
default:
|
||||
DPUTS(1, "BUG: tried to create param node without valid flag");
|
||||
break;
|
||||
}
|
||||
pm->unsetfn = stdunsetfn;
|
||||
}
|
||||
|
||||
/* Create a parameter, so that it can be assigned to. Returns NULL if the *
|
||||
* parameter already exists or can't be created, otherwise returns the *
|
||||
* parameter node. If a parameter of the same name exists in an outer *
|
||||
|
@ -413,27 +566,51 @@ createparam(char *name, int flags)
|
|||
pm = (Param) alloc(sizeof *pm);
|
||||
pm->flags = flags;
|
||||
|
||||
if(!(pm->flags & PM_SPECIAL)) {
|
||||
switch (PM_TYPE(flags)) {
|
||||
if(!(pm->flags & PM_SPECIAL))
|
||||
assigngetset(pm);
|
||||
return pm;
|
||||
}
|
||||
|
||||
/* Copy a parameter */
|
||||
|
||||
/**/
|
||||
void
|
||||
copyparam(Param tpm, Param pm, int toplevel)
|
||||
{
|
||||
/*
|
||||
* Note that tpm, into which we're copying, may not be in permanent
|
||||
* storage. However, the values themselves are later used directly
|
||||
* to set the parameter, so must be permanently allocated (in accordance
|
||||
* with sets.?fn() usage).
|
||||
*/
|
||||
PERMALLOC {
|
||||
tpm->flags = pm->flags;
|
||||
if (!toplevel)
|
||||
tpm->flags &= ~PM_SPECIAL;
|
||||
switch (PM_TYPE(pm->flags)) {
|
||||
case PM_SCALAR:
|
||||
pm->sets.cfn = strsetfn;
|
||||
pm->gets.cfn = strgetfn;
|
||||
tpm->u.str = ztrdup(pm->gets.cfn(pm));
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
pm->sets.ifn = intsetfn;
|
||||
pm->gets.ifn = intgetfn;
|
||||
tpm->u.val = pm->gets.ifn(pm);
|
||||
break;
|
||||
case PM_ARRAY:
|
||||
pm->sets.afn = arrsetfn;
|
||||
pm->gets.afn = arrgetfn;
|
||||
tpm->u.arr = arrdup(pm->gets.afn(pm));
|
||||
break;
|
||||
default:
|
||||
DPUTS(1, "BUG: tried to create param node without valid flag");
|
||||
case PM_HASHED:
|
||||
tpm->u.hash = copyparamtable(pm->gets.hfn(pm), pm->nam);
|
||||
break;
|
||||
}
|
||||
pm->unsetfn = stdunsetfn;
|
||||
}
|
||||
return pm;
|
||||
} LASTALLOC;
|
||||
/*
|
||||
* If called from inside an associative array, that array is later going
|
||||
* to be passed as a real parameter, so we need the gets and sets
|
||||
* functions to be useful. However, the saved associated array is
|
||||
* not itself special, so we just use the standard ones.
|
||||
* This is also why we switch off PM_SPECIAL.
|
||||
*/
|
||||
if (!toplevel)
|
||||
assigngetset(tpm);
|
||||
}
|
||||
|
||||
/* Return 1 if the string s is a valid identifier, else return 0. */
|
||||
|
@ -577,6 +754,23 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
singsub(&s);
|
||||
|
||||
if (!rev) {
|
||||
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
HashTable ht = v->pm->gets.hfn(v->pm);
|
||||
if (!ht) {
|
||||
ht = newparamtable(17, v->pm->nam);
|
||||
v->pm->sets.hfn(v->pm, ht);
|
||||
}
|
||||
if (!(v->pm = (Param) ht->getnode(ht, s))) {
|
||||
HashTable tht = paramtab;
|
||||
paramtab = ht;
|
||||
v->pm = createparam(s, PM_SCALAR|PM_UNSET);
|
||||
paramtab = tht;
|
||||
}
|
||||
v->isarr = 0;
|
||||
v->a = 0;
|
||||
*w = v->b = -1;
|
||||
r = isset(KSHARRAYS) ? 1 : 0;
|
||||
} else
|
||||
if (!(r = mathevalarg(s, &s)) || (isset(KSHARRAYS) && r >= 0))
|
||||
r++;
|
||||
if (word && !v->isarr) {
|
||||
|
@ -799,11 +993,12 @@ getvalue(char **pptr, int bracks)
|
|||
s = t = *pptr;
|
||||
garr = NULL;
|
||||
|
||||
if (idigit(*s))
|
||||
if (idigit(*s)) {
|
||||
if (bracks >= 0)
|
||||
ppar = zstrtol(s, &s, 10);
|
||||
else
|
||||
ppar = *s++ - '0';
|
||||
}
|
||||
else if (iident(*s))
|
||||
while (iident(*s))
|
||||
s++;
|
||||
|
@ -844,7 +1039,7 @@ getvalue(char **pptr, int bracks)
|
|||
if (!pm || (pm->flags & PM_UNSET))
|
||||
return NULL;
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY)
|
||||
if (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))
|
||||
v->isarr = isvarat ? -1 : 1;
|
||||
v->pm = pm;
|
||||
v->inv = 0;
|
||||
|
@ -863,12 +1058,12 @@ getvalue(char **pptr, int bracks)
|
|||
*pptr = s;
|
||||
if (v->a > MAX_ARRLEN ||
|
||||
v->a < -MAX_ARRLEN) {
|
||||
zerr("subscript to %s: %d", (v->a < 0) ? "small" : "big", v->a);
|
||||
zerr("subscript too %s: %d", (v->a < 0) ? "small" : "big", v->a);
|
||||
return NULL;
|
||||
}
|
||||
if (v->b > MAX_ARRLEN ||
|
||||
v->b < -MAX_ARRLEN) {
|
||||
zerr("subscript to %s: %d", (v->b < 0) ? "small" : "big", v->b);
|
||||
zerr("subscript too %s: %d", (v->b < 0) ? "small" : "big", v->b);
|
||||
return NULL;
|
||||
}
|
||||
return v;
|
||||
|
@ -891,11 +1086,12 @@ getstrvalue(Value v)
|
|||
}
|
||||
|
||||
switch(PM_TYPE(v->pm->flags)) {
|
||||
case PM_HASHED:
|
||||
case PM_ARRAY:
|
||||
ss = getvaluearr(v);
|
||||
if (v->isarr)
|
||||
s = sepjoin(v->pm->gets.afn(v->pm), NULL);
|
||||
s = sepjoin(ss, NULL);
|
||||
else {
|
||||
ss = v->pm->gets.afn(v->pm);
|
||||
if (v->a < 0)
|
||||
v->a += arrlen(ss);
|
||||
s = (v->a >= arrlen(ss) || v->a < 0) ? (char *) hcalloc(1) : ss[v->a];
|
||||
|
@ -913,8 +1109,9 @@ getstrvalue(Value v)
|
|||
break;
|
||||
}
|
||||
|
||||
if (v->a == 0 && v->b == -1)
|
||||
if (v->a == 0 && v->b == -1) {
|
||||
LASTALLOC_RETURN s;
|
||||
}
|
||||
if (v->a < 0)
|
||||
v->a += strlen(s);
|
||||
if (v->b < 0)
|
||||
|
@ -946,7 +1143,7 @@ getarrvalue(Value v)
|
|||
s[0] = dupstring(buf);
|
||||
return s;
|
||||
}
|
||||
s = v->pm->gets.afn(v->pm);
|
||||
s = getvaluearr(v);
|
||||
if (v->a == 0 && v->b == -1)
|
||||
return s;
|
||||
if (v->a < 0)
|
||||
|
@ -993,6 +1190,7 @@ setstrvalue(Value v, char *val)
|
|||
zsfree(val);
|
||||
return;
|
||||
}
|
||||
v->pm->flags &= ~PM_UNSET;
|
||||
switch (PM_TYPE(v->pm->flags)) {
|
||||
case PM_SCALAR:
|
||||
MUSTUSEHEAP("setstrvalue");
|
||||
|
@ -1103,17 +1301,25 @@ setarrvalue(Value v, char **val)
|
|||
freearray(val);
|
||||
return;
|
||||
}
|
||||
if (PM_TYPE(v->pm->flags) != PM_ARRAY) {
|
||||
if (PM_TYPE(v->pm->flags) & ~(PM_ARRAY|PM_HASHED)) {
|
||||
freearray(val);
|
||||
zerr("attempt to assign array value to non-array", NULL, 0);
|
||||
return;
|
||||
}
|
||||
if (v->a == 0 && v->b == -1)
|
||||
(v->pm->sets.afn) (v->pm, val);
|
||||
else {
|
||||
if (v->a == 0 && v->b == -1) {
|
||||
if (PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
arrhashsetfn(v->pm, val);
|
||||
else
|
||||
(v->pm->sets.afn) (v->pm, val);
|
||||
} else {
|
||||
char **old, **new, **p, **q, **r;
|
||||
int n, ll, i;
|
||||
|
||||
if ((PM_TYPE(v->pm->flags) == PM_HASHED)) {
|
||||
freearray(val);
|
||||
zerr("attempt to set slice of associative array", NULL, 0);
|
||||
return;
|
||||
}
|
||||
if (v->inv && unset(KSHARRAYS))
|
||||
v->a--, v->b--;
|
||||
q = old = v->pm->gets.afn(v->pm);
|
||||
|
@ -1187,6 +1393,20 @@ getaparam(char *s)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Retrieve an assoc array parameter as an array */
|
||||
|
||||
/**/
|
||||
char **
|
||||
gethparam(char *s)
|
||||
{
|
||||
Value v;
|
||||
|
||||
if (!idigit(*s) && (v = getvalue(&s, 0)) &&
|
||||
PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
return paramvalarr(v->pm->gets.hfn(v->pm), SCANPM_WANTVALS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
Param
|
||||
setsparam(char *s, char *val)
|
||||
|
@ -1248,7 +1468,7 @@ setaparam(char *s, char **val)
|
|||
} else {
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_ARRAY);
|
||||
else if (PM_TYPE(v->pm->flags) != PM_ARRAY &&
|
||||
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
!(v->pm->flags & PM_SPECIAL)) {
|
||||
int uniq = v->pm->flags & PM_UNIQUE;
|
||||
unsetparam(t);
|
||||
|
@ -1338,7 +1558,7 @@ unsetparam_pm(Param pm, int altflag, int exp)
|
|||
* is called. Beyond that, there is an ambiguity: should *
|
||||
* foo() { local bar; unset bar; } make the global bar *
|
||||
* available or not? The following makes the answer "no". */
|
||||
if (locallevel >= pm->level)
|
||||
if ((locallevel && locallevel >= pm->level) || (pm->flags & PM_SPECIAL))
|
||||
return;
|
||||
|
||||
paramtab->removenode(paramtab, pm->nam); /* remove parameter node from table */
|
||||
|
@ -1363,6 +1583,7 @@ stdunsetfn(Param pm, int exp)
|
|||
switch (PM_TYPE(pm->flags)) {
|
||||
case PM_SCALAR: pm->sets.cfn(pm, NULL); break;
|
||||
case PM_ARRAY: pm->sets.afn(pm, NULL); break;
|
||||
case PM_HASHED: pm->sets.hfn(pm, NULL); break;
|
||||
}
|
||||
pm->flags |= PM_UNSET;
|
||||
}
|
||||
|
@ -1429,6 +1650,70 @@ arrsetfn(Param pm, char **x)
|
|||
pm->u.arr = x;
|
||||
}
|
||||
|
||||
/* Function to get value of an association parameter */
|
||||
|
||||
/**/
|
||||
static HashTable
|
||||
hashgetfn(Param pm)
|
||||
{
|
||||
return pm->u.hash;
|
||||
}
|
||||
|
||||
/* Flag to freeparamnode to unset the struct */
|
||||
|
||||
static int delunset;
|
||||
|
||||
/* Function to set value of an association parameter */
|
||||
|
||||
/**/
|
||||
static void
|
||||
hashsetfn(Param pm, HashTable x)
|
||||
{
|
||||
if (pm->u.hash && pm->u.hash != x) {
|
||||
/* The parameters in the hash table need to be unset *
|
||||
* before being deleted. */
|
||||
int odelunset = delunset;
|
||||
delunset = 1;
|
||||
deletehashtable(pm->u.hash);
|
||||
delunset = odelunset;
|
||||
}
|
||||
pm->u.hash = x;
|
||||
}
|
||||
|
||||
/* Function to set value of an association parameter using key/value pairs */
|
||||
|
||||
/**/
|
||||
static void
|
||||
arrhashsetfn(Param pm, char **val)
|
||||
{
|
||||
/* Best not to shortcut this by using the existing hash table, *
|
||||
* since that could cause trouble for special hashes. This way, *
|
||||
* it's up to pm->sets.hfn() what to do. */
|
||||
int alen = arrlen(val);
|
||||
HashTable opmtab = paramtab, ht;
|
||||
char **aptr = val;
|
||||
Value v = (Value) hcalloc(sizeof *v);
|
||||
v->b = -1;
|
||||
|
||||
if (alen % 2) {
|
||||
freearray(val);
|
||||
zerr("bad set of key/value pairs for associative array\n",
|
||||
NULL, 0);
|
||||
return;
|
||||
}
|
||||
ht = paramtab = newparamtable(17, pm->nam);
|
||||
while (*aptr) {
|
||||
/* The parameter name is ztrdup'd... */
|
||||
v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET);
|
||||
zsfree(*aptr++);
|
||||
/* ...but we can use the value without copying. */
|
||||
setstrvalue(v, *aptr++);
|
||||
}
|
||||
paramtab = opmtab;
|
||||
pm->sets.hfn(pm, ht);
|
||||
free(val); /* not freearray() */
|
||||
}
|
||||
|
||||
/* This function is used as the set function for *
|
||||
* special parameters that cannot be set by the user. */
|
||||
|
||||
|
@ -2189,3 +2474,107 @@ scanendscope(HashNode hn, int flags)
|
|||
if(pm->level > locallevel)
|
||||
unsetparam_pm(pm, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* Parameter Hash Table Functions */
|
||||
/**********************************/
|
||||
|
||||
/**/
|
||||
void
|
||||
freeparamnode(HashNode hn)
|
||||
{
|
||||
Param pm = (Param) hn;
|
||||
|
||||
/* Since the second flag to unsetfn isn't used, I don't *
|
||||
* know what its value should be. */
|
||||
if (delunset)
|
||||
pm->unsetfn(pm, 1);
|
||||
zsfree(pm->nam);
|
||||
zfree(pm, sizeof(struct param));
|
||||
}
|
||||
|
||||
/* Print a parameter */
|
||||
|
||||
/**/
|
||||
void
|
||||
printparamnode(HashNode hn, int printflags)
|
||||
{
|
||||
Param p = (Param) hn;
|
||||
char *t, **u;
|
||||
|
||||
if (p->flags & PM_UNSET)
|
||||
return;
|
||||
|
||||
/* Print the attributes of the parameter */
|
||||
if (printflags & PRINT_TYPE) {
|
||||
if (p->flags & PM_INTEGER)
|
||||
printf("integer ");
|
||||
else if (p->flags & PM_ARRAY)
|
||||
printf("array ");
|
||||
else if (p->flags & PM_HASHED)
|
||||
printf("association ");
|
||||
if (p->flags & PM_LEFT)
|
||||
printf("left justified %d ", p->ct);
|
||||
if (p->flags & PM_RIGHT_B)
|
||||
printf("right justified %d ", p->ct);
|
||||
if (p->flags & PM_RIGHT_Z)
|
||||
printf("zero filled %d ", p->ct);
|
||||
if (p->flags & PM_LOWER)
|
||||
printf("lowercase ");
|
||||
if (p->flags & PM_UPPER)
|
||||
printf("uppercase ");
|
||||
if (p->flags & PM_READONLY)
|
||||
printf("readonly ");
|
||||
if (p->flags & PM_TAGGED)
|
||||
printf("tagged ");
|
||||
if (p->flags & PM_EXPORTED)
|
||||
printf("exported ");
|
||||
}
|
||||
|
||||
if (printflags & PRINT_NAMEONLY) {
|
||||
zputs(p->nam, stdout);
|
||||
putchar('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
/* How the value is displayed depends *
|
||||
* on the type of the parameter */
|
||||
quotedzputs(p->nam, stdout);
|
||||
putchar('=');
|
||||
switch (PM_TYPE(p->flags)) {
|
||||
case PM_SCALAR:
|
||||
/* string: simple output */
|
||||
if (p->gets.cfn && (t = p->gets.cfn(p)))
|
||||
quotedzputs(t, stdout);
|
||||
putchar('\n');
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
/* integer */
|
||||
printf("%ld\n", p->gets.ifn(p));
|
||||
break;
|
||||
case PM_ARRAY:
|
||||
/* array */
|
||||
putchar('(');
|
||||
u = p->gets.afn(p);
|
||||
if(*u) {
|
||||
quotedzputs(*u++, stdout);
|
||||
while (*u) {
|
||||
putchar(' ');
|
||||
quotedzputs(*u++, stdout);
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
break;
|
||||
case PM_HASHED:
|
||||
/* association */
|
||||
putchar('(');
|
||||
{
|
||||
HashTable ht = p->gets.hfn(p);
|
||||
if (ht)
|
||||
scanhashtable(ht, 0, 0, 0, ht->printnode, 0);
|
||||
}
|
||||
printf(")\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
256
Src/prompt.c
256
Src/prompt.c
|
@ -71,6 +71,10 @@ static int bufspc;
|
|||
|
||||
static char *bp;
|
||||
|
||||
/* Position of the start of the current line in the buffer */
|
||||
|
||||
static char *bufline;
|
||||
|
||||
/* bp1 is an auxilliary pointer into the buffer, which when non-NULL is *
|
||||
* moved whenever the buffer is reallocated. It is used when data is *
|
||||
* being temporarily held in the buffer. */
|
||||
|
@ -81,11 +85,9 @@ static char *bp1;
|
|||
|
||||
static char *fm;
|
||||
|
||||
/* Current truncation string (metafied), the length at which truncation *
|
||||
* occurs, and the direction in which it occurs. */
|
||||
/* Non-zero if truncating the current segment of the buffer. */
|
||||
|
||||
static char *truncstr;
|
||||
static int trunclen, truncatleft;
|
||||
static int trunclen;
|
||||
|
||||
/* Current level of nesting of %{ / %} sequences. */
|
||||
|
||||
|
@ -95,10 +97,6 @@ static int dontcount;
|
|||
|
||||
static char *rstring, *Rstring;
|
||||
|
||||
/* If non-zero, Inpar, Outpar and Nularg can be added to the buffer. */
|
||||
|
||||
static int nonsp;
|
||||
|
||||
/* Perform prompt expansion on a string, putting the result in a *
|
||||
* permanently-allocated string. If ns is non-zero, this string *
|
||||
* may have embedded Inpar and Outpar, which indicate a toggling *
|
||||
|
@ -130,9 +128,8 @@ promptexpand(char *s, int ns, char *rs, char *Rs)
|
|||
|
||||
rstring = rs;
|
||||
Rstring = Rs;
|
||||
nonsp = ns;
|
||||
fm = s;
|
||||
bp = buf = zalloc(bufspc = 256);
|
||||
bp = bufline = buf = zalloc(bufspc = 256);
|
||||
bp1 = NULL;
|
||||
trunclen = 0;
|
||||
putpromptchar(1, '\0');
|
||||
|
@ -140,6 +137,15 @@ promptexpand(char *s, int ns, char *rs, char *Rs)
|
|||
if(dontcount)
|
||||
*bp++ = Outpar;
|
||||
*bp = 0;
|
||||
if (!ns) {
|
||||
/* If zero, Inpar, Outpar and Nularg should be removed. */
|
||||
for (bp = buf; *bp; bp++) {
|
||||
if (*bp == Meta)
|
||||
bp++;
|
||||
else if (*bp == Inpar || *bp == Outpar || *bp == Nularg)
|
||||
chuck(bp);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -164,7 +170,7 @@ putpromptchar(int doprint, int endchar)
|
|||
arg = zstrtol(fm, &fm, 10);
|
||||
}
|
||||
if (*fm == '(') {
|
||||
int tc;
|
||||
int tc, otrunclen;
|
||||
|
||||
if (idigit(*++fm)) {
|
||||
arg = zstrtol(fm, &fm, 10);
|
||||
|
@ -224,6 +230,12 @@ putpromptchar(int doprint, int endchar)
|
|||
if (getegid() == arg)
|
||||
test = 1;
|
||||
break;
|
||||
case 'l':
|
||||
*bp = '\0';
|
||||
countprompt(bufline, &t0, 0);
|
||||
if (t0 >= arg)
|
||||
test = 1;
|
||||
break;
|
||||
case 'L':
|
||||
if (shlvl >= arg)
|
||||
test = 1;
|
||||
|
@ -249,10 +261,15 @@ putpromptchar(int doprint, int endchar)
|
|||
if (!*fm || !(sep = *++fm))
|
||||
return 0;
|
||||
fm++;
|
||||
/* Don't do the current truncation until we get back */
|
||||
otrunclen = trunclen;
|
||||
trunclen = 0;
|
||||
if (!putpromptchar(test == 1 && doprint, sep) || !*++fm ||
|
||||
!putpromptchar(test == 0 && doprint, ')')) {
|
||||
trunclen = otrunclen;
|
||||
return 0;
|
||||
}
|
||||
trunclen = otrunclen;
|
||||
continue;
|
||||
}
|
||||
if (!doprint)
|
||||
|
@ -377,72 +394,24 @@ putpromptchar(int doprint, int endchar)
|
|||
tsetcap(TCUNDERLINEEND, 1);
|
||||
break;
|
||||
case '[':
|
||||
if (idigit(*++fm))
|
||||
trunclen = zstrtol(fm, &fm, 10);
|
||||
else
|
||||
trunclen = arg;
|
||||
if (trunclen) {
|
||||
truncatleft = *fm && *fm != ']' && *fm++ == '<';
|
||||
bp1 = bp;
|
||||
while (*fm && *fm != ']') {
|
||||
if (*fm == '\\' && fm[1])
|
||||
++fm;
|
||||
addbufspc(1);
|
||||
*bp++ = *fm++;
|
||||
}
|
||||
addbufspc(2);
|
||||
if (bp1 == bp)
|
||||
*bp++ = '<';
|
||||
*bp = '\0';
|
||||
zsfree(truncstr);
|
||||
truncstr = ztrdup(bp = bp1);
|
||||
bp1 = NULL;
|
||||
} else {
|
||||
while (*fm && *fm != ']') {
|
||||
if (*fm == '\\' && fm[1])
|
||||
fm++;
|
||||
fm++;
|
||||
}
|
||||
}
|
||||
if(!*fm)
|
||||
return 0;
|
||||
if (idigit(*++fm))
|
||||
arg = zstrtol(fm, &fm, 10);
|
||||
if (!prompttrunc(arg, ']', doprint, endchar))
|
||||
return *fm;
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
if((trunclen = arg)) {
|
||||
char ch = *fm++;
|
||||
truncatleft = ch == '<';
|
||||
bp1 = bp;
|
||||
while (*fm && *fm != ch) {
|
||||
if (*fm == '\\' && fm[1])
|
||||
++fm;
|
||||
addbufspc(1);
|
||||
*bp++ = *fm++;
|
||||
}
|
||||
addbufspc(1);
|
||||
*bp = '\0';
|
||||
zsfree(truncstr);
|
||||
truncstr = ztrdup(bp = bp1);
|
||||
bp1 = NULL;
|
||||
} else {
|
||||
char ch = *fm++;
|
||||
while(*fm && *fm != ch) {
|
||||
if (*fm == '\\' && fm[1])
|
||||
fm++;
|
||||
fm++;
|
||||
}
|
||||
}
|
||||
if(!*fm)
|
||||
return 0;
|
||||
if (!prompttrunc(arg, *fm, doprint, endchar))
|
||||
return *fm;
|
||||
break;
|
||||
case '{': /*}*/
|
||||
if (!dontcount++ && nonsp) {
|
||||
if (!dontcount++) {
|
||||
addbufspc(1);
|
||||
*bp++ = Inpar;
|
||||
}
|
||||
break;
|
||||
case /*{*/ '}':
|
||||
if (dontcount && !--dontcount && nonsp) {
|
||||
if (dontcount && !--dontcount) {
|
||||
addbufspc(1);
|
||||
*bp++ = Outpar;
|
||||
}
|
||||
|
@ -569,7 +538,7 @@ putpromptchar(int doprint, int endchar)
|
|||
break;
|
||||
}
|
||||
} else if(*fm == '!' && isset(PROMPTBANG)) {
|
||||
if(doprint)
|
||||
if(doprint) {
|
||||
if(fm[1] == '!') {
|
||||
fm++;
|
||||
addbufspc(1);
|
||||
|
@ -579,6 +548,7 @@ putpromptchar(int doprint, int endchar)
|
|||
sprintf(bp, "%d", curhist);
|
||||
bp += strlen(bp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char c = *fm == Meta ? *++fm ^ 32 : *fm;
|
||||
|
||||
|
@ -604,6 +574,8 @@ pputc(char c)
|
|||
c ^= 32;
|
||||
}
|
||||
*bp++ = c;
|
||||
if (c == '\n' && !dontcount)
|
||||
bufline = bp;
|
||||
}
|
||||
|
||||
/* Make sure there is room for `need' more characters in the buffer. */
|
||||
|
@ -627,46 +599,19 @@ addbufspc(int need)
|
|||
}
|
||||
|
||||
/* stradd() adds a metafied string to the prompt, *
|
||||
* in a visible representation, doing truncation. */
|
||||
* in a visible representation. */
|
||||
|
||||
/**/
|
||||
void
|
||||
stradd(char *d)
|
||||
{
|
||||
/* dlen is the full length of the string we want to add */
|
||||
int dlen = niceztrlen(d);
|
||||
char *ps, *pd, *pc, *t;
|
||||
int tlen, maxlen;
|
||||
addbufspc(dlen);
|
||||
char *ps, *pc;
|
||||
addbufspc(niceztrlen(d));
|
||||
/* This loop puts the nice representation of the string into the prompt *
|
||||
* buffer. It might be modified later. Note that bp isn't changed. */
|
||||
for(ps=d, pd=bp; *ps; ps++)
|
||||
* buffer. */
|
||||
for(ps=d; *ps; ps++)
|
||||
for(pc=nicechar(*ps == Meta ? STOUC(*++ps)^32 : STOUC(*ps)); *pc; pc++)
|
||||
*pd++ = *pc;
|
||||
if(!trunclen || dlen <= trunclen) {
|
||||
/* No truncation is needed, so update bp and return, *
|
||||
* leaving the full string in the prompt. */
|
||||
bp += dlen;
|
||||
return;
|
||||
}
|
||||
/* We need to truncate. t points to the truncation string -- which is *
|
||||
* inserted literally, without nice representation. tlen is its *
|
||||
* length, and maxlen is the amout of the main string that we want to *
|
||||
* keep. Note that if the truncation string is longer than the *
|
||||
* truncation length (tlen > trunclen), the truncation string is used *
|
||||
* in full. */
|
||||
addbufspc(tlen = ztrlen(t = truncstr));
|
||||
maxlen = tlen < trunclen ? trunclen - tlen : 0;
|
||||
if(truncatleft) {
|
||||
memmove(bp + strlen(t), bp + dlen - maxlen, maxlen);
|
||||
while(*t)
|
||||
*bp++ = *t++;
|
||||
bp += maxlen;
|
||||
} else {
|
||||
bp += maxlen;
|
||||
while(*t)
|
||||
*bp++ = *t++;
|
||||
}
|
||||
*bp++ = *pc;
|
||||
}
|
||||
|
||||
/* tsetcap(), among other things, can write a termcap string into the buffer. */
|
||||
|
@ -684,12 +629,12 @@ tsetcap(int cap, int flag)
|
|||
tputs(tcstr[cap], 1, putshout);
|
||||
break;
|
||||
case 1:
|
||||
if (!dontcount && nonsp) {
|
||||
if (!dontcount) {
|
||||
addbufspc(1);
|
||||
*bp++ = Inpar;
|
||||
}
|
||||
tputs(tcstr[cap], 1, putstr);
|
||||
if (!dontcount && nonsp) {
|
||||
if (!dontcount) {
|
||||
int glitch = 0;
|
||||
|
||||
if (cap == TCSTANDOUTBEG || cap == TCSTANDOUTEND)
|
||||
|
@ -764,3 +709,108 @@ countprompt(char *str, int *wp, int *hp)
|
|||
if(hp)
|
||||
*hp = h;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
prompttrunc(int arg, int truncchar, int doprint, int endchar)
|
||||
{
|
||||
if (arg) {
|
||||
char ch = *fm, *ptr = bp, *truncstr;
|
||||
int truncatleft = ch == '<';
|
||||
|
||||
/*
|
||||
* If there is already a truncation active, return so that
|
||||
* can be finished, backing up so that the new truncation
|
||||
* can be started afterwards.
|
||||
*/
|
||||
if (trunclen) {
|
||||
while (*--fm != '%')
|
||||
;
|
||||
fm--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
trunclen = arg;
|
||||
if (*fm != ']')
|
||||
fm++;
|
||||
while (*fm && *fm != truncchar) {
|
||||
if (*fm == '\\' && fm[1])
|
||||
++fm;
|
||||
addbufspc(1);
|
||||
*bp++ = *fm++;
|
||||
}
|
||||
if (!*fm)
|
||||
return 0;
|
||||
if (bp == ptr && truncchar == ']') {
|
||||
addbufspc(1);
|
||||
*bp++ = '<';
|
||||
}
|
||||
truncstr = ztrduppfx(ptr, bp - ptr);
|
||||
|
||||
bp = ptr;
|
||||
fm++;
|
||||
putpromptchar(doprint, endchar);
|
||||
*bp = '\0';
|
||||
if (bp - ptr > trunclen) {
|
||||
/*
|
||||
* We need to truncate. t points to the truncation string -- *
|
||||
* which is inserted literally, without nice representation. *
|
||||
* tlen is its length, and maxlen is the amount of the main *
|
||||
* string that we want to keep. Note that if the truncation *
|
||||
* string is longer than the truncation length (tlen > *
|
||||
* trunclen), the truncation string is used in full. *
|
||||
*/
|
||||
char *t = truncstr;
|
||||
int fullen = bp - ptr;
|
||||
int tlen = ztrlen(t), maxlen;
|
||||
if (tlen > fullen) {
|
||||
addbufspc(tlen - fullen);
|
||||
bp += tlen - fullen;
|
||||
} else
|
||||
bp -= fullen - trunclen;
|
||||
maxlen = tlen < trunclen ? trunclen - tlen : 0;
|
||||
if (truncatleft) {
|
||||
if (maxlen)
|
||||
memmove(ptr + strlen(t), ptr + fullen - maxlen,
|
||||
maxlen);
|
||||
while (*t)
|
||||
*ptr++ = *t++;
|
||||
} else {
|
||||
ptr += maxlen;
|
||||
while (*t)
|
||||
*ptr++ = *t++;
|
||||
}
|
||||
}
|
||||
zsfree(truncstr);
|
||||
trunclen = 0;
|
||||
/*
|
||||
* We may have returned early from the previous putpromptchar *
|
||||
* because we found another truncation following this one. *
|
||||
* In that case we need to do the rest now. *
|
||||
*/
|
||||
if (!*fm)
|
||||
return 0;
|
||||
if (*fm != endchar) {
|
||||
fm++;
|
||||
/*
|
||||
* With trunclen set to zero, we always reach endchar *
|
||||
* (or the terminating NULL) this time round. *
|
||||
*/
|
||||
if (!putpromptchar(doprint, endchar))
|
||||
return 0;
|
||||
/* Now we have to trick it into matching endchar again */
|
||||
fm--;
|
||||
}
|
||||
} else {
|
||||
if (*fm != ']')
|
||||
fm++;
|
||||
while(*fm && *fm != truncchar) {
|
||||
if (*fm == '\\' && fm[1])
|
||||
fm++;
|
||||
fm++;
|
||||
}
|
||||
if (trunclen || !*fm)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
30
Src/subst.c
30
Src/subst.c
|
@ -716,6 +716,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int eval = 0;
|
||||
int nojoin = 0;
|
||||
char inbrace = 0; /* != 0 means ${...}, otherwise $... */
|
||||
char hkeys = 0; /* 1 means get keys from associative array */
|
||||
char hvals = 1; /* > hkeys get values of associative array */
|
||||
|
||||
*s++ = '\0';
|
||||
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
||||
|
@ -732,12 +734,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (*s == Inbrace) {
|
||||
inbrace = 1;
|
||||
s++;
|
||||
if (*s == '(' || *s == Inpar) {
|
||||
if (*s == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
||||
hkeys = 1;
|
||||
s++;
|
||||
} else if (*s == '(' || *s == Inpar) {
|
||||
char *t, sav;
|
||||
int tt = 0;
|
||||
long num;
|
||||
int escapes = 0;
|
||||
int klen;
|
||||
#define UNTOK(C) (itok(C) ? ztokens[(C) - Pound] : (C))
|
||||
#define UNTOK_AND_ESCAPE(X) {\
|
||||
untokenize(X = dupstring(s + 1));\
|
||||
if (escapes) {\
|
||||
|
@ -851,7 +857,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
prenum = num;
|
||||
else
|
||||
postnum = num;
|
||||
if (s[1] != sav)
|
||||
if (UNTOK(s[1]) != UNTOK(sav))
|
||||
break;
|
||||
t = get_strarg(++s);
|
||||
if (!*t)
|
||||
|
@ -865,7 +871,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
*t = sav;
|
||||
sav = *s;
|
||||
s = t + 1;
|
||||
if (*s != sav) {
|
||||
if (UNTOK(*s) != UNTOK(sav)) {
|
||||
s--;
|
||||
break;
|
||||
}
|
||||
|
@ -886,6 +892,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
escapes = 1;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
hkeys = 1;
|
||||
break;
|
||||
case 'v':
|
||||
hvals = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
flagerr:
|
||||
zerr("error in flags", NULL, 0);
|
||||
|
@ -986,9 +999,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (getindex(&s, v) || s == os)
|
||||
break;
|
||||
}
|
||||
if ((isarr = v->isarr))
|
||||
if ((isarr = v->isarr)) {
|
||||
/* No way to reach here with v->inv != 0, so getvaluearr() *
|
||||
* will definitely be called by getarrvalue(). Slicing of *
|
||||
* associations isn't done, so use v->a and v->b for flags */
|
||||
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
v->a = hkeys;
|
||||
v->b = hvals;
|
||||
}
|
||||
aval = getarrvalue(v);
|
||||
else {
|
||||
} else {
|
||||
if (v->pm->flags & PM_ARRAY) {
|
||||
int tmplen = arrlen(v->pm->gets.afn(v->pm));
|
||||
|
||||
|
|
|
@ -450,6 +450,8 @@ getsimptext(Cmd cmd)
|
|||
taddchr('(');
|
||||
taddlist(v->arr);
|
||||
taddstr(") ");
|
||||
} else if (PM_TYPE(v->type) == PM_HASHED) {
|
||||
/* XXX */
|
||||
} else {
|
||||
taddstr(v->str);
|
||||
taddchr(' ');
|
||||
|
|
|
@ -510,8 +510,8 @@ adduserdir(char *s, char *t, int flags, int always)
|
|||
if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
|
||||
return;
|
||||
|
||||
/* Never hash PWD, because it's never useful */
|
||||
if (!strcmp(s, "PWD"))
|
||||
/* Never hash PWD unless it was explicitly requested */
|
||||
if (!always && !strcmp(s, "PWD"))
|
||||
return;
|
||||
|
||||
/* Normal parameter assignments generate calls to this function, *
|
||||
|
|
|
@ -59,6 +59,7 @@ freeheap
|
|||
getaparam
|
||||
gethashnode
|
||||
gethashnode2
|
||||
gethparam
|
||||
getiparam
|
||||
getkeystring
|
||||
getlinknode
|
||||
|
|
|
@ -538,6 +538,7 @@ struct value {
|
|||
int inv; /* should we return the index ? */
|
||||
int a; /* first element of array slice, or -1 */
|
||||
int b; /* last element of array slice, or -1 */
|
||||
char **arr; /* cache for hash turned into array */
|
||||
};
|
||||
|
||||
/* structure for foo=bar assignments */
|
||||
|
@ -813,6 +814,7 @@ struct param {
|
|||
char **arr; /* value if declared array (PM_ARRAY) */
|
||||
char *str; /* value if declared string (PM_SCALAR) */
|
||||
long val; /* value if declared integer (PM_INTEGER) */
|
||||
HashTable hash; /* value if declared assoc (PM_HASHED) */
|
||||
} u;
|
||||
|
||||
/* pointer to function to set value of this parameter */
|
||||
|
@ -820,6 +822,7 @@ struct param {
|
|||
void (*cfn) _((Param, char *));
|
||||
void (*ifn) _((Param, long));
|
||||
void (*afn) _((Param, char **));
|
||||
void (*hfn) _((Param, HashTable));
|
||||
} sets;
|
||||
|
||||
/* pointer to function to get value of this parameter */
|
||||
|
@ -827,6 +830,7 @@ struct param {
|
|||
char *(*cfn) _((Param));
|
||||
long (*ifn) _((Param));
|
||||
char **(*afn) _((Param));
|
||||
HashTable (*hfn) _((Param));
|
||||
} gets;
|
||||
|
||||
/* pointer to function to unset this parameter */
|
||||
|
@ -845,8 +849,9 @@ struct param {
|
|||
#define PM_SCALAR 0 /* scalar */
|
||||
#define PM_ARRAY (1<<0) /* array */
|
||||
#define PM_INTEGER (1<<1) /* integer */
|
||||
#define PM_HASHED (1<<15) /* association */
|
||||
|
||||
#define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY))
|
||||
#define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY|PM_HASHED))
|
||||
|
||||
#define PM_LEFT (1<<2) /* left justify and remove leading blanks */
|
||||
#define PM_RIGHT_B (1<<3) /* right justify and fill with leading blanks */
|
||||
|
|
6
config.guess
vendored
6
config.guess
vendored
|
@ -557,6 +557,12 @@ EOF
|
|||
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
||||
echo i586-unisys-sysv4
|
||||
exit 0 ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:Rhapsody:*:*)
|
||||
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
|
|
2
config.sub
vendored
2
config.sub
vendored
|
@ -689,7 +689,7 @@ case $os in
|
|||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -linux* | -uxpv*)
|
||||
| -linux* | -uxpv* | -rhapsody* )
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-sunos5*)
|
||||
|
|
|
@ -5,7 +5,7 @@ patches. (The version number built into the shell has not been changed.)
|
|||
|
||||
Zoli's AIX dynamic loading patch from 3933, slightly updated, without
|
||||
some hunks which weren't needed on AIX 3.x so I don't know how to
|
||||
update properly.
|
||||
update them properly
|
||||
|
||||
My completion widgets patch
|
||||
|
||||
|
@ -18,24 +18,85 @@ My patch in 4477 to rename three functions to avoid clashes when
|
|||
dynamic loading (particularly necessary on IRIX and AIX), including
|
||||
the effect of Sven's additional fix in 4488
|
||||
|
||||
My patch 4513 for case-insensitive globbing via flags, plus fixlet 4552
|
||||
Sven's magna opera patch-or 4510 and patch-match 4509 to add control
|
||||
of alternative matches and arbitrary mapping between characters in the
|
||||
command line and the matched string, plus all known related fixes
|
||||
4526, 4527, 4534, 4555, 4557
|
||||
|
||||
Sven's magna opera patch-or 4510 and patch-match 4509 to add control of
|
||||
alternative matches and arbitrary mapping between characters in the
|
||||
command line and the matched, plus all known fixes 4526, 4527, 4534,
|
||||
4555, 4557
|
||||
My patch 4513 for case-insensitive globbing via flags, plus fixlet 4552
|
||||
|
||||
My ~PWD patch 4533
|
||||
|
||||
My suggestion for fixing the suffix on a yank in 4564
|
||||
|
||||
Bart's deltochar patch including new flags to allow commands not to
|
||||
interrupt cumulative effects in 4570
|
||||
interrupt cumulative effects in 4570 (new flag merged with compctl
|
||||
widgets flags).
|
||||
|
||||
Bart's doc fiz 4574
|
||||
Bart's doc fix 4574
|
||||
|
||||
Sven's latest word on the fixsuffix() horror in 4576, plus a
|
||||
fixsuffix() added by hand in delcharorlist() which I've somehow missed
|
||||
along the way
|
||||
A fixsuffix() added by hand in delcharorlist() which I've somehow
|
||||
missed along the way. The fixsuffix() horror is probably not yet
|
||||
resolved; 4576 has side effects and hasn't been applied.
|
||||
|
||||
My latest version of lete2ctl, not posted
|
||||
My latest version of lete2ctl, not posted but available at
|
||||
http://www.ifh.de/~pws/computing/lete2ctl .
|
||||
|
||||
Bart's chpwd() fix 4589
|
||||
|
||||
Second edition
|
||||
|
||||
Added line in zle_tricky.c missed when patching by hand, spotted by
|
||||
Bart. (Whitespace is still non-canonical.)
|
||||
|
||||
Fixed up my compctl widgets patch for use with Sven's rewrite, which I
|
||||
hadn't done properly before.
|
||||
|
||||
Bart's function fixes, 4471
|
||||
|
||||
Bart's doc fixes, 4472
|
||||
|
||||
Bart's PWD and OLDPWD reshuffle, 4589
|
||||
|
||||
My test-line-length patch for prompts, 4591
|
||||
|
||||
Configure patch from Wilfredo Sanchez in 4594, with some extra
|
||||
tabbification and without the setterm() hunk, since I've already renamed
|
||||
that to zsetterm(), avoiding the conflict
|
||||
|
||||
My globbing fix for a bug which shows up in `case' constructs, 4595
|
||||
|
||||
Alternative version of the ~PWD patch (allow users to hash PWD
|
||||
explicitly if that's what turns them on), 4596
|
||||
|
||||
Bart's experimental associative array patch, 4598, plus various
|
||||
additions, 4599, 4602, 4608, 4641, 4653, 4654. No documentation yet;
|
||||
if you want to play with this, so far:
|
||||
% typeset -A hash # create associative array $hash
|
||||
% hash[one]=eins hash[two]=zwei # assign elements
|
||||
% hash=(one eins two zwei) # same, assign whole array (*)
|
||||
% print $hash[one] # retrieve elements
|
||||
eins
|
||||
% print $hash # whole array looks like normal array
|
||||
eins zwei
|
||||
% print ${(k)hash} # flag to get keys
|
||||
one two
|
||||
% print ${(kv)hash} # flag to get keys and values (**)
|
||||
one eins two zwei
|
||||
Comparison of (*) and (**) will reveal how to copy an associative
|
||||
array, but you always need to declare it with typeset -A or an
|
||||
ordinary array will appear. There is a predefined special associative
|
||||
array $testhash, for testing purposes only, which will eventually
|
||||
disappear.
|
||||
|
||||
My rewrite of prompt truncation, 4601
|
||||
|
||||
Bart's params error message fix, 4606
|
||||
|
||||
My input fix for 8 bit characters, 4612
|
||||
|
||||
Bart's version of the *** fix, 4624
|
||||
|
||||
Bart's parameter substitution flag delimiter fix, 4644
|
||||
|
||||
My special parameter unset fix, 4662
|
||||
|
|
Loading…
Reference in a new issue