mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-01 21:51:40 +02:00
zsh-3.1.5-pws-4
This commit is contained in:
parent
9003d99d16
commit
2a5a899a55
47 changed files with 1371 additions and 341 deletions
|
@ -27,5 +27,5 @@
|
||||||
# This must also serve as a shell script, so do not add spaces around the
|
# This must also serve as a shell script, so do not add spaces around the
|
||||||
# `=' signs.
|
# `=' signs.
|
||||||
|
|
||||||
VERSION=3.1.5-pws-3
|
VERSION=3.1.5-pws-4
|
||||||
VERSION_DATE='December 12, 1998'
|
VERSION_DATE='December 17, 1998'
|
||||||
|
|
|
@ -53,7 +53,7 @@ gives the ascii value of this character and an expression of the form
|
||||||
of the parameter var(foo).
|
of the parameter var(foo).
|
||||||
|
|
||||||
Named parameters and subscripted arrays can be referenced by name within an
|
Named parameters and subscripted arrays can be referenced by name within an
|
||||||
arithmetic expression without using the parameter substitution syntax.
|
arithmetic expression without using the parameter expansion syntax.
|
||||||
|
|
||||||
An internal integer representation of a named parameter
|
An internal integer representation of a named parameter
|
||||||
can be specified with the tt(integer) builtin.
|
can be specified with the tt(integer) builtin.
|
||||||
|
|
|
@ -47,7 +47,7 @@ cindex(aliases, listing)
|
||||||
item(tt(alias) [ tt(-gmrL) ] [ var(name)[tt(=)var(value)] ... ])(
|
item(tt(alias) [ tt(-gmrL) ] [ var(name)[tt(=)var(value)] ... ])(
|
||||||
For each var(name) with a corresponding var(value), define an alias
|
For each var(name) with a corresponding var(value), define an alias
|
||||||
with that value. A trailing space in var(value) causes the next word
|
with that value. A trailing space in var(value) causes the next word
|
||||||
to be checked for alias substitution. If the tt(-g) flag is present,
|
to be checked for alias expansion. If the tt(-g) flag is present,
|
||||||
define a global alias; global aliases are expanded even if they do not
|
define a global alias; global aliases are expanded even if they do not
|
||||||
occur in command position.
|
occur in command position.
|
||||||
|
|
||||||
|
@ -879,23 +879,50 @@ findex(typeset)
|
||||||
cindex(parameters, setting)
|
cindex(parameters, setting)
|
||||||
cindex(parameters, declaring)
|
cindex(parameters, declaring)
|
||||||
item(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ var(name)[tt(=)var(value)] ... ])(
|
item(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ var(name)[tt(=)var(value)] ... ])(
|
||||||
Set attributes and values for shell parameters.
|
Set or display attributes and values for shell parameters.
|
||||||
When invoked inside a function a new parameter is created which will be
|
|
||||||
unset when the function completes. The new parameter will not be
|
A parameter is created for each var(name) that does not already refer
|
||||||
exported unless tt(ALL_EXPORT) is set, in which case the parameter will be
|
to one. When inside a function, a new parameter is created for every
|
||||||
exported provided no parameter of that name already exists.
|
var(name) (even those that already exist), and is unset again when the
|
||||||
The following attributes are valid:
|
function completes. See
|
||||||
|
ifzman(`Local Parameters' in zmanref(zshparam))\
|
||||||
|
ifnzman(noderef(Local Parameters))\
|
||||||
|
. Local parameters are not exported unless tt(ALL_EXPORT) is set, in
|
||||||
|
which case the parameter is exported em(only) when var(name) does not
|
||||||
|
already appear in the environment.
|
||||||
|
|
||||||
|
For each nofill(var(name)tt(=)var(value)) assignment, the parameter
|
||||||
|
var(name) set to var(value). Note that arrays currently cannot be
|
||||||
|
assigned in tt(typeset) expressions; scalars and integers only.
|
||||||
|
|
||||||
|
For each remaining var(name) that refers to a parameter that is set,
|
||||||
|
the name and value of the parameter are printed in the form of an
|
||||||
|
assignment. Nothing is printed for newly-created parameters.
|
||||||
|
|
||||||
|
If no var(name) is present, the names and values of all parameters are
|
||||||
|
printed. In this case the attribute flags restrict the the display to
|
||||||
|
only those parameters that have the specified attributes. Using
|
||||||
|
`tt(PLUS())' rather than `tt(-)' to introduce the flag causes the
|
||||||
|
attribute to be turned off, and suppresses printing of the names and
|
||||||
|
values. If only the tt(-m) flag is given the arguments are taken as
|
||||||
|
patterns (should be quoted) and all parameters (or functions with the
|
||||||
|
tt(-f) flag) with matching names are printed.
|
||||||
|
|
||||||
|
The following attribute flags may be specified:
|
||||||
|
|
||||||
startitem()
|
startitem()
|
||||||
item(tt(-A))(
|
item(tt(-A))(
|
||||||
Declare var(name) to be an em(A)ssociation parameter (also known as a hash).
|
The names refer to associative array parameters; see
|
||||||
|
ifzman(`Array Parameters' in zmanref(zshparam))\
|
||||||
|
ifnzman(noderef(Array Parameters))\
|
||||||
|
.
|
||||||
)
|
)
|
||||||
item(tt(-L))(
|
item(tt(-L))(
|
||||||
Left justify and remove leading blanks from var(value).
|
Left justify and remove leading blanks from var(value).
|
||||||
If var(n) is nonzero, it defines the width of the field;
|
If var(n) is nonzero, it defines the width of the field;
|
||||||
otherwise it is determined by the width of the value of the first
|
otherwise it is determined by the width of the value of the first
|
||||||
assignment.
|
assignment.
|
||||||
When the parameter is printed, it is filled on the right with
|
When the parameter is expanded, it is filled on the right with
|
||||||
blanks or truncated if necessary to fit the field.
|
blanks or truncated if necessary to fit the field.
|
||||||
Leading zeros are removed if the tt(-Z) flag is also set.
|
Leading zeros are removed if the tt(-Z) flag is also set.
|
||||||
)
|
)
|
||||||
|
@ -904,13 +931,13 @@ Right justify and fill with leading blanks. If var(n) is nonzero
|
||||||
if defines the width of the field;
|
if defines the width of the field;
|
||||||
otherwise it is determined by the width of the value of the first
|
otherwise it is determined by the width of the value of the first
|
||||||
assignment.
|
assignment.
|
||||||
When the parameter is printed, the field is left filled with
|
When the parameter is expanded, the field is left filled with
|
||||||
blanks or truncated from the end.
|
blanks or truncated from the end.
|
||||||
)
|
)
|
||||||
item(tt(-U))(
|
item(tt(-U))(
|
||||||
For arrays keep only the first element of each duplications. It can also be
|
For arrays (but not for associative arrays), keep only the first
|
||||||
set for colon separated special parameters like tt(PATH) or tt(FIGNORE),
|
occurrence of each duplicated value. This may also be set for
|
||||||
etc.
|
colon-separated special parameters like tt(PATH) or tt(FIGNORE), etc.
|
||||||
)
|
)
|
||||||
item(tt(-Z))(
|
item(tt(-Z))(
|
||||||
Right justify and fill with leading zeros if the first non-blank
|
Right justify and fill with leading zeros if the first non-blank
|
||||||
|
@ -920,8 +947,9 @@ otherwise it is determined by the width of the value of the
|
||||||
first assignment.
|
first assignment.
|
||||||
)
|
)
|
||||||
item(tt(-a))(
|
item(tt(-a))(
|
||||||
On its own, this option produces a list of all array parameters.
|
The names refer to array parameters. For historical reasons, scalar
|
||||||
If any non-options are provided, the tt(typeset) command is silently ignored.
|
parameters are created even when this flag is specified, but the
|
||||||
|
output is restricted to arrays (including associative arrays).
|
||||||
)
|
)
|
||||||
item(tt(-f))(
|
item(tt(-f))(
|
||||||
The names refer to functions rather than parameters. No assignments
|
The names refer to functions rather than parameters. No assignments
|
||||||
|
@ -933,12 +961,13 @@ function definition when the function is first referenced; see
|
||||||
noderef(Functions).
|
noderef(Functions).
|
||||||
)
|
)
|
||||||
item(tt(-i))(
|
item(tt(-i))(
|
||||||
Use an internal integer representation. If var(n) is nonzero
|
Use an internal integer representation. If var(n) is nonzero it
|
||||||
it defines the output arithmetic base, otherwise it is determined by the first
|
defines the output arithmetic base, otherwise it is determined by the
|
||||||
assignment.
|
first assignment.
|
||||||
)
|
)
|
||||||
item(tt(-l))(
|
item(tt(-l))(
|
||||||
Convert to lower case.
|
Convert the result to lower case whenever the parameter is expanded.
|
||||||
|
The value is em(not) converted when assigned.
|
||||||
)
|
)
|
||||||
item(tt(-r))(
|
item(tt(-r))(
|
||||||
The given var(name)s are marked readonly.
|
The given var(name)s are marked readonly.
|
||||||
|
@ -947,22 +976,14 @@ item(tt(-t))(
|
||||||
Tags the named parameters. Tags have no special meaning to the shell.
|
Tags the named parameters. Tags have no special meaning to the shell.
|
||||||
)
|
)
|
||||||
item(tt(-u))(
|
item(tt(-u))(
|
||||||
Convert to upper case.
|
Convert the result to upper case whenever the parameter is expanded.
|
||||||
|
The value is em(not) converted when assigned.
|
||||||
)
|
)
|
||||||
item(tt(-x))(
|
item(tt(-x))(
|
||||||
Mark for automatic export to the environment of subsequently
|
Mark for automatic export to the environment of subsequently
|
||||||
executed commands.
|
executed commands.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
|
||||||
Using `tt(PLUS())' rather than `tt(-)' causes these flags to be turned off.
|
|
||||||
If no arguments are given but flags are specified,
|
|
||||||
a list of named parameters which have these flags set is printed.
|
|
||||||
Using `tt(PLUS())' instead of `tt(-)' keeps their values from being printed.
|
|
||||||
If no arguments or options are given, the names and attributes
|
|
||||||
of all parameters are printed. If only the tt(-m) flag is given the
|
|
||||||
arguments are taken as patterns (should be quoted) and all parameters
|
|
||||||
or functions (with the tt(-f) flag) with matching names are printed.
|
|
||||||
)
|
)
|
||||||
findex(ulimit)
|
findex(ulimit)
|
||||||
cindex(resource limits)
|
cindex(resource limits)
|
||||||
|
|
|
@ -32,9 +32,9 @@ The usual zsh startup/shutdown scripts are not executed. Login shells
|
||||||
source tt(/etc/profile) followed by tt($HOME/.profile). If the
|
source tt(/etc/profile) followed by tt($HOME/.profile). If the
|
||||||
tt(ENV) environment variable is set on invocation, tt($ENV) is sourced
|
tt(ENV) environment variable is set on invocation, tt($ENV) is sourced
|
||||||
after the profile scripts. The value of tt(ENV) is subjected to
|
after the profile scripts. The value of tt(ENV) is subjected to
|
||||||
parameter expansion, command substitution, and arithmetic expansion before
|
parameter expansion, command substitution, and arithmetic expansion
|
||||||
being interpreted as a pathname. Note that the tt(PRIVILEGED) option
|
before being interpreted as a pathname. Note that the tt(PRIVILEGED)
|
||||||
also affects the execution of startup files.
|
option also affects the execution of startup files.
|
||||||
|
|
||||||
The following options are set if the shell is invoked as tt(sh) or
|
The following options are set if the shell is invoked as tt(sh) or
|
||||||
tt(ksh):
|
tt(ksh):
|
||||||
|
|
|
@ -348,8 +348,9 @@ words are used as prefixes.
|
||||||
item(tt(-q))(
|
item(tt(-q))(
|
||||||
If used with a suffix as specified by the tt(-S) option, this
|
If used with a suffix as specified by the tt(-S) option, this
|
||||||
causes the suffix to be removed if the next character typed is a blank
|
causes the suffix to be removed if the next character typed is a blank
|
||||||
or does not insert anything (the same rule as used for the
|
or does not insert anything or if the suffix consists of only one character
|
||||||
tt(AUTO_REMOVE_SLASH) option). The option is most useful for list
|
and the next character typed is the same character (the same rule as used
|
||||||
|
for the tt(AUTO_REMOVE_SLASH) option). The option is most useful for list
|
||||||
separators (comma, colon, etc.).
|
separators (comma, colon, etc.).
|
||||||
)
|
)
|
||||||
item(tt(-l) var(cmd))(
|
item(tt(-l) var(cmd))(
|
||||||
|
|
159
Doc/Zsh/expn.yo
159
Doc/Zsh/expn.yo
|
@ -5,15 +5,15 @@ sect(Description)
|
||||||
The types of expansions performed are
|
The types of expansions performed are
|
||||||
|
|
||||||
startlist()
|
startlist()
|
||||||
list(em(history expansion))
|
list(em(History Expansion))
|
||||||
list(em(alias expansion))
|
list(em(Alias Expansion))
|
||||||
list(em(process substitution))
|
list(em(Process Substitution))
|
||||||
list(em(parameter expansion))
|
list(em(Parameter Expansion))
|
||||||
list(em(command substitution))
|
list(em(Command Substitution))
|
||||||
list(em(arithmetic expansion))
|
list(em(Arithmetic Expansion))
|
||||||
list(em(brace expansion))
|
list(em(Brace Expansion))
|
||||||
list(em(filename expansion))
|
list(em(Filename Expansion))
|
||||||
list(em(filename generation))
|
list(em(Filename Generation))
|
||||||
endlist()
|
endlist()
|
||||||
|
|
||||||
Expansion is done in the above specified order in five steps. The
|
Expansion is done in the above specified order in five steps. The
|
||||||
|
@ -29,8 +29,8 @@ em(filename expansion) followed by em(filename generation).
|
||||||
|
|
||||||
If the tt(SH_FILE_EXPANSION) option is set, the order of expansion is modified
|
If the tt(SH_FILE_EXPANSION) option is set, the order of expansion is modified
|
||||||
for compatibility with bf(sh) and bf(ksh). em(Filename expansion)
|
for compatibility with bf(sh) and bf(ksh). em(Filename expansion)
|
||||||
is performed immediately after em(alias substitution),
|
is performed immediately after em(alias expansion),
|
||||||
preceding the set of five substitutions mentioned above.
|
preceding the set of five expansions mentioned above.
|
||||||
startmenu()
|
startmenu()
|
||||||
menu(History Expansion)
|
menu(History Expansion)
|
||||||
menu(Process Substitution)
|
menu(Process Substitution)
|
||||||
|
@ -52,7 +52,7 @@ corrections and the repetition of complicated commands or arguments.
|
||||||
Command lines are saved in the history list, the size of which
|
Command lines are saved in the history list, the size of which
|
||||||
is controlled by the tt(HISTSIZE)
|
is controlled by the tt(HISTSIZE)
|
||||||
vindex(HISTSIZE, use of)
|
vindex(HISTSIZE, use of)
|
||||||
variable. The most recent command is retained in any case.
|
parameter. The most recent command is retained in any case.
|
||||||
A history expansion begins with the first character of the
|
A history expansion begins with the first character of the
|
||||||
tt(histchars) parameter which is `tt(!)'
|
tt(histchars) parameter which is `tt(!)'
|
||||||
by default and may occur anywhere on the command line; history
|
by default and may occur anywhere on the command line; history
|
||||||
|
@ -175,8 +175,8 @@ Convert the words to all uppercase.
|
||||||
)
|
)
|
||||||
item(tt(f))(
|
item(tt(f))(
|
||||||
(This and the following
|
(This and the following
|
||||||
tt(F), tt(w) and tt(W) modifier only work with parameter and
|
tt(F), tt(w) and tt(W) modifier only work with parameter expansion and
|
||||||
filename expansion.)
|
filename generation.)
|
||||||
Repeats the immediately (without a colon) following modifier until the
|
Repeats the immediately (without a colon) following modifier until the
|
||||||
resulting word doesn't change any more.
|
resulting word doesn't change any more.
|
||||||
)
|
)
|
||||||
|
@ -200,13 +200,13 @@ item(tt(s/)var(l)tt(/)var(r)[tt(/)])(
|
||||||
Substitute var(r) for var(l) as described below.
|
Substitute var(r) for var(l) as described below.
|
||||||
Unless preceded immediately by a tt(g), with no colon between,
|
Unless preceded immediately by a tt(g), with no colon between,
|
||||||
the substitution is done only for the
|
the substitution is done only for the
|
||||||
first string that matches var(l). For arrays and filename
|
first string that matches var(l). For arrays and for filename
|
||||||
expansion, this applies to each word of the expanded text.
|
generation, this applies to each word of the expanded text.
|
||||||
)
|
)
|
||||||
item(tt(&))(
|
item(tt(&))(
|
||||||
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
|
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
|
||||||
immediately by a tt(g). In variable expansion the tt(&) must appear
|
immediately by a tt(g). In variable expansion the tt(&) must appear
|
||||||
inside braces, and in filename expansion it must be quoted with a
|
inside braces, and in filename generation it must be quoted with a
|
||||||
backslash.
|
backslash.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
@ -309,25 +309,27 @@ zmanref(zshparam)
|
||||||
ifnzman(\
|
ifnzman(\
|
||||||
noderef(Parameters)
|
noderef(Parameters)
|
||||||
)\
|
)\
|
||||||
for a description of parameters.
|
for a description of parameters, including arrays, associative arrays,
|
||||||
|
and subscript notation to access individual array elements.
|
||||||
|
|
||||||
In the expansions discussed below that require a pattern, the form of
|
In the expansions discussed below that require a pattern, the form of
|
||||||
the pattern is the same as that used for filename generation;
|
the pattern is the same as that used for filename generation;
|
||||||
see noderef(Filename Generation). Note that this pattern, along with
|
see noderef(Filename Generation). Note that this pattern, along with
|
||||||
the replacement text of a substitution, is itself subject to
|
the replacement text of any substitutions, are themselves subject to
|
||||||
parameter, command and arithmetic substitution. In addition to the
|
parameter expansion, command substitution, and arithmetic expansion.
|
||||||
following operations, the file modifiers described in
|
In addition to the following operations, the file modifiers described in
|
||||||
noderef(Modifiers) in noderef(History Expansion) can be
|
noderef(Modifiers) in noderef(History Expansion) can be
|
||||||
applied: for example, tt(${i:s/foo/bar/}) performs string
|
applied: for example, tt(${i:s/foo/bar/}) performs string
|
||||||
substitution on the value of parameter tt($i).
|
substitution on the expansion of parameter tt($i).
|
||||||
|
|
||||||
startitem()
|
startitem()
|
||||||
item(tt(${)var(name)tt(}))(
|
item(tt(${)var(name)tt(}))(
|
||||||
The value, if any, of the parameter var(name) is substituted.
|
The value, if any, of the parameter var(name) is substituted.
|
||||||
The braces are required if var(name) is followed by
|
The braces are required if the expansion is to be followed by
|
||||||
a letter, digit, or underscore that is not to be interpreted
|
a letter, digit, or underscore that is not to be interpreted
|
||||||
as part of its name.
|
as part of var(name).
|
||||||
|
|
||||||
If var(name) is an array parameter, then the values of each
|
If var(name) is an array parameter, then the value of each
|
||||||
element of var(name) is substituted, one element per word.
|
element of var(name) is substituted, one element per word.
|
||||||
Otherwise, the expansion results in one word only; no field
|
Otherwise, the expansion results in one word only; no field
|
||||||
splitting is done on the result unless the tt(SH_WORD_SPLIT)
|
splitting is done on the result unless the tt(SH_WORD_SPLIT)
|
||||||
|
@ -342,10 +344,12 @@ If var(name) is set and is non-null then substitute its
|
||||||
value; otherwise substitute var(word). If var(name) is
|
value; otherwise substitute var(word). If var(name) is
|
||||||
missing, substitute var(word).
|
missing, substitute var(word).
|
||||||
)
|
)
|
||||||
item(tt(${)var(name)tt(:=)var(word)tt(}))(
|
xitem(tt(${)var(name)tt(:=)var(word)tt(}))
|
||||||
If var(name) is unset or is null then
|
item(tt(${)var(name)tt(::=)var(word)tt(}))(
|
||||||
set it to var(word); the value of the parameter is then
|
In the first form, if var(name) is unset or is null then
|
||||||
substituted.
|
set it to var(word); in the second form, unconditionally
|
||||||
|
set var(name) to var(word). In both forms, the value of
|
||||||
|
the parameter is then substituted.
|
||||||
)
|
)
|
||||||
item(tt(${)var(name)tt(:?)var(word)tt(}))(
|
item(tt(${)var(name)tt(:?)var(word)tt(}))(
|
||||||
If var(name) is set and is non-null, then substitute
|
If var(name) is set and is non-null, then substitute
|
||||||
|
@ -360,13 +364,14 @@ enditem()
|
||||||
|
|
||||||
If the colon is omitted from one of the above expressions
|
If the colon is omitted from one of the above expressions
|
||||||
containing a colon, then the shell only checks whether
|
containing a colon, then the shell only checks whether
|
||||||
var(name) is set or not, not whether it is null.
|
var(name) is set, not whether its value is null.
|
||||||
|
|
||||||
|
In the following expressions, when var(name) is an array and
|
||||||
|
the substitution is not quoted, or if the tt((@)) flag or the
|
||||||
|
`var(name)tt([@])' syntax is used, matching and replacement is
|
||||||
|
performed on each array element separately.
|
||||||
|
|
||||||
startitem()
|
startitem()
|
||||||
item(tt(${)var(name)tt(::=)var(word)tt(}))(
|
|
||||||
Set var(name) to var(word); the value of the parameter is then
|
|
||||||
substituted.
|
|
||||||
)
|
|
||||||
xitem(tt(${)var(name)tt(#)var(pattern)tt(}))
|
xitem(tt(${)var(name)tt(#)var(pattern)tt(}))
|
||||||
item(tt(${)var(name)tt(##)var(pattern)tt(}))(
|
item(tt(${)var(name)tt(##)var(pattern)tt(}))(
|
||||||
If the var(pattern) matches the beginning of the value of
|
If the var(pattern) matches the beginning of the value of
|
||||||
|
@ -375,9 +380,7 @@ the matched portion deleted; otherwise, just
|
||||||
substitute the value of var(name). In the first
|
substitute the value of var(name). In the first
|
||||||
form, the smallest matching pattern is preferred;
|
form, the smallest matching pattern is preferred;
|
||||||
in the second form, the largest matching pattern is
|
in the second form, the largest matching pattern is
|
||||||
preferred. If var(name) is an array and the substitution
|
preferred.
|
||||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
|
||||||
is used, matching is performed on each array elements separately.
|
|
||||||
)
|
)
|
||||||
xitem(tt(${)var(name)tt(%)var(pattern)tt(}))
|
xitem(tt(${)var(name)tt(%)var(pattern)tt(}))
|
||||||
item(tt(${)var(name)tt(%%)var(pattern)tt(}))(
|
item(tt(${)var(name)tt(%%)var(pattern)tt(}))(
|
||||||
|
@ -387,43 +390,38 @@ the matched portion deleted; otherwise, just
|
||||||
substitute the value of var(name). In the first
|
substitute the value of var(name). In the first
|
||||||
form, the smallest matching pattern is preferred;
|
form, the smallest matching pattern is preferred;
|
||||||
in the second form, the largest matching pattern is
|
in the second form, the largest matching pattern is
|
||||||
preferred. If var(name) is an array and the substitution
|
preferred.
|
||||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
|
||||||
is used, matching is performed on each array elements separately.
|
|
||||||
)
|
)
|
||||||
item(tt(${)var(name)tt(:#)var(pattern)tt(}))(
|
item(tt(${)var(name)tt(:#)var(pattern)tt(}))(
|
||||||
If the var(pattern) matches the value of var(name), then substitute
|
If the var(pattern) matches the value of var(name), then substitute
|
||||||
the empty string; otherwise, just substitute the value of var(name).
|
the empty string; otherwise, just substitute the value of var(name).
|
||||||
If var(name) is an array and the substitution
|
If var(name) is an array
|
||||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
the matching array elements are removed (use the tt((M)) flag to
|
||||||
is used, matching is performed on each array elements separately, and
|
|
||||||
the matched array elements are removed (use the tt((M)) flag to
|
|
||||||
remove the non-matched elements).
|
remove the non-matched elements).
|
||||||
)
|
)
|
||||||
xitem(tt(${)var(name)tt(/)var(pattern)tt(/)var(repl)tt(}))
|
xitem(tt(${)var(name)tt(/)var(pattern)tt(/)var(repl)tt(}))
|
||||||
item(tt(${)var(name)tt(//)var(pattern)tt(/)var(repl)tt(}))(
|
item(tt(${)var(name)tt(//)var(pattern)tt(/)var(repl)tt(}))(
|
||||||
Substitute the longest possible match of var(pattern) in the value of
|
Replace by string var(repl), the longest possible match of
|
||||||
variable var(name) with the string var(repl). The first form
|
var(pattern) in the expansion of parameter var(name). The first form
|
||||||
substitutes just the first occurrence, the second all occurrences.
|
replaces just the first occurrence, the second form all occurrences.
|
||||||
The var(pattern) may begin with a var(#), in which case the
|
The var(pattern) may begin with a var(#), in which case the
|
||||||
var(pattern) must match at the start of the string, or var(%), in
|
var(pattern) must match at the start of the string, or var(%), in
|
||||||
which case it must match at the end of the string. The var(repl) may
|
which case it must match at the end of the string. The var(repl) may
|
||||||
be an empty string, in which case the final tt(/) may also be omitted.
|
be an empty string, in which case the final tt(/) may also be omitted.
|
||||||
To quote the final tt(/) in other cases it should be preceded by two
|
To quote the final tt(/) in other cases it should be preceded by two
|
||||||
backslashes (i.e., a quoted backslash); this is not necessary if the
|
backslashes (i.e., a quoted backslash); this is not necessary if the
|
||||||
tt(/) occurs inside a substituted paramter. Substitution of an array
|
tt(/) occurs inside a substituted parameter.
|
||||||
is as described for tt(#) and tt(%) above.
|
|
||||||
|
|
||||||
The first tt(/) may be preceded by a tt(:), in which case the match
|
The first tt(/) may be preceded by a tt(:), in which case the match
|
||||||
will only succeed if it matches the entire word. Note also the
|
will only succeed if it matches the entire word. Note also the
|
||||||
effect of the tt(I) and tt(S) parameter expansion flags below: the
|
effect of the tt(I) and tt(S) parameter expansion flags below; however,
|
||||||
flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful, however.
|
the flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful.
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
|
|
||||||
nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy"))
|
nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy")
|
||||||
nofill(tt(print ${foo//${~sub}/$rep}))
|
tt(print ${foo//${~sub}/$rep})
|
||||||
nofill(tt(print ${(S)foo//${~sub}/$rep}))
|
tt(print ${(S)foo//${~sub}/$rep}))
|
||||||
|
|
||||||
Here, the tt(~) ensures that the text of tt($sub) is treated as a
|
Here, the tt(~) ensures that the text of tt($sub) is treated as a
|
||||||
pattern rather than a plain string. In the first case, the longest
|
pattern rather than a plain string. In the first case, the longest
|
||||||
|
@ -436,6 +434,8 @@ If var(spec) is one of the above substitutions, substitute
|
||||||
the length in characters of the result instead of
|
the length in characters of the result instead of
|
||||||
the result itself. If var(spec) is an array expression,
|
the result itself. If var(spec) is an array expression,
|
||||||
substitute the number of elements of the result.
|
substitute the number of elements of the result.
|
||||||
|
Note that tt(^), tt(=), and tt(~), below, must appear
|
||||||
|
to the left of tt(#) when these forms are combined.
|
||||||
)
|
)
|
||||||
item(tt(${^)var(spec)tt(}))(
|
item(tt(${^)var(spec)tt(}))(
|
||||||
pindex(RC_EXPAND_PARAM, use of)
|
pindex(RC_EXPAND_PARAM, use of)
|
||||||
|
@ -465,24 +465,27 @@ cindex(sh, field splitting style)
|
||||||
Turn on the tt(SH_WORD_SPLIT) option for the
|
Turn on the tt(SH_WORD_SPLIT) option for the
|
||||||
evaluation of var(spec); if the `tt(=)' is doubled, turn it off.
|
evaluation of var(spec); if the `tt(=)' is doubled, turn it off.
|
||||||
vindex(IFS, use of)
|
vindex(IFS, use of)
|
||||||
When this option is set, parameter values are split into
|
When this option is set, parameter expansions are split into
|
||||||
separate words using tt(IFS) as a delimiter
|
separate words before substitution, using tt(IFS) as a delimiter.
|
||||||
before substitution.
|
|
||||||
This is done by default in most other shells.
|
This is done by default in most other shells.
|
||||||
|
|
||||||
|
Note that splitting is applied to var(word) in the assignment forms
|
||||||
|
of var(spec) em(before) the assignment to var(name) is performed.
|
||||||
|
This affects the result of array assignments with the tt(A) flag.
|
||||||
)
|
)
|
||||||
item(tt(${~)var(spec)tt(}))(
|
item(tt(${~)var(spec)tt(}))(
|
||||||
pindex(GLOB_SUBST)
|
pindex(GLOB_SUBST)
|
||||||
Turn on the tt(GLOB_SUBST) option for the evaluation of
|
Turn on the tt(GLOB_SUBST) option for the evaluation of
|
||||||
var(spec); if the `tt(~)' is doubled, turn it off. When this option is
|
var(spec); if the `tt(~)' is doubled, turn it off. When this option is
|
||||||
set, any pattern characters resulting
|
set, any pattern characters resulting
|
||||||
from the substitution become eligible for file expansion and filename
|
from parameter expansion are eligible for filename expansion and filename
|
||||||
generation.
|
generation.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
|
||||||
If a tt(${)...tt(}) type parameter expression or a
|
If a tt(${)...tt(}) type parameter expression or a
|
||||||
tt($LPAR())...tt(RPAR()) type command substitution is used in place of
|
tt($LPAR())...tt(RPAR()) type command substitution is used in place of
|
||||||
var(name) above, it is substituted first and the result is used as if
|
var(name) above, it is expanded first and the result is used as if
|
||||||
it were the value of var(name). Thus it is
|
it were the value of var(name). Thus it is
|
||||||
possible to perform nested operations: tt(${${foo#head}%tail})
|
possible to perform nested operations: tt(${${foo#head}%tail})
|
||||||
substitues the value of tt($foo) with both tt(head) and tt(tail)
|
substitues the value of tt($foo) with both tt(head) and tt(tail)
|
||||||
|
@ -491,7 +494,7 @@ combination with the flags described next; see the example below.
|
||||||
subsect(Parameter Expansion Flags)
|
subsect(Parameter Expansion Flags)
|
||||||
cindex(parameter expansion flags)
|
cindex(parameter expansion flags)
|
||||||
cindex(flags, parameter expansion)
|
cindex(flags, parameter expansion)
|
||||||
cindex(expansion, parameter, flags)
|
cindex(substitution, parameter, flags)
|
||||||
If the opening brace is directly followed by an opening parenthesis,
|
If the opening brace is directly followed by an opening parenthesis,
|
||||||
the string up to the matching closing parenthesis will be taken as a
|
the string up to the matching closing parenthesis will be taken as a
|
||||||
list of flags. Where arguments are valid, any character, or the
|
list of flags. Where arguments are valid, any character, or the
|
||||||
|
@ -501,9 +504,14 @@ in place of the colon as delimiters. The following flags are supported:
|
||||||
|
|
||||||
startitem()
|
startitem()
|
||||||
item(tt(A))(
|
item(tt(A))(
|
||||||
Create an array parameter with
|
Create an array parameter with tt(${)...tt(=)...tt(}),
|
||||||
tt(${)...tt(:=)...tt(}) or tt(${)...tt(::=)...tt(}).
|
tt(${)...tt(:=)...tt(}) or tt(${)...tt(::=)...tt(}).
|
||||||
Assignment is made before sorting or padding.
|
If this flag is repeated (as in tt(AA)), create an associative
|
||||||
|
array parameter. Assignment is made before sorting or padding.
|
||||||
|
The var(name) part may be a subscripted range for ordinary
|
||||||
|
arrays; the var(word) part em(must) be converted to an array, for
|
||||||
|
example by using tt(${(AA)=)...tt(}) to activate word splitting,
|
||||||
|
when creating an associative array.
|
||||||
)
|
)
|
||||||
item(tt(@))(
|
item(tt(@))(
|
||||||
In double quotes, array elements are put into separate words.
|
In double quotes, array elements are put into separate words.
|
||||||
|
@ -531,7 +539,9 @@ item(tt(U))(
|
||||||
Convert all letters in the result to upper case.
|
Convert all letters in the result to upper case.
|
||||||
)
|
)
|
||||||
item(tt(C))(
|
item(tt(C))(
|
||||||
Capitalize the resulting words.
|
Capitalize the resulting words. `Words' in this case refers to sequences
|
||||||
|
of alphanumeric characters separated by non-alphanumerics, em(not) to words
|
||||||
|
that result from field splitting.
|
||||||
)
|
)
|
||||||
item(tt(c))(
|
item(tt(c))(
|
||||||
With tt(${#)var(name)tt(}), count the total number of characters in an array,
|
With tt(${#)var(name)tt(}), count the total number of characters in an array,
|
||||||
|
@ -545,9 +555,22 @@ item(tt(W))(
|
||||||
Similar to tt(w) with the difference that empty words between
|
Similar to tt(w) with the difference that empty words between
|
||||||
repeated delimiters are also counted.
|
repeated delimiters are also counted.
|
||||||
)
|
)
|
||||||
|
item(tt(k))(
|
||||||
|
If var(name) refers to an associative array, substitute the em(keys)
|
||||||
|
(element names) rather than the values of the elements. Used with
|
||||||
|
subscripts (including ordinary arrays), force indices or keys to be
|
||||||
|
substituted even if the subscript form refers to values. However,
|
||||||
|
this flag may not be combined with subscript ranges.
|
||||||
|
)
|
||||||
|
item(tt(v))(
|
||||||
|
Used with tt(k), substitute (as two consecutive words) both the key
|
||||||
|
and the value of each associative array element. Used with subscripts,
|
||||||
|
force values to be substituted even if the subscript form refers to
|
||||||
|
indices or keys.
|
||||||
|
)
|
||||||
item(tt(p))(
|
item(tt(p))(
|
||||||
Recognize the same escape sequences as the tt(print) builtin
|
Recognize the same escape sequences as the tt(print) builtin
|
||||||
in string arguments to subsequent flags.
|
in string arguments to any of the flags described below.
|
||||||
)
|
)
|
||||||
item(tt(l:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))(
|
item(tt(l:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))(
|
||||||
Pad the resulting words on the left. Each word will be truncated if
|
Pad the resulting words on the left. Each word will be truncated if
|
||||||
|
@ -579,9 +602,13 @@ item(tt(f))(
|
||||||
Split the result of the expansion to lines. This is a shorthand
|
Split the result of the expansion to lines. This is a shorthand
|
||||||
for `tt(ps:\n:)'.
|
for `tt(ps:\n:)'.
|
||||||
)
|
)
|
||||||
|
enditem()
|
||||||
|
|
||||||
|
The following flags are meaningful with the tt(${)...tt(#)...tt(}),
|
||||||
|
tt(${)...tt(%)...tt(}), or tt(${)...tt(/)...tt(}) forms.
|
||||||
|
|
||||||
|
startitem()
|
||||||
item(tt(S))(
|
item(tt(S))(
|
||||||
(This and all remaining flags are used with the tt(${)...tt(#)...tt(}) or
|
|
||||||
tt(${)...tt(%)...tt(}) forms.)
|
|
||||||
Search substrings as well as beginnings or ends; with tt(#) start
|
Search substrings as well as beginnings or ends; with tt(#) start
|
||||||
from the beginning and with tt(%) start from the end of the string.
|
from the beginning and with tt(%) start from the end of the string.
|
||||||
With substitution via tt(${)...tt(/)...tt(}) or
|
With substitution via tt(${)...tt(/)...tt(}) or
|
||||||
|
|
|
@ -307,9 +307,9 @@ cindex(aliases, global)
|
||||||
An alias is defined using the tt(alias) builtin; global aliases
|
An alias is defined using the tt(alias) builtin; global aliases
|
||||||
may be defined using the tt(-g) option to that builtin.
|
may be defined using the tt(-g) option to that builtin.
|
||||||
|
|
||||||
Alias substitution is done on the shell input before any
|
Alias expansion is done on the shell input before any
|
||||||
other substitution except history substitution. Therefore,
|
other expansion except history expansion. Therefore,
|
||||||
if an alias is defined for the word tt(foo), alias substitution
|
if an alias is defined for the word tt(foo), alias expansion
|
||||||
may be avoided by quoting part of the word, e.g. tt(\foo).
|
may be avoided by quoting part of the word, e.g. tt(\foo).
|
||||||
But there is nothing to prevent an alias being defined
|
But there is nothing to prevent an alias being defined
|
||||||
for tt(\foo) as well.
|
for tt(\foo) as well.
|
||||||
|
|
|
@ -139,7 +139,7 @@ pindex(BANG_HIST)
|
||||||
cindex(history, enable substitution)
|
cindex(history, enable substitution)
|
||||||
cindex(enable history substitution)
|
cindex(enable history substitution)
|
||||||
item(tt(BANG_HIST) (tt(PLUS()K)))(
|
item(tt(BANG_HIST) (tt(PLUS()K)))(
|
||||||
Perform textual history substitution, bf(csh)-style,
|
Perform textual history expansion, bf(csh)-style,
|
||||||
treating the character `tt(!)' specially.
|
treating the character `tt(!)' specially.
|
||||||
)
|
)
|
||||||
pindex(BARE_GLOB_QUAL)
|
pindex(BARE_GLOB_QUAL)
|
||||||
|
@ -263,9 +263,9 @@ in a command have no matches.
|
||||||
Overrides tt(NULL_GLOB).
|
Overrides tt(NULL_GLOB).
|
||||||
)
|
)
|
||||||
pindex(EQUALS)
|
pindex(EQUALS)
|
||||||
cindex(filename substitution, =)
|
cindex(filename expansion, =)
|
||||||
item(tt(EQUALS))(
|
item(tt(EQUALS))(
|
||||||
Perform tt(=) filename substitution.
|
Perform tt(=) filename expansion.
|
||||||
(See noderef(Filename Expansion).)
|
(See noderef(Filename Expansion).)
|
||||||
)
|
)
|
||||||
pindex(ERR_EXIT)
|
pindex(ERR_EXIT)
|
||||||
|
@ -344,7 +344,7 @@ Do not require a leading `tt(.)' in a filename to be matched explicitly.
|
||||||
)
|
)
|
||||||
pindex(GLOB_SUBST)
|
pindex(GLOB_SUBST)
|
||||||
item(tt(GLOB_SUBST))(
|
item(tt(GLOB_SUBST))(
|
||||||
Treat any characters resulting from parameter substitution as being
|
Treat any characters resulting from parameter expansion as being
|
||||||
eligible for file expansion and filename generation, and any
|
eligible for file expansion and filename generation, and any
|
||||||
characters resulting from command substitution as being eligible for
|
characters resulting from command substitution as being eligible for
|
||||||
filename generation.
|
filename generation.
|
||||||
|
@ -412,9 +412,9 @@ being added to the history list.
|
||||||
pindex(HIST_VERIFY)
|
pindex(HIST_VERIFY)
|
||||||
cindex(history, verifying substitution)
|
cindex(history, verifying substitution)
|
||||||
item(tt(HIST_VERIFY))(
|
item(tt(HIST_VERIFY))(
|
||||||
Whenever the user enters a line with history substitution,
|
Whenever the user enters a line with history expansion,
|
||||||
don't execute the line directly; instead, perform
|
don't execute the line directly; instead, perform
|
||||||
history substitution and reload the line into the editing buffer.
|
history expansion and reload the line into the editing buffer.
|
||||||
)
|
)
|
||||||
pindex(HUP)
|
pindex(HUP)
|
||||||
cindex(jobs, HUP)
|
cindex(jobs, HUP)
|
||||||
|
|
|
@ -7,7 +7,8 @@ A name may be any sequence of alphanumeric
|
||||||
characters and underscores, or the single characters
|
characters and underscores, or the single characters
|
||||||
`tt(*)', `tt(@)', `tt(#)', `tt(?)', `tt(-)', `tt($)', or `tt(!)'.
|
`tt(*)', `tt(@)', `tt(#)', `tt(?)', `tt(-)', `tt($)', or `tt(!)'.
|
||||||
The value may be a em(scalar) (a string),
|
The value may be a em(scalar) (a string),
|
||||||
an integer, or an array.
|
an integer, an array (indexed numerically), or an em(associative)
|
||||||
|
array (an unordered set of name-value pairs, indexed by name).
|
||||||
To assign a scalar or integer value to a parameter,
|
To assign a scalar or integer value to a parameter,
|
||||||
use the tt(typeset) builtin.
|
use the tt(typeset) builtin.
|
||||||
findex(typeset, use of)
|
findex(typeset, use of)
|
||||||
|
@ -17,10 +18,12 @@ The value of a parameter may also be assigned by writing:
|
||||||
|
|
||||||
nofill(var(name)tt(=)var(value))
|
nofill(var(name)tt(=)var(value))
|
||||||
|
|
||||||
If the integer attribute, tt(-i), is set for var(name),
|
If the integer attribute, tt(-i), is set for var(name), the var(value)
|
||||||
the var(value) is subject to arithmetic evaluation.
|
is subject to arithmetic evaluation. See noderef(Array Parameters)
|
||||||
|
for additional forms of assignment.
|
||||||
|
|
||||||
In the parameter lists, the mark `<S>' indicates that the parameter is special.
|
In the parameter lists that follow, the mark `<S>' indicates that the
|
||||||
|
parameter is special.
|
||||||
Special parameters cannot have their type changed, and they stay special even
|
Special parameters cannot have their type changed, and they stay special even
|
||||||
if unset. `<Z>' indicates that the parameter does not exist when the shell
|
if unset. `<Z>' indicates that the parameter does not exist when the shell
|
||||||
initialises in tt(sh) or tt(ksh) emulation mode.
|
initialises in tt(sh) or tt(ksh) emulation mode.
|
||||||
|
@ -55,6 +58,15 @@ The value of an array parameter may be assigned by writing:
|
||||||
|
|
||||||
nofill(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
|
nofill(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
|
||||||
|
|
||||||
|
If no parameter var(name) exists, an ordinary array parameter is created.
|
||||||
|
Associative arrays must be declared first, by `tt(typeset -A) var(name)'.
|
||||||
|
When var(name) refers to an associative array, the parenthesized list is
|
||||||
|
interpreted as alternating keys and values:
|
||||||
|
|
||||||
|
nofill(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
|
||||||
|
|
||||||
|
Every var(key) must have a var(value) in this case.
|
||||||
|
|
||||||
Individual elements of an array may be selected using a
|
Individual elements of an array may be selected using a
|
||||||
subscript. A subscript of the form `tt([)var(exp)tt(])'
|
subscript. A subscript of the form `tt([)var(exp)tt(])'
|
||||||
selects the single element var(exp), where var(exp) is
|
selects the single element var(exp), where var(exp) is
|
||||||
|
@ -64,6 +76,9 @@ The elements are numbered beginning with 1 unless the
|
||||||
tt(KSH_ARRAYS) option is set when they are numbered from zero.
|
tt(KSH_ARRAYS) option is set when they are numbered from zero.
|
||||||
pindex(KSH_ARRAYS, use of)
|
pindex(KSH_ARRAYS, use of)
|
||||||
|
|
||||||
|
The same subscripting syntax is used for associative arrays,
|
||||||
|
except that no arithmetic expansion is applied to var(EXP).
|
||||||
|
|
||||||
A subscript of the form `tt([*])' or `tt([@])' evaluates to all
|
A subscript of the form `tt([*])' or `tt([@])' evaluates to all
|
||||||
elements of an array; there is no difference between the two
|
elements of an array; there is no difference between the two
|
||||||
except when they appear within double quotes.
|
except when they appear within double quotes.
|
||||||
|
@ -73,6 +88,7 @@ except when they appear within double quotes.
|
||||||
A subscript of the form `tt([)var(exp1)tt(,)var(exp2)tt(])'
|
A subscript of the form `tt([)var(exp1)tt(,)var(exp2)tt(])'
|
||||||
selects all elements in the range var(exp1) to var(exp2),
|
selects all elements in the range var(exp1) to var(exp2),
|
||||||
inclusive.
|
inclusive.
|
||||||
|
(Associative arrays are unordered, and so do not support ranges.)
|
||||||
If one of the subscripts evaluates to a negative number,
|
If one of the subscripts evaluates to a negative number,
|
||||||
say tt(-)var(n), then the var(n)th element from the end
|
say tt(-)var(n), then the var(n)th element from the end
|
||||||
of the array is used. Thus `tt($foo[-3])' is the third element
|
of the array is used. Thus `tt($foo[-3])' is the third element
|
||||||
|
@ -90,7 +106,9 @@ option is set, the braced form is the only one that will
|
||||||
work, the subscript otherwise not being treated specially.
|
work, the subscript otherwise not being treated specially.
|
||||||
|
|
||||||
If a subscript is used on the left side of an assignment the selected
|
If a subscript is used on the left side of an assignment the selected
|
||||||
range is replaced by the expression on the right side.
|
element or range is replaced by the expression on the right side. An
|
||||||
|
array (but not an associative array) may be created by assignment to a
|
||||||
|
range or element.
|
||||||
|
|
||||||
If the opening bracket or the comma is directly followed by an opening
|
If the opening bracket or the comma is directly followed by an opening
|
||||||
parentheses the string up to the matching closing one is considered to
|
parentheses the string up to the matching closing one is considered to
|
||||||
|
@ -123,21 +141,27 @@ result is the first matching array element, substring or word (if the
|
||||||
parameter is an array, if it is a scalar, or if it is a scalar and the
|
parameter is an array, if it is a scalar, or if it is a scalar and the
|
||||||
`tt(w)' flag is given, respectively); note that this is like giving a
|
`tt(w)' flag is given, respectively); note that this is like giving a
|
||||||
number: `tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])' work.
|
number: `tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])' work.
|
||||||
|
If the parameter is an associative array, only the value part of each pair
|
||||||
|
is compared to the pattern.
|
||||||
)
|
)
|
||||||
item(tt(R))(
|
item(tt(R))(
|
||||||
like `tt(r)', but gives the last match.
|
like `tt(r)', but gives the last match. For associative arrays, gives
|
||||||
|
all possible matches.
|
||||||
)
|
)
|
||||||
item(tt(i))(
|
item(tt(i))(
|
||||||
like `tt(r)', but gives the index of the match instead; this may not
|
like `tt(r)', but gives the index of the match instead; this may not
|
||||||
be combined with a second argument.
|
be combined with a second argument. For associative arrays, the key
|
||||||
|
part of each pair is compared to the pattern, and the first matching
|
||||||
|
key found is used.
|
||||||
)
|
)
|
||||||
item(tt(I))(
|
item(tt(I))(
|
||||||
like `tt(i), but gives the index of the last match.
|
like `tt(i), but gives the index of the last match, or all possible
|
||||||
|
matching keys in an associative array.
|
||||||
)
|
)
|
||||||
item(tt(n:)var(expr)tt(:))(
|
item(tt(n:)var(expr)tt(:))(
|
||||||
if combined with `tt(r)', `tt(R)', `tt(i)' or `tt(I)', makes them give
|
if combined with `tt(r)', `tt(R)', `tt(i)' or `tt(I)', makes them give
|
||||||
the var(n)th or var(n)th last match (if var(expr) evaluates to
|
the var(n)th or var(n)th last match (if var(expr) evaluates to
|
||||||
var(n)).
|
var(n)). This flag is ignored when the array is associative.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
texinode(Positional Parameters)(Parameters Set By The Shell)(Array Parameters)(Parameters)
|
texinode(Positional Parameters)(Parameters Set By The Shell)(Array Parameters)(Parameters)
|
||||||
|
@ -417,7 +441,7 @@ vindex(histchars)
|
||||||
item(tt(histchars) <S>)(
|
item(tt(histchars) <S>)(
|
||||||
Three characters used by the shell's history and lexical analysis
|
Three characters used by the shell's history and lexical analysis
|
||||||
mechanism. The first character signals the start of a history
|
mechanism. The first character signals the start of a history
|
||||||
substitution (default `tt(!)'). The second character signals the
|
expansion (default `tt(!)'). The second character signals the
|
||||||
start of a quick history substitution (default `tt(^)'). The third
|
start of a quick history substitution (default `tt(^)'). The third
|
||||||
character is the comment character (default `tt(#)').
|
character is the comment character (default `tt(#)').
|
||||||
)
|
)
|
||||||
|
@ -442,7 +466,7 @@ vindex(IFS)
|
||||||
item(tt(IFS) <S>)(
|
item(tt(IFS) <S>)(
|
||||||
Internal field separators (by default space, tab, newline and NUL), that
|
Internal field separators (by default space, tab, newline and NUL), that
|
||||||
are used to separate words which result from
|
are used to separate words which result from
|
||||||
command or parameter substitution and words read by
|
command or parameter expansion and words read by
|
||||||
the tt(read) builtin. Any characters from the set space, tab and
|
the tt(read) builtin. Any characters from the set space, tab and
|
||||||
newline that appear in the IFS are called em(IFS white space).
|
newline that appear in the IFS are called em(IFS white space).
|
||||||
One or more IFS white space characters or one non-IFS white space
|
One or more IFS white space characters or one non-IFS white space
|
||||||
|
@ -518,7 +542,7 @@ An array (colon-separated list) of filenames to check for
|
||||||
new mail. Each filename can be followed by a `tt(?)' and a
|
new mail. Each filename can be followed by a `tt(?)' and a
|
||||||
message that will be printed. The message will undergo
|
message that will be printed. The message will undergo
|
||||||
parameter expansion, command substitution and arithmetic
|
parameter expansion, command substitution and arithmetic
|
||||||
substitution with the variable tt($_) defined as the name
|
expansion with the variable tt($_) defined as the name
|
||||||
of the file that has changed. The default message is
|
of the file that has changed. The default message is
|
||||||
`tt(You have new mail)'. If an element is a directory
|
`tt(You have new mail)'. If an element is a directory
|
||||||
instead of a file the shell will recursively check every
|
instead of a file the shell will recursively check every
|
||||||
|
|
|
@ -16,7 +16,7 @@ input/output specifications.
|
||||||
|
|
||||||
The following may appear anywhere in a simple command
|
The following may appear anywhere in a simple command
|
||||||
or may precede or follow a complex command.
|
or may precede or follow a complex command.
|
||||||
Substitution occurs before var(word) or var(digit)
|
Expansion occurs before var(word) or var(digit)
|
||||||
is used except as noted below.
|
is used except as noted below.
|
||||||
If the result of substitution on var(word)
|
If the result of substitution on var(word)
|
||||||
produces more than one filename,
|
produces more than one filename,
|
||||||
|
@ -57,7 +57,7 @@ exist, even if tt(CLOBBER) is unset.
|
||||||
item(tt(<<)[tt(-)] var(word))(
|
item(tt(<<)[tt(-)] var(word))(
|
||||||
The shell input is read up to a line that is the same as
|
The shell input is read up to a line that is the same as
|
||||||
var(word), or to an end-of-file.
|
var(word), or to an end-of-file.
|
||||||
No parameter substitution, command substitution or
|
No parameter expansion, command substitution or
|
||||||
filename generation is performed on var(word).
|
filename generation is performed on var(word).
|
||||||
The resulting document, called a
|
The resulting document, called a
|
||||||
em(here-document), becomes the standard input.
|
em(here-document), becomes the standard input.
|
||||||
|
|
|
@ -45,13 +45,8 @@ while [[ -n "$pref" ]]; do
|
||||||
if [[ "$head" = *[\[\(\*\?\$\~]* ]]; then
|
if [[ "$head" = *[\[\(\*\?\$\~]* ]]; then
|
||||||
wild=$head
|
wild=$head
|
||||||
else
|
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
|
# Simulate case-insensitive globbing for ASCII characters
|
||||||
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
||||||
# The following could all be one expansion, but for readability:
|
# 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/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/g/gG/:gs/h/hH/:gs/i/iI/:gs/j/jJ/:gs/k/kK/:gs/l/lL/
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
# Runs as a filter. Should ignore anything which isn't a "complete".
|
# Runs as a filter. Should ignore anything which isn't a "complete".
|
||||||
# It expects each "complete" statement to be the first thing on a line.
|
# It expects each "complete" statement to be the first thing on a line.
|
||||||
# All the examples in the tcsh manual give sensible results.
|
# All the examples in the tcsh manual give sensible results.
|
||||||
|
# Author: Peter Stephenson <pws@ibmth.df.unipi.it>
|
||||||
#
|
#
|
||||||
# Option:
|
# Option:
|
||||||
# -x (exact): only applies in the case of command disambiguation (is
|
# -x (exact): only applies in the case of command disambiguation (is
|
||||||
|
@ -38,6 +39,11 @@
|
||||||
# (5) Make sure all command names with wildcards are processed together --
|
# (5) Make sure all command names with wildcards are processed together --
|
||||||
# they need to be lumped into one "compctl -C" or "compctl -D"
|
# they need to be lumped into one "compctl -C" or "compctl -D"
|
||||||
# statement for zsh.
|
# statement for zsh.
|
||||||
|
# (6) Group completion (complete's g flag) is not built into zsh, so
|
||||||
|
# you need perl to be available to generate the groups. If this
|
||||||
|
# script is useful, I assume that's not a problem.
|
||||||
|
# (7) I don't know what `completing completions' means, so the X
|
||||||
|
# flag to complete is not handled.
|
||||||
|
|
||||||
# Handle options
|
# Handle options
|
||||||
if (@ARGV) {
|
if (@ARGV) {
|
||||||
|
@ -113,6 +119,13 @@ sub gettype {
|
||||||
# Nothing (n) can be handled by returning nothing. (C.f. King Lear, I.i.)
|
# Nothing (n) can be handled by returning nothing. (C.f. King Lear, I.i.)
|
||||||
if ($c =~ /[abcjuv]/) {
|
if ($c =~ /[abcjuv]/) {
|
||||||
$ret = "-$c";
|
$ret = "-$c";
|
||||||
|
} elsif ($c eq 'C') {
|
||||||
|
if (defined($glob)) {
|
||||||
|
$ret = "-W $glob -/g '*(.*)'";
|
||||||
|
undef($glob);
|
||||||
|
} else {
|
||||||
|
$ret = '-c';
|
||||||
|
}
|
||||||
} elsif ($c eq 'S') {
|
} elsif ($c eq 'S') {
|
||||||
$ret = '-k signals';
|
$ret = '-k signals';
|
||||||
} elsif ($c eq 'd') {
|
} elsif ($c eq 'd') {
|
||||||
|
@ -121,18 +134,42 @@ sub gettype {
|
||||||
} else {
|
} else {
|
||||||
$ret = '-/';
|
$ret = '-/';
|
||||||
}
|
}
|
||||||
|
} elsif ($c eq 'D') {
|
||||||
|
if (defined($glob)) {
|
||||||
|
$ret = "-W $glob -/";
|
||||||
|
undef($glob);
|
||||||
|
} else {
|
||||||
|
$ret = '-/';
|
||||||
|
}
|
||||||
} elsif ($c eq 'e') {
|
} elsif ($c eq 'e') {
|
||||||
$ret = '-E';
|
$ret = '-E';
|
||||||
} elsif ($c eq 'f' && !$glob) {
|
} elsif ($c eq 'f' && !$glob) {
|
||||||
$ret = '-f';
|
$ret = '-f';
|
||||||
|
} elsif ($c eq 'F') {
|
||||||
|
if (defined($glob)) {
|
||||||
|
$ret = "-W $glob -f";
|
||||||
|
undef($glob);
|
||||||
|
} else {
|
||||||
|
$ret = '-f';
|
||||||
|
}
|
||||||
|
} elsif ($c eq 'g') {
|
||||||
|
$ret = "-s '\$(perl -e '\\''while ((\$name) = getgrent)\n" .
|
||||||
|
"{ print \$name, \"\\n\"; }'\\'')'";
|
||||||
} elsif ($c eq 'l') {
|
} elsif ($c eq 'l') {
|
||||||
$ret = q!-k "(`limit | awk '{print $1}'`)"!;
|
$ret = q!-k "(`limit | awk '{print $1}'`)"!;
|
||||||
} elsif ($c eq 'p') {
|
} elsif ($c eq 'p') {
|
||||||
$ret = "-W $glob -f", undef($glob) if defined($glob);
|
$ret = "-W $glob -f", undef($glob) if defined($glob);
|
||||||
} elsif ($c eq 's') {
|
} elsif ($c eq 's') {
|
||||||
$ret = '-p';
|
$ret = '-p';
|
||||||
} elsif ($c eq 't') {
|
} elsif ($c eq 't') {
|
||||||
$qual = '.';
|
$qual = '.';
|
||||||
|
} elsif ($c eq 'T') {
|
||||||
|
if (defined($glob)) {
|
||||||
|
$ret = "-W $glob -g '*(.)'";
|
||||||
|
undef($glob);
|
||||||
|
} else {
|
||||||
|
$ret = "-g '*(.)'";
|
||||||
|
}
|
||||||
} elsif ($c eq 'x') {
|
} elsif ($c eq 'x') {
|
||||||
$glob =~ s/'/'\\''/g;
|
$glob =~ s/'/'\\''/g;
|
||||||
$ret = "-X '$glob'";
|
$ret = "-X '$glob'";
|
||||||
|
@ -190,7 +227,7 @@ $" = " - ";
|
||||||
|
|
||||||
while (<>) {
|
while (<>) {
|
||||||
if (/^\s*complete\s/) {
|
if (/^\s*complete\s/) {
|
||||||
undef(@stuff);
|
undef(@stuff);
|
||||||
$default = '';
|
$default = '';
|
||||||
$_ = $';
|
$_ = $';
|
||||||
while (/\\$/) {
|
while (/\\$/) {
|
||||||
|
@ -211,7 +248,7 @@ while (<>) {
|
||||||
# Loop over remaining arguments to "complete".
|
# Loop over remaining arguments to "complete".
|
||||||
$sep = substr($word,1,1);
|
$sep = substr($word,1,1);
|
||||||
$sep =~ s/(\W)/\\$1/g;
|
$sep =~ s/(\W)/\\$1/g;
|
||||||
@split = split(/$sep/,$word);
|
@split = split(/$sep/,$word,4);
|
||||||
for ($i = 0; $i < 3; $i++) {
|
for ($i = 0; $i < 3; $i++) {
|
||||||
while ($split[$i] =~ /\\$/) {
|
while ($split[$i] =~ /\\$/) {
|
||||||
substr($split[$i],-1,1) = "";
|
substr($split[$i],-1,1) = "";
|
||||||
|
@ -225,7 +262,9 @@ while (<>) {
|
||||||
# The "complete" catch-all: treat this as compctl\'s
|
# The "complete" catch-all: treat this as compctl\'s
|
||||||
# default (requiring no pattern matching).
|
# default (requiring no pattern matching).
|
||||||
$default .= &gettype($type) . ' ';
|
$default .= &gettype($type) . ' ';
|
||||||
defined($suffix) && ($defsuf .= $suffix);
|
defined($suffix) &&
|
||||||
|
(defined($defsuf) ? ($defsuf .= $suffix)
|
||||||
|
: ($defsuf = $suffix));
|
||||||
} else {
|
} else {
|
||||||
$pat = &getpat($pat,$arg);
|
$pat = &getpat($pat,$arg);
|
||||||
$type = &gettype($type);
|
$type = &gettype($type);
|
||||||
|
|
|
@ -574,6 +574,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("unlimit", 0, bin_unlimit, 0, -1, 0, "hs", NULL),
|
BUILTIN("unlimit", 0, bin_unlimit, 0, -1, 0, "hs", NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_rlimits(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_rlimits(Module m)
|
boot_rlimits(Module m)
|
||||||
|
@ -590,4 +597,12 @@ cleanup_rlimits(Module m)
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_rlimits(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -183,6 +183,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("sched", 0, bin_sched, 0, -1, 0, NULL, NULL),
|
BUILTIN("sched", 0, bin_sched, 0, -1, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_sched(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_sched(Module m)
|
boot_sched(Module m)
|
||||||
|
@ -211,4 +218,11 @@ cleanup_sched(Module m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_sched(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -122,6 +122,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("setcap", 0, bin_setcap, 2, -1, 0, NULL, NULL),
|
BUILTIN("setcap", 0, bin_setcap, 2, -1, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_cap(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_cap(Module m)
|
boot_cap(Module m)
|
||||||
|
@ -138,4 +145,12 @@ cleanup_cap(Module m)
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_cap(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -96,6 +96,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("clone", 0, bin_clone, 1, 1, 0, NULL, NULL),
|
BUILTIN("clone", 0, bin_clone, 1, 1, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_clone(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_clone(Module m)
|
boot_clone(Module m)
|
||||||
|
@ -112,4 +119,12 @@ cleanup_clone(Module m)
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_clone(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,16 +51,14 @@ bin_example(char *nam, char **args, char *ops, int func)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static int
|
static int
|
||||||
cond_p_len(Conddef c, char **a)
|
cond_p_len(char **a, int id)
|
||||||
{
|
{
|
||||||
char *s1 = a[0], *s2 = a[1];
|
char *s1 = cond_str(a, 0);
|
||||||
|
|
||||||
singsub(&s1);
|
if (a[1]) {
|
||||||
untokenize(s1);
|
long v = cond_val(a, 1);
|
||||||
if (s2) {
|
|
||||||
singsub(&s2);
|
return strlen(s1) == v;
|
||||||
untokenize(s2);
|
|
||||||
return strlen(s1) == matheval(s2);
|
|
||||||
} else {
|
} else {
|
||||||
return !s1[0];
|
return !s1[0];
|
||||||
}
|
}
|
||||||
|
@ -68,14 +66,10 @@ cond_p_len(Conddef c, char **a)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static int
|
static int
|
||||||
cond_i_ex(Conddef c, char **a)
|
cond_i_ex(char **a, int id)
|
||||||
{
|
{
|
||||||
char *s1 = a[0], *s2 = a[1];
|
char *s1 = cond_str(a, 0), *s2 = cond_str(a, 1);
|
||||||
|
|
||||||
singsub(&s1);
|
|
||||||
untokenize(s1);
|
|
||||||
singsub(&s2);
|
|
||||||
untokenize(s2);
|
|
||||||
return !strcmp("example", dyncat(s1, s2));
|
return !strcmp("example", dyncat(s1, s2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,14 +99,23 @@ static struct builtin bintab[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct conddef cotab[] = {
|
static struct conddef cotab[] = {
|
||||||
CONDDEF("len", 0, 1, 2, cond_p_len),
|
CONDDEF("len", 0, cond_p_len, 1, 2, 0),
|
||||||
CONDDEF("ex", CONDF_INFIX, 0, 0, cond_i_ex),
|
CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct funcwrap wrapper[] = {
|
static struct funcwrap wrapper[] = {
|
||||||
WRAPDEF(ex_wrapper),
|
WRAPDEF(ex_wrapper),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_example(Module m)
|
||||||
|
{
|
||||||
|
printf("The example module has now been set up.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_example(Module m)
|
boot_example(Module m)
|
||||||
|
@ -133,4 +136,14 @@ cleanup_example(Module m)
|
||||||
deletewrapper(m, wrapper);
|
deletewrapper(m, wrapper);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_example(Module m)
|
||||||
|
{
|
||||||
|
printf("Thank you for using the example module. Have a nice day.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -509,6 +509,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("sync", 0, bin_sync, 0, 0, 0, NULL, NULL),
|
BUILTIN("sync", 0, bin_sync, 0, 0, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_files(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_files(Module m)
|
boot_files(Module m)
|
||||||
|
@ -525,4 +532,12 @@ cleanup_files(Module m)
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_files(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -569,6 +569,13 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("stat", 0, bin_stat, 0, -1, 0, NULL, NULL),
|
BUILTIN("stat", 0, bin_stat, 0, -1, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_stat(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_stat(Module m)
|
boot_stat(Module m)
|
||||||
|
@ -586,4 +593,11 @@ cleanup_stat(Module m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_stat(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,9 +62,9 @@
|
||||||
/* it's a TELNET based protocol, but don't think I like doing this */
|
/* it's a TELNET based protocol, but don't think I like doing this */
|
||||||
#include <arpa/telnet.h>
|
#include <arpa/telnet.h>
|
||||||
|
|
||||||
/* bet there are machines which have neither INADDR_NONE nor in_addr_t. */
|
/* pinch the definition from <netinet/in.h> for deficient headers */
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define INADDR_NONE (in_addr_t)-1
|
#define INADDR_NONE 0xffffffff
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1354,7 +1354,11 @@ zfsenddata(char *name, int recv, int progress, long startat)
|
||||||
* We do this here in case we needed to wait for a RETR
|
* We do this here in case we needed to wait for a RETR
|
||||||
* command to tell us how many bytes are coming.
|
* command to tell us how many bytes are coming.
|
||||||
*/
|
*/
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
/* Now add in the bit of the file we've got/sent already */
|
/* Now add in the bit of the file we've got/sent already */
|
||||||
sofar = last_sofar = startat;
|
sofar = last_sofar = startat;
|
||||||
}
|
}
|
||||||
|
@ -1482,8 +1486,12 @@ zfsenddata(char *name, int recv, int progress, long startat)
|
||||||
break;
|
break;
|
||||||
if (!ret && sofar != last_sofar && progress &&
|
if (!ret && sofar != last_sofar && progress &&
|
||||||
(l = getshfunc("zftp_progress")) != &dummy_list) {
|
(l = getshfunc("zftp_progress")) != &dummy_list) {
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
|
zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
last_sofar = sofar;
|
last_sofar = sofar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1650,7 +1658,7 @@ zftp_open(char *name, char **args, int flags)
|
||||||
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
|
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
zsock.sin_port = ntohs(zservp->s_port);
|
zsock.sin_port = zservp->s_port;
|
||||||
zcfd = zfmovefd(socket(zsock.sin_family, SOCK_STREAM, 0));
|
zcfd = zfmovefd(socket(zsock.sin_family, SOCK_STREAM, 0));
|
||||||
if (zcfd < 0) {
|
if (zcfd < 0) {
|
||||||
zwarnnam(name, "socket failed: %e", NULL, errno);
|
zwarnnam(name, "socket failed: %e", NULL, errno);
|
||||||
|
@ -2102,9 +2110,13 @@ zfgetcwd(void)
|
||||||
* front end. By putting it here, and in close when ZFTP_PWD is unset,
|
* front end. By putting it here, and in close when ZFTP_PWD is unset,
|
||||||
* we at least cover the bases.
|
* we at least cover the bases.
|
||||||
*/
|
*/
|
||||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list)
|
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
|
||||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
int osc = sfcontext;
|
||||||
|
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
|
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2303,9 +2315,13 @@ zftp_getput(char *name, char **args, int flags)
|
||||||
zsfree(ln);
|
zsfree(ln);
|
||||||
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
|
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
|
||||||
/* progress to finish: ZFTP_TRANSFER set to GF or PF */
|
/* progress to finish: ZFTP_TRANSFER set to GF or PF */
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
|
zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
|
||||||
ZFPM_READONLY);
|
ZFPM_READONLY);
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
}
|
}
|
||||||
if (rest) {
|
if (rest) {
|
||||||
zsfree(rest);
|
zsfree(rest);
|
||||||
|
@ -2428,9 +2444,13 @@ zftp_close(char *name, char **args, int flags)
|
||||||
zfunsetparam(*aptr);
|
zfunsetparam(*aptr);
|
||||||
|
|
||||||
/* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */
|
/* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */
|
||||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list)
|
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
|
||||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
int osc = sfcontext;
|
||||||
|
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
|
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
|
}
|
||||||
/* tidy up status variables, because mess is bad */
|
/* tidy up status variables, because mess is bad */
|
||||||
zfclosing = zfdrrrring = 0;
|
zfclosing = zfdrrrring = 0;
|
||||||
|
|
||||||
|
@ -2556,6 +2576,13 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
||||||
|
|
||||||
/* The load/unload routines required by the zsh library interface */
|
/* The load/unload routines required by the zsh library interface */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_zftp(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_zftp(Module m)
|
boot_zftp(Module m)
|
||||||
|
@ -2593,4 +2620,11 @@ cleanup_zftp(Module m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_zftp(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -98,7 +98,7 @@ struct compcond {
|
||||||
struct compctl {
|
struct compctl {
|
||||||
int refc; /* reference count */
|
int refc; /* reference count */
|
||||||
Compctl next; /* next compctl for -x */
|
Compctl next; /* next compctl for -x */
|
||||||
unsigned long mask, mask2; /* mask of things to complete (CC_*) */
|
unsigned long mask, mask2; /* masks of things to complete (CC_*) */
|
||||||
char *keyvar; /* for -k (variable) */
|
char *keyvar; /* for -k (variable) */
|
||||||
char *glob; /* for -g (globbing) */
|
char *glob; /* for -g (globbing) */
|
||||||
char *str; /* for -s (expansion) */
|
char *str; /* for -s (expansion) */
|
||||||
|
@ -110,7 +110,7 @@ struct compctl {
|
||||||
char *withd; /* for -w (with directory */
|
char *withd; /* for -w (with directory */
|
||||||
char *hpat; /* for -H (history pattern) */
|
char *hpat; /* for -H (history pattern) */
|
||||||
int hnum; /* for -H (number of events to search) */
|
int hnum; /* for -H (number of events to search) */
|
||||||
char *gname;
|
char *gname; /* for -J and -V (group name) */
|
||||||
Compctl ext; /* for -x (first of the compctls after -x) */
|
Compctl ext; /* for -x (first of the compctls after -x) */
|
||||||
Compcond cond; /* for -x (condition for this compctl) */
|
Compcond cond; /* for -x (condition for this compctl) */
|
||||||
Compctl xor; /* for + (next of the xor'ed compctls) */
|
Compctl xor; /* for + (next of the xor'ed compctls) */
|
||||||
|
@ -169,7 +169,6 @@ struct cexpl {
|
||||||
char *str; /* the string */
|
char *str; /* the string */
|
||||||
int count; /* the number of matches */
|
int count; /* the number of matches */
|
||||||
int fcount; /* number of matches with fignore ignored */
|
int fcount; /* number of matches with fignore ignored */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This describes a group of matches. */
|
/* This describes a group of matches. */
|
||||||
|
|
|
@ -430,7 +430,7 @@ quotename(const char *s, char **e, char *te, int *pl)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_comp1(Module m)
|
setup_comp1(Module m)
|
||||||
{
|
{
|
||||||
compctlreadptr = compctlread;
|
compctlreadptr = compctlread;
|
||||||
clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *));
|
clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *));
|
||||||
|
@ -446,11 +446,25 @@ boot_comp1(Module m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_comp1(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
cleanup_comp1(Module m)
|
cleanup_comp1(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_comp1(Module m)
|
||||||
{
|
{
|
||||||
deletehashtable(compctltab);
|
deletehashtable(compctltab);
|
||||||
zfree(clwords, clwsize * sizeof(char *));
|
zfree(clwords, clwsize * sizeof(char *));
|
||||||
|
|
|
@ -1636,15 +1636,22 @@ static struct builtin bintab[] = {
|
||||||
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
|
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_compctl(Module m)
|
||||||
|
{
|
||||||
|
compctltab->printnode = printcompctlp;
|
||||||
|
printcompctlptr = printcompctl;
|
||||||
|
compctl_widgetptr = compctl_widget;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_compctl(Module m)
|
boot_compctl(Module m)
|
||||||
{
|
{
|
||||||
if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)))
|
if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)))
|
||||||
return 1;
|
return 1;
|
||||||
compctltab->printnode = printcompctlp;
|
|
||||||
printcompctlptr = printcompctl;
|
|
||||||
compctl_widgetptr = compctl_widget;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,10 +1661,18 @@ boot_compctl(Module m)
|
||||||
int
|
int
|
||||||
cleanup_compctl(Module m)
|
cleanup_compctl(Module m)
|
||||||
{
|
{
|
||||||
compctltab->printnode = NULL;
|
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_compctl(Module m)
|
||||||
|
{
|
||||||
|
compctltab->printnode = NULL;
|
||||||
printcompctlptr = NULL;
|
printcompctlptr = NULL;
|
||||||
compctl_widgetptr = NULL;
|
compctl_widgetptr = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -71,6 +71,13 @@ deltochar(void)
|
||||||
feep();
|
feep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_deltochar(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_deltochar(Module m)
|
boot_deltochar(Module m)
|
||||||
|
@ -93,4 +100,12 @@ cleanup_deltochar(Module m)
|
||||||
deletezlefunction(w_deletetochar);
|
deletezlefunction(w_deletetochar);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_deltochar(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -603,11 +603,15 @@ execzlefunc(Thingy func)
|
||||||
zsfree(msg);
|
zsfree(msg);
|
||||||
feep();
|
feep();
|
||||||
} else {
|
} else {
|
||||||
startparamscope();
|
int osc = sfcontext;
|
||||||
makezleparams();
|
|
||||||
doshfunc(w->u.fnnam, l, NULL, 0, 1);
|
startparamscope();
|
||||||
endparamscope();
|
makezleparams();
|
||||||
lastcmd = 0;
|
sfcontext = SFC_WIDGET;
|
||||||
|
doshfunc(w->u.fnnam, l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
|
endparamscope();
|
||||||
|
lastcmd = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -856,7 +860,7 @@ static struct builtin bintab[] = {
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_zle(Module m)
|
setup_zle(Module m)
|
||||||
{
|
{
|
||||||
/* Set up editor entry points */
|
/* Set up editor entry points */
|
||||||
trashzleptr = trashzle;
|
trashzleptr = trashzle;
|
||||||
|
@ -875,6 +879,13 @@ boot_zle(Module m)
|
||||||
/* initialise the keymap system */
|
/* initialise the keymap system */
|
||||||
init_keymaps();
|
init_keymaps();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_zle(Module m)
|
||||||
|
{
|
||||||
addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -885,15 +896,21 @@ boot_zle(Module m)
|
||||||
int
|
int
|
||||||
cleanup_zle(Module m)
|
cleanup_zle(Module m)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
if(zleactive) {
|
if(zleactive) {
|
||||||
zerrnam(m->nam, "can't unload the zle module while zle is active",
|
zerrnam(m->nam, "can't unload the zle module while zle is active",
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_zle(Module m)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
cleanup_keymaps();
|
cleanup_keymaps();
|
||||||
deletehashtable(thingytab);
|
deletehashtable(thingytab);
|
||||||
|
|
||||||
|
|
|
@ -3801,15 +3801,23 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
||||||
|
|
||||||
/* Completion after `~', maketildelist adds the usernames *
|
/* Completion after `~', maketildelist adds the usernames *
|
||||||
* and named directories. */
|
* and named directories. */
|
||||||
if (ic == Tilde)
|
if (ic == Tilde) {
|
||||||
|
char *oi = ipre;
|
||||||
|
|
||||||
|
ipre = (ipre ? dyncat("~", ipre) : "~");
|
||||||
maketildelist();
|
maketildelist();
|
||||||
else if (ic == Equals) {
|
ipre = oi;
|
||||||
|
} else if (ic == Equals) {
|
||||||
/* Completion after `=', get the command names from *
|
/* Completion after `=', get the command names from *
|
||||||
* the cmdnamtab and aliases from aliastab. */
|
* the cmdnamtab and aliases from aliastab. */
|
||||||
|
char *oi = ipre;
|
||||||
|
|
||||||
|
ipre = (ipre ? dyncat("=", ipre) : "=");
|
||||||
if (isset(HASHLISTALL))
|
if (isset(HASHLISTALL))
|
||||||
cmdnamtab->filltable(cmdnamtab);
|
cmdnamtab->filltable(cmdnamtab);
|
||||||
dumphashtable(cmdnamtab, -7);
|
dumphashtable(cmdnamtab, -7);
|
||||||
dumphashtable(aliastab, -2);
|
dumphashtable(aliastab, -2);
|
||||||
|
ipre = oi;
|
||||||
} else {
|
} else {
|
||||||
/* Normal file completion... */
|
/* Normal file completion... */
|
||||||
if (ispattern & 1) {
|
if (ispattern & 1) {
|
||||||
|
@ -4082,6 +4090,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
||||||
if ((list = getshfunc(cc->func)) != &dummy_list) {
|
if ((list = getshfunc(cc->func)) != &dummy_list) {
|
||||||
/* We have it, so build a argument list. */
|
/* We have it, so build a argument list. */
|
||||||
LinkList args = newlinklist();
|
LinkList args = newlinklist();
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
addlinknode(args, cc->func);
|
addlinknode(args, cc->func);
|
||||||
|
|
||||||
|
@ -4099,8 +4108,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
||||||
|
|
||||||
/* This flag allows us to use read -l and -c. */
|
/* This flag allows us to use read -l and -c. */
|
||||||
incompctlfunc = 1;
|
incompctlfunc = 1;
|
||||||
|
sfcontext = SFC_COMPLETE;
|
||||||
/* Call the function. */
|
/* Call the function. */
|
||||||
doshfunc(cc->func, list, args, 0, 1);
|
doshfunc(cc->func, list, args, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
incompctlfunc = 0;
|
incompctlfunc = 0;
|
||||||
/* And get the result from the reply parameter. */
|
/* And get the result from the reply parameter. */
|
||||||
if ((r = get_user_var("reply")))
|
if ((r = get_user_var("reply")))
|
||||||
|
@ -4246,6 +4257,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
||||||
LinkList args = newlinklist();
|
LinkList args = newlinklist();
|
||||||
LinkNode ln;
|
LinkNode ln;
|
||||||
Cmatch m;
|
Cmatch m;
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
addlinknode(args, cc->ylist);
|
addlinknode(args, cc->ylist);
|
||||||
for (ln = firstnode(matches); ln; ln = nextnode(ln)) {
|
for (ln = firstnode(matches); ln; ln = nextnode(ln)) {
|
||||||
|
@ -4263,7 +4275,9 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
||||||
|
|
||||||
/* No harm in allowing read -l and -c here, too */
|
/* No harm in allowing read -l and -c here, too */
|
||||||
incompctlfunc = 1;
|
incompctlfunc = 1;
|
||||||
|
sfcontext = SFC_COMPLETE;
|
||||||
doshfunc(cc->ylist, list, args, 0, 1);
|
doshfunc(cc->ylist, list, args, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
incompctlfunc = 0;
|
incompctlfunc = 0;
|
||||||
uv = "reply";
|
uv = "reply";
|
||||||
}
|
}
|
||||||
|
|
|
@ -992,9 +992,13 @@ cd_new_pwd(int func, LinkNode dir, int chaselinks)
|
||||||
|
|
||||||
/* execute the chpwd function */
|
/* execute the chpwd function */
|
||||||
if ((l = getshfunc("chpwd")) != &dummy_list) {
|
if ((l = getshfunc("chpwd")) != &dummy_list) {
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("chpwd", l, NULL, 0, 1);
|
doshfunc("chpwd", l, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirstacksize = getiparam("DIRSTACKSIZE");
|
dirstacksize = getiparam("DIRSTACKSIZE");
|
||||||
|
@ -1469,7 +1473,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
||||||
Param pm;
|
Param pm;
|
||||||
Asgment asg;
|
Asgment asg;
|
||||||
Comp com;
|
Comp com;
|
||||||
char *optstr = "aiLRZlurtxU----A";
|
char *optstr = "aiALRZlurtxU";
|
||||||
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
||||||
int initon, initoff, of, i;
|
int initon, initoff, of, i;
|
||||||
int returnval = 0, printflags = 0;
|
int returnval = 0, printflags = 0;
|
||||||
|
|
58
Src/cond.c
58
Src/cond.c
|
@ -48,7 +48,8 @@ evalcond(Cond c)
|
||||||
{
|
{
|
||||||
Conddef cd;
|
Conddef cd;
|
||||||
|
|
||||||
if ((cd = getconddef((c->type == COND_MODI), (char *) c->left, 1))) {
|
if ((cd = getconddef((c->type == COND_MODI),
|
||||||
|
((char *) c->left) + 1, 1))) {
|
||||||
if (c->type == COND_MOD) {
|
if (c->type == COND_MOD) {
|
||||||
int l = arrlen((char **) c->right);
|
int l = arrlen((char **) c->right);
|
||||||
|
|
||||||
|
@ -57,10 +58,24 @@ evalcond(Cond c)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cd->handler(cd, (char **) c->right);
|
return cd->handler((char **) c->right, cd->condid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char **a = (char **) c->right, *s = a[0];
|
||||||
|
|
||||||
|
if (s && s[0] == '-' &&
|
||||||
|
(cd = getconddef(0, s + 1, 1))) {
|
||||||
|
int l = arrlen(a);
|
||||||
|
|
||||||
|
if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
|
||||||
|
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
a[0] = (char *) c->left;
|
||||||
|
return cd->handler(a, cd->condid);
|
||||||
|
} else
|
||||||
|
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,3 +259,38 @@ optison(char *s)
|
||||||
else
|
else
|
||||||
return isset(i);
|
return isset(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
char *
|
||||||
|
cond_str(char **args, int num)
|
||||||
|
{
|
||||||
|
char *s = args[num];
|
||||||
|
|
||||||
|
singsub(&s);
|
||||||
|
untokenize(s);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
long
|
||||||
|
cond_val(char **args, int num)
|
||||||
|
{
|
||||||
|
char *s = args[num];
|
||||||
|
|
||||||
|
singsub(&s);
|
||||||
|
untokenize(s);
|
||||||
|
|
||||||
|
return matheval(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
cond_match(char **args, int num, char *str)
|
||||||
|
{
|
||||||
|
char *s = args[num];
|
||||||
|
|
||||||
|
singsub(&s);
|
||||||
|
|
||||||
|
return matchpat(str, s);
|
||||||
|
}
|
||||||
|
|
22
Src/exec.c
22
Src/exec.c
|
@ -113,7 +113,12 @@ pid_t cmdoutpid;
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int cmdoutval;
|
int cmdoutval;
|
||||||
|
|
||||||
|
/* The context in which a shell function is called, see SFC_* in zsh.h. */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int sfcontext;
|
||||||
|
|
||||||
/* Stack to save some variables before executing a signal handler function */
|
/* Stack to save some variables before executing a signal handler function */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
@ -2771,19 +2776,14 @@ runshfunc(List list, FuncWrap wrap, char *name)
|
||||||
char *ou;
|
char *ou;
|
||||||
|
|
||||||
while (wrap) {
|
while (wrap) {
|
||||||
wrap->module->flags |= MOD_WRAPPER;
|
wrap->module->wrapper++;
|
||||||
wrap->count++;
|
|
||||||
cont = wrap->handler(list, wrap->next, name);
|
cont = wrap->handler(list, wrap->next, name);
|
||||||
wrap->count--;
|
wrap->module->wrapper--;
|
||||||
if (!wrap->count) {
|
|
||||||
wrap->module->flags &= ~MOD_WRAPPER;
|
|
||||||
#ifdef DYNAMIC
|
#ifdef DYNAMIC
|
||||||
if (wrap->module->flags & MOD_UNLOAD) {
|
if (!wrap->module->wrapper &&
|
||||||
wrap->module->flags &= ~MOD_UNLOAD;
|
(wrap->module->flags & MOD_UNLOAD))
|
||||||
unload_module(wrap->module, NULL);
|
unload_module(wrap->module, NULL);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
if (!cont)
|
if (!cont)
|
||||||
return;
|
return;
|
||||||
wrap = wrap->next;
|
wrap = wrap->next;
|
||||||
|
|
|
@ -1947,7 +1947,7 @@ getmatch(char **sp, char *pat, int fl, int n, char *replstr)
|
||||||
{
|
{
|
||||||
Comp c;
|
Comp c;
|
||||||
char *s = *sp, *t, *start, sav;
|
char *s = *sp, *t, *start, sav;
|
||||||
int i, j, l = strlen(*sp), matched;
|
int i, l = strlen(*sp), matched;
|
||||||
|
|
||||||
MUSTUSEHEAP("getmatch"); /* presumably covered by prefork() test */
|
MUSTUSEHEAP("getmatch"); /* presumably covered by prefork() test */
|
||||||
repllist = NULL;
|
repllist = NULL;
|
||||||
|
|
|
@ -111,13 +111,17 @@ loop(int toplevel, int justonce)
|
||||||
if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) {
|
if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) {
|
||||||
Histent he = gethistent(curhist);
|
Histent he = gethistent(curhist);
|
||||||
LinkList args;
|
LinkList args;
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
PERMALLOC {
|
PERMALLOC {
|
||||||
args = newlinklist();
|
args = newlinklist();
|
||||||
addlinknode(args, "preexec");
|
addlinknode(args, "preexec");
|
||||||
if (he && he->text)
|
if (he && he->text)
|
||||||
addlinknode(args, he->text);
|
addlinknode(args, he->text);
|
||||||
} LASTALLOC;
|
} LASTALLOC;
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("preexec", prelist, args, 0, 1);
|
doshfunc("preexec", prelist, args, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
freelinklist(args, (FreeFunc) NULL);
|
freelinklist(args, (FreeFunc) NULL);
|
||||||
errflag = 0;
|
errflag = 0;
|
||||||
}
|
}
|
||||||
|
@ -613,6 +617,7 @@ setupvals(void)
|
||||||
breaks = loops = 0;
|
breaks = loops = 0;
|
||||||
lastmailcheck = time(NULL);
|
lastmailcheck = time(NULL);
|
||||||
locallevel = sourcelevel = 0;
|
locallevel = sourcelevel = 0;
|
||||||
|
sfcontext = SFC_DIRECT;
|
||||||
trapreturn = 0;
|
trapreturn = 0;
|
||||||
noerrexit = -1;
|
noerrexit = -1;
|
||||||
nohistsave = 1;
|
nohistsave = 1;
|
||||||
|
|
|
@ -104,7 +104,7 @@ BEGIN {
|
||||||
gsub(/@!/, ",", dcltor)
|
gsub(/@!/, ",", dcltor)
|
||||||
|
|
||||||
# If this is a module boot/cleanup function, conditionally rename it.
|
# If this is a module boot/cleanup function, conditionally rename it.
|
||||||
if(" " dtype " " ~ / int / && dcltor ~ / *@\+(boot|cleanup)_[_0-9A-Za-z]+@- *_\(\( *Module +[_0-9A-Za-z]+ *\)\) */) {
|
if(" " dtype " " ~ / int / && dcltor ~ / *@\+(boot|cleanup|setup|finish)_[_0-9A-Za-z]+@- *_\(\( *Module +[_0-9A-Za-z]+ *\)\) */) {
|
||||||
modtype = dnam
|
modtype = dnam
|
||||||
sub(/_.*$/, "", modtype)
|
sub(/_.*$/, "", modtype)
|
||||||
output = output "# if defined(DYNAMIC_NAME_CLASH_OK) && defined(MODULE)\n"
|
output = output "# if defined(DYNAMIC_NAME_CLASH_OK) && defined(MODULE)\n"
|
||||||
|
|
|
@ -55,6 +55,6 @@ for bin_mod in $bin_mods; do
|
||||||
exit 1 ;;
|
exit 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
echo " mod.nam = \"$bin_mod\"; boot_$bin_mod(&mod);"
|
echo " mod.nam = \"$bin_mod\"; setup_$bin_mod(&mod); boot_$bin_mod(&mod);"
|
||||||
done_mods="$done_mods$bin_mod "
|
done_mods="$done_mods$bin_mod "
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,15 +1,35 @@
|
||||||
#include "zsh.mdh"
|
#include "zsh.mdh"
|
||||||
|
|
||||||
|
int setup_ _((Module));
|
||||||
int boot_ _((Module));
|
int boot_ _((Module));
|
||||||
int cleanup_ _((Module));
|
int cleanup_ _((Module));
|
||||||
|
int finish_ _((Module));
|
||||||
int modentry _((int boot, Module m));
|
int modentry _((int boot, Module m));
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
modentry(int boot, Module m)
|
modentry(int boot, Module m)
|
||||||
{
|
{
|
||||||
if (boot)
|
switch (boot) {
|
||||||
|
case 0:
|
||||||
|
return setup_(m);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
return boot_(m);
|
return boot_(m);
|
||||||
else
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
return cleanup_(m);
|
return cleanup_(m);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return finish_(m);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
zerr("bad call to modentry", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
257
Src/module.c
257
Src/module.c
|
@ -34,6 +34,13 @@
|
||||||
* as a separate module. It is initialised by main(), so there's nothing *
|
* as a separate module. It is initialised by main(), so there's nothing *
|
||||||
* for the boot function to do. */
|
* for the boot function to do. */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_zsh(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_zsh(Module m)
|
boot_zsh(Module m)
|
||||||
|
@ -114,7 +121,6 @@ addwrapper(Module m, FuncWrap w)
|
||||||
w->next = NULL;
|
w->next = NULL;
|
||||||
w->flags |= WRAPF_ADDED;
|
w->flags |= WRAPF_ADDED;
|
||||||
w->module = m;
|
w->module = m;
|
||||||
w->count = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -256,24 +262,58 @@ load_and_bind(const char *fn)
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# ifdef HAVE_DL_H
|
||||||
# include <nlist.h>
|
# include <dl.h>
|
||||||
# include <link.h>
|
# define RTLD_LAZY BIND_DEFERRED
|
||||||
|
# define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
# else
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <nlist.h>
|
||||||
|
# include <link.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef HAVE_DLCLOSE
|
|
||||||
# define dlclose(X) ((X), 0)
|
#ifdef HPUXDYNAMIC
|
||||||
|
# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
# define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static
|
||||||
|
void *
|
||||||
|
hpux_dlsym(void *handle, char *name)
|
||||||
|
{
|
||||||
|
void *sym_addr;
|
||||||
|
if (!shl_findsym((shl_t *)&handle, name, TYPE_UNDEFINED, &sym_addr))
|
||||||
|
return sym_addr;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define dlsym(handle,name) hpux_dlsym(handle,name)
|
||||||
|
# define dlerror() 0
|
||||||
|
#else
|
||||||
|
# ifndef HAVE_DLCLOSE
|
||||||
|
# define dlclose(X) ((X), 0)
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DLSYM_NEEDS_UNDERSCORE
|
#ifdef DLSYM_NEEDS_UNDERSCORE
|
||||||
|
# define STR_SETUP "_setup_"
|
||||||
|
# define STR_SETUP_S "_setup_%s"
|
||||||
# define STR_BOOT "_boot_"
|
# define STR_BOOT "_boot_"
|
||||||
# define STR_BOOT_S "_boot_%s"
|
# define STR_BOOT_S "_boot_%s"
|
||||||
# define STR_CLEANUP "_cleanup_"
|
# define STR_CLEANUP "_cleanup_"
|
||||||
# define STR_CLEANUP_S "_cleanup_%s"
|
# define STR_CLEANUP_S "_cleanup_%s"
|
||||||
|
# define STR_FINISH "_finish_"
|
||||||
|
# define STR_FINISH_S "_finish_%s"
|
||||||
#else /* !DLSYM_NEEDS_UNDERSCORE */
|
#else /* !DLSYM_NEEDS_UNDERSCORE */
|
||||||
|
# define STR_SETUP "setup_"
|
||||||
|
# define STR_SETUP_S "setup_%s"
|
||||||
# define STR_BOOT "boot_"
|
# define STR_BOOT "boot_"
|
||||||
# define STR_BOOT_S "boot_%s"
|
# define STR_BOOT_S "boot_%s"
|
||||||
# define STR_CLEANUP "cleanup_"
|
# define STR_CLEANUP "cleanup_"
|
||||||
# define STR_CLEANUP_S "cleanup_%s"
|
# define STR_CLEANUP_S "cleanup_%s"
|
||||||
|
# define STR_FINISH "finish_"
|
||||||
|
# define STR_FINISH_S "finish_%s"
|
||||||
#endif /* !DLSYM_NEEDS_UNDERSCORE */
|
#endif /* !DLSYM_NEEDS_UNDERSCORE */
|
||||||
|
|
||||||
#endif /* !AIXDYNAMIC */
|
#endif /* !AIXDYNAMIC */
|
||||||
|
@ -355,6 +395,13 @@ find_module(const char *name)
|
||||||
|
|
||||||
#ifdef AIXDYNAMIC
|
#ifdef AIXDYNAMIC
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
setup_module(Module m)
|
||||||
|
{
|
||||||
|
return ((int (*)_((int,Module))) m->handle)(0, m);
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static int
|
static int
|
||||||
init_module(Module m)
|
init_module(Module m)
|
||||||
|
@ -366,14 +413,20 @@ init_module(Module m)
|
||||||
static int
|
static int
|
||||||
cleanup_module(Module m)
|
cleanup_module(Module m)
|
||||||
{
|
{
|
||||||
return ((int (*)_((int,Module))) m->handle)(0, m);
|
return ((int (*)_((int,Module))) m->handle)(2, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
finish_module(Module m)
|
||||||
|
{
|
||||||
|
return ((int (*)_((int,Module))) m->handle)(3, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/**/
|
static Module_func
|
||||||
static int
|
module_func(Module m, char *name, char *name_s)
|
||||||
init_module(Module m)
|
|
||||||
{
|
{
|
||||||
char *s, *t;
|
char *s, *t;
|
||||||
#ifndef DYNAMIC_NAME_CLASH_OK
|
#ifndef DYNAMIC_NAME_CLASH_OK
|
||||||
|
@ -389,13 +442,34 @@ init_module(Module m)
|
||||||
if ((t = strrchr(s, '.')))
|
if ((t = strrchr(s, '.')))
|
||||||
*t = '\0';
|
*t = '\0';
|
||||||
#ifdef DYNAMIC_NAME_CLASH_OK
|
#ifdef DYNAMIC_NAME_CLASH_OK
|
||||||
fn = (Module_func) dlsym(m->handle, STR_BOOT);
|
fn = (Module_func) dlsym(m->handle, name);
|
||||||
#else /* !DYNAMIC_NAME_CLASH_OK */
|
#else /* !DYNAMIC_NAME_CLASH_OK */
|
||||||
if (strlen(s) + 6 > PATH_MAX)
|
if (strlen(s) + 6 > PATH_MAX)
|
||||||
return 1;
|
return NULL;
|
||||||
sprintf(buf, STR_BOOT_S, s);
|
sprintf(buf, name_s, s);
|
||||||
fn = (Module_func) dlsym(m->handle, buf);
|
fn = (Module_func) dlsym(m->handle, buf);
|
||||||
#endif /* !DYNAMIC_NAME_CLASH_OK */
|
#endif /* !DYNAMIC_NAME_CLASH_OK */
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
setup_module(Module m)
|
||||||
|
{
|
||||||
|
Module_func fn = module_func(m, STR_SETUP, STR_SETUP_S);
|
||||||
|
|
||||||
|
if (fn)
|
||||||
|
return fn(m);
|
||||||
|
zwarnnam(m->nam, "no setup function", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
init_module(Module m)
|
||||||
|
{
|
||||||
|
Module_func fn = module_func(m, STR_BOOT, STR_BOOT_S);
|
||||||
|
|
||||||
if(fn)
|
if(fn)
|
||||||
return fn(m);
|
return fn(m);
|
||||||
zwarnnam(m->nam, "no boot function", NULL, 0);
|
zwarnnam(m->nam, "no boot function", NULL, 0);
|
||||||
|
@ -406,33 +480,34 @@ init_module(Module m)
|
||||||
static int
|
static int
|
||||||
cleanup_module(Module m)
|
cleanup_module(Module m)
|
||||||
{
|
{
|
||||||
char *s, *t;
|
Module_func fn = module_func(m, STR_CLEANUP, STR_CLEANUP_S);
|
||||||
#ifndef DYNAMIC_NAME_CLASH_OK
|
|
||||||
char buf[PATH_MAX + 1];
|
|
||||||
#endif
|
|
||||||
Module_func fn;
|
|
||||||
|
|
||||||
s = strrchr(m->nam, '/');
|
|
||||||
if (s)
|
|
||||||
s = dupstring(++s);
|
|
||||||
else
|
|
||||||
s = m->nam;
|
|
||||||
if ((t = strrchr(s, '.')))
|
|
||||||
*t = '\0';
|
|
||||||
#ifdef DYNAMIC_NAME_CLASH_OK
|
|
||||||
fn = (Module_func) dlsym(m->handle, STR_CLEANUP);
|
|
||||||
#else /* !DYNAMIC_NAME_CLASH_OK */
|
|
||||||
if (strlen(s) + 9 > PATH_MAX)
|
|
||||||
return 1;
|
|
||||||
sprintf(buf, STR_CLEANUP_S, s);
|
|
||||||
fn = (Module_func) dlsym(m->handle, buf);
|
|
||||||
#endif /* !DYNAMIC_NAME_CLASH_OK */
|
|
||||||
if(fn)
|
if(fn)
|
||||||
return fn(m);
|
return fn(m);
|
||||||
zwarnnam(m->nam, "no cleanup function", NULL, 0);
|
zwarnnam(m->nam, "no cleanup function", NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note that this function does more than just calling finish_foo(), *
|
||||||
|
* it really unloads the module. */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
finish_module(Module m)
|
||||||
|
{
|
||||||
|
Module_func fn = module_func(m, STR_FINISH, STR_FINISH_S);
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (fn)
|
||||||
|
r = fn(m);
|
||||||
|
else {
|
||||||
|
zwarnnam(m->nam, "no finish function", NULL, 0);
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
dlclose(m->handle);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !AIXDYNAMIC */
|
#endif /* !AIXDYNAMIC */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
@ -449,8 +524,8 @@ load_module(char const *name)
|
||||||
m = zcalloc(sizeof(*m));
|
m = zcalloc(sizeof(*m));
|
||||||
m->nam = ztrdup(name);
|
m->nam = ztrdup(name);
|
||||||
m->handle = handle;
|
m->handle = handle;
|
||||||
if (init_module(m)) {
|
if (setup_module(m) || init_module(m)) {
|
||||||
dlclose(handle);
|
finish_module(m);
|
||||||
zsfree(m->nam);
|
zsfree(m->nam);
|
||||||
zfree(m, sizeof(*m));
|
zfree(m, sizeof(*m));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -459,25 +534,35 @@ load_module(char const *name)
|
||||||
addlinknode(modules, m);
|
addlinknode(modules, m);
|
||||||
} LASTALLOC;
|
} LASTALLOC;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
m = (Module) getdata(node);
|
m = (Module) getdata(node);
|
||||||
if (m->handle)
|
if (m->flags & MOD_UNLOAD)
|
||||||
|
m->flags &= ~MOD_UNLOAD;
|
||||||
|
else if (m->handle)
|
||||||
return m;
|
return m;
|
||||||
if (m->flags & MOD_BUSY) {
|
if (m->flags & MOD_BUSY) {
|
||||||
zerr("circular dependencies for module %s", name, 0);
|
zerr("circular dependencies for module %s", name, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
m->flags |= MOD_BUSY;
|
m->flags |= MOD_BUSY;
|
||||||
for (n = firstnode(m->deps); n; incnode(n))
|
if (m->deps)
|
||||||
if (!load_module((char *) getdata(n))) {
|
for (n = firstnode(m->deps); n; incnode(n))
|
||||||
m->flags &= ~MOD_BUSY;
|
if (!load_module((char *) getdata(n))) {
|
||||||
|
m->flags &= ~MOD_BUSY;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m->flags &= ~MOD_BUSY;
|
||||||
|
if (!m->handle) {
|
||||||
|
if (!(m->handle = do_load_module(name)))
|
||||||
|
return NULL;
|
||||||
|
if (setup_module(m)) {
|
||||||
|
finish_module(m->handle);
|
||||||
|
m->handle = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
m->flags &= ~MOD_BUSY;
|
}
|
||||||
if (!(m->handle = do_load_module(name)))
|
|
||||||
return NULL;
|
|
||||||
if (init_module(m)) {
|
if (init_module(m)) {
|
||||||
dlclose(m->handle);
|
finish_module(m->handle);
|
||||||
m->handle = NULL;
|
m->handle = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -756,12 +841,53 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
|
||||||
int
|
int
|
||||||
unload_module(Module m, LinkNode node)
|
unload_module(Module m, LinkNode node)
|
||||||
{
|
{
|
||||||
if (m->handle && cleanup_module(m))
|
if (m->handle && !(m->flags & MOD_UNLOAD) && cleanup_module(m))
|
||||||
return 1;
|
return 1;
|
||||||
else {
|
else {
|
||||||
|
int del = (m->flags & MOD_UNLOAD);
|
||||||
|
|
||||||
|
if (m->wrapper) {
|
||||||
|
m->flags |= MOD_UNLOAD;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
m->flags &= ~MOD_UNLOAD;
|
||||||
if (m->handle)
|
if (m->handle)
|
||||||
dlclose(m->handle);
|
finish_module(m);
|
||||||
m->handle = NULL;
|
m->handle = NULL;
|
||||||
|
if (del && m->deps) {
|
||||||
|
/* The module was unloaded delayed, unload all modules *
|
||||||
|
* on which it depended. */
|
||||||
|
LinkNode n;
|
||||||
|
|
||||||
|
for (n = firstnode(m->deps); n; incnode(n)) {
|
||||||
|
LinkNode dn = find_module((char *) getdata(n));
|
||||||
|
Module dm;
|
||||||
|
|
||||||
|
if (dn && (dm = (Module) getdata(dn)) &&
|
||||||
|
(dm->flags & MOD_UNLOAD)) {
|
||||||
|
/* See if this is the only module depending on it. */
|
||||||
|
|
||||||
|
LinkNode an;
|
||||||
|
Module am;
|
||||||
|
int du = 1;
|
||||||
|
|
||||||
|
for (an = firstnode(modules); du && an; incnode(an)) {
|
||||||
|
am = (Module) getdata(an);
|
||||||
|
if (am != m && am->handle && am->deps) {
|
||||||
|
LinkNode sn;
|
||||||
|
|
||||||
|
for (sn = firstnode(am->deps); du && sn;
|
||||||
|
incnode(sn)) {
|
||||||
|
if (!strcmp((char *) getdata(sn), dm->nam))
|
||||||
|
du = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (du)
|
||||||
|
unload_module(dm, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!m->deps) {
|
if(!m->deps) {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
for (node = firstnode(modules); node; incnode(node))
|
for (node = firstnode(modules); node; incnode(node))
|
||||||
|
@ -791,24 +917,29 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
||||||
node = find_module(*args);
|
node = find_module(*args);
|
||||||
if (node) {
|
if (node) {
|
||||||
LinkNode mn, dn;
|
LinkNode mn, dn;
|
||||||
|
int del = 0;
|
||||||
|
|
||||||
for (mn = firstnode(modules); mn; incnode(mn)) {
|
for (mn = firstnode(modules); mn; incnode(mn)) {
|
||||||
m = (Module) getdata(mn);
|
m = (Module) getdata(mn);
|
||||||
if (m->deps && m->handle)
|
if (m->deps && m->handle)
|
||||||
for (dn = firstnode(m->deps); dn; incnode(dn))
|
for (dn = firstnode(m->deps); dn; incnode(dn))
|
||||||
if (!strcmp((char *) getdata(dn), *args)) {
|
if (!strcmp((char *) getdata(dn), *args)) {
|
||||||
zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0);
|
if (m->flags & MOD_UNLOAD)
|
||||||
ret = 1;
|
del = 1;
|
||||||
goto cont;
|
else {
|
||||||
|
zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0);
|
||||||
|
ret = 1;
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m = (Module) getdata(node);
|
m = (Module) getdata(node);
|
||||||
if (!(m->flags & MOD_WRAPPER)) {
|
if (del)
|
||||||
if (unload_module(m, node))
|
m->wrapper++;
|
||||||
ret = 1;
|
if (unload_module(m, node))
|
||||||
}
|
ret = 1;
|
||||||
else
|
if (del)
|
||||||
m->flags |= MOD_UNLOAD;
|
m->wrapper--;
|
||||||
} else if (!ops['i']) {
|
} else if (!ops['i']) {
|
||||||
zwarnnam(nam, "no such module %s", *args, 0);
|
zwarnnam(nam, "no such module %s", *args, 0);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -820,7 +951,7 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
||||||
/* list modules */
|
/* list modules */
|
||||||
for (node = firstnode(modules); node; incnode(node)) {
|
for (node = firstnode(modules); node; incnode(node)) {
|
||||||
m = (Module) getdata(node);
|
m = (Module) getdata(node);
|
||||||
if (m->handle) {
|
if (m->handle && !(m->flags & MOD_UNLOAD)) {
|
||||||
if(ops['L']) {
|
if(ops['L']) {
|
||||||
printf("zmodload ");
|
printf("zmodload ");
|
||||||
if(m->nam[0] == '-')
|
if(m->nam[0] == '-')
|
||||||
|
@ -835,8 +966,11 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
||||||
} else {
|
} else {
|
||||||
/* load modules */
|
/* load modules */
|
||||||
for (; *args; args++) {
|
for (; *args; args++) {
|
||||||
|
Module m;
|
||||||
|
|
||||||
node = find_module(*args);
|
node = find_module(*args);
|
||||||
if (node && ((Module) getdata(node))->handle) {
|
if (node && (m = ((Module) getdata(node)))->handle &&
|
||||||
|
!(m->flags & MOD_UNLOAD)) {
|
||||||
if (!ops['i']) {
|
if (!ops['i']) {
|
||||||
zwarnnam(nam, "module %s already loaded.", *args, 0);
|
zwarnnam(nam, "module %s already loaded.", *args, 0);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -894,8 +1028,6 @@ getconddef(int inf, char *name, int autol)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DYNAMIC
|
|
||||||
|
|
||||||
/* This adds the given condition definition. The return value is zero on *
|
/* This adds the given condition definition. The return value is zero on *
|
||||||
* success and 1 on failure. If there is a matching definition for an *
|
* success and 1 on failure. If there is a matching definition for an *
|
||||||
* autoloaded condition, it is removed. */
|
* autoloaded condition, it is removed. */
|
||||||
|
@ -909,10 +1041,11 @@ addconddef(Conddef c)
|
||||||
if (p) {
|
if (p) {
|
||||||
if (!p->module || (p->flags & CONDF_ADDED))
|
if (!p->module || (p->flags & CONDF_ADDED))
|
||||||
return 1;
|
return 1;
|
||||||
|
#ifdef DYNAMIC
|
||||||
/* There is an autoload definition. */
|
/* There is an autoload definition. */
|
||||||
|
|
||||||
deleteconddef(p);
|
deleteconddef(p);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
c->next = condtab;
|
c->next = condtab;
|
||||||
condtab = c;
|
condtab = c;
|
||||||
|
@ -942,6 +1075,8 @@ addconddefs(char const *nam, Conddef c, int size)
|
||||||
return hadf ? hads : 1;
|
return hadf ? hads : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC
|
||||||
|
|
||||||
/* This adds a definition for autoloading a module for a condition. */
|
/* This adds a definition for autoloading a module for a condition. */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
@ -1014,4 +1149,4 @@ deleteconddefs(char const *nam, Conddef c, int size)
|
||||||
return hadf ? hads : 1;
|
return hadf ? hads : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DYNAMIC */
|
#endif
|
||||||
|
|
78
Src/params.c
78
Src/params.c
|
@ -301,14 +301,6 @@ copyparamtable(HashTable ht, char *name)
|
||||||
return nht;
|
return nht;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SCANPM_WANTVALS (1<<0)
|
|
||||||
#define SCANPM_WANTKEYS (1<<1)
|
|
||||||
#define SCANPM_WANTINDEX (1<<2) /* Useful only if nested arrays */
|
|
||||||
#define SCANPM_MATCHKEY (1<<3)
|
|
||||||
#define SCANPM_MATCHVAL (1<<4)
|
|
||||||
#define SCANPM_MATCHMANY (1<<5)
|
|
||||||
#define SCANPM_ISVAR_AT ((-1)<<15) /* Only sign bit is significant */
|
|
||||||
|
|
||||||
static unsigned numparamvals;
|
static unsigned numparamvals;
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
@ -641,6 +633,7 @@ isident(char *s)
|
||||||
if (!iident(*ss))
|
if (!iident(*ss))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* If this exhaust `s' or the next two characters *
|
/* If this exhaust `s' or the next two characters *
|
||||||
* are [(, then it is a valid identifier. */
|
* are [(, then it is a valid identifier. */
|
||||||
if (!*ss || (*ss == '[' && ss[1] == '('))
|
if (!*ss || (*ss == '[' && ss[1] == '('))
|
||||||
|
@ -650,6 +643,7 @@ isident(char *s)
|
||||||
* definitely not a valid identifier. */
|
* definitely not a valid identifier. */
|
||||||
if (*ss != '[')
|
if (*ss != '[')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
noeval = 1;
|
noeval = 1;
|
||||||
(void)mathevalarg(++ss, &ss);
|
(void)mathevalarg(++ss, &ss);
|
||||||
if (*ss == ',')
|
if (*ss == ',')
|
||||||
|
@ -658,6 +652,19 @@ isident(char *s)
|
||||||
if (*ss != ']' || ss[1])
|
if (*ss != ']' || ss[1])
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
#else
|
||||||
|
/* If the next character is not [, then it is *
|
||||||
|
* definitely not a valid identifier. */
|
||||||
|
if (!*ss)
|
||||||
|
return 1;
|
||||||
|
if (*ss != '[')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Require balanced [ ] pairs */
|
||||||
|
if (skipparens('[', ']', &ss))
|
||||||
|
return 0;
|
||||||
|
return !*ss;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **garr;
|
static char **garr;
|
||||||
|
@ -755,6 +762,8 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
||||||
if (ind) {
|
if (ind) {
|
||||||
v->isarr |= SCANPM_WANTKEYS;
|
v->isarr |= SCANPM_WANTKEYS;
|
||||||
v->isarr &= ~SCANPM_WANTVALS;
|
v->isarr &= ~SCANPM_WANTVALS;
|
||||||
|
} else if (rev) {
|
||||||
|
v->isarr |= SCANPM_WANTVALS;
|
||||||
}
|
}
|
||||||
if (!down)
|
if (!down)
|
||||||
v->isarr &= ~SCANPM_MATCHMANY;
|
v->isarr &= ~SCANPM_MATCHMANY;
|
||||||
|
@ -788,8 +797,9 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
||||||
v->pm = createparam(s, PM_SCALAR|PM_UNSET);
|
v->pm = createparam(s, PM_SCALAR|PM_UNSET);
|
||||||
paramtab = tht;
|
paramtab = tht;
|
||||||
}
|
}
|
||||||
v->isarr = 0;
|
v->isarr = (*inv ? SCANPM_WANTINDEX : 0);
|
||||||
v->a = 0;
|
v->a = 0;
|
||||||
|
*inv = 0; /* We've already obtained the "index" (key) */
|
||||||
*w = v->b = -1;
|
*w = v->b = -1;
|
||||||
r = isset(KSHARRAYS) ? 1 : 0;
|
r = isset(KSHARRAYS) ? 1 : 0;
|
||||||
} else
|
} else
|
||||||
|
@ -979,9 +989,11 @@ getindex(char **pptr, Value v)
|
||||||
}
|
}
|
||||||
if (a > 0 && (isset(KSHARRAYS) || (v->pm->flags & PM_HASHED)))
|
if (a > 0 && (isset(KSHARRAYS) || (v->pm->flags & PM_HASHED)))
|
||||||
a--;
|
a--;
|
||||||
v->inv = 1;
|
if (v->isarr != SCANPM_WANTINDEX) {
|
||||||
v->isarr = 0;
|
v->inv = 1;
|
||||||
v->a = v->b = a;
|
v->isarr = 0;
|
||||||
|
v->a = v->b = a;
|
||||||
|
}
|
||||||
if (*s == ',') {
|
if (*s == ',') {
|
||||||
zerr("invalid subscript", NULL, 0);
|
zerr("invalid subscript", NULL, 0);
|
||||||
while (*s != ']' && *s != Outbrack)
|
while (*s != ']' && *s != Outbrack)
|
||||||
|
@ -1546,35 +1558,37 @@ setaparam(char *s, char **val)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
Param
|
Param
|
||||||
sethparam(char *s, char **kvarr)
|
sethparam(char *s, char **val)
|
||||||
{
|
{
|
||||||
Value v;
|
Value v;
|
||||||
Param pm;
|
char *t = s;
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (!isident(s)) {
|
if (!isident(s)) {
|
||||||
zerr("not an identifier: %s", s, 0);
|
zerr("not an identifier: %s", s, 0);
|
||||||
freearray(kvarr);
|
freearray(val);
|
||||||
errflag = 1;
|
errflag = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
t=ztrdup(s); /* Is this a memory leak? */
|
if (strchr(s, '[')) {
|
||||||
/* Why does getvalue(s, 1) set s to empty string? */
|
freearray(val);
|
||||||
if ((v = getvalue(&t, 1)))
|
zerr("attempt to set slice of associative array", NULL, 0);
|
||||||
if (v->pm->flags & PM_SPECIAL) {
|
errflag = 1;
|
||||||
zerr("not overriding a special: %s", s, 0);
|
return NULL;
|
||||||
freearray(kvarr);
|
} else {
|
||||||
errflag = 1;
|
if (!(v = getvalue(&s, 1)))
|
||||||
|
createparam(t, PM_HASHED);
|
||||||
|
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||||
|
!(v->pm->flags & PM_SPECIAL)) {
|
||||||
|
unsetparam(t);
|
||||||
|
createparam(t, PM_HASHED);
|
||||||
|
v = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!v)
|
||||||
|
if (!(v = getvalue(&t, 1)))
|
||||||
return NULL;
|
return NULL;
|
||||||
} else
|
setarrvalue(v, val);
|
||||||
unsetparam(s);
|
return v->pm;
|
||||||
|
|
||||||
pm = createparam(s, PM_HASHED);
|
|
||||||
DPUTS(!pm, "BUG: parameter not created");
|
|
||||||
|
|
||||||
arrhashsetfn(pm, kvarr);
|
|
||||||
|
|
||||||
return pm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
|
|
@ -1339,7 +1339,7 @@ par_cond_double(char *a, char *b)
|
||||||
|
|
||||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
||||||
n->type = COND_MOD;
|
n->type = COND_MOD;
|
||||||
n->left = (void *) (a + 1);
|
n->left = (void *) a;
|
||||||
d[0] = b;
|
d[0] = b;
|
||||||
d[1] = NULL;
|
d[1] = NULL;
|
||||||
n->right = (void *) arrdup(d);
|
n->right = (void *) arrdup(d);
|
||||||
|
@ -1386,7 +1386,7 @@ par_cond_triple(char *a, char *b, char *c)
|
||||||
|
|
||||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
||||||
n->type = COND_MODI;
|
n->type = COND_MODI;
|
||||||
n->left = (void *) (b + 1);
|
n->left = (void *) b;
|
||||||
d[0] = a;
|
d[0] = a;
|
||||||
d[1] = c;
|
d[1] = c;
|
||||||
d[2] = NULL;
|
d[2] = NULL;
|
||||||
|
@ -1397,7 +1397,7 @@ par_cond_triple(char *a, char *b, char *c)
|
||||||
|
|
||||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
||||||
n->type = COND_MOD;
|
n->type = COND_MOD;
|
||||||
n->left = (void *) (a + 1);
|
n->left = (void *) a;
|
||||||
d[0] = b;
|
d[0] = b;
|
||||||
d[1] = c;
|
d[1] = c;
|
||||||
d[2] = NULL;
|
d[2] = NULL;
|
||||||
|
|
|
@ -703,6 +703,8 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
||||||
execsave();
|
execsave();
|
||||||
breaks = 0;
|
breaks = 0;
|
||||||
if (*sigtr & ZSIG_FUNC) {
|
if (*sigtr & ZSIG_FUNC) {
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
PERMALLOC {
|
PERMALLOC {
|
||||||
args = newlinklist();
|
args = newlinklist();
|
||||||
name = (char *) zalloc(5 + strlen(sigs[sig]));
|
name = (char *) zalloc(5 + strlen(sigs[sig]));
|
||||||
|
@ -712,7 +714,9 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
||||||
addlinknode(args, num);
|
addlinknode(args, num);
|
||||||
} LASTALLOC;
|
} LASTALLOC;
|
||||||
trapreturn = -1;
|
trapreturn = -1;
|
||||||
|
sfcontext = SFC_SIGNAL;
|
||||||
doshfunc(name, sigfn, args, 0, 1);
|
doshfunc(name, sigfn, args, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
freelinklist(args, (FreeFunc) NULL);
|
freelinklist(args, (FreeFunc) NULL);
|
||||||
zsfree(name);
|
zsfree(name);
|
||||||
} else HEAPALLOC {
|
} else HEAPALLOC {
|
||||||
|
|
28
Src/subst.c
28
Src/subst.c
|
@ -720,8 +720,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
int eval = 0;
|
int eval = 0;
|
||||||
int nojoin = 0;
|
int nojoin = 0;
|
||||||
char inbrace = 0; /* != 0 means ${...}, otherwise $... */
|
char inbrace = 0; /* != 0 means ${...}, otherwise $... */
|
||||||
char hkeys = 0; /* 1 means get keys from associative array */
|
char hkeys = 0;
|
||||||
char hvals = 0; /* > hkeys get values of associative array */
|
char hvals = 0;
|
||||||
|
|
||||||
*s++ = '\0';
|
*s++ = '\0';
|
||||||
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
||||||
|
@ -739,7 +739,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
inbrace = 1;
|
inbrace = 1;
|
||||||
s++;
|
s++;
|
||||||
if (*s == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
if (*s == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
||||||
hkeys = 1;
|
hkeys = SCANPM_WANTKEYS;
|
||||||
s++;
|
s++;
|
||||||
} else if (*s == '(' || *s == Inpar) {
|
} else if (*s == '(' || *s == Inpar) {
|
||||||
char *t, sav;
|
char *t, sav;
|
||||||
|
@ -762,7 +762,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
case Outpar:
|
case Outpar:
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
arrasg = 1;
|
++arrasg;
|
||||||
break;
|
break;
|
||||||
case '@':
|
case '@':
|
||||||
nojoin = 1;
|
nojoin = 1;
|
||||||
|
@ -897,10 +897,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'k':
|
case 'k':
|
||||||
hkeys = 1;
|
hkeys = SCANPM_WANTKEYS;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
hvals = 2;
|
hvals = SCANPM_WANTVALS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -979,9 +979,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
*s = sav;
|
*s = sav;
|
||||||
v = (Value) NULL;
|
v = (Value) NULL;
|
||||||
} else {
|
} else {
|
||||||
/* 2 == SCANPM_WANTKEYS, 1 == SCANPM_WANTVALS, see params.c */
|
|
||||||
if (!(v = fetchvalue(&s, (unset(KSHARRAYS) || inbrace) ? 1 : -1,
|
if (!(v = fetchvalue(&s, (unset(KSHARRAYS) || inbrace) ? 1 : -1,
|
||||||
(hkeys ? 2 : 0) + ((hvals > hkeys) ? 1 : 0))))
|
hkeys|hvals)))
|
||||||
vunset = 1;
|
vunset = 1;
|
||||||
}
|
}
|
||||||
while (v || ((inbrace || (unset(KSHARRAYS) && vunset)) && isbrack(*s))) {
|
while (v || ((inbrace || (unset(KSHARRAYS) && vunset)) && isbrack(*s))) {
|
||||||
|
@ -1010,7 +1009,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
if ((isarr = v->isarr)) {
|
if ((isarr = v->isarr)) {
|
||||||
/* No way to get here with v->inv != 0, so getvaluearr() *
|
/* No way to get here with v->inv != 0, so getvaluearr() *
|
||||||
* is called by getarrvalue(); needn't test PM_HASHED. */
|
* is called by getarrvalue(); needn't test PM_HASHED. */
|
||||||
aval = getarrvalue(v);
|
if (v->isarr == SCANPM_WANTINDEX) {
|
||||||
|
isarr = v->isarr = 0;
|
||||||
|
val = dupstring(v->pm->nam);
|
||||||
|
} else
|
||||||
|
aval = getarrvalue(v);
|
||||||
} else {
|
} else {
|
||||||
if (v->pm->flags & PM_ARRAY) {
|
if (v->pm->flags & PM_ARRAY) {
|
||||||
int tmplen = arrlen(v->pm->gets.afn(v->pm));
|
int tmplen = arrlen(v->pm->gets.afn(v->pm));
|
||||||
|
@ -1260,7 +1263,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
*p++ = ztrdup(*t++);
|
*p++ = ztrdup(*t++);
|
||||||
}
|
}
|
||||||
*p++ = NULL;
|
*p++ = NULL;
|
||||||
setaparam(idbeg, a);
|
if (arrasg > 1) {
|
||||||
|
Param pm = sethparam(idbeg, a);
|
||||||
|
if (pm)
|
||||||
|
aval = paramvalarr(pm->gets.hfn(pm), hkeys|hvals);
|
||||||
|
} else
|
||||||
|
setaparam(idbeg, a);
|
||||||
} else {
|
} else {
|
||||||
untokenize(val);
|
untokenize(val);
|
||||||
setsparam(idbeg, ztrdup(val));
|
setsparam(idbeg, ztrdup(val));
|
||||||
|
|
22
Src/utils.c
22
Src/utils.c
|
@ -427,7 +427,7 @@ get_username(void)
|
||||||
cached_username = ztrdup("");
|
cached_username = ztrdup("");
|
||||||
}
|
}
|
||||||
#else /* !HAVE_GETPWUID */
|
#else /* !HAVE_GETPWUID */
|
||||||
cached_uid = current_uid;
|
cached_uid = getuid();
|
||||||
#endif /* !HAVE_GETPWUID */
|
#endif /* !HAVE_GETPWUID */
|
||||||
return cached_username;
|
return cached_username;
|
||||||
}
|
}
|
||||||
|
@ -510,16 +510,13 @@ adduserdir(char *s, char *t, int flags, int always)
|
||||||
if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
|
if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Never hash PWD unless it was explicitly requested */
|
|
||||||
if (!always && !strcmp(s, "PWD"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Normal parameter assignments generate calls to this function, *
|
/* Normal parameter assignments generate calls to this function, *
|
||||||
* with always==0. Unless the AUTO_NAME_DIRS option is set, we *
|
* with always==0. Unless the AUTO_NAME_DIRS option is set, we *
|
||||||
* don't let such assignments actually create directory names. *
|
* don't let such assignments actually create directory names. *
|
||||||
* Instead, a reference to the parameter as a directory name can *
|
* Instead, a reference to the parameter as a directory name can *
|
||||||
* cause the actual creation of the hash table entry. */
|
* cause the actual creation of the hash table entry. Never hash *
|
||||||
if (!always && unset(AUTONAMEDIRS) &&
|
* PWD unless it was explicitly requested (or already hashed). */
|
||||||
|
if (!always && (unset(AUTONAMEDIRS) || !strcmp(s, "PWD")) &&
|
||||||
!nameddirtab->getnode2(nameddirtab, s))
|
!nameddirtab->getnode2(nameddirtab, s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -633,8 +630,13 @@ preprompt(void)
|
||||||
|
|
||||||
/* If a shell function named "precmd" exists, *
|
/* If a shell function named "precmd" exists, *
|
||||||
* then execute it. */
|
* then execute it. */
|
||||||
if ((list = getshfunc("precmd")) != &dummy_list)
|
if ((list = getshfunc("precmd")) != &dummy_list) {
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("precmd", list, NULL, 0, 1);
|
doshfunc("precmd", list, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
|
}
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -643,7 +645,11 @@ preprompt(void)
|
||||||
* executed "periodic", then execute it now. */
|
* executed "periodic", then execute it now. */
|
||||||
if (period && (time(NULL) > lastperiodic + period) &&
|
if (period && (time(NULL) > lastperiodic + period) &&
|
||||||
(list = getshfunc("periodic")) != &dummy_list) {
|
(list = getshfunc("periodic")) != &dummy_list) {
|
||||||
|
int osc = sfcontext;
|
||||||
|
|
||||||
|
sfcontext = SFC_HOOK;
|
||||||
doshfunc("periodic", list, NULL, 0, 1);
|
doshfunc("periodic", list, NULL, 0, 1);
|
||||||
|
sfcontext = osc;
|
||||||
lastperiodic = time(NULL);
|
lastperiodic = time(NULL);
|
||||||
}
|
}
|
||||||
if (errflag)
|
if (errflag)
|
||||||
|
|
|
@ -23,6 +23,8 @@ closem
|
||||||
cmdnamtab
|
cmdnamtab
|
||||||
columns
|
columns
|
||||||
compctlreadptr
|
compctlreadptr
|
||||||
|
cond_str
|
||||||
|
cond_val
|
||||||
coprocin
|
coprocin
|
||||||
coprocout
|
coprocout
|
||||||
countlinknodes
|
countlinknodes
|
||||||
|
@ -173,6 +175,7 @@ sethparam
|
||||||
setlimits
|
setlimits
|
||||||
setsparam
|
setsparam
|
||||||
settyinfo
|
settyinfo
|
||||||
|
sfcontext
|
||||||
shfunctab
|
shfunctab
|
||||||
shingetline
|
shingetline
|
||||||
shout
|
shout
|
||||||
|
|
63
Src/zsh.h
63
Src/zsh.h
|
@ -460,23 +460,24 @@ struct cond {
|
||||||
#define COND_MOD 16
|
#define COND_MOD 16
|
||||||
#define COND_MODI 17
|
#define COND_MODI 17
|
||||||
|
|
||||||
typedef int (*CondHandler) _((Conddef, char **));
|
typedef int (*CondHandler) _((char **, int));
|
||||||
|
|
||||||
struct conddef {
|
struct conddef {
|
||||||
Conddef next; /* next in list */
|
Conddef next; /* next in list */
|
||||||
char *name; /* the condition name */
|
char *name; /* the condition name */
|
||||||
int flags; /* see CONDF_* below */
|
int flags; /* see CONDF_* below */
|
||||||
|
CondHandler handler; /* handler function */
|
||||||
int min; /* minimum number of strings */
|
int min; /* minimum number of strings */
|
||||||
int max; /* maximum number of strings */
|
int max; /* maximum number of strings */
|
||||||
CondHandler handler; /* handler function */
|
int condid; /* for overloading handler functions */
|
||||||
char *module; /* module to autoload */
|
char *module; /* module to autoload */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CONDF_INFIX 1
|
#define CONDF_INFIX 1
|
||||||
#define CONDF_ADDED 2
|
#define CONDF_ADDED 2
|
||||||
|
|
||||||
#define CONDDEF(name, flags, min, max, handler) \
|
#define CONDDEF(name, flags, handler, min, max, condid) \
|
||||||
{ NULL, name, flags, min, max, handler, NULL }
|
{ NULL, name, flags, handler, min, max, condid, NULL }
|
||||||
|
|
||||||
struct forcmd { /* for/select */
|
struct forcmd { /* for/select */
|
||||||
/* Cmd->args contains list of words to loop thru */
|
/* Cmd->args contains list of words to loop thru */
|
||||||
|
@ -772,6 +773,14 @@ struct shfunc {
|
||||||
List funcdef; /* function definition */
|
List funcdef; /* function definition */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Shell function context types. */
|
||||||
|
|
||||||
|
#define SFC_DIRECT 0 /* called directly from the user */
|
||||||
|
#define SFC_SIGNAL 1 /* signal handler */
|
||||||
|
#define SFC_HOOK 2 /* one of the special functions */
|
||||||
|
#define SFC_WIDGET 3 /* user defined widget */
|
||||||
|
#define SFC_COMPLETE 4 /* called from completion code */
|
||||||
|
|
||||||
/* node in list of function call wrappers */
|
/* node in list of function call wrappers */
|
||||||
|
|
||||||
typedef int (*WrapFunc) _((List, FuncWrap, char *));
|
typedef int (*WrapFunc) _((List, FuncWrap, char *));
|
||||||
|
@ -781,13 +790,12 @@ struct funcwrap {
|
||||||
int flags;
|
int flags;
|
||||||
WrapFunc handler;
|
WrapFunc handler;
|
||||||
Module module;
|
Module module;
|
||||||
int count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WRAPF_ADDED 1
|
#define WRAPF_ADDED 1
|
||||||
|
|
||||||
#define WRAPDEF(func) \
|
#define WRAPDEF(func) \
|
||||||
{ NULL, 0, func, NULL, 0 }
|
{ NULL, 0, func, NULL }
|
||||||
|
|
||||||
/* node in builtin command hash table (builtintab) */
|
/* node in builtin command hash table (builtintab) */
|
||||||
|
|
||||||
|
@ -836,11 +844,11 @@ struct module {
|
||||||
int flags;
|
int flags;
|
||||||
void *handle;
|
void *handle;
|
||||||
LinkList deps;
|
LinkList deps;
|
||||||
|
int wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MOD_BUSY (1<<0)
|
#define MOD_BUSY (1<<0)
|
||||||
#define MOD_WRAPPER (1<<1)
|
#define MOD_UNLOAD (1<<1)
|
||||||
#define MOD_UNLOAD (1<<2)
|
|
||||||
|
|
||||||
/* node used in parameter hash table (paramtab) */
|
/* node used in parameter hash table (paramtab) */
|
||||||
|
|
||||||
|
@ -890,28 +898,37 @@ struct param {
|
||||||
#define PM_SCALAR 0 /* scalar */
|
#define PM_SCALAR 0 /* scalar */
|
||||||
#define PM_ARRAY (1<<0) /* array */
|
#define PM_ARRAY (1<<0) /* array */
|
||||||
#define PM_INTEGER (1<<1) /* integer */
|
#define PM_INTEGER (1<<1) /* integer */
|
||||||
#define PM_HASHED (1<<15) /* association */
|
#define PM_HASHED (1<<2) /* association */
|
||||||
|
|
||||||
#define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY|PM_HASHED))
|
#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_LEFT (1<<3) /* left justify and remove leading blanks */
|
||||||
#define PM_RIGHT_B (1<<3) /* right justify and fill with leading blanks */
|
#define PM_RIGHT_B (1<<4) /* right justify and fill with leading blanks */
|
||||||
#define PM_RIGHT_Z (1<<4) /* right justify and fill with leading zeros */
|
#define PM_RIGHT_Z (1<<5) /* right justify and fill with leading zeros */
|
||||||
#define PM_LOWER (1<<5) /* all lower case */
|
#define PM_LOWER (1<<6) /* all lower case */
|
||||||
|
|
||||||
/* The following are the same since they *
|
/* The following are the same since they *
|
||||||
* both represent -u option to typeset */
|
* both represent -u option to typeset */
|
||||||
#define PM_UPPER (1<<6) /* all upper case */
|
#define PM_UPPER (1<<7) /* all upper case */
|
||||||
#define PM_UNDEFINED (1<<6) /* undefined (autoloaded) shell function */
|
#define PM_UNDEFINED (1<<7) /* undefined (autoloaded) shell function */
|
||||||
|
|
||||||
#define PM_READONLY (1<<7) /* readonly */
|
#define PM_READONLY (1<<8) /* readonly */
|
||||||
#define PM_TAGGED (1<<8) /* tagged */
|
#define PM_TAGGED (1<<9) /* tagged */
|
||||||
#define PM_EXPORTED (1<<9) /* exported */
|
#define PM_EXPORTED (1<<10) /* exported */
|
||||||
#define PM_UNIQUE (1<<10) /* remove duplicates */
|
#define PM_UNIQUE (1<<11) /* remove duplicates */
|
||||||
#define PM_SPECIAL (1<<11) /* special builtin parameter */
|
#define PM_SPECIAL (1<<12) /* special builtin parameter */
|
||||||
#define PM_DONTIMPORT (1<<12) /* do not import this variable */
|
#define PM_DONTIMPORT (1<<13) /* do not import this variable */
|
||||||
#define PM_RESTRICTED (1<<13) /* cannot be changed in restricted mode */
|
#define PM_RESTRICTED (1<<14) /* cannot be changed in restricted mode */
|
||||||
#define PM_UNSET (1<<14) /* has null value */
|
#define PM_UNSET (1<<15) /* has null value */
|
||||||
|
|
||||||
|
/* Flags for extracting elements of arrays and associative arrays */
|
||||||
|
#define SCANPM_WANTVALS (1<<0)
|
||||||
|
#define SCANPM_WANTKEYS (1<<1)
|
||||||
|
#define SCANPM_WANTINDEX (1<<2)
|
||||||
|
#define SCANPM_MATCHKEY (1<<3)
|
||||||
|
#define SCANPM_MATCHVAL (1<<4)
|
||||||
|
#define SCANPM_MATCHMANY (1<<5)
|
||||||
|
#define SCANPM_ISVAR_AT ((-1)<<15) /* Only sign bit is significant */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for doing matches inside parameter substitutions, i.e.
|
* Flags for doing matches inside parameter substitutions, i.e.
|
||||||
|
|
|
@ -112,6 +112,297 @@ C coding style
|
||||||
groups of statements in the interests of clarity. There should never
|
groups of statements in the interests of clarity. There should never
|
||||||
be two consecutive blank lines.
|
be two consecutive blank lines.
|
||||||
|
|
||||||
|
Modules
|
||||||
|
-------
|
||||||
|
|
||||||
|
Modules are described by a file named `foo.mdd' for a module
|
||||||
|
`foo'. This file is actually a shell script that will sourced when zsh
|
||||||
|
is build. To describe the module it can/should set the following shell
|
||||||
|
variables:
|
||||||
|
|
||||||
|
- moddeps modules on which this module depends (default none)
|
||||||
|
- nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||||
|
- alwayslink if non-empty, always link the module into the executable
|
||||||
|
- autobins builtins defined by the module, for autoloading
|
||||||
|
- objects .o files making up this module (*must* be defined)
|
||||||
|
- proto .pro files for this module (default generated from $objects)
|
||||||
|
- headers extra headers for this module (default none)
|
||||||
|
- hdrdeps extra headers on which the .mdh depends (default none)
|
||||||
|
- otherincs extra headers that are included indirectly (default none)
|
||||||
|
|
||||||
|
Be sure to put the values in quotes. For further enlightenment have a
|
||||||
|
look at the `mkmakemod.sh' script in the Src directory of the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
Modules have to define four functions which will automatically called
|
||||||
|
by the zsh core. The first one, named `setup_foo' for a module named
|
||||||
|
`foo', should set up any data needed in the module, at least any data
|
||||||
|
other modules may be interested in. The second one, named `boot_foo',
|
||||||
|
should register all builtins, conditional codes, and function wrappers
|
||||||
|
(i.e. anything that will be visible to the user) and will be called
|
||||||
|
after the `setup'-function.
|
||||||
|
The third one, named `cleanup_foo' for module `foo' is called when the
|
||||||
|
user tries to unload a module and should de-register the builtins
|
||||||
|
etc. The last function, `finish_foo' is called when the module is
|
||||||
|
actually unloaded and should finalize all the data initialized in the
|
||||||
|
`setup'-function. Since the last two functions are only executed when
|
||||||
|
the module is used as an dynamically loaded module you can surround
|
||||||
|
it with `#ifdef MODULE' and `#endif'.
|
||||||
|
In short, the `cleanup'-function should undo what the `boot'-function
|
||||||
|
did, and the `finish'-function should undo what the `setup'-function
|
||||||
|
did.
|
||||||
|
All of these functions should return zero if they succeeded and
|
||||||
|
non-zero otherwise.
|
||||||
|
|
||||||
|
Builtins are described in a table, for example:
|
||||||
|
|
||||||
|
static struct builtin bintab[] = {
|
||||||
|
BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
Here `BUILTIN(...)' is a macro that simplifies the description. Its
|
||||||
|
arguments are:
|
||||||
|
- the name of the builtin as a string
|
||||||
|
- optional flags (see BINF_* in zsh.h)
|
||||||
|
- the C-function implementing the builtin
|
||||||
|
- the minimum number of arguments the builtin needs
|
||||||
|
- the maximum number of arguments the builtin can handle or -1 if
|
||||||
|
the builtin can get any number of arguments
|
||||||
|
- an integer that is passed to the handler function and can be used
|
||||||
|
to distinguish builtins if the same C-function is used to
|
||||||
|
implement multiple builtins
|
||||||
|
- the options the builtin accepts, given as a string containing the
|
||||||
|
option characters (the above example makes the builtin accept the
|
||||||
|
options `f', `l', `a', `g', and `s')
|
||||||
|
- and finally a optional string containing option characters that
|
||||||
|
will always be reported as set when calling the C-function (this,
|
||||||
|
too, can be used when using one C-function to implement multiple
|
||||||
|
builtins)
|
||||||
|
|
||||||
|
The definition of the handler function looks like:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_example(char *nam, char **args, char *ops, int func)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The special comment /**/ is used by the zsh Makefile to generate the
|
||||||
|
`*.pro' files. The arguments of the function are the number under
|
||||||
|
which this function was invoked (the name of the builtin, but for
|
||||||
|
functions that implement more than one builtin this information is
|
||||||
|
needed). The second argument is the array of arguments *excluding* the
|
||||||
|
options that were defined in the struct and which are handled by the
|
||||||
|
calling code. These options are given as the third argument. It is an
|
||||||
|
array of 256 characters in which the n'th element is non-zero if the
|
||||||
|
option with ASCII-value n was set (i.e. you can easily test if an
|
||||||
|
option was used by `if (ops['f'])' etc.). The last argument is the
|
||||||
|
integer value from the table (the sixth argument to `BUILTIN(...)').
|
||||||
|
The integer return value by the function is the value returned by the
|
||||||
|
builtin in shell level.
|
||||||
|
|
||||||
|
To register builtins in zsh and thereby making them visible to the
|
||||||
|
user the function `addbuiltins()' is used:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_example(Module m)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The arguments are the name of the module (taken from the argument in
|
||||||
|
the example), the table of definitions and the number of entries in
|
||||||
|
this table.
|
||||||
|
The return value is 1 if everything went fine, 2 if at least one
|
||||||
|
builtin couldn't be defined, and 0 if none of the builtin could be
|
||||||
|
defined.
|
||||||
|
|
||||||
|
To de-register builtins use the function `deletebuiltins()':
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
cleanup_example(Module m)
|
||||||
|
{
|
||||||
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The arguments and the return value are the same as for `addbuiltins()'
|
||||||
|
|
||||||
|
The definition of condition codes in modules is equally simple. First
|
||||||
|
we need a table with the descriptions:
|
||||||
|
|
||||||
|
static struct conddef cotab[] = {
|
||||||
|
CONDDEF("len", 0, cond_p_len, 1, 2, 0),
|
||||||
|
CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
Again a macro is used, with the following arguments:
|
||||||
|
|
||||||
|
- the name of the condition code without the leading hyphen
|
||||||
|
(i.e. the example makes the condition codes `-len' and `-ex'
|
||||||
|
usable in `[[...]]' constructs)
|
||||||
|
- an optional flag which for now can only be CONDF_INFIX; if this is
|
||||||
|
given, an infix operator is created (i.e. the above makes
|
||||||
|
`[[ -len str ]]' and `[[ s1 -ex s2 ]]' available)
|
||||||
|
- the C-function implementing the conditional
|
||||||
|
- for non-infix condition codes the next two arguments give the
|
||||||
|
minimum and maximum number of string the conditional can handle
|
||||||
|
(i.e. `-len' can get one or two strings); as with builtins giving
|
||||||
|
-1 as the maximum number means that the conditional accepts any
|
||||||
|
number of strings
|
||||||
|
- finally as the last argument an integer that is passed to the
|
||||||
|
handler function that can be used to distinguish different
|
||||||
|
condition codes if the same C-function implements more than one of
|
||||||
|
them
|
||||||
|
|
||||||
|
The definition for the function looks like:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
cond_p_len(char **a, int id)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The first argument is an array containing the strings (NULL-terminated
|
||||||
|
like the array of arguments for builtins), the second argument is the
|
||||||
|
integer value stored in the table (the last argument to `CONDDEF(...)').
|
||||||
|
The value returned by the function should be non-zero if the condition
|
||||||
|
is true and zero otherwise.
|
||||||
|
|
||||||
|
Note that no preprocessing is done on the strings. This means that
|
||||||
|
no substitutions are performed on them and that they will be
|
||||||
|
tokenized. There are three helper functions available:
|
||||||
|
|
||||||
|
- char *cond_str(args, num)
|
||||||
|
The first argument is the array of strings the handler function
|
||||||
|
got as an argument and the second one is an index into this array.
|
||||||
|
The return value is the num'th string from the array with
|
||||||
|
substitutions performed and untokenized.
|
||||||
|
- long cond_val(args, num)
|
||||||
|
The arguments are the same as for cond_str(). The return value is
|
||||||
|
the result of the mathematical evaluation of the num'th string
|
||||||
|
form the array.
|
||||||
|
- int cond_match(args, num, str)
|
||||||
|
Again, the first two arguments are the same as for the other
|
||||||
|
functions. The third argument is any string. The result of the
|
||||||
|
function is non-zero if the the num'th string from the array taken
|
||||||
|
as a glob pattern matches the given string.
|
||||||
|
|
||||||
|
Registering and de-resgitering condition codes with the shell is
|
||||||
|
almost exactly the same as for builtins, using the functions
|
||||||
|
`addconddefs()' and `deleteconddefs()' instead:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_example(Module m)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
cleanup_example(Module m)
|
||||||
|
{
|
||||||
|
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments and return values are the same as for the functions for
|
||||||
|
builtins.
|
||||||
|
|
||||||
|
Finally, modules can define wrapper functions. These functions are
|
||||||
|
called whenever a shell function is to be executed.
|
||||||
|
|
||||||
|
The definition is simple:
|
||||||
|
|
||||||
|
static struct funcwrap wrapper[] = {
|
||||||
|
WRAPDEF(ex_wrapper),
|
||||||
|
};
|
||||||
|
|
||||||
|
The macro `WRAPDEF(...)' gets the C-function as its only argument.
|
||||||
|
This function should be defined like:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
ex_wrapper(List list, FuncWrap w, char *name)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
runshfunc(list, w, name);
|
||||||
|
...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
The first two arguments should only be used to pass them to
|
||||||
|
`runshfunc()' which will execute the shell function. The last argument
|
||||||
|
is the name of the function to be executed. The arguments passed to
|
||||||
|
the function can be accessed vie the global variable `pparams' (a
|
||||||
|
NULL-terminated array of strings).
|
||||||
|
The return value of the wrapper function should be zero if it calls
|
||||||
|
`runshfunc()' itself and non-zero otherwise. This can be used for
|
||||||
|
wrapper functions that only need to run under certain conditions or
|
||||||
|
that don't need to clean anything up after the shell function has
|
||||||
|
finished:
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
ex_wrapper(List list, FuncWrap w, char *name)
|
||||||
|
{
|
||||||
|
if (wrapper_need_to_run) {
|
||||||
|
...
|
||||||
|
runshfunc(list, w, name);
|
||||||
|
...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inside these wrapper functions the global variable `sfcontext' will be
|
||||||
|
set to a vlue indicating the circumstances under which the shell
|
||||||
|
function was called. It can have any of the following values:
|
||||||
|
|
||||||
|
- SFC_DIRECT: the function was invoked directly by the user
|
||||||
|
- SFC_SIGNAL: the function was invoked as a signal handler
|
||||||
|
- SFC_HOOK: the function was automatically invoked as one of the
|
||||||
|
special functions known by the shell (like `chpwd')
|
||||||
|
- SFC_WIDGET: the function was called from the zsh line editor as a
|
||||||
|
user-defined widget
|
||||||
|
- SFC_COMPLETE: the function was called from the completion code
|
||||||
|
(e.g. with `compctl -K func')
|
||||||
|
|
||||||
|
If a module invokes a shell function (e.g. as a hook function), the
|
||||||
|
value of this variable should only be changed temporarily and restored
|
||||||
|
to its previous value after the shell function has finished.
|
||||||
|
|
||||||
|
There is a problem when the user tries to unload a module that has
|
||||||
|
defined wrappers from a shell function. In this case the module can't
|
||||||
|
be unloaded immediately since the wrapper function is still on the
|
||||||
|
call stack. The zsh code delays unloading modules until all wrappers
|
||||||
|
from them have finished. To hide this from the user, the module's
|
||||||
|
cleanup function is run immediatly so that all builtins, condition
|
||||||
|
codes, and wrapper function defined by the module are
|
||||||
|
de-registered. But if there is some module-global state that has to be
|
||||||
|
finalized (e.g. some memory that has to be freed) and that is used by
|
||||||
|
the wrapper functions finalizing this data in the cleanup function
|
||||||
|
won't work.
|
||||||
|
This is why ther are two functions each for the initialization and
|
||||||
|
finalization of modules. The `boot'- and `cleanup'-functions are run
|
||||||
|
whenever the user calls `zmodload' or `zmodload -u' and should only
|
||||||
|
register or de-register the module's interface that is visible to the
|
||||||
|
user. Anything else should be done in the `setup'- and
|
||||||
|
`finish'-functions. Otherwise modules that other modules depend upon
|
||||||
|
may destroy their state too early and wrapper functions in the latter
|
||||||
|
modules may stop working since the state they use is already destroyed.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -222,3 +222,6 @@
|
||||||
|
|
||||||
/* Define to 1 if you want to use dynamically loaded modules on AIX */
|
/* Define to 1 if you want to use dynamically loaded modules on AIX */
|
||||||
#undef AIXDYNAMIC
|
#undef AIXDYNAMIC
|
||||||
|
|
||||||
|
/* Define to 1 if you want to use dynamically loaded modules on HPUX 10 */
|
||||||
|
#undef HPUXDYNAMIC
|
||||||
|
|
81
aczsh.m4
81
aczsh.m4
|
@ -56,6 +56,18 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5 &&
|
||||||
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
||||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -63,6 +75,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -116,6 +129,18 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5 &&
|
||||||
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
||||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -123,6 +148,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -130,6 +156,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
#define RTLD_GLOBAL 0
|
#define RTLD_GLOBAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
void *handle1, *handle2;
|
void *handle1, *handle2;
|
||||||
|
@ -177,6 +204,18 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5 &&
|
||||||
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
$CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&5 2>&5 &&
|
||||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -184,6 +223,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -234,6 +274,18 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5; then
|
||||||
save_ldflags=$LDFLAGS
|
save_ldflags=$LDFLAGS
|
||||||
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
|
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -241,6 +293,7 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5; then
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -294,6 +347,18 @@ elif
|
||||||
save_ldflags=$LDFLAGS
|
save_ldflags=$LDFLAGS
|
||||||
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS -s"
|
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS -s"
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -301,6 +366,7 @@ elif
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -348,6 +414,18 @@ echo 'int fred () { return 42; }' > conftest1.c
|
||||||
if $CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&5 2>&5 &&
|
if $CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&5 2>&5 &&
|
||||||
$DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS -s conftest1.o $LIBS 1>&5 2>&5; then
|
$DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS -s conftest1.o $LIBS 1>&5 2>&5; then
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -355,6 +433,7 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS -s conftest1.o $LIBS 1>&5 2>&5; t
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -389,7 +468,7 @@ dnl
|
||||||
|
|
||||||
AC_DEFUN(zsh_PATH_UTMP,
|
AC_DEFUN(zsh_PATH_UTMP,
|
||||||
[AC_CACHE_CHECK([for $1 file], [zsh_cv_path_$1],
|
[AC_CACHE_CHECK([for $1 file], [zsh_cv_path_$1],
|
||||||
[for dir in /etc /usr/etc /var/adm /usr/adm /var/run ./conftest; do
|
[for dir in /etc /usr/etc /var/adm /usr/adm /var/run /var/log ./conftest; do
|
||||||
zsh_cv_path_$1=${dir}/$1
|
zsh_cv_path_$1=${dir}/$1
|
||||||
test -f $zsh_cv_path_$1 && break
|
test -f $zsh_cv_path_$1 && break
|
||||||
zsh_cv_path_$1=no
|
zsh_cv_path_$1=no
|
||||||
|
|
37
configure.in
37
configure.in
|
@ -45,6 +45,9 @@ AC_DEFINE_UNQUOTED(OSTYPE, "$host_os")
|
||||||
dnl -----------------------------
|
dnl -----------------------------
|
||||||
dnl CHECKING COMMAND LINE OPTIONS
|
dnl CHECKING COMMAND LINE OPTIONS
|
||||||
dnl -----------------------------
|
dnl -----------------------------
|
||||||
|
dnl Handle --program-prefix, --program-suffix, etc.
|
||||||
|
AC_ARG_PROGRAM
|
||||||
|
|
||||||
dnl Do you want to debug zsh?
|
dnl Do you want to debug zsh?
|
||||||
undefine([zsh-debug])dnl
|
undefine([zsh-debug])dnl
|
||||||
AC_ARG_ENABLE(zsh-debug,
|
AC_ARG_ENABLE(zsh-debug,
|
||||||
|
@ -211,7 +214,7 @@ if test -n "$auto_cflags"; then
|
||||||
fi
|
fi
|
||||||
if test -n "$auto_ldflags"; then
|
if test -n "$auto_ldflags"; then
|
||||||
case "${enable_zsh_debug}$host_os" in
|
case "${enable_zsh_debug}$host_os" in
|
||||||
yesaix*) ;; # AIX ld does not accept -g
|
yesaix*|yeshpux*) ;; # AIX ld does not accept -g
|
||||||
yes*) LDFLAGS=-g ;;
|
yes*) LDFLAGS=-g ;;
|
||||||
*) LDFLAGS=-s ;;
|
*) LDFLAGS=-s ;;
|
||||||
esac
|
esac
|
||||||
|
@ -340,6 +343,7 @@ AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \
|
||||||
utmp.h utmpx.h sys/types.h pwd.h grp.h)
|
utmp.h utmpx.h sys/types.h pwd.h grp.h)
|
||||||
if test $dynamic = yes; then
|
if test $dynamic = yes; then
|
||||||
AC_CHECK_HEADERS(dlfcn.h)
|
AC_CHECK_HEADERS(dlfcn.h)
|
||||||
|
AC_CHECK_HEADERS(dl.h)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Some SCO systems cannot include both sys/time.h and sys/select.h
|
dnl Some SCO systems cannot include both sys/time.h and sys/select.h
|
||||||
|
@ -619,7 +623,8 @@ AC_CHECK_FUNCS(memcpy memmove \
|
||||||
getgrgid getgrnam getpwent getpwnam getpwuid)
|
getgrgid getgrnam getpwent getpwnam getpwuid)
|
||||||
|
|
||||||
if test $dynamic = yes; then
|
if test $dynamic = yes; then
|
||||||
AC_CHECK_FUNCS(dlopen dlerror dlsym dlclose load loadquery loadbind unload)
|
AC_CHECK_FUNCS(dlopen dlerror dlsym dlclose load loadquery loadbind unload \
|
||||||
|
shl_load shl_unload shl_findsym)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -902,6 +907,7 @@ dnl dynamic loading
|
||||||
dnl ---------------
|
dnl ---------------
|
||||||
L=N
|
L=N
|
||||||
aixdynamic=no
|
aixdynamic=no
|
||||||
|
hpuxdynamic=no
|
||||||
if test "$ac_cv_func_dlopen" != yes ||
|
if test "$ac_cv_func_dlopen" != yes ||
|
||||||
test "$ac_cv_func_dlsym" != yes ||
|
test "$ac_cv_func_dlsym" != yes ||
|
||||||
test "$ac_cv_func_dlerror" != yes; then
|
test "$ac_cv_func_dlerror" != yes; then
|
||||||
|
@ -909,7 +915,19 @@ if test "$ac_cv_func_dlopen" != yes ||
|
||||||
test "$ac_cv_func_unload" != yes ||
|
test "$ac_cv_func_unload" != yes ||
|
||||||
test "$ac_cv_func_loadbind" != yes ||
|
test "$ac_cv_func_loadbind" != yes ||
|
||||||
test "$ac_cv_func_loadquery" != yes; then
|
test "$ac_cv_func_loadquery" != yes; then
|
||||||
dynamic=no
|
if test "$ac_cv_func_shl_load" != yes ||
|
||||||
|
test "$ac_cv_func_shl_unload" != yes ||
|
||||||
|
test "$ac_cv_func_shl_findsym" != yes; then
|
||||||
|
dynamic=no
|
||||||
|
elif test "x$dynamic" = xyes; then
|
||||||
|
hpuxdynamic=yes
|
||||||
|
DL_EXT="${DL_EXT=sl}"
|
||||||
|
dnl autoheader won't allow us to define anything which isn't
|
||||||
|
dnl going into a header, and we can't undefine anything, so
|
||||||
|
dnl just define this anyway and rely on the later tests to
|
||||||
|
dnl define DYNAMIC or not.
|
||||||
|
AC_DEFINE(HPUXDYNAMIC)dnl
|
||||||
|
fi
|
||||||
elif test "x$dynamic" = xyes; then
|
elif test "x$dynamic" = xyes; then
|
||||||
aixdynamic=yes
|
aixdynamic=yes
|
||||||
fi
|
fi
|
||||||
|
@ -990,6 +1008,18 @@ EOM
|
||||||
$DLLD -o conftest.$DL_EXT $LDFLAGS $DLLDFLAGS conftest.o 1>&5 2>&5 &&
|
$DLLD -o conftest.$DL_EXT $LDFLAGS $DLLDFLAGS conftest.o 1>&5 2>&5 &&
|
||||||
AC_TRY_RUN([
|
AC_TRY_RUN([
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef HPUXDYNAMIC
|
||||||
|
#include <dl.h>
|
||||||
|
#define RTLD_LAZY BIND_DEFERRED
|
||||||
|
#define RTLD_GLOBAL DYNAMIC_PATH
|
||||||
|
|
||||||
|
char *zsh_gl_sym_addr ;
|
||||||
|
|
||||||
|
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||||
|
#define dlclose(handle) shl_unload((shl_t)(handle))
|
||||||
|
#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
|
||||||
|
#define dlerror() 0
|
||||||
|
#else
|
||||||
#ifdef HAVE_DLFCN_H
|
#ifdef HAVE_DLFCN_H
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#else
|
#else
|
||||||
|
@ -997,6 +1027,7 @@ EOM
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef RTLD_LAZY
|
#ifndef RTLD_LAZY
|
||||||
#define RTLD_LAZY 1
|
#define RTLD_LAZY 1
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -169,3 +169,47 @@ Bart's associative array patches for implentation of subscripting flags,
|
||||||
4763, plus fix 4766; typeset output 4764
|
4763, plus fix 4766; typeset output 4764
|
||||||
|
|
||||||
Sven's completion listing fix, 4767
|
Sven's completion listing fix, 4767
|
||||||
|
|
||||||
|
Fourth edition
|
||||||
|
|
||||||
|
Compilation fix for static linking, 4779
|
||||||
|
|
||||||
|
Phil's patch for wtmp in /var/log on Linux, which someone else sent
|
||||||
|
before... except it needs to be applied to aczsh.m4 and propagated
|
||||||
|
from there, 4783
|
||||||
|
|
||||||
|
Phil's removal of now useless j in glob.c, 4784
|
||||||
|
|
||||||
|
Bart's collection in 4788: put back some missing patches.
|
||||||
|
|
||||||
|
Param's patches from Bart in 4789, 4794, 4795: fix sethparam() and move
|
||||||
|
flags; make sure setsparam() and sethparam() are consistent with
|
||||||
|
existing parameters; allow assoc array assignment with
|
||||||
|
${(AA)=assoc::=key1 value1 key2 value2}
|
||||||
|
|
||||||
|
Return to not hashing PWD from Bart in 4791
|
||||||
|
|
||||||
|
Handle --program-suffix and --program-prefix (but not --target, so I
|
||||||
|
removed the comment) from Bart in 4792
|
||||||
|
|
||||||
|
Compilation with no HAVE_GETPWUID, 4801
|
||||||
|
|
||||||
|
INADDR_NONE in zftp, 4805
|
||||||
|
|
||||||
|
Sven's unloading modules, 4806, 4815, 4820, plus my AIX (and
|
||||||
|
DYNAMIC_NAME_CLASH_OK) fix, 4822, then Sven's 4830
|
||||||
|
|
||||||
|
Parameter's documentation changes by Bart, 4817
|
||||||
|
|
||||||
|
Network order fix for zftp from Sven, 4821
|
||||||
|
|
||||||
|
My patch (with Gene Cohler's suggestions) for dynamical loading under
|
||||||
|
HPUX 10, 4824, plus fixes, 4833, 4843
|
||||||
|
|
||||||
|
Bart's random assoc array fixes, 4826, 4836, plus Sven's 4831
|
||||||
|
|
||||||
|
Sven's ignored character fix, 4828
|
||||||
|
|
||||||
|
More Sven condition patches, 4837, 4842
|
||||||
|
|
||||||
|
Final (???) isident() fix from Sven, 4845
|
||||||
|
|
Loading…
Reference in a new issue