1
0
Fork 0
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:
Tanaka Akira 1999-04-15 18:10:10 +00:00
parent 9003d99d16
commit 2a5a899a55
47 changed files with 1371 additions and 341 deletions

View file

@ -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'

View file

@ -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.

View file

@ -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)

View file

@ -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):

View file

@ -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))(

View file

@ -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

View file

@ -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.

View file

@ -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)

View file

@ -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

View file

@ -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.

View file

@ -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/

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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. */

View file

@ -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 *));

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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";
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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"

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}
/**/

View file

@ -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;

View file

@ -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 {

View file

@ -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));

View file

@ -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)

View file

@ -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

View file

@ -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.

View file

@ -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
-------------

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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