mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-01 09:41:44 +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
|
||||
# `=' signs.
|
||||
|
||||
VERSION=3.1.5-pws-3
|
||||
VERSION_DATE='December 12, 1998'
|
||||
VERSION=3.1.5-pws-4
|
||||
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).
|
||||
|
||||
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
|
||||
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)] ... ])(
|
||||
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
|
||||
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
|
||||
occur in command position.
|
||||
|
||||
|
@ -879,23 +879,50 @@ findex(typeset)
|
|||
cindex(parameters, setting)
|
||||
cindex(parameters, declaring)
|
||||
item(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ var(name)[tt(=)var(value)] ... ])(
|
||||
Set 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
|
||||
exported unless tt(ALL_EXPORT) is set, in which case the parameter will be
|
||||
exported provided no parameter of that name already exists.
|
||||
The following attributes are valid:
|
||||
Set or display attributes and values for shell parameters.
|
||||
|
||||
A parameter is created for each var(name) that does not already refer
|
||||
to one. When inside a function, a new parameter is created for every
|
||||
var(name) (even those that already exist), and is unset again when the
|
||||
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()
|
||||
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))(
|
||||
Left justify and remove leading blanks from var(value).
|
||||
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
|
||||
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.
|
||||
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;
|
||||
otherwise it is determined by the width of the value of the first
|
||||
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.
|
||||
)
|
||||
item(tt(-U))(
|
||||
For arrays keep only the first element of each duplications. It can also be
|
||||
set for colon separated special parameters like tt(PATH) or tt(FIGNORE),
|
||||
etc.
|
||||
For arrays (but not for associative arrays), keep only the first
|
||||
occurrence of each duplicated value. This may also be set for
|
||||
colon-separated special parameters like tt(PATH) or tt(FIGNORE), etc.
|
||||
)
|
||||
item(tt(-Z))(
|
||||
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.
|
||||
)
|
||||
item(tt(-a))(
|
||||
On its own, this option produces a list of all array parameters.
|
||||
If any non-options are provided, the tt(typeset) command is silently ignored.
|
||||
The names refer to array parameters. For historical reasons, scalar
|
||||
parameters are created even when this flag is specified, but the
|
||||
output is restricted to arrays (including associative arrays).
|
||||
)
|
||||
item(tt(-f))(
|
||||
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).
|
||||
)
|
||||
item(tt(-i))(
|
||||
Use an internal integer representation. If var(n) is nonzero
|
||||
it defines the output arithmetic base, otherwise it is determined by the first
|
||||
assignment.
|
||||
Use an internal integer representation. If var(n) is nonzero it
|
||||
defines the output arithmetic base, otherwise it is determined by the
|
||||
first assignment.
|
||||
)
|
||||
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))(
|
||||
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.
|
||||
)
|
||||
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))(
|
||||
Mark for automatic export to the environment of subsequently
|
||||
executed commands.
|
||||
)
|
||||
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)
|
||||
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
|
||||
tt(ENV) environment variable is set on invocation, tt($ENV) is sourced
|
||||
after the profile scripts. The value of tt(ENV) is subjected to
|
||||
parameter expansion, command substitution, and arithmetic expansion before
|
||||
being interpreted as a pathname. Note that the tt(PRIVILEGED) option
|
||||
also affects the execution of startup files.
|
||||
parameter expansion, command substitution, and arithmetic expansion
|
||||
before being interpreted as a pathname. Note that the tt(PRIVILEGED)
|
||||
option also affects the execution of startup files.
|
||||
|
||||
The following options are set if the shell is invoked as tt(sh) or
|
||||
tt(ksh):
|
||||
|
|
|
@ -348,8 +348,9 @@ words are used as prefixes.
|
|||
item(tt(-q))(
|
||||
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
|
||||
or does not insert anything (the same rule as used for the
|
||||
tt(AUTO_REMOVE_SLASH) option). The option is most useful for list
|
||||
or does not insert anything or if the suffix consists of only one character
|
||||
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.).
|
||||
)
|
||||
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
|
||||
|
||||
startlist()
|
||||
list(em(history expansion))
|
||||
list(em(alias expansion))
|
||||
list(em(process substitution))
|
||||
list(em(parameter expansion))
|
||||
list(em(command substitution))
|
||||
list(em(arithmetic expansion))
|
||||
list(em(brace expansion))
|
||||
list(em(filename expansion))
|
||||
list(em(filename generation))
|
||||
list(em(History Expansion))
|
||||
list(em(Alias Expansion))
|
||||
list(em(Process Substitution))
|
||||
list(em(Parameter Expansion))
|
||||
list(em(Command Substitution))
|
||||
list(em(Arithmetic Expansion))
|
||||
list(em(Brace Expansion))
|
||||
list(em(Filename Expansion))
|
||||
list(em(Filename Generation))
|
||||
endlist()
|
||||
|
||||
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
|
||||
for compatibility with bf(sh) and bf(ksh). em(Filename expansion)
|
||||
is performed immediately after em(alias substitution),
|
||||
preceding the set of five substitutions mentioned above.
|
||||
is performed immediately after em(alias expansion),
|
||||
preceding the set of five expansions mentioned above.
|
||||
startmenu()
|
||||
menu(History Expansion)
|
||||
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
|
||||
is controlled by the tt(HISTSIZE)
|
||||
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
|
||||
tt(histchars) parameter which is `tt(!)'
|
||||
by default and may occur anywhere on the command line; history
|
||||
|
@ -175,8 +175,8 @@ Convert the words to all uppercase.
|
|||
)
|
||||
item(tt(f))(
|
||||
(This and the following
|
||||
tt(F), tt(w) and tt(W) modifier only work with parameter and
|
||||
filename expansion.)
|
||||
tt(F), tt(w) and tt(W) modifier only work with parameter expansion and
|
||||
filename generation.)
|
||||
Repeats the immediately (without a colon) following modifier until the
|
||||
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.
|
||||
Unless preceded immediately by a tt(g), with no colon between,
|
||||
the substitution is done only for the
|
||||
first string that matches var(l). For arrays and filename
|
||||
expansion, this applies to each word of the expanded text.
|
||||
first string that matches var(l). For arrays and for filename
|
||||
generation, this applies to each word of the expanded text.
|
||||
)
|
||||
item(tt(&))(
|
||||
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
|
||||
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.
|
||||
)
|
||||
enditem()
|
||||
|
@ -309,25 +309,27 @@ zmanref(zshparam)
|
|||
ifnzman(\
|
||||
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
|
||||
the pattern is the same as that used for filename generation;
|
||||
see noderef(Filename Generation). Note that this pattern, along with
|
||||
the replacement text of a substitution, is itself subject to
|
||||
parameter, command and arithmetic substitution. In addition to the
|
||||
following operations, the file modifiers described in
|
||||
the replacement text of any substitutions, are themselves subject to
|
||||
parameter expansion, command substitution, and arithmetic expansion.
|
||||
In addition to the following operations, the file modifiers described in
|
||||
noderef(Modifiers) in noderef(History Expansion) can be
|
||||
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()
|
||||
item(tt(${)var(name)tt(}))(
|
||||
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
|
||||
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.
|
||||
Otherwise, the expansion results in one word only; no field
|
||||
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
|
||||
missing, substitute var(word).
|
||||
)
|
||||
item(tt(${)var(name)tt(:=)var(word)tt(}))(
|
||||
If var(name) is unset or is null then
|
||||
set it to var(word); the value of the parameter is then
|
||||
substituted.
|
||||
xitem(tt(${)var(name)tt(:=)var(word)tt(}))
|
||||
item(tt(${)var(name)tt(::=)var(word)tt(}))(
|
||||
In the first form, if var(name) is unset or is null then
|
||||
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(}))(
|
||||
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
|
||||
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()
|
||||
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(}))
|
||||
item(tt(${)var(name)tt(##)var(pattern)tt(}))(
|
||||
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
|
||||
form, the smallest matching pattern is preferred;
|
||||
in the second form, the largest matching pattern is
|
||||
preferred. If var(name) is an array and the substitution
|
||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
||||
is used, matching is performed on each array elements separately.
|
||||
preferred.
|
||||
)
|
||||
xitem(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
|
||||
form, the smallest matching pattern is preferred;
|
||||
in the second form, the largest matching pattern is
|
||||
preferred. If var(name) is an array and the substitution
|
||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
||||
is used, matching is performed on each array elements separately.
|
||||
preferred.
|
||||
)
|
||||
item(tt(${)var(name)tt(:#)var(pattern)tt(}))(
|
||||
If the var(pattern) matches the value of var(name), then substitute
|
||||
the empty string; otherwise, just substitute the value of var(name).
|
||||
If var(name) is an array and the substitution
|
||||
is not quoted or the tt((@)) flag or the `var(name)tt([@])' syntax
|
||||
is used, matching is performed on each array elements separately, and
|
||||
the matched array elements are removed (use the tt((M)) flag to
|
||||
If var(name) is an array
|
||||
the matching array elements are removed (use the tt((M)) flag to
|
||||
remove the non-matched elements).
|
||||
)
|
||||
xitem(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
|
||||
variable var(name) with the string var(repl). The first form
|
||||
substitutes just the first occurrence, the second all occurrences.
|
||||
Replace by string var(repl), the longest possible match of
|
||||
var(pattern) in the expansion of parameter var(name). The first form
|
||||
replaces just the first occurrence, the second form all occurrences.
|
||||
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
|
||||
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.
|
||||
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
|
||||
tt(/) occurs inside a substituted paramter. Substitution of an array
|
||||
is as described for tt(#) and tt(%) above.
|
||||
tt(/) occurs inside a substituted parameter.
|
||||
|
||||
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
|
||||
effect of the tt(I) and tt(S) parameter expansion flags below: the
|
||||
flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful, however.
|
||||
effect of the tt(I) and tt(S) parameter expansion flags below; however,
|
||||
the flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful.
|
||||
|
||||
For example,
|
||||
|
||||
nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy"))
|
||||
nofill(tt(print ${foo//${~sub}/$rep}))
|
||||
nofill(tt(print ${(S)foo//${~sub}/$rep}))
|
||||
nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy")
|
||||
tt(print ${foo//${~sub}/$rep})
|
||||
tt(print ${(S)foo//${~sub}/$rep}))
|
||||
|
||||
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
|
||||
|
@ -436,6 +434,8 @@ If var(spec) is one of the above substitutions, substitute
|
|||
the length in characters of the result instead of
|
||||
the result itself. If var(spec) is an array expression,
|
||||
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(}))(
|
||||
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
|
||||
evaluation of var(spec); if the `tt(=)' is doubled, turn it off.
|
||||
vindex(IFS, use of)
|
||||
When this option is set, parameter values are split into
|
||||
separate words using tt(IFS) as a delimiter
|
||||
before substitution.
|
||||
When this option is set, parameter expansions are split into
|
||||
separate words before substitution, using tt(IFS) as a delimiter.
|
||||
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(}))(
|
||||
pindex(GLOB_SUBST)
|
||||
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
|
||||
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.
|
||||
)
|
||||
enditem()
|
||||
|
||||
If a tt(${)...tt(}) type parameter expression or a
|
||||
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
|
||||
possible to perform nested operations: tt(${${foo#head}%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)
|
||||
cindex(parameter expansion flags)
|
||||
cindex(flags, parameter expansion)
|
||||
cindex(expansion, parameter, flags)
|
||||
cindex(substitution, parameter, flags)
|
||||
If the opening brace is directly followed by an opening parenthesis,
|
||||
the string up to the matching closing parenthesis will be taken as a
|
||||
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()
|
||||
item(tt(A))(
|
||||
Create an array parameter with
|
||||
Create an array parameter with 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(@))(
|
||||
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.
|
||||
)
|
||||
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))(
|
||||
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
|
||||
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))(
|
||||
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(:))(
|
||||
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
|
||||
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))(
|
||||
(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
|
||||
from the beginning and with tt(%) start from the end of the string.
|
||||
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
|
||||
may be defined using the tt(-g) option to that builtin.
|
||||
|
||||
Alias substitution is done on the shell input before any
|
||||
other substitution except history substitution. Therefore,
|
||||
if an alias is defined for the word tt(foo), alias substitution
|
||||
Alias expansion is done on the shell input before any
|
||||
other expansion except history expansion. Therefore,
|
||||
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).
|
||||
But there is nothing to prevent an alias being defined
|
||||
for tt(\foo) as well.
|
||||
|
|
|
@ -139,7 +139,7 @@ pindex(BANG_HIST)
|
|||
cindex(history, enable substitution)
|
||||
cindex(enable history substitution)
|
||||
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.
|
||||
)
|
||||
pindex(BARE_GLOB_QUAL)
|
||||
|
@ -263,9 +263,9 @@ in a command have no matches.
|
|||
Overrides tt(NULL_GLOB).
|
||||
)
|
||||
pindex(EQUALS)
|
||||
cindex(filename substitution, =)
|
||||
cindex(filename expansion, =)
|
||||
item(tt(EQUALS))(
|
||||
Perform tt(=) filename substitution.
|
||||
Perform tt(=) filename expansion.
|
||||
(See noderef(Filename Expansion).)
|
||||
)
|
||||
pindex(ERR_EXIT)
|
||||
|
@ -344,7 +344,7 @@ Do not require a leading `tt(.)' in a filename to be matched explicitly.
|
|||
)
|
||||
pindex(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
|
||||
characters resulting from command substitution as being eligible for
|
||||
filename generation.
|
||||
|
@ -412,9 +412,9 @@ being added to the history list.
|
|||
pindex(HIST_VERIFY)
|
||||
cindex(history, verifying substitution)
|
||||
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
|
||||
history substitution and reload the line into the editing buffer.
|
||||
history expansion and reload the line into the editing buffer.
|
||||
)
|
||||
pindex(HUP)
|
||||
cindex(jobs, HUP)
|
||||
|
|
|
@ -7,7 +7,8 @@ A name may be any sequence of alphanumeric
|
|||
characters and underscores, or the single characters
|
||||
`tt(*)', `tt(@)', `tt(#)', `tt(?)', `tt(-)', `tt($)', or `tt(!)'.
|
||||
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,
|
||||
use the tt(typeset) builtin.
|
||||
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))
|
||||
|
||||
If the integer attribute, tt(-i), is set for var(name),
|
||||
the var(value) is subject to arithmetic evaluation.
|
||||
If the integer attribute, tt(-i), is set for var(name), the var(value)
|
||||
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
|
||||
if unset. `<Z>' indicates that the parameter does not exist when the shell
|
||||
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()))
|
||||
|
||||
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
|
||||
subscript. A subscript of the form `tt([)var(exp)tt(])'
|
||||
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.
|
||||
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
|
||||
elements of an array; there is no difference between the two
|
||||
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(])'
|
||||
selects all elements in the range var(exp1) to var(exp2),
|
||||
inclusive.
|
||||
(Associative arrays are unordered, and so do not support ranges.)
|
||||
If one of the subscripts evaluates to a negative number,
|
||||
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
|
||||
|
@ -90,7 +106,9 @@ option is set, the braced form is the only one that will
|
|||
work, the subscript otherwise not being treated specially.
|
||||
|
||||
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
|
||||
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
|
||||
`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.
|
||||
If the parameter is an associative array, only the value part of each pair
|
||||
is compared to the pattern.
|
||||
)
|
||||
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))(
|
||||
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))(
|
||||
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(:))(
|
||||
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
|
||||
var(n)).
|
||||
var(n)). This flag is ignored when the array is associative.
|
||||
)
|
||||
enditem()
|
||||
texinode(Positional Parameters)(Parameters Set By The Shell)(Array Parameters)(Parameters)
|
||||
|
@ -417,7 +441,7 @@ vindex(histchars)
|
|||
item(tt(histchars) <S>)(
|
||||
Three characters used by the shell's history and lexical analysis
|
||||
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
|
||||
character is the comment character (default `tt(#)').
|
||||
)
|
||||
|
@ -442,7 +466,7 @@ vindex(IFS)
|
|||
item(tt(IFS) <S>)(
|
||||
Internal field separators (by default space, tab, newline and NUL), that
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
message that will be printed. The message will undergo
|
||||
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
|
||||
`tt(You have new mail)'. If an element is a directory
|
||||
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
|
||||
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.
|
||||
If the result of substitution on var(word)
|
||||
produces more than one filename,
|
||||
|
@ -57,7 +57,7 @@ exist, even if tt(CLOBBER) is unset.
|
|||
item(tt(<<)[tt(-)] var(word))(
|
||||
The shell input is read up to a line that is the same as
|
||||
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).
|
||||
The resulting document, called a
|
||||
em(here-document), becomes the standard input.
|
||||
|
|
|
@ -45,13 +45,8 @@ while [[ -n "$pref" ]]; do
|
|||
if [[ "$head" = *[\[\(\*\?\$\~]* ]]; then
|
||||
wild=$head
|
||||
else
|
||||
[[ -z "$pref" ]] && globdir=
|
||||
# if path segment contains wildcards, don't add another.
|
||||
if [[ "$head" = *[\[\(\*\?\$\~]* || -z "$head" ]]; then
|
||||
wild=$head
|
||||
else
|
||||
# Simulate case-insensitive globbing for ASCII characters
|
||||
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
||||
wild="[${(j(][))${(s())head:l}}]*" # :gs/a/[a]/ etc.
|
||||
# The following could all be one expansion, but for readability:
|
||||
wild=$wild:gs/a/aA/:gs/b/bB/:gs/c/cC/:gs/d/dD/:gs/e/eE/:gs/f/fF/
|
||||
wild=$wild:gs/g/gG/:gs/h/hH/:gs/i/iI/:gs/j/jJ/:gs/k/kK/:gs/l/lL/
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
# 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.
|
||||
# All the examples in the tcsh manual give sensible results.
|
||||
# Author: Peter Stephenson <pws@ibmth.df.unipi.it>
|
||||
#
|
||||
# Option:
|
||||
# -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 --
|
||||
# they need to be lumped into one "compctl -C" or "compctl -D"
|
||||
# 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
|
||||
if (@ARGV) {
|
||||
|
@ -113,6 +119,13 @@ sub gettype {
|
|||
# Nothing (n) can be handled by returning nothing. (C.f. King Lear, I.i.)
|
||||
if ($c =~ /[abcjuv]/) {
|
||||
$ret = "-$c";
|
||||
} elsif ($c eq 'C') {
|
||||
if (defined($glob)) {
|
||||
$ret = "-W $glob -/g '*(.*)'";
|
||||
undef($glob);
|
||||
} else {
|
||||
$ret = '-c';
|
||||
}
|
||||
} elsif ($c eq 'S') {
|
||||
$ret = '-k signals';
|
||||
} elsif ($c eq 'd') {
|
||||
|
@ -121,18 +134,42 @@ sub gettype {
|
|||
} else {
|
||||
$ret = '-/';
|
||||
}
|
||||
} elsif ($c eq 'D') {
|
||||
if (defined($glob)) {
|
||||
$ret = "-W $glob -/";
|
||||
undef($glob);
|
||||
} else {
|
||||
$ret = '-/';
|
||||
}
|
||||
} elsif ($c eq 'e') {
|
||||
$ret = '-E';
|
||||
} elsif ($c eq 'f' && !$glob) {
|
||||
$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') {
|
||||
$ret = q!-k "(`limit | awk '{print $1}'`)"!;
|
||||
} 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') {
|
||||
$ret = '-p';
|
||||
$ret = '-p';
|
||||
} elsif ($c eq 't') {
|
||||
$qual = '.';
|
||||
} elsif ($c eq 'T') {
|
||||
if (defined($glob)) {
|
||||
$ret = "-W $glob -g '*(.)'";
|
||||
undef($glob);
|
||||
} else {
|
||||
$ret = "-g '*(.)'";
|
||||
}
|
||||
} elsif ($c eq 'x') {
|
||||
$glob =~ s/'/'\\''/g;
|
||||
$ret = "-X '$glob'";
|
||||
|
@ -190,7 +227,7 @@ $" = " - ";
|
|||
|
||||
while (<>) {
|
||||
if (/^\s*complete\s/) {
|
||||
undef(@stuff);
|
||||
undef(@stuff);
|
||||
$default = '';
|
||||
$_ = $';
|
||||
while (/\\$/) {
|
||||
|
@ -211,7 +248,7 @@ while (<>) {
|
|||
# Loop over remaining arguments to "complete".
|
||||
$sep = substr($word,1,1);
|
||||
$sep =~ s/(\W)/\\$1/g;
|
||||
@split = split(/$sep/,$word);
|
||||
@split = split(/$sep/,$word,4);
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
while ($split[$i] =~ /\\$/) {
|
||||
substr($split[$i],-1,1) = "";
|
||||
|
@ -225,7 +262,9 @@ while (<>) {
|
|||
# The "complete" catch-all: treat this as compctl\'s
|
||||
# default (requiring no pattern matching).
|
||||
$default .= &gettype($type) . ' ';
|
||||
defined($suffix) && ($defsuf .= $suffix);
|
||||
defined($suffix) &&
|
||||
(defined($defsuf) ? ($defsuf .= $suffix)
|
||||
: ($defsuf = $suffix));
|
||||
} else {
|
||||
$pat = &getpat($pat,$arg);
|
||||
$type = &gettype($type);
|
||||
|
|
|
@ -574,6 +574,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("unlimit", 0, bin_unlimit, 0, -1, 0, "hs", NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_rlimits(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_rlimits(Module m)
|
||||
|
@ -590,4 +597,12 @@ cleanup_rlimits(Module m)
|
|||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_rlimits(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -183,6 +183,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("sched", 0, bin_sched, 0, -1, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_sched(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_sched(Module m)
|
||||
|
@ -211,4 +218,11 @@ cleanup_sched(Module m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_sched(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -122,6 +122,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("setcap", 0, bin_setcap, 2, -1, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_cap(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_cap(Module m)
|
||||
|
@ -138,4 +145,12 @@ cleanup_cap(Module m)
|
|||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_cap(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -96,6 +96,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("clone", 0, bin_clone, 1, 1, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_clone(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_clone(Module m)
|
||||
|
@ -112,4 +119,12 @@ cleanup_clone(Module m)
|
|||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_clone(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,16 +51,14 @@ bin_example(char *nam, char **args, char *ops, int func)
|
|||
|
||||
/**/
|
||||
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);
|
||||
untokenize(s1);
|
||||
if (s2) {
|
||||
singsub(&s2);
|
||||
untokenize(s2);
|
||||
return strlen(s1) == matheval(s2);
|
||||
if (a[1]) {
|
||||
long v = cond_val(a, 1);
|
||||
|
||||
return strlen(s1) == v;
|
||||
} else {
|
||||
return !s1[0];
|
||||
}
|
||||
|
@ -68,14 +66,10 @@ cond_p_len(Conddef c, char **a)
|
|||
|
||||
/**/
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -105,14 +99,23 @@ static struct builtin bintab[] = {
|
|||
};
|
||||
|
||||
static struct conddef cotab[] = {
|
||||
CONDDEF("len", 0, 1, 2, cond_p_len),
|
||||
CONDDEF("ex", CONDF_INFIX, 0, 0, cond_i_ex),
|
||||
CONDDEF("len", 0, cond_p_len, 1, 2, 0),
|
||||
CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
|
||||
};
|
||||
|
||||
static struct funcwrap wrapper[] = {
|
||||
WRAPDEF(ex_wrapper),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_example(Module m)
|
||||
{
|
||||
printf("The example module has now been set up.\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_example(Module m)
|
||||
|
@ -133,4 +136,14 @@ cleanup_example(Module m)
|
|||
deletewrapper(m, wrapper);
|
||||
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
|
||||
|
|
|
@ -509,6 +509,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("sync", 0, bin_sync, 0, 0, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_files(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_files(Module m)
|
||||
|
@ -525,4 +532,12 @@ cleanup_files(Module m)
|
|||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_files(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -569,6 +569,13 @@ static struct builtin bintab[] = {
|
|||
BUILTIN("stat", 0, bin_stat, 0, -1, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_stat(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_stat(Module m)
|
||||
|
@ -586,4 +593,11 @@ cleanup_stat(Module m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_stat(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,9 +62,9 @@
|
|||
/* it's a TELNET based protocol, but don't think I like doing this */
|
||||
#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
|
||||
#define INADDR_NONE (in_addr_t)-1
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#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
|
||||
* command to tell us how many bytes are coming.
|
||||
*/
|
||||
int osc = sfcontext;
|
||||
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
/* Now add in the bit of the file we've got/sent already */
|
||||
sofar = last_sofar = startat;
|
||||
}
|
||||
|
@ -1482,8 +1486,12 @@ zfsenddata(char *name, int recv, int progress, long startat)
|
|||
break;
|
||||
if (!ret && sofar != last_sofar && progress &&
|
||||
(l = getshfunc("zftp_progress")) != &dummy_list) {
|
||||
int osc = sfcontext;
|
||||
|
||||
zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
last_sofar = sofar;
|
||||
}
|
||||
}
|
||||
|
@ -1650,7 +1658,7 @@ zftp_open(char *name, char **args, int flags)
|
|||
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));
|
||||
if (zcfd < 0) {
|
||||
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,
|
||||
* we at least cover the bases.
|
||||
*/
|
||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list)
|
||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
|
||||
int osc = sfcontext;
|
||||
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2303,9 +2315,13 @@ zftp_getput(char *name, char **args, int flags)
|
|||
zsfree(ln);
|
||||
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
|
||||
/* progress to finish: ZFTP_TRANSFER set to GF or PF */
|
||||
int osc = sfcontext;
|
||||
|
||||
zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
|
||||
ZFPM_READONLY);
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("zftp_progress", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
}
|
||||
if (rest) {
|
||||
zsfree(rest);
|
||||
|
@ -2428,9 +2444,13 @@ zftp_close(char *name, char **args, int flags)
|
|||
zfunsetparam(*aptr);
|
||||
|
||||
/* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */
|
||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list)
|
||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
|
||||
int osc = sfcontext;
|
||||
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("zftp_chpwd", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
}
|
||||
/* tidy up status variables, because mess is bad */
|
||||
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 */
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_zftp(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_zftp(Module m)
|
||||
|
@ -2593,4 +2620,11 @@ cleanup_zftp(Module m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_zftp(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -98,7 +98,7 @@ struct compcond {
|
|||
struct compctl {
|
||||
int refc; /* reference count */
|
||||
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 *glob; /* for -g (globbing) */
|
||||
char *str; /* for -s (expansion) */
|
||||
|
@ -110,7 +110,7 @@ struct compctl {
|
|||
char *withd; /* for -w (with directory */
|
||||
char *hpat; /* for -H (history pattern) */
|
||||
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) */
|
||||
Compcond cond; /* for -x (condition for this compctl) */
|
||||
Compctl xor; /* for + (next of the xor'ed compctls) */
|
||||
|
@ -169,7 +169,6 @@ struct cexpl {
|
|||
char *str; /* the string */
|
||||
int count; /* the number of matches */
|
||||
int fcount; /* number of matches with fignore ignored */
|
||||
|
||||
};
|
||||
|
||||
/* This describes a group of matches. */
|
||||
|
|
|
@ -430,7 +430,7 @@ quotename(const char *s, char **e, char *te, int *pl)
|
|||
|
||||
/**/
|
||||
int
|
||||
boot_comp1(Module m)
|
||||
setup_comp1(Module m)
|
||||
{
|
||||
compctlreadptr = compctlread;
|
||||
clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *));
|
||||
|
@ -446,11 +446,25 @@ boot_comp1(Module m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_comp1(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
/**/
|
||||
int
|
||||
cleanup_comp1(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_comp1(Module m)
|
||||
{
|
||||
deletehashtable(compctltab);
|
||||
zfree(clwords, clwsize * sizeof(char *));
|
||||
|
|
|
@ -1636,15 +1636,22 @@ static struct builtin bintab[] = {
|
|||
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
|
||||
boot_compctl(Module m)
|
||||
{
|
||||
if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)))
|
||||
return 1;
|
||||
compctltab->printnode = printcompctlp;
|
||||
printcompctlptr = printcompctl;
|
||||
compctl_widgetptr = compctl_widget;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1654,10 +1661,18 @@ boot_compctl(Module m)
|
|||
int
|
||||
cleanup_compctl(Module m)
|
||||
{
|
||||
compctltab->printnode = NULL;
|
||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_compctl(Module m)
|
||||
{
|
||||
compctltab->printnode = NULL;
|
||||
printcompctlptr = NULL;
|
||||
compctl_widgetptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -71,6 +71,13 @@ deltochar(void)
|
|||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_deltochar(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_deltochar(Module m)
|
||||
|
@ -93,4 +100,12 @@ cleanup_deltochar(Module m)
|
|||
deletezlefunction(w_deletetochar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_deltochar(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -603,11 +603,15 @@ execzlefunc(Thingy func)
|
|||
zsfree(msg);
|
||||
feep();
|
||||
} else {
|
||||
startparamscope();
|
||||
makezleparams();
|
||||
doshfunc(w->u.fnnam, l, NULL, 0, 1);
|
||||
endparamscope();
|
||||
lastcmd = 0;
|
||||
int osc = sfcontext;
|
||||
|
||||
startparamscope();
|
||||
makezleparams();
|
||||
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
|
||||
boot_zle(Module m)
|
||||
setup_zle(Module m)
|
||||
{
|
||||
/* Set up editor entry points */
|
||||
trashzleptr = trashzle;
|
||||
|
@ -875,6 +879,13 @@ boot_zle(Module m)
|
|||
/* initialise the keymap system */
|
||||
init_keymaps();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_zle(Module m)
|
||||
{
|
||||
addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
@ -885,15 +896,21 @@ boot_zle(Module m)
|
|||
int
|
||||
cleanup_zle(Module m)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(zleactive) {
|
||||
zerrnam(m->nam, "can't unload the zle module while zle is active",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_zle(Module m)
|
||||
{
|
||||
int i;
|
||||
|
||||
cleanup_keymaps();
|
||||
deletehashtable(thingytab);
|
||||
|
||||
|
|
|
@ -3801,15 +3801,23 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
|
||||
/* Completion after `~', maketildelist adds the usernames *
|
||||
* and named directories. */
|
||||
if (ic == Tilde)
|
||||
if (ic == Tilde) {
|
||||
char *oi = ipre;
|
||||
|
||||
ipre = (ipre ? dyncat("~", ipre) : "~");
|
||||
maketildelist();
|
||||
else if (ic == Equals) {
|
||||
ipre = oi;
|
||||
} else if (ic == Equals) {
|
||||
/* Completion after `=', get the command names from *
|
||||
* the cmdnamtab and aliases from aliastab. */
|
||||
char *oi = ipre;
|
||||
|
||||
ipre = (ipre ? dyncat("=", ipre) : "=");
|
||||
if (isset(HASHLISTALL))
|
||||
cmdnamtab->filltable(cmdnamtab);
|
||||
dumphashtable(cmdnamtab, -7);
|
||||
dumphashtable(aliastab, -2);
|
||||
ipre = oi;
|
||||
} else {
|
||||
/* Normal file completion... */
|
||||
if (ispattern & 1) {
|
||||
|
@ -4082,6 +4090,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
if ((list = getshfunc(cc->func)) != &dummy_list) {
|
||||
/* We have it, so build a argument list. */
|
||||
LinkList args = newlinklist();
|
||||
int osc = sfcontext;
|
||||
|
||||
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. */
|
||||
incompctlfunc = 1;
|
||||
sfcontext = SFC_COMPLETE;
|
||||
/* Call the function. */
|
||||
doshfunc(cc->func, list, args, 0, 1);
|
||||
sfcontext = osc;
|
||||
incompctlfunc = 0;
|
||||
/* And get the result from the reply parameter. */
|
||||
if ((r = get_user_var("reply")))
|
||||
|
@ -4246,6 +4257,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
LinkList args = newlinklist();
|
||||
LinkNode ln;
|
||||
Cmatch m;
|
||||
int osc = sfcontext;
|
||||
|
||||
addlinknode(args, cc->ylist);
|
||||
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 */
|
||||
incompctlfunc = 1;
|
||||
sfcontext = SFC_COMPLETE;
|
||||
doshfunc(cc->ylist, list, args, 0, 1);
|
||||
sfcontext = osc;
|
||||
incompctlfunc = 0;
|
||||
uv = "reply";
|
||||
}
|
||||
|
|
|
@ -992,9 +992,13 @@ cd_new_pwd(int func, LinkNode dir, int chaselinks)
|
|||
|
||||
/* execute the chpwd function */
|
||||
if ((l = getshfunc("chpwd")) != &dummy_list) {
|
||||
int osc = sfcontext;
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("chpwd", l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
}
|
||||
|
||||
dirstacksize = getiparam("DIRSTACKSIZE");
|
||||
|
@ -1469,7 +1473,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
Param pm;
|
||||
Asgment asg;
|
||||
Comp com;
|
||||
char *optstr = "aiLRZlurtxU----A";
|
||||
char *optstr = "aiALRZlurtxU";
|
||||
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
||||
int initon, initoff, of, i;
|
||||
int returnval = 0, printflags = 0;
|
||||
|
|
58
Src/cond.c
58
Src/cond.c
|
@ -48,7 +48,8 @@ evalcond(Cond c)
|
|||
{
|
||||
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) {
|
||||
int l = arrlen((char **) c->right);
|
||||
|
||||
|
@ -57,10 +58,24 @@ evalcond(Cond c)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -244,3 +259,38 @@ optison(char *s)
|
|||
else
|
||||
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;
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
/**/
|
||||
|
@ -2771,19 +2776,14 @@ runshfunc(List list, FuncWrap wrap, char *name)
|
|||
char *ou;
|
||||
|
||||
while (wrap) {
|
||||
wrap->module->flags |= MOD_WRAPPER;
|
||||
wrap->count++;
|
||||
wrap->module->wrapper++;
|
||||
cont = wrap->handler(list, wrap->next, name);
|
||||
wrap->count--;
|
||||
if (!wrap->count) {
|
||||
wrap->module->flags &= ~MOD_WRAPPER;
|
||||
wrap->module->wrapper--;
|
||||
#ifdef DYNAMIC
|
||||
if (wrap->module->flags & MOD_UNLOAD) {
|
||||
wrap->module->flags &= ~MOD_UNLOAD;
|
||||
unload_module(wrap->module, NULL);
|
||||
}
|
||||
if (!wrap->module->wrapper &&
|
||||
(wrap->module->flags & MOD_UNLOAD))
|
||||
unload_module(wrap->module, NULL);
|
||||
#endif
|
||||
}
|
||||
if (!cont)
|
||||
return;
|
||||
wrap = wrap->next;
|
||||
|
|
|
@ -1947,7 +1947,7 @@ getmatch(char **sp, char *pat, int fl, int n, char *replstr)
|
|||
{
|
||||
Comp c;
|
||||
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 */
|
||||
repllist = NULL;
|
||||
|
|
|
@ -111,13 +111,17 @@ loop(int toplevel, int justonce)
|
|||
if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) {
|
||||
Histent he = gethistent(curhist);
|
||||
LinkList args;
|
||||
int osc = sfcontext;
|
||||
|
||||
PERMALLOC {
|
||||
args = newlinklist();
|
||||
addlinknode(args, "preexec");
|
||||
if (he && he->text)
|
||||
addlinknode(args, he->text);
|
||||
} LASTALLOC;
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("preexec", prelist, args, 0, 1);
|
||||
sfcontext = osc;
|
||||
freelinklist(args, (FreeFunc) NULL);
|
||||
errflag = 0;
|
||||
}
|
||||
|
@ -613,6 +617,7 @@ setupvals(void)
|
|||
breaks = loops = 0;
|
||||
lastmailcheck = time(NULL);
|
||||
locallevel = sourcelevel = 0;
|
||||
sfcontext = SFC_DIRECT;
|
||||
trapreturn = 0;
|
||||
noerrexit = -1;
|
||||
nohistsave = 1;
|
||||
|
|
|
@ -104,7 +104,7 @@ BEGIN {
|
|||
gsub(/@!/, ",", dcltor)
|
||||
|
||||
# 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
|
||||
sub(/_.*$/, "", modtype)
|
||||
output = output "# if defined(DYNAMIC_NAME_CLASH_OK) && defined(MODULE)\n"
|
||||
|
|
|
@ -55,6 +55,6 @@ for bin_mod in $bin_mods; do
|
|||
exit 1 ;;
|
||||
esac
|
||||
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
|
||||
|
|
|
@ -1,15 +1,35 @@
|
|||
#include "zsh.mdh"
|
||||
|
||||
int setup_ _((Module));
|
||||
int boot_ _((Module));
|
||||
int cleanup_ _((Module));
|
||||
int finish_ _((Module));
|
||||
int modentry _((int boot, Module m));
|
||||
|
||||
/**/
|
||||
int
|
||||
modentry(int boot, Module m)
|
||||
{
|
||||
if (boot)
|
||||
switch (boot) {
|
||||
case 0:
|
||||
return setup_(m);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return boot_(m);
|
||||
else
|
||||
break;
|
||||
|
||||
case 2:
|
||||
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 *
|
||||
* for the boot function to do. */
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_zsh(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_zsh(Module m)
|
||||
|
@ -114,7 +121,6 @@ addwrapper(Module m, FuncWrap w)
|
|||
w->next = NULL;
|
||||
w->flags |= WRAPF_ADDED;
|
||||
w->module = m;
|
||||
w->count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -256,24 +262,58 @@ load_and_bind(const char *fn)
|
|||
#ifdef HAVE_DLFCN_H
|
||||
# include <dlfcn.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <nlist.h>
|
||||
# include <link.h>
|
||||
# ifdef HAVE_DL_H
|
||||
# include <dl.h>
|
||||
# define RTLD_LAZY BIND_DEFERRED
|
||||
# define RTLD_GLOBAL DYNAMIC_PATH
|
||||
# else
|
||||
# include <sys/types.h>
|
||||
# include <nlist.h>
|
||||
# include <link.h>
|
||||
# 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
|
||||
|
||||
#ifdef DLSYM_NEEDS_UNDERSCORE
|
||||
# define STR_SETUP "_setup_"
|
||||
# define STR_SETUP_S "_setup_%s"
|
||||
# define STR_BOOT "_boot_"
|
||||
# define STR_BOOT_S "_boot_%s"
|
||||
# define STR_CLEANUP "_cleanup_"
|
||||
# define STR_CLEANUP_S "_cleanup_%s"
|
||||
# define STR_FINISH "_finish_"
|
||||
# define STR_FINISH_S "_finish_%s"
|
||||
#else /* !DLSYM_NEEDS_UNDERSCORE */
|
||||
# define STR_SETUP "setup_"
|
||||
# define STR_SETUP_S "setup_%s"
|
||||
# define STR_BOOT "boot_"
|
||||
# define STR_BOOT_S "boot_%s"
|
||||
# define STR_CLEANUP "cleanup_"
|
||||
# define STR_CLEANUP_S "cleanup_%s"
|
||||
# define STR_FINISH "finish_"
|
||||
# define STR_FINISH_S "finish_%s"
|
||||
#endif /* !DLSYM_NEEDS_UNDERSCORE */
|
||||
|
||||
#endif /* !AIXDYNAMIC */
|
||||
|
@ -355,6 +395,13 @@ find_module(const char *name)
|
|||
|
||||
#ifdef AIXDYNAMIC
|
||||
|
||||
/**/
|
||||
static int
|
||||
setup_module(Module m)
|
||||
{
|
||||
return ((int (*)_((int,Module))) m->handle)(0, m);
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
init_module(Module m)
|
||||
|
@ -366,14 +413,20 @@ init_module(Module m)
|
|||
static int
|
||||
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
|
||||
|
||||
/**/
|
||||
static int
|
||||
init_module(Module m)
|
||||
static Module_func
|
||||
module_func(Module m, char *name, char *name_s)
|
||||
{
|
||||
char *s, *t;
|
||||
#ifndef DYNAMIC_NAME_CLASH_OK
|
||||
|
@ -389,13 +442,34 @@ init_module(Module m)
|
|||
if ((t = strrchr(s, '.')))
|
||||
*t = '\0';
|
||||
#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 */
|
||||
if (strlen(s) + 6 > PATH_MAX)
|
||||
return 1;
|
||||
sprintf(buf, STR_BOOT_S, s);
|
||||
return NULL;
|
||||
sprintf(buf, name_s, s);
|
||||
fn = (Module_func) dlsym(m->handle, buf);
|
||||
#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)
|
||||
return fn(m);
|
||||
zwarnnam(m->nam, "no boot function", NULL, 0);
|
||||
|
@ -406,33 +480,34 @@ init_module(Module m)
|
|||
static int
|
||||
cleanup_module(Module m)
|
||||
{
|
||||
char *s, *t;
|
||||
#ifndef DYNAMIC_NAME_CLASH_OK
|
||||
char buf[PATH_MAX + 1];
|
||||
#endif
|
||||
Module_func fn;
|
||||
Module_func fn = module_func(m, STR_CLEANUP, STR_CLEANUP_S);
|
||||
|
||||
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)
|
||||
return fn(m);
|
||||
zwarnnam(m->nam, "no cleanup function", NULL, 0);
|
||||
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 */
|
||||
|
||||
/**/
|
||||
|
@ -449,8 +524,8 @@ load_module(char const *name)
|
|||
m = zcalloc(sizeof(*m));
|
||||
m->nam = ztrdup(name);
|
||||
m->handle = handle;
|
||||
if (init_module(m)) {
|
||||
dlclose(handle);
|
||||
if (setup_module(m) || init_module(m)) {
|
||||
finish_module(m);
|
||||
zsfree(m->nam);
|
||||
zfree(m, sizeof(*m));
|
||||
return NULL;
|
||||
|
@ -459,25 +534,35 @@ load_module(char const *name)
|
|||
addlinknode(modules, m);
|
||||
} LASTALLOC;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
m = (Module) getdata(node);
|
||||
if (m->handle)
|
||||
if (m->flags & MOD_UNLOAD)
|
||||
m->flags &= ~MOD_UNLOAD;
|
||||
else if (m->handle)
|
||||
return m;
|
||||
if (m->flags & MOD_BUSY) {
|
||||
zerr("circular dependencies for module %s", name, 0);
|
||||
return NULL;
|
||||
}
|
||||
m->flags |= MOD_BUSY;
|
||||
for (n = firstnode(m->deps); n; incnode(n))
|
||||
if (!load_module((char *) getdata(n))) {
|
||||
m->flags &= ~MOD_BUSY;
|
||||
if (m->deps)
|
||||
for (n = firstnode(m->deps); n; incnode(n))
|
||||
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;
|
||||
}
|
||||
m->flags &= ~MOD_BUSY;
|
||||
if (!(m->handle = do_load_module(name)))
|
||||
return NULL;
|
||||
}
|
||||
if (init_module(m)) {
|
||||
dlclose(m->handle);
|
||||
finish_module(m->handle);
|
||||
m->handle = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -756,12 +841,53 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
|
|||
int
|
||||
unload_module(Module m, LinkNode node)
|
||||
{
|
||||
if (m->handle && cleanup_module(m))
|
||||
if (m->handle && !(m->flags & MOD_UNLOAD) && cleanup_module(m))
|
||||
return 1;
|
||||
else {
|
||||
int del = (m->flags & MOD_UNLOAD);
|
||||
|
||||
if (m->wrapper) {
|
||||
m->flags |= MOD_UNLOAD;
|
||||
return 0;
|
||||
}
|
||||
m->flags &= ~MOD_UNLOAD;
|
||||
if (m->handle)
|
||||
dlclose(m->handle);
|
||||
finish_module(m);
|
||||
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 (!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);
|
||||
if (node) {
|
||||
LinkNode mn, dn;
|
||||
int del = 0;
|
||||
|
||||
for (mn = firstnode(modules); mn; incnode(mn)) {
|
||||
m = (Module) getdata(mn);
|
||||
if (m->deps && m->handle)
|
||||
for (dn = firstnode(m->deps); dn; incnode(dn))
|
||||
if (!strcmp((char *) getdata(dn), *args)) {
|
||||
zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0);
|
||||
ret = 1;
|
||||
goto cont;
|
||||
if (m->flags & MOD_UNLOAD)
|
||||
del = 1;
|
||||
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);
|
||||
if (!(m->flags & MOD_WRAPPER)) {
|
||||
if (unload_module(m, node))
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
m->flags |= MOD_UNLOAD;
|
||||
if (del)
|
||||
m->wrapper++;
|
||||
if (unload_module(m, node))
|
||||
ret = 1;
|
||||
if (del)
|
||||
m->wrapper--;
|
||||
} else if (!ops['i']) {
|
||||
zwarnnam(nam, "no such module %s", *args, 0);
|
||||
ret = 1;
|
||||
|
@ -820,7 +951,7 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
|||
/* list modules */
|
||||
for (node = firstnode(modules); node; incnode(node)) {
|
||||
m = (Module) getdata(node);
|
||||
if (m->handle) {
|
||||
if (m->handle && !(m->flags & MOD_UNLOAD)) {
|
||||
if(ops['L']) {
|
||||
printf("zmodload ");
|
||||
if(m->nam[0] == '-')
|
||||
|
@ -835,8 +966,11 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
|||
} else {
|
||||
/* load modules */
|
||||
for (; *args; args++) {
|
||||
Module m;
|
||||
|
||||
node = find_module(*args);
|
||||
if (node && ((Module) getdata(node))->handle) {
|
||||
if (node && (m = ((Module) getdata(node)))->handle &&
|
||||
!(m->flags & MOD_UNLOAD)) {
|
||||
if (!ops['i']) {
|
||||
zwarnnam(nam, "module %s already loaded.", *args, 0);
|
||||
ret = 1;
|
||||
|
@ -894,8 +1028,6 @@ getconddef(int inf, char *name, int autol)
|
|||
return p;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC
|
||||
|
||||
/* 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 *
|
||||
* autoloaded condition, it is removed. */
|
||||
|
@ -909,10 +1041,11 @@ addconddef(Conddef c)
|
|||
if (p) {
|
||||
if (!p->module || (p->flags & CONDF_ADDED))
|
||||
return 1;
|
||||
|
||||
#ifdef DYNAMIC
|
||||
/* There is an autoload definition. */
|
||||
|
||||
deleteconddef(p);
|
||||
#endif
|
||||
}
|
||||
c->next = condtab;
|
||||
condtab = c;
|
||||
|
@ -942,6 +1075,8 @@ addconddefs(char const *nam, Conddef c, int size)
|
|||
return hadf ? hads : 1;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif /* DYNAMIC */
|
||||
#endif
|
||||
|
|
78
Src/params.c
78
Src/params.c
|
@ -301,14 +301,6 @@ copyparamtable(HashTable ht, char *name)
|
|||
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;
|
||||
|
||||
/**/
|
||||
|
@ -641,6 +633,7 @@ isident(char *s)
|
|||
if (!iident(*ss))
|
||||
break;
|
||||
|
||||
#if 0
|
||||
/* If this exhaust `s' or the next two characters *
|
||||
* are [(, then it is a valid identifier. */
|
||||
if (!*ss || (*ss == '[' && ss[1] == '('))
|
||||
|
@ -650,6 +643,7 @@ isident(char *s)
|
|||
* definitely not a valid identifier. */
|
||||
if (*ss != '[')
|
||||
return 0;
|
||||
|
||||
noeval = 1;
|
||||
(void)mathevalarg(++ss, &ss);
|
||||
if (*ss == ',')
|
||||
|
@ -658,6 +652,19 @@ isident(char *s)
|
|||
if (*ss != ']' || ss[1])
|
||||
return 0;
|
||||
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;
|
||||
|
@ -755,6 +762,8 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
if (ind) {
|
||||
v->isarr |= SCANPM_WANTKEYS;
|
||||
v->isarr &= ~SCANPM_WANTVALS;
|
||||
} else if (rev) {
|
||||
v->isarr |= SCANPM_WANTVALS;
|
||||
}
|
||||
if (!down)
|
||||
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);
|
||||
paramtab = tht;
|
||||
}
|
||||
v->isarr = 0;
|
||||
v->isarr = (*inv ? SCANPM_WANTINDEX : 0);
|
||||
v->a = 0;
|
||||
*inv = 0; /* We've already obtained the "index" (key) */
|
||||
*w = v->b = -1;
|
||||
r = isset(KSHARRAYS) ? 1 : 0;
|
||||
} else
|
||||
|
@ -979,9 +989,11 @@ getindex(char **pptr, Value v)
|
|||
}
|
||||
if (a > 0 && (isset(KSHARRAYS) || (v->pm->flags & PM_HASHED)))
|
||||
a--;
|
||||
v->inv = 1;
|
||||
v->isarr = 0;
|
||||
v->a = v->b = a;
|
||||
if (v->isarr != SCANPM_WANTINDEX) {
|
||||
v->inv = 1;
|
||||
v->isarr = 0;
|
||||
v->a = v->b = a;
|
||||
}
|
||||
if (*s == ',') {
|
||||
zerr("invalid subscript", NULL, 0);
|
||||
while (*s != ']' && *s != Outbrack)
|
||||
|
@ -1546,35 +1558,37 @@ setaparam(char *s, char **val)
|
|||
|
||||
/**/
|
||||
Param
|
||||
sethparam(char *s, char **kvarr)
|
||||
sethparam(char *s, char **val)
|
||||
{
|
||||
Value v;
|
||||
Param pm;
|
||||
char *t;
|
||||
char *t = s;
|
||||
|
||||
if (!isident(s)) {
|
||||
zerr("not an identifier: %s", s, 0);
|
||||
freearray(kvarr);
|
||||
freearray(val);
|
||||
errflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
t=ztrdup(s); /* Is this a memory leak? */
|
||||
/* Why does getvalue(s, 1) set s to empty string? */
|
||||
if ((v = getvalue(&t, 1)))
|
||||
if (v->pm->flags & PM_SPECIAL) {
|
||||
zerr("not overriding a special: %s", s, 0);
|
||||
freearray(kvarr);
|
||||
errflag = 1;
|
||||
if (strchr(s, '[')) {
|
||||
freearray(val);
|
||||
zerr("attempt to set slice of associative array", NULL, 0);
|
||||
errflag = 1;
|
||||
return NULL;
|
||||
} else {
|
||||
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;
|
||||
} else
|
||||
unsetparam(s);
|
||||
|
||||
pm = createparam(s, PM_HASHED);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
|
||||
arrhashsetfn(pm, kvarr);
|
||||
|
||||
return pm;
|
||||
setarrvalue(v, val);
|
||||
return v->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->type = COND_MOD;
|
||||
n->left = (void *) (a + 1);
|
||||
n->left = (void *) a;
|
||||
d[0] = b;
|
||||
d[1] = NULL;
|
||||
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->type = COND_MODI;
|
||||
n->left = (void *) (b + 1);
|
||||
n->left = (void *) b;
|
||||
d[0] = a;
|
||||
d[1] = c;
|
||||
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->type = COND_MOD;
|
||||
n->left = (void *) (a + 1);
|
||||
n->left = (void *) a;
|
||||
d[0] = b;
|
||||
d[1] = c;
|
||||
d[2] = NULL;
|
||||
|
|
|
@ -703,6 +703,8 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
|||
execsave();
|
||||
breaks = 0;
|
||||
if (*sigtr & ZSIG_FUNC) {
|
||||
int osc = sfcontext;
|
||||
|
||||
PERMALLOC {
|
||||
args = newlinklist();
|
||||
name = (char *) zalloc(5 + strlen(sigs[sig]));
|
||||
|
@ -712,7 +714,9 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
|
|||
addlinknode(args, num);
|
||||
} LASTALLOC;
|
||||
trapreturn = -1;
|
||||
sfcontext = SFC_SIGNAL;
|
||||
doshfunc(name, sigfn, args, 0, 1);
|
||||
sfcontext = osc;
|
||||
freelinklist(args, (FreeFunc) NULL);
|
||||
zsfree(name);
|
||||
} 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 nojoin = 0;
|
||||
char inbrace = 0; /* != 0 means ${...}, otherwise $... */
|
||||
char hkeys = 0; /* 1 means get keys from associative array */
|
||||
char hvals = 0; /* > hkeys get values of associative array */
|
||||
char hkeys = 0;
|
||||
char hvals = 0;
|
||||
|
||||
*s++ = '\0';
|
||||
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
||||
|
@ -739,7 +739,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
inbrace = 1;
|
||||
s++;
|
||||
if (*s == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
||||
hkeys = 1;
|
||||
hkeys = SCANPM_WANTKEYS;
|
||||
s++;
|
||||
} else if (*s == '(' || *s == Inpar) {
|
||||
char *t, sav;
|
||||
|
@ -762,7 +762,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
case Outpar:
|
||||
break;
|
||||
case 'A':
|
||||
arrasg = 1;
|
||||
++arrasg;
|
||||
break;
|
||||
case '@':
|
||||
nojoin = 1;
|
||||
|
@ -897,10 +897,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
break;
|
||||
|
||||
case 'k':
|
||||
hkeys = 1;
|
||||
hkeys = SCANPM_WANTKEYS;
|
||||
break;
|
||||
case 'v':
|
||||
hvals = 2;
|
||||
hvals = SCANPM_WANTVALS;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -979,9 +979,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
*s = sav;
|
||||
v = (Value) NULL;
|
||||
} else {
|
||||
/* 2 == SCANPM_WANTKEYS, 1 == SCANPM_WANTVALS, see params.c */
|
||||
if (!(v = fetchvalue(&s, (unset(KSHARRAYS) || inbrace) ? 1 : -1,
|
||||
(hkeys ? 2 : 0) + ((hvals > hkeys) ? 1 : 0))))
|
||||
hkeys|hvals)))
|
||||
vunset = 1;
|
||||
}
|
||||
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)) {
|
||||
/* No way to get here with v->inv != 0, so getvaluearr() *
|
||||
* 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 {
|
||||
if (v->pm->flags & PM_ARRAY) {
|
||||
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++ = 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 {
|
||||
untokenize(val);
|
||||
setsparam(idbeg, ztrdup(val));
|
||||
|
|
22
Src/utils.c
22
Src/utils.c
|
@ -427,7 +427,7 @@ get_username(void)
|
|||
cached_username = ztrdup("");
|
||||
}
|
||||
#else /* !HAVE_GETPWUID */
|
||||
cached_uid = current_uid;
|
||||
cached_uid = getuid();
|
||||
#endif /* !HAVE_GETPWUID */
|
||||
return cached_username;
|
||||
}
|
||||
|
@ -510,16 +510,13 @@ adduserdir(char *s, char *t, int flags, int always)
|
|||
if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
|
||||
return;
|
||||
|
||||
/* Never hash PWD unless it was explicitly requested */
|
||||
if (!always && !strcmp(s, "PWD"))
|
||||
return;
|
||||
|
||||
/* Normal parameter assignments generate calls to this function, *
|
||||
* with always==0. Unless the AUTO_NAME_DIRS option is set, we *
|
||||
* don't let such assignments actually create directory names. *
|
||||
* Instead, a reference to the parameter as a directory name can *
|
||||
* cause the actual creation of the hash table entry. */
|
||||
if (!always && unset(AUTONAMEDIRS) &&
|
||||
* cause the actual creation of the hash table entry. Never hash *
|
||||
* PWD unless it was explicitly requested (or already hashed). */
|
||||
if (!always && (unset(AUTONAMEDIRS) || !strcmp(s, "PWD")) &&
|
||||
!nameddirtab->getnode2(nameddirtab, s))
|
||||
return;
|
||||
|
||||
|
@ -633,8 +630,13 @@ preprompt(void)
|
|||
|
||||
/* If a shell function named "precmd" exists, *
|
||||
* 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);
|
||||
sfcontext = osc;
|
||||
}
|
||||
if (errflag)
|
||||
return;
|
||||
|
||||
|
@ -643,7 +645,11 @@ preprompt(void)
|
|||
* executed "periodic", then execute it now. */
|
||||
if (period && (time(NULL) > lastperiodic + period) &&
|
||||
(list = getshfunc("periodic")) != &dummy_list) {
|
||||
int osc = sfcontext;
|
||||
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("periodic", list, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
lastperiodic = time(NULL);
|
||||
}
|
||||
if (errflag)
|
||||
|
|
|
@ -23,6 +23,8 @@ closem
|
|||
cmdnamtab
|
||||
columns
|
||||
compctlreadptr
|
||||
cond_str
|
||||
cond_val
|
||||
coprocin
|
||||
coprocout
|
||||
countlinknodes
|
||||
|
@ -173,6 +175,7 @@ sethparam
|
|||
setlimits
|
||||
setsparam
|
||||
settyinfo
|
||||
sfcontext
|
||||
shfunctab
|
||||
shingetline
|
||||
shout
|
||||
|
|
63
Src/zsh.h
63
Src/zsh.h
|
@ -460,23 +460,24 @@ struct cond {
|
|||
#define COND_MOD 16
|
||||
#define COND_MODI 17
|
||||
|
||||
typedef int (*CondHandler) _((Conddef, char **));
|
||||
typedef int (*CondHandler) _((char **, int));
|
||||
|
||||
struct conddef {
|
||||
Conddef next; /* next in list */
|
||||
char *name; /* the condition name */
|
||||
int flags; /* see CONDF_* below */
|
||||
CondHandler handler; /* handler function */
|
||||
int min; /* minimum number of strings */
|
||||
int max; /* maximum number of strings */
|
||||
CondHandler handler; /* handler function */
|
||||
int condid; /* for overloading handler functions */
|
||||
char *module; /* module to autoload */
|
||||
};
|
||||
|
||||
#define CONDF_INFIX 1
|
||||
#define CONDF_ADDED 2
|
||||
|
||||
#define CONDDEF(name, flags, min, max, handler) \
|
||||
{ NULL, name, flags, min, max, handler, NULL }
|
||||
#define CONDDEF(name, flags, handler, min, max, condid) \
|
||||
{ NULL, name, flags, handler, min, max, condid, NULL }
|
||||
|
||||
struct forcmd { /* for/select */
|
||||
/* Cmd->args contains list of words to loop thru */
|
||||
|
@ -772,6 +773,14 @@ struct shfunc {
|
|||
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 */
|
||||
|
||||
typedef int (*WrapFunc) _((List, FuncWrap, char *));
|
||||
|
@ -781,13 +790,12 @@ struct funcwrap {
|
|||
int flags;
|
||||
WrapFunc handler;
|
||||
Module module;
|
||||
int count;
|
||||
};
|
||||
|
||||
#define WRAPF_ADDED 1
|
||||
|
||||
#define WRAPDEF(func) \
|
||||
{ NULL, 0, func, NULL, 0 }
|
||||
{ NULL, 0, func, NULL }
|
||||
|
||||
/* node in builtin command hash table (builtintab) */
|
||||
|
||||
|
@ -836,11 +844,11 @@ struct module {
|
|||
int flags;
|
||||
void *handle;
|
||||
LinkList deps;
|
||||
int wrapper;
|
||||
};
|
||||
|
||||
#define MOD_BUSY (1<<0)
|
||||
#define MOD_WRAPPER (1<<1)
|
||||
#define MOD_UNLOAD (1<<2)
|
||||
#define MOD_UNLOAD (1<<1)
|
||||
|
||||
/* node used in parameter hash table (paramtab) */
|
||||
|
||||
|
@ -890,28 +898,37 @@ struct param {
|
|||
#define PM_SCALAR 0 /* scalar */
|
||||
#define PM_ARRAY (1<<0) /* array */
|
||||
#define PM_INTEGER (1<<1) /* integer */
|
||||
#define PM_HASHED (1<<15) /* association */
|
||||
#define PM_HASHED (1<<2) /* association */
|
||||
|
||||
#define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY|PM_HASHED))
|
||||
|
||||
#define PM_LEFT (1<<2) /* left justify and remove leading blanks */
|
||||
#define PM_RIGHT_B (1<<3) /* right justify and fill with leading blanks */
|
||||
#define PM_RIGHT_Z (1<<4) /* right justify and fill with leading zeros */
|
||||
#define PM_LOWER (1<<5) /* all lower case */
|
||||
#define PM_LEFT (1<<3) /* left justify and remove leading blanks */
|
||||
#define PM_RIGHT_B (1<<4) /* right justify and fill with leading blanks */
|
||||
#define PM_RIGHT_Z (1<<5) /* right justify and fill with leading zeros */
|
||||
#define PM_LOWER (1<<6) /* all lower case */
|
||||
|
||||
/* The following are the same since they *
|
||||
* both represent -u option to typeset */
|
||||
#define PM_UPPER (1<<6) /* all upper case */
|
||||
#define PM_UNDEFINED (1<<6) /* undefined (autoloaded) shell function */
|
||||
#define PM_UPPER (1<<7) /* all upper case */
|
||||
#define PM_UNDEFINED (1<<7) /* undefined (autoloaded) shell function */
|
||||
|
||||
#define PM_READONLY (1<<7) /* readonly */
|
||||
#define PM_TAGGED (1<<8) /* tagged */
|
||||
#define PM_EXPORTED (1<<9) /* exported */
|
||||
#define PM_UNIQUE (1<<10) /* remove duplicates */
|
||||
#define PM_SPECIAL (1<<11) /* special builtin parameter */
|
||||
#define PM_DONTIMPORT (1<<12) /* do not import this variable */
|
||||
#define PM_RESTRICTED (1<<13) /* cannot be changed in restricted mode */
|
||||
#define PM_UNSET (1<<14) /* has null value */
|
||||
#define PM_READONLY (1<<8) /* readonly */
|
||||
#define PM_TAGGED (1<<9) /* tagged */
|
||||
#define PM_EXPORTED (1<<10) /* exported */
|
||||
#define PM_UNIQUE (1<<11) /* remove duplicates */
|
||||
#define PM_SPECIAL (1<<12) /* special builtin parameter */
|
||||
#define PM_DONTIMPORT (1<<13) /* do not import this variable */
|
||||
#define PM_RESTRICTED (1<<14) /* cannot be changed in restricted mode */
|
||||
#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.
|
||||
|
|
|
@ -112,6 +112,297 @@ C coding style
|
|||
groups of statements in the interests of clarity. There should never
|
||||
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
|
||||
-------------
|
||||
|
||||
|
|
|
@ -222,3 +222,6 @@
|
|||
|
||||
/* Define to 1 if you want to use dynamically loaded modules on AIX */
|
||||
#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 &&
|
||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -63,6 +75,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#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 &&
|
||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -123,6 +148,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
@ -130,6 +156,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
|||
#define RTLD_GLOBAL 0
|
||||
#endif
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
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 &&
|
||||
$DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -184,6 +223,7 @@ $DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&5 2>&5; then
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
@ -234,6 +274,18 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5; then
|
|||
save_ldflags=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -241,6 +293,7 @@ $DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&5 2>&5; then
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
@ -294,6 +347,18 @@ elif
|
|||
save_ldflags=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS -s"
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -301,6 +366,7 @@ elif
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
@ -348,6 +414,18 @@ echo 'int fred () { return 42; }' > conftest1.c
|
|||
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
|
||||
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
|
||||
#include <dlfcn.h>
|
||||
#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 <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
@ -389,7 +468,7 @@ dnl
|
|||
|
||||
AC_DEFUN(zsh_PATH_UTMP,
|
||||
[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
|
||||
test -f $zsh_cv_path_$1 && break
|
||||
zsh_cv_path_$1=no
|
||||
|
|
37
configure.in
37
configure.in
|
@ -45,6 +45,9 @@ AC_DEFINE_UNQUOTED(OSTYPE, "$host_os")
|
|||
dnl -----------------------------
|
||||
dnl CHECKING COMMAND LINE OPTIONS
|
||||
dnl -----------------------------
|
||||
dnl Handle --program-prefix, --program-suffix, etc.
|
||||
AC_ARG_PROGRAM
|
||||
|
||||
dnl Do you want to debug zsh?
|
||||
undefine([zsh-debug])dnl
|
||||
AC_ARG_ENABLE(zsh-debug,
|
||||
|
@ -211,7 +214,7 @@ if test -n "$auto_cflags"; then
|
|||
fi
|
||||
if test -n "$auto_ldflags"; then
|
||||
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 ;;
|
||||
*) LDFLAGS=-s ;;
|
||||
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)
|
||||
if test $dynamic = yes; then
|
||||
AC_CHECK_HEADERS(dlfcn.h)
|
||||
AC_CHECK_HEADERS(dl.h)
|
||||
fi
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -902,6 +907,7 @@ dnl dynamic loading
|
|||
dnl ---------------
|
||||
L=N
|
||||
aixdynamic=no
|
||||
hpuxdynamic=no
|
||||
if test "$ac_cv_func_dlopen" != yes ||
|
||||
test "$ac_cv_func_dlsym" != yes ||
|
||||
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_loadbind" != yes ||
|
||||
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
|
||||
aixdynamic=yes
|
||||
fi
|
||||
|
@ -990,6 +1008,18 @@ EOM
|
|||
$DLLD -o conftest.$DL_EXT $LDFLAGS $DLLDFLAGS conftest.o 1>&5 2>&5 &&
|
||||
AC_TRY_RUN([
|
||||
#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
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
|
@ -997,6 +1027,7 @@ EOM
|
|||
#include <nlist.h>
|
||||
#include <link.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif
|
||||
|
|
|
@ -169,3 +169,47 @@ Bart's associative array patches for implentation of subscripting flags,
|
|||
4763, plus fix 4766; typeset output 4764
|
||||
|
||||
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