mirror of
https://github.com/zdharma-continuum/zinit.git
synced 2026-09-10 07:36:38 -04:00
✂️ Relocate module
This commit is contained in:
parent
5df5fb6b46
commit
3020177e1c
51
README.md
51
README.md
|
|
@ -1021,56 +1021,7 @@ # Skip the not really helping Ubuntu global compinit
|
|||
|
||||
# Zinit Module
|
||||
|
||||
## Motivation
|
||||
|
||||
The module is a binary Zsh module (think about `zmodload` Zsh command, it's that topic) which transparently and
|
||||
automatically **compiles sourced scripts**. Many plugin managers do not offer compilation of plugins, the module is
|
||||
a solution to this. Even if a plugin manager does compile plugin's main script (like Zinit does), the script can
|
||||
source smaller helper scripts or dependency libraries (for example, the prompt `geometry-zsh/geometry` does that)
|
||||
and there are very few solutions to that, which are demanding (e.g. specifying all helper files in plugin load
|
||||
command and investigating updates to the plugin – in Zinit case: by using `compile` ice-mod).
|
||||
|
||||

|
||||
|
||||
|
||||
## Module Installation
|
||||
|
||||
### Without Zinit
|
||||
|
||||
To install just the binary Zinit module **standalone** (Zinit is not needed, the module can be used with any
|
||||
other plugin manager), execute:
|
||||
|
||||
```zsh
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/mod-install.sh)"
|
||||
```
|
||||
|
||||
This script will display what to add to `~/.zshrc` (2 lines) and show usage instructions.
|
||||
|
||||
### With Zinit
|
||||
|
||||
Zinit users can build the module by issuing following command instead of running above `mod-install.sh` script
|
||||
(the script is for e.g. `zgen` users or users of any other plugin manager):
|
||||
|
||||
```zsh
|
||||
zinit module build
|
||||
```
|
||||
|
||||
This command will compile the module and display instructions on what to add to `~/.zshrc`.
|
||||
|
||||
## Measuring Time of `source`s
|
||||
|
||||
Besides the compilation-feature, the module also measures **duration** of each script sourcing. Issue `zpmod source-study` after loading the module at top of `~/.zshrc` to see a list of all sourced files with the time the
|
||||
sourcing took in milliseconds on the left. This feature allows to profile the shell startup. Also, no script can
|
||||
pass-through that check and you will obtain a complete list of all loaded scripts, like if Zshell itself was
|
||||
investigating this. The list can be surprising.
|
||||
|
||||
## Debugging
|
||||
|
||||
To enable debug messages from the module set:
|
||||
|
||||
```zsh
|
||||
typeset -g ZPLG_MOD_DEBUG=1
|
||||
```
|
||||
The module is now hosted [in its own repository](https://github.com/zdharma-continuum/zinit-module)
|
||||
|
||||
# Hints and Tips
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
* 18-11-2021
|
||||
- The zinit module has been relocated to
|
||||
[its own repository](https://github.com/zdharma-continuum/zinit-module)
|
||||
|
||||
* 16-11-2021
|
||||
- A brand-new installer has been developed. A few new features have been
|
||||
added. There are a bunch of new env vars you can set:
|
||||
|
|
|
|||
15
doc/zinit.1
15
doc/zinit.1
|
|
@ -50,19 +50,6 @@ News
|
|||
\fBDisabling System-Wide \fBcompinit\fR Call (Ubuntu)\fR \fI(Disabling System-Wide compinit Call (Ubuntu))\fR
|
||||
.RE 0
|
||||
|
||||
.IP \(bu 4
|
||||
\fBzinit Module\fR \fI(zinit Module)\fR
|
||||
.RS 4
|
||||
.IP \(bu 4
|
||||
\fBMotivation\fR \fI(Motivation)\fR
|
||||
.IP \(bu 4
|
||||
\fBInstallation\fR \fI(Installation)\fR
|
||||
.IP \(bu 4
|
||||
\fBMeasuring Time of \fBsource\fRs\fR \fI(Measuring Time of sources)\fR
|
||||
.IP \(bu 4
|
||||
\fBDebugging\fR \fI(Debugging)\fR
|
||||
.RE 0
|
||||
|
||||
.IP \(bu 4
|
||||
\fBHints and Tips\fR \fI(Hints and Tips)\fR
|
||||
.RS 4
|
||||
|
|
@ -641,7 +628,7 @@ Command@Description
|
|||
\fBsrv {service-id} \[lB]cmd\[rB]\fR@ Control a service, command can be: stop,start,restart,next,quit; \fBnext\fR moves the service to another Zshell.
|
||||
\fBrecall {plg-spec}\[rs]|URL\fR@ Fetch saved ice modifiers and construct \fBzinit ice ...\fR command.
|
||||
\fBenv-whitelist \[lB]-v\[rB] \[lB]-h\[rB] {env..}\fR@ Allows to specify names (also patterns) of variables left unchanged during an unload. \fB-v\fR \[en] verbose.
|
||||
\fBmodule\fR@ Manage binary Zsh module shipped with zinit, see \fBzinit module help\fR.
|
||||
\fBmodule\fR@ Manage binary Zsh module, see \fBzinit module help\fR.
|
||||
.TE
|
||||
.SS "Updating zinit and Plugins"
|
||||
.P
|
||||
|
|
|
|||
|
|
@ -1,71 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
col_pname="[33m"
|
||||
col_error="[31m"
|
||||
col_info="[32m"
|
||||
col_info2="[32m"
|
||||
col_rst="[0m"
|
||||
|
||||
echo "${col_info}Re-run this script to update (from Github) and rebuild the module.$col_rst"
|
||||
|
||||
#
|
||||
# Clone or pull
|
||||
#
|
||||
|
||||
ZINIT_HOME="${ZDOTDIR:-$HOME}/.zinit"
|
||||
|
||||
if ! test -d "$ZINIT_HOME"; then
|
||||
mkdir "$ZINIT_HOME"
|
||||
chmod g-rwX "$ZINIT_HOME"
|
||||
fi
|
||||
|
||||
echo ">>> Downloading zdharma-continuum/zinit module to $ZINIT_HOME/mod-bin"
|
||||
if test -d "$ZINIT_HOME/mod-bin/.git"; then
|
||||
cd "$ZINIT_HOME/mod-bin" || exit 9
|
||||
git pull origin master
|
||||
else
|
||||
cd "$ZINIT_HOME" || exit 9
|
||||
git clone --depth 10 https://github.com/zdharma-continuum/zinit.git mod-bin
|
||||
fi
|
||||
echo ">>> Done"
|
||||
|
||||
#
|
||||
# Build the module
|
||||
#
|
||||
|
||||
cd "$ZINIT_HOME/mod-bin/zmodules" || exit 9
|
||||
echo "$col_pname== Building module zdharma-continuum/zinit, running: a make clean, then ./configure and then make ==$col_rst"
|
||||
echo "$col_pname== The module sources are located at: $ZINIT_HOME/mod-bin/zmodules ==$col_rst"
|
||||
if test -f Makefile; then
|
||||
if [ "$1" = "--clean" ]; then
|
||||
echo "$col_info2-- make distclean --$col_rst"
|
||||
make distclean
|
||||
true
|
||||
else
|
||||
echo "$col_info2-- make clean (pass --clean to invoke \`make distclean') --$col_rst"
|
||||
make clean
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$col_info2-- ./configure --$col_rst"
|
||||
if CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O3" LDFLAGS=-L/usr/local/lib \
|
||||
./configure --disable-gdbm --without-tcsetpgrp; then
|
||||
echo "$col_info2-- make --$col_rst"
|
||||
if make; then
|
||||
echo "${col_info}Module has been built correctly.$col_rst"
|
||||
echo "To load the module, add following 2 lines to .zshrc, at top:"
|
||||
echo " module_path+=( \"$ZINIT_HOME/mod-bin/zmodules/Src\" )"
|
||||
echo " zmodload zdharma-continuum/zinit"
|
||||
echo ""
|
||||
echo "After loading, use command \`zpmod' to communicate with the module."
|
||||
echo "See \`zpmod -h' for more information. There are two main features,"
|
||||
echo "invocation of \`zpmod source-study' which shows \`source' profile"
|
||||
echo "data, and guaranteed, automatic compilation of any sourced script"
|
||||
echo "while the module is loaded (check with Zsh command \`zmodload')."
|
||||
else
|
||||
echo "${col_error}Module didn't build.$col_rst. You can copy the error messages and submit"
|
||||
echo "error-report at: https://github.com/zdharma-continuum/zinit/issues"
|
||||
fi
|
||||
fi
|
||||
|
||||
# vim: set ft=sh et ts=2 sw=2 :
|
||||
|
|
@ -3303,16 +3303,18 @@ EOF
|
|||
# It's an attempt to plugin only this one function into `zinit' function
|
||||
# defined in zinit.zsh, to not make this file longer than it's needed.
|
||||
.zinit-module() {
|
||||
local module_dir="${ZINIT[HOME_DIR]}/module"
|
||||
if [[ "$1" = "build" ]]; then
|
||||
.zinit-build-module "${@[2,-1]}"
|
||||
elif [[ "$1" = "info" ]]; then
|
||||
if [[ "$2" = "--link" ]]; then
|
||||
builtin print -r "You can copy the error messages and submit"
|
||||
builtin print -r "error-report at: https://github.com/zdharma-continuum/zinit/issues"
|
||||
builtin print -r "error-report at: https://github.com/zdharma-continuum/zinit-module/issues"
|
||||
else
|
||||
builtin print -r "To load the module, add following 2 lines to .zshrc, at top:"
|
||||
builtin print -r " module_path+=( \"${ZINIT[BIN_DIR]}/zmodules/Src\" )"
|
||||
builtin print -r " zmodload zdharma/zplugin"
|
||||
# TODO: Update when we move the C code source to the main dir of the repo
|
||||
builtin print -r " module_path+=( \"${module_dir}/zmodules/Src\" )"
|
||||
builtin print -r " zmodload zdharma/zinit"
|
||||
builtin print -r ""
|
||||
builtin print -r "After loading, use command \`zpmod' to communicate with the module."
|
||||
builtin print -r "See \`zpmod -h' for more information."
|
||||
|
|
@ -3335,9 +3337,14 @@ EOF
|
|||
.zinit-build-module() {
|
||||
setopt localoptions localtraps
|
||||
trap 'return 1' INT TERM
|
||||
( builtin cd -q "${ZINIT[BIN_DIR]}"/zmodules
|
||||
+zinit-message "{pname}== Building module zdharma/zplugin, running: make clean, then ./configure and then make =={rst}"
|
||||
+zinit-message "{pname}== The module sources are located at: "${ZINIT[BIN_DIR]}"/zmodules =={rst}"
|
||||
local module_dir="${ZINIT[HOME_DIR]}/module" # TODO: Make this ZINIT[MODULE_DIR] ie configurable
|
||||
command git clone "https://github.com/zdharma-continuum/zinit-module.git" "${module_dir}" || {
|
||||
builtin print "${ZINIT[col-error]}Failed to clone module repo${ZINIT[col-rst]}"
|
||||
return 1
|
||||
}
|
||||
( builtin cd -q "${module_dir}/zmodules" # TODO: Move the source of the module to the root of the repo
|
||||
+zinit-message "{pname}== Building module zdharma-continuum/zinit-module, running: make clean, then ./configure and then make =={rst}"
|
||||
+zinit-message "{pname}== The module sources are located at: "${module_path}" =={rst}"
|
||||
if [[ -f Makefile ]] {
|
||||
if [[ "$1" = "--clean" ]] {
|
||||
noglob +zinit-message {p}-- make distclean --{rst}
|
||||
|
|
@ -3360,7 +3367,7 @@ EOF
|
|||
.zinit-module info --link
|
||||
}
|
||||
}
|
||||
builtin print $EPOCHSECONDS >! "${ZINIT[BIN_DIR]}"/zmodules/COMPILED_AT
|
||||
builtin print $EPOCHSECONDS >! "${module_path}/COMPILED_AT"
|
||||
)
|
||||
}
|
||||
# ]]]
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
Makefile
|
||||
META-FAQ
|
||||
config.cache
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.modules
|
||||
config.modules.sh
|
||||
config.status
|
||||
configure
|
||||
cscope.out
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
autom4te.cache
|
||||
*.swp
|
||||
.git
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
DISTFILES_SRC='
|
||||
META-FAQ
|
||||
configure config.h.in stamp-h.in
|
||||
'
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
# Top-most editorconfig file
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
tab_width = 8
|
||||
indent_size = 2
|
||||
indent_style = tab
|
||||
|
||||
[ChangeLog]
|
||||
indent_size = 8
|
||||
|
||||
[*.[ch]]
|
||||
indent_size = 4
|
||||
155
zmodules/.gitignore
vendored
155
zmodules/.gitignore
vendored
|
|
@ -1,155 +0,0 @@
|
|||
Makefile
|
||||
tags
|
||||
TAGS
|
||||
*.o
|
||||
*.o.c
|
||||
*.orig
|
||||
*.a
|
||||
*.so
|
||||
*.dll
|
||||
*~
|
||||
.*.sw?
|
||||
\#*
|
||||
|
||||
/META-FAQ
|
||||
/config.cache
|
||||
/config.h
|
||||
/config.log
|
||||
/config.modules
|
||||
/config.modules.sh
|
||||
/config.status
|
||||
/config.status.lineno
|
||||
/cscope.out
|
||||
/stamp-h
|
||||
/autom4te.cache
|
||||
|
||||
Config/defs.mk
|
||||
|
||||
CVS
|
||||
.#*
|
||||
|
||||
Doc/help
|
||||
Doc/help.txt
|
||||
Doc/help/[_a-zA-Z0-9]*
|
||||
|
||||
Doc/intro.pdf
|
||||
Doc/intro.ps
|
||||
Doc/intro.a4.pdf
|
||||
Doc/intro.a4.ps
|
||||
Doc/intro.us.pdf
|
||||
Doc/intro.us.ps
|
||||
Doc/version.yo
|
||||
Doc/texi2html.conf
|
||||
Doc/zsh*.1
|
||||
Doc/zsh.texi
|
||||
Doc/zsh.info*
|
||||
Doc/*.html
|
||||
Doc/zsh.aux
|
||||
Doc/zsh.toc
|
||||
Doc/zsh.cp
|
||||
Doc/zsh.cps
|
||||
Doc/zsh.fn
|
||||
Doc/zsh.fns
|
||||
Doc/zsh.ky
|
||||
Doc/zsh.kys
|
||||
Doc/zsh.pg
|
||||
Doc/zsh.pgs
|
||||
Doc/zsh.vr
|
||||
Doc/zsh.vrs
|
||||
Doc/zsh.log
|
||||
Doc/zsh.dvi
|
||||
Doc/zsh_a4.dvi
|
||||
Doc/zsh_us.dvi
|
||||
Doc/zsh.tp
|
||||
Doc/zsh.tps
|
||||
Doc/zsh.idx
|
||||
Doc/zsh_*.ps
|
||||
Doc/infodir
|
||||
Doc/zsh.pdf
|
||||
Doc/zsh_a4.pdf
|
||||
Doc/zsh_us.pdf
|
||||
|
||||
Doc/Zsh/modlist.yo
|
||||
Doc/Zsh/modmenu.yo
|
||||
Doc/Zsh/manmodmenu.yo
|
||||
|
||||
Etc/FAQ
|
||||
Etc/FAQ.html
|
||||
|
||||
Src/*.epro
|
||||
Src/*.export
|
||||
Src/*.mdh
|
||||
Src/*.mdh.tmp
|
||||
Src/*.mdhi
|
||||
Src/*.mdhs
|
||||
Src/*.syms
|
||||
Src/Makemod.in
|
||||
Src/Makemod
|
||||
Src/[_a-zA-Z0-9]*.pro
|
||||
Src/ansi2knr
|
||||
Src/bltinmods.list
|
||||
Src/cscope.out
|
||||
Src/libzsh.so*
|
||||
Src/modules-bltin
|
||||
Src/modules.index
|
||||
Src/modules.index.tmp
|
||||
Src/modules.stamp
|
||||
Src/patchlevel.h
|
||||
Src/sigcount.h
|
||||
Src/signames.c
|
||||
Src/signames2.c
|
||||
Src/stamp-modobjs
|
||||
Src/stamp-modobjs.tmp
|
||||
Src/tags
|
||||
Src/TAGS
|
||||
Src/version.h
|
||||
Src/zsh
|
||||
Src/zsh.exe
|
||||
Src/zshcurses.h
|
||||
Src/zshpaths.h
|
||||
Src/zshterm.h
|
||||
Src/zshxmods.h
|
||||
|
||||
Src/Builtins/Makefile.in
|
||||
Src/Builtins/*.export
|
||||
Src/Builtins/so_locations
|
||||
Src/Builtins/*.pro
|
||||
Src/Builtins/*.epro
|
||||
Src/Builtins/*.syms
|
||||
Src/Builtins/*.mdh
|
||||
Src/Builtins/*.mdhi
|
||||
Src/Builtins/*.mdhs
|
||||
Src/Builtins/*.mdh.tmp
|
||||
Src/Builtins/rlimits.h
|
||||
|
||||
Src/Modules/Makefile.in
|
||||
Src/Modules/*.export
|
||||
Src/Modules/so_locations
|
||||
Src/Modules/*.pro
|
||||
Src/Modules/*.epro
|
||||
Src/Modules/*.syms
|
||||
Src/Modules/*.mdh
|
||||
Src/Modules/*.mdhi
|
||||
Src/Modules/*.mdhs
|
||||
Src/Modules/*.mdh.tmp
|
||||
Src/Modules/errnames.c
|
||||
Src/Modules/errcount.h
|
||||
Src/Modules/curses_keys.h
|
||||
|
||||
Src/Zle/Makefile.in
|
||||
Src/Zle/*.export
|
||||
Src/Zle/so_locations
|
||||
Src/Zle/*.pro
|
||||
Src/Zle/*.epro
|
||||
Src/Zle/*.syms
|
||||
Src/Zle/*.mdh
|
||||
Src/Zle/*.mdhi
|
||||
Src/Zle/*.mdhs
|
||||
Src/Zle/*.mdh.tmp
|
||||
Src/Zle/thingies.list
|
||||
Src/Zle/widgets.list
|
||||
Src/Zle/zle_things.h
|
||||
Src/Zle/zle_widget.h
|
||||
|
||||
Test/*.tmp
|
||||
/.project
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
autoconf
|
||||
autoheader
|
||||
echo > stamp-h.in
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
defs.mk
|
||||
*.swp
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
AC_DEFUN([zsh_OOT],
|
||||
[
|
||||
AC_CHECK_HEADERS(stdarg.h varargs.h termios.h termio.h)
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
|
||||
AC_DEFINE([ZSH_OOT_MODULE], [], [Out-of-tree module])
|
||||
])
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for cleanup
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
mostlyclean: mostlyclean-recursive mostlyclean-here
|
||||
clean: clean-recursive clean-here
|
||||
distclean: distclean-recursive distclean-here
|
||||
realclean: realclean-recursive realclean-here
|
||||
|
||||
mostlyclean-here:
|
||||
clean-here: mostlyclean-here
|
||||
distclean-here: clean-here
|
||||
realclean-here: distclean-here
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive realclean-recursive:
|
||||
@subdirs='$(SUBDIRS)'; if test -n "$$subdirs"; then \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$subdirs; do \
|
||||
(cd $$subdir && $(MAKE) $(MAKEDEFS) $$target) || exit 1; \
|
||||
done; \
|
||||
fi
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for building Makefiles
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
config: Makefile
|
||||
@subdirs='$(SUBDIRS)'; for subdir in $$subdirs; do \
|
||||
(cd $$subdir && $(MAKE) $(MAKEDEFS) $@) || exit 1; \
|
||||
done
|
||||
|
||||
CONFIG_INCS = \
|
||||
$(dir_top)/Config/clean.mk $(dir_top)/Config/config.mk \
|
||||
$(dir_top)/Config/defs.mk $(dir_top)/Config/version.mk
|
||||
|
||||
Makefile: Makefile.in $(dir_top)/config.status $(CONFIG_INCS)
|
||||
cd $(dir_top) && \
|
||||
$(SHELL) ./config.status `echo $(subdir)/$@ | sed 's%^./%%'`
|
||||
|
||||
$(dir_top)/Config/defs.mk: $(sdir_top)/Config/defs.mk.in $(dir_top)/config.status
|
||||
cd $(dir_top) && \
|
||||
$(SHELL) ./config.status Config/defs.mk
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#
|
||||
# Basic Makefile definitions
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
# fundamentals
|
||||
SHELL = /bin/sh
|
||||
@SET_MAKE@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
# headers
|
||||
ZSH_CURSES_H = @ZSH_CURSES_H@
|
||||
ZSH_TERM_H = @ZSH_TERM_H@
|
||||
|
||||
# install basename
|
||||
tzsh = @tzsh@
|
||||
|
||||
# installation directories
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
MODDIR = $(libdir)/$(tzsh)/$(VERSION)
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
fndir = @fndir@
|
||||
fixed_sitefndir = @fixed_sitefndir@
|
||||
sitefndir = @sitefndir@
|
||||
scriptdir = @scriptdir@
|
||||
sitescriptdir = @sitescriptdir@
|
||||
htmldir = @htmldir@
|
||||
runhelpdir = @runhelpdir@
|
||||
runhelp = @runhelp@
|
||||
|
||||
# compilation
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
DEFS = @DEFS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
|
||||
DLCFLAGS = @DLCFLAGS@
|
||||
DLLDFLAGS = @DLLDFLAGS@
|
||||
LIBLDFLAGS = @LIBLDFLAGS@
|
||||
EXELDFLAGS = @EXELDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
DL_EXT = @DL_EXT@
|
||||
DLLD = @DLLD@
|
||||
EXPOPT = @EXPOPT@
|
||||
IMPOPT = @IMPOPT@
|
||||
|
||||
# utilities
|
||||
AWK = @AWK@
|
||||
ANSI2KNR = @ANSI2KNR@
|
||||
YODL = @YODL@ @YODL_OPTIONS@
|
||||
YODL2TXT = @YODL@2txt
|
||||
YODL2HTML = @YODL@2html
|
||||
|
||||
# install utility
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
# variables used in determining what to install
|
||||
FUNCTIONS_SUBDIRS = @FUNCTIONS_SUBDIRS@
|
||||
|
||||
# Additional fpath entries (eg. for vendor specific directories).
|
||||
additionalfpath = @additionalfpath@
|
||||
|
||||
# flags passed to recursive makes in subdirectories
|
||||
MAKEDEFS = \
|
||||
prefix='$(prefix)' exec_prefix='$(exec_prefix)' bindir='$(bindir)' \
|
||||
libdir='$(libdir)' MODDIR='$(MODDIR)' infodir='$(infodir)' mandir='$(mandir)' \
|
||||
datadir='$(datadir)' fndir='$(fndir)' htmldir='$(htmldir)' runhelpdir='$(runhelpdir)' \
|
||||
CC='$(CC)' CPPFLAGS='$(CPPFLAGS)' DEFS='$(DEFS)' CFLAGS='$(CFLAGS)' \
|
||||
LDFLAGS='$(LDFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \
|
||||
DLCFLAGS='$(DLCFLAGS)' DLLDFLAGS='$(DLLDFLAGS)' \
|
||||
LIBLDFLAGS='$(LIBLDFLAGS)' EXELDFLAGS='$(EXELDFLAGS)' \
|
||||
LIBS='$(LIBS)' DL_EXT='$(DL_EXT)' DLLD='$(DLLD)' \
|
||||
AWK='$(AWK)' ANSI2KNR='$(ANSI2KNR)' \
|
||||
YODL='$(YODL)' YODL2TXT='$(YODL2TXT)' YODL2HTML='$(YODL2HTML)' \
|
||||
FUNCTIONS_INSTALL='$(FUNCTIONS_INSTALL)' tzsh='$(tzsh)'
|
||||
|
||||
# override built-in suffix list
|
||||
.SUFFIXES:
|
||||
|
||||
# parallel build is not supported (pmake, gmake)
|
||||
.NOTPARALLEL:
|
||||
|
||||
# parallel build is not supported (dmake)
|
||||
.NO_PARALLEL:
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
fndir=$DESTDIR$fndir
|
||||
scriptdir=$DESTDIR$scriptdir
|
||||
|
||||
/bin/sh $sdir_top/mkinstalldirs $fndir || exit 1;
|
||||
|
||||
allfuncs="`grep ' functions=.' ${dir_top}/config.modules |
|
||||
sed -e '/^#/d' -e '/ link=no/d' -e 's/^.* functions=//'`"
|
||||
|
||||
allfuncs="`cd $sdir_top; echo ${allfuncs}`"
|
||||
|
||||
test -d installfnsdir || mkdir installfnsdir
|
||||
|
||||
# We now have a list of files, but we need to use `test -f' to check
|
||||
# (1) the glob got expanded (2) we are not looking at directories.
|
||||
for file in $allfuncs; do
|
||||
if test -f $sdir_top/$file; then
|
||||
case "$file" in
|
||||
*/CVS/*) continue;;
|
||||
esac
|
||||
if test x$FUNCTIONS_SUBDIRS != x && test x$FUNCTIONS_SUBDIRS != xno; then
|
||||
case "$file" in
|
||||
Completion/*/*)
|
||||
subdir="`echo $file | sed -e 's%/[^/]*/[^/]*$%%'`"
|
||||
instdir="$fndir/$subdir"
|
||||
;;
|
||||
Completion/*)
|
||||
instdir="$fndir/Completion"
|
||||
;;
|
||||
Scripts/*)
|
||||
instdir="$scriptdir"
|
||||
;;
|
||||
*)
|
||||
subdir="`echo $file | sed -e 's%/[^/]*$%%' -e 's%^Functions/%%'`"
|
||||
instdir="$fndir/$subdir"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
case "$file" in
|
||||
Scripts/*)
|
||||
instdir="$scriptdir"
|
||||
;;
|
||||
*)
|
||||
instdir="$fndir"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
basename=`basename $file`
|
||||
ok=0
|
||||
if test -d $instdir || /bin/sh $sdir_top/mkinstalldirs $instdir; then
|
||||
if sed "s|@runhelpdir@|$runhelpdir|" <$sdir_top/$file \
|
||||
>installfnsdir/$basename; then
|
||||
if $INSTALL_DATA installfnsdir/$basename $instdir; then
|
||||
ok=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
case $ok in
|
||||
0)
|
||||
rm -rf installfnsdir
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
read line < $sdir_top/$file
|
||||
case "$line" in
|
||||
'#!'*)
|
||||
chmod +x $instdir/`echo $file | sed -e 's%^.*/%%'`
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf installfnsdir
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
fndir=$DESTDIR$fndir
|
||||
scriptdir=$DESTDIR$scriptdir
|
||||
|
||||
allfuncs="`grep ' functions=' ${dir_top}/config.modules |
|
||||
sed -e '/^#/d' -e '/ link=no/d' -e 's/^.* functions=//'`"
|
||||
|
||||
allfuncs="`cd ${sdir_top}; echo ${allfuncs}`"
|
||||
|
||||
case $fndir in
|
||||
*$VERSION*)
|
||||
# Version specific function directory, safe to remove completely.
|
||||
rm -rf $fndir
|
||||
;;
|
||||
*) # The following will only apply with a custom install directory
|
||||
# with no version information. This is rather undesirable.
|
||||
# But let's try and do the best we can.
|
||||
# We now have a list of files, but we need to use `test -f' to check
|
||||
# (1) the glob got expanded (2) we are not looking at directories.
|
||||
for file in $allfuncs; do
|
||||
case $file in
|
||||
Scripts/*)
|
||||
;;
|
||||
*)
|
||||
if test -f $sdir_top/$file; then
|
||||
if test x$FUNCTIONS_SUBDIRS != x -a x$FUNCTIONS_SUBDIRS != xno; then
|
||||
file=`echo $file | sed -e 's%%^(Functions|Completion)/%'`
|
||||
rm -f $fndir/$file
|
||||
else
|
||||
bfile="`echo $file | sed -e 's%^.*/%%'`"
|
||||
rm -f "$fndir/$bfile"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
case $scriptdir in
|
||||
*$VERSION*)
|
||||
# $scriptdir might be the parent of fndir.
|
||||
rm -rf $scriptdir
|
||||
;;
|
||||
*) for file in $allfuncs; do
|
||||
case $file in
|
||||
Scripts/*)
|
||||
if test -f $sdir_top/$file; then
|
||||
bfile="`echo $file | sed -e 's%^.*/%%'`"
|
||||
rm -f "$scriptdir/$bfile"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#
|
||||
# Makefile fragment for version numbers
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
# This must also serve as a shell script, so do not add spaces around the
|
||||
# `=' signs.
|
||||
|
||||
VERSION=5.3.1-dev-0
|
||||
VERSION_DATE='December 22, 2016'
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
Unless otherwise noted in the header of specific files, files in this
|
||||
distribution have the licence shown below.
|
||||
|
||||
However, note that certain shell functions are licensed under versions
|
||||
of the GNU General Public Licence. Anyone distributing the shell as a
|
||||
binary including those files needs to take account of this. Search
|
||||
shell functions for "Copyright" for specific copyright information.
|
||||
None of the core functions are affected by this, so those files may
|
||||
simply be omitted.
|
||||
|
||||
--
|
||||
|
||||
The Z Shell is copyright (c) 1992-2017 Paul Falstad, Richard Coleman,
|
||||
Zoltán Hidvégi, Andrew Main, Peter Stephenson, Sven Wischnowsky, and
|
||||
others. All rights reserved. Individual authors, whether or not
|
||||
specifically named, retain copyright in all changes; in what follows, they
|
||||
are referred to as `the Zsh Development Group'. This is for convenience
|
||||
only and this body has no legal status. The Z shell is distributed under
|
||||
the following licence; any provisions made in individual files take
|
||||
precedence.
|
||||
|
||||
Permission is hereby granted, without written agreement and without
|
||||
licence or royalty fees, to use, copy, modify, and distribute this
|
||||
software and to distribute modified versions of this software for any
|
||||
purpose, provided that the above copyright notice and the following
|
||||
two paragraphs appear in all copies of this software.
|
||||
|
||||
In no event shall the Zsh Development Group be liable to any party for
|
||||
direct, indirect, special, incidental, or consequential damages arising out
|
||||
of the use of this software and its documentation, even if the Zsh
|
||||
Development Group have been advised of the possibility of such damage.
|
||||
|
||||
The Zsh Development Group specifically disclaim any warranties, including,
|
||||
but not limited to, the implied warranties of merchantability and fitness
|
||||
for a particular purpose. The software provided hereunder is on an "as is"
|
||||
basis, and the Zsh Development Group have no obligation to provide
|
||||
maintenance, support, updates, enhancements, or modifications.
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
#
|
||||
# Makefile for top level of zsh distribution
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
subdir = .
|
||||
dir_top = .
|
||||
SUBDIRS = Src
|
||||
|
||||
@VERSION_MK@
|
||||
|
||||
# source/build directories
|
||||
VPATH = @srcdir@
|
||||
sdir = @srcdir@
|
||||
sdir_top = @top_srcdir@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
@DEFS_MK@
|
||||
|
||||
# ========== DEPENDENCIES FOR BUILDING ==========
|
||||
|
||||
# default target
|
||||
all: config.h config.modules
|
||||
cd Src && $(MAKE) $(MAKEDEFS) $@
|
||||
|
||||
# prepare module configuration
|
||||
prep:
|
||||
@cd Src && $(MAKE) $(MAKEDEFS) $@
|
||||
|
||||
# ========== DEPENDENCIES FOR CLEANUP ==========
|
||||
|
||||
@CLEAN_MK@
|
||||
|
||||
distclean-here:
|
||||
rm -f Makefile config.h config.status config.log config.cache config.modules config.modules.sh stamp-h Config/defs.mk
|
||||
rm -rf autom4te.cache
|
||||
|
||||
realclean-here:
|
||||
cd $(sdir) && rm -f config.h.in stamp-h.in configure
|
||||
|
||||
# ========== DEPENDENCIES FOR MAINTENANCE ==========
|
||||
|
||||
@CONFIG_MK@
|
||||
|
||||
config: config.h
|
||||
|
||||
config.status: $(sdir)/configure
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(sdir)/configure: $(sdir)/aclocal.m4 $(sdir)/aczsh.m4 $(sdir)/configure.ac
|
||||
cd $(sdir) && autoconf
|
||||
|
||||
config.h: stamp-h
|
||||
stamp-h: $(sdir)/config.h.in config.status
|
||||
cd $(dir_top) && $(SHELL) ./config.status config.h $@
|
||||
|
||||
config.modules: $(sdir)/config.h.in config.status config.modules.sh
|
||||
cd $(dir_top) && $(SHELL) ./config.status $@ && \
|
||||
$(SHELL) ./config.modules.sh
|
||||
|
||||
$(sdir)/config.h.in: $(sdir)/stamp-h.in
|
||||
$(sdir)/stamp-h.in: $(sdir)/configure
|
||||
cd $(sdir) && autoheader
|
||||
echo > $(sdir)/stamp-h.in
|
||||
|
||||
FORCE:
|
||||
|
|
@ -1 +0,0 @@
|
|||
1580588806
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
*.dll
|
||||
*.epro
|
||||
*.export
|
||||
*.mdh
|
||||
*.mdh.tmp
|
||||
*.mdhi
|
||||
*.mdhs
|
||||
*.o
|
||||
*.o.c
|
||||
*.so
|
||||
*.swp
|
||||
*.syms
|
||||
Makefile
|
||||
Makemod.in Makemod
|
||||
[_a-zA-Z0-9]*.pro
|
||||
ansi2knr
|
||||
bltinmods.list
|
||||
cscope.out
|
||||
libzsh.so*
|
||||
modules-bltin
|
||||
modules.index
|
||||
modules.index.tmp
|
||||
modules.stamp
|
||||
patchlevel.h
|
||||
sigcount.h
|
||||
signames.c signames2.c
|
||||
stamp-modobjs
|
||||
stamp-modobjs.tmp
|
||||
tags TAGS
|
||||
version.h
|
||||
zsh
|
||||
zshcurses.h
|
||||
zshpaths.h
|
||||
zshterm.h
|
||||
zshxmods.h
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
set ai
|
||||
set sw=4
|
||||
27
zmodules/Src/.indent.pro
vendored
27
zmodules/Src/.indent.pro
vendored
|
|
@ -1,27 +0,0 @@
|
|||
--dont-format-comments
|
||||
--procnames-start-lines
|
||||
--no-parameter-indentation
|
||||
--indent-level4
|
||||
--line-comments-indentation4
|
||||
--cuddle-else
|
||||
--brace-indent0
|
||||
--dont-star-comments
|
||||
--blank-lines-after-declarations
|
||||
--blank-lines-after-procedures
|
||||
--no-blank-lines-after-commas
|
||||
--comment-indentation33
|
||||
--declaration-comment-column33
|
||||
--no-comment-delimiters-on-blank-lines
|
||||
--continuation-indentation4
|
||||
--case-indentation0
|
||||
--else-endif-column33
|
||||
--no-space-after-casts
|
||||
--no-blank-before-sizeof
|
||||
--declaration-indentation0
|
||||
--continue-at-parentheses
|
||||
--no-space-after-function-call-names
|
||||
--swallow-optional-blank-lines
|
||||
--dont-space-special-semicolon
|
||||
--tab-size8
|
||||
--line-length132
|
||||
--braces-on-if-line
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
#
|
||||
# Makefile for Src subdirectory
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
subdir = Src
|
||||
dir_top = ..
|
||||
SUBDIRS =
|
||||
|
||||
@VERSION_MK@
|
||||
|
||||
# source/build directories
|
||||
VPATH = @srcdir@
|
||||
sdir = @srcdir@
|
||||
sdir_top = @top_srcdir@
|
||||
INSTALL = @INSTALL@
|
||||
LN = @LN@
|
||||
|
||||
@DEFS_MK@
|
||||
|
||||
sdir_src = $(sdir)
|
||||
dir_src = .
|
||||
|
||||
# ========= DEPENDENCIES FOR BUILDING ==========
|
||||
|
||||
LINK = $(CC) $(LDFLAGS) $(EXELDFLAGS) $(EXTRA_LDFLAGS) -o $@
|
||||
DLLINK = $(DLLD) $(LDFLAGS) $(LIBLDFLAGS) $(DLLDFLAGS) -o $@
|
||||
|
||||
all: zsh.export modules
|
||||
.PHONY: all
|
||||
|
||||
modules: headers
|
||||
.PHONY: modules
|
||||
|
||||
L = @L@
|
||||
|
||||
LSTMP =
|
||||
LLIST =
|
||||
NSTMP = stamp-modobjs
|
||||
NLIST = `cat stamp-modobjs`
|
||||
|
||||
LIBZSH = libzsh-$(VERSION).$(DL_EXT)
|
||||
NIBZSH =
|
||||
INSTLIB = @INSTLIB@
|
||||
UNINSTLIB = @UNINSTLIB@
|
||||
|
||||
ZSH_EXPORT = $(EXPOPT)zsh.export
|
||||
ZSH_NXPORT =
|
||||
ENTRYOBJ = modentry..o
|
||||
NNTRYOBJ =
|
||||
|
||||
LDRUNPATH = LD_RUN_PATH=$(libdir)/$(tzsh)
|
||||
NDRUNPATH =
|
||||
|
||||
EXTRAZSHOBJS = @EXTRAZSHOBJS@
|
||||
|
||||
stamp-modobjs: modobjs
|
||||
@if cmp -s stamp-modobjs.tmp stamp-modobjs; then \
|
||||
rm -f stamp-modobjs.tmp; \
|
||||
echo "\`stamp-modobjs' is up to date."; \
|
||||
else \
|
||||
mv -f stamp-modobjs.tmp stamp-modobjs; \
|
||||
echo "Updated \`stamp-modobjs'."; \
|
||||
fi
|
||||
|
||||
modobjs: headers rm-modobjs-tmp
|
||||
.PHONY: modobjs
|
||||
|
||||
rm-modobjs-tmp:
|
||||
rm -f stamp-modobjs.tmp
|
||||
.PHONY: rm-modobjs-tmp
|
||||
|
||||
@CONFIG_MK@
|
||||
|
||||
Makemod: $(CONFIG_INCS) $(dir_top)/config.modules
|
||||
@case $(sdir_top) in \
|
||||
/*) top_srcdir=$(sdir_top) ;; \
|
||||
*) top_srcdir=$(subdir)/$(sdir_top) ;; \
|
||||
esac; \
|
||||
export top_srcdir; \
|
||||
echo 'cd $(dir_top) && $(SHELL)' \
|
||||
'$$top_srcdir/$(subdir)/mkmakemod.sh $(subdir) Makemod'; \
|
||||
cd $(dir_top) && \
|
||||
$(SHELL) $$top_srcdir/$(subdir)/mkmakemod.sh $(subdir) Makemod
|
||||
prep: Makemod
|
||||
@$(MAKE) -f Makemod $(MAKEDEFS) prep || rm -f Makemod
|
||||
.PHONY: prep
|
||||
|
||||
FORCE:
|
||||
.PHONY: FORCE
|
||||
|
||||
# ========== LINKING IN MODULES ==========
|
||||
|
||||
mymods.conf:
|
||||
@echo Linking with the standard modules.
|
||||
|
||||
modules: $(@E@NTRYOBJ)
|
||||
|
||||
$(ENTRYOBJ): FORCE
|
||||
@$(MAKE) -f Makemod $(MAKEDEFS) $@
|
||||
|
||||
# ========== DEPENDENCIES FOR CLEANUP ==========
|
||||
|
||||
# Since module cleanup rules depend on Makemod, they come first. This
|
||||
# forces module stuff to get cleaned before Makemod itself gets
|
||||
# deleted.
|
||||
|
||||
mostlyclean-here:
|
||||
rm -f stamp-modobjs stamp-modobjs.tmp
|
||||
.PHONY: mostlyclean-here
|
||||
|
||||
clean-here:
|
||||
rm -f modules.stamp zsh$(EXEEXT)
|
||||
rm -f libzsh-*.$(DL_EXT)
|
||||
.PHONY: clean-here
|
||||
|
||||
distclean-here:
|
||||
rm -f TAGS tags
|
||||
rm -f Makefile
|
||||
.PHONY: distclean-here
|
||||
|
||||
mostlyclean: mostlyclean-modules
|
||||
clean: clean-modules
|
||||
distclean: distclean-modules
|
||||
realclean: realclean-modules
|
||||
.PHONY: mostlyclean clean distclean realclean
|
||||
|
||||
# Don't remake Makemod just to delete things, even if it doesn't exist.
|
||||
mostlyclean-modules clean-modules distclean-modules realclean-modules:
|
||||
if test -f Makemod; then \
|
||||
$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \
|
||||
fi; \
|
||||
exit 0
|
||||
.PHONY: mostlyclean-modules clean-modules distclean-modules \
|
||||
realclean-modules
|
||||
|
||||
@CLEAN_MK@
|
||||
|
||||
# ========== RECURSIVE MAKES ==========
|
||||
|
||||
modobjs modules headers proto zsh.export: Makemod
|
||||
@$(MAKE) -f Makemod $(MAKEDEFS) $@
|
||||
.PHONY: headers proto
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
#
|
||||
# Makemod.in.in
|
||||
#
|
||||
# Copyright (c) 1995-1997 Richard Coleman
|
||||
# All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, without written agreement and without
|
||||
# license or royalty fees, to use, copy, modify, and distribute this
|
||||
# software and to distribute modified versions of this software for any
|
||||
# purpose, provided that the above copyright notice and the following
|
||||
# two paragraphs appear in all copies of this software.
|
||||
#
|
||||
# In no event shall Richard Coleman or the Zsh Development Group be liable
|
||||
# to any party for direct, indirect, special, incidental, or consequential
|
||||
# damages arising out of the use of this software and its documentation,
|
||||
# even if Richard Coleman and the Zsh Development Group have been advised of
|
||||
# the possibility of such damage.
|
||||
#
|
||||
# Richard Coleman and the Zsh Development Group specifically disclaim any
|
||||
# warranties, including, but not limited to, the implied warranties of
|
||||
# merchantability and fitness for a particular purpose. The software
|
||||
# provided hereunder is on an "as is" basis, and Richard Coleman and the
|
||||
# Zsh Development Group have no obligation to provide maintenance,
|
||||
# support, updates, enhancements, or modifications.
|
||||
#
|
||||
|
||||
# ========== OVERRIDABLE VARIABLES ==========
|
||||
|
||||
# subdir is done by mkmakemod.sh
|
||||
# dir_top is done by mkmakemod.sh
|
||||
# SUBDIRS is done by mkmakemod.sh
|
||||
|
||||
@VERSION_MK@
|
||||
|
||||
# source/build directories
|
||||
VPATH = @srcdir@
|
||||
sdir = @srcdir@
|
||||
sdir_top = @top_srcdir@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
@DEFS_MK@
|
||||
|
||||
sdir_src = $(sdir_top)/Src
|
||||
dir_src = $(dir_top)/Src
|
||||
|
||||
# ========== COMPILATION RULES ==========
|
||||
|
||||
DNCFLAGS =
|
||||
|
||||
COMPILE = $(CC) -c -I. -I$(dir_top)/Src -I$(sdir_top)/Src -I$(sdir_top)/Src/Zle -I$(sdir) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(D@L@CFLAGS)
|
||||
DLCOMPILE = $(CC) -c -I. -I$(dir_top)/Src -I$(sdir_top)/Src -I$(sdir_top)/Src/Zle -I$(sdir) $(CPPFLAGS) $(DEFS) -DMODULE $(CFLAGS) $(DLCFLAGS)
|
||||
LINK = $(CC) $(LDFLAGS) $(EXELDFLAGS) $(EXTRA_LDFLAGS) -o $@
|
||||
DLLINK = $(DLLD) $(LDFLAGS) $(LIBLDFLAGS) $(DLLDFLAGS) -o $@
|
||||
|
||||
KNR_OBJ=.o
|
||||
KNROBJ=._foo_
|
||||
|
||||
ANSIOBJ=.o
|
||||
ANSI_OBJ=._foo_
|
||||
|
||||
.SUFFIXES: .c .$(DL_EXT) ..o .._foo_ .o ._foo_ .syms .pro .epro
|
||||
|
||||
.c$(ANSI@U@OBJ):
|
||||
$(COMPILE) -o $@ $<
|
||||
@rm -f $(dir_src)/stamp-modobjs
|
||||
|
||||
.c$(KNR@U@OBJ):
|
||||
@ANSI2KNR@ $< > $@.c
|
||||
$(COMPILE) -o $@ $@.c
|
||||
rm -f $@.c
|
||||
@rm -f $(dir_src)/stamp-modobjs
|
||||
|
||||
.c.$(ANSI@U@OBJ):
|
||||
$(DLCOMPILE) -o $@ $<
|
||||
|
||||
.c.$(KNR@U@OBJ):
|
||||
@ANSI2KNR@ $< > $@.c
|
||||
$(DLCOMPILE) -o $@ $@.c
|
||||
rm -f $@.c
|
||||
|
||||
.c.syms:
|
||||
$(AWK) -f $(sdir_src)/makepro.awk $< $(subdir) > $@
|
||||
|
||||
.syms.epro:
|
||||
(echo '/* Generated automatically */'; sed -n '/^E/{s/^E//;p;}' < $<) \
|
||||
> $@
|
||||
(echo '/* Generated automatically */'; sed -n '/^L/{s/^L//;p;}' < $<) \
|
||||
> `echo $@ | sed 's/\.epro$$/.pro/'`
|
||||
|
||||
PROTODEPS = $(sdir_src)/makepro.awk
|
||||
|
||||
# ========== DEPENDENCIES FOR BUILDING ==========
|
||||
|
||||
all: modobjs modules
|
||||
.PHONY: all
|
||||
|
||||
modobjs: $(MODOBJS)
|
||||
modules: $(MODULES)
|
||||
headers: $(MDHS)
|
||||
proto: $(PROTOS)
|
||||
.PHONY: modobjs modules headers proto
|
||||
|
||||
prep:
|
||||
@case $(sdir_top) in \
|
||||
/*) top_srcdir=$(sdir_top) ;; \
|
||||
*) top_srcdir=$(subdir)/$(sdir_top) ;; \
|
||||
esac; \
|
||||
export top_srcdir; \
|
||||
cd $(dir_top) || exit 1; \
|
||||
subdirs='$(SUBDIRS)'; \
|
||||
for subdir in $$subdirs; do \
|
||||
dir=$(subdir)/$$subdir; \
|
||||
test -d $$dir || mkdir $$dir; \
|
||||
$(SHELL) $$top_srcdir/Src/mkmakemod.sh $$dir Makefile || exit 1; \
|
||||
( cd $$dir && $(MAKE) $(MAKEDEFS) $@ ) || exit 1; \
|
||||
done
|
||||
.PHONY: prep
|
||||
|
||||
headers: $(dir_src)/modules.stamp
|
||||
$(dir_src)/modules.stamp: $(MDDS)
|
||||
$(MAKE) -f $(makefile) $(MAKEDEFS) prep
|
||||
echo 'timestamp for *.mdd files' > $@
|
||||
.PHONY: headers
|
||||
|
||||
FORCE:
|
||||
.PHONY: FORCE
|
||||
|
||||
# ========== DEPENDENCIES FOR INSTALLING ==========
|
||||
|
||||
install: install.bin install.modules
|
||||
uninstall: uninstall.bin uninstall.modules
|
||||
.PHONY: install uninstall
|
||||
|
||||
install.bin: install.bin-here
|
||||
uninstall.bin: uninstall.bin-here
|
||||
install.modules: install.modules-here
|
||||
uninstall.modules: uninstall.modules-here
|
||||
.PHONY: install.bin uninstall.bin install.modules uninstall.modules
|
||||
|
||||
install.bin-here uninstall.bin-here:
|
||||
install.modules-here uninstall.modules-here:
|
||||
.PHONY: install.bin-here install.modules-here
|
||||
|
||||
# ========== DEPENDENCIES FOR CLEANUP ==========
|
||||
|
||||
@CLEAN_MK@
|
||||
|
||||
mostlyclean-here:
|
||||
rm -f *.o *.export *.$(DL_EXT)
|
||||
.PHONY: mostlyclean-here
|
||||
|
||||
clean-here:
|
||||
rm -f *.o.c *.syms *.pro *.epro *.mdh *.mdhi *.mdhs *.mdh.tmp
|
||||
.PHONY: clean-here
|
||||
|
||||
distclean-here:
|
||||
rm -f $(makefile) $(makefile).in
|
||||
.PHONY: distclean-here
|
||||
|
||||
# ========== RECURSIVE MAKES ==========
|
||||
|
||||
install.bin uninstall.bin install.modules uninstall.modules \
|
||||
modobjs modules headers proto:
|
||||
@subdirs='$(SUBDIRS)'; for subdir in $$subdirs; do \
|
||||
( cd $$subdir && $(MAKE) $(MAKEDEFS) $@ ) || exit 1; \
|
||||
done
|
||||
|
||||
# ========== DEPENDENCIES FOR MAINTENANCE ==========
|
||||
|
||||
$(makefile): $(makefile).in $(dir_top)/config.status
|
||||
@case $(sdir_top) in \
|
||||
/*) top_srcdir=$(sdir_top) ;; \
|
||||
*) top_srcdir=$(subdir)/$(sdir_top) ;; \
|
||||
esac; \
|
||||
export top_srcdir; \
|
||||
echo 'cd $(dir_top) && $(SHELL)' \
|
||||
'$$top_srcdir/Src/mkmakemod.sh -m $(subdir) $(makefile)'; \
|
||||
cd $(dir_top) && \
|
||||
$(SHELL) $$top_srcdir/Src/mkmakemod.sh -m $(subdir) $(makefile)
|
||||
|
||||
$(makefile).in: $(sdir_src)/mkmakemod.sh $(sdir_src)/Makemod.in.in $(MDDS) \
|
||||
$(dir_top)/config.modules
|
||||
@case $(sdir_top) in \
|
||||
/*) top_srcdir=$(sdir_top) ;; \
|
||||
*) top_srcdir=$(subdir)/$(sdir_top) ;; \
|
||||
esac; \
|
||||
export top_srcdir; \
|
||||
echo 'cd $(dir_top) && $(SHELL)' \
|
||||
'$$top_srcdir/Src/mkmakemod.sh -i $(subdir) $(makefile)'; \
|
||||
cd $(dir_top) && \
|
||||
$(SHELL) $$top_srcdir/Src/mkmakemod.sh -i $(subdir) $(makefile)
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,742 +0,0 @@
|
|||
/*
|
||||
* compat.c - compatibility routines for the deprived
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "zsh.mdh"
|
||||
#include "compat.pro"
|
||||
|
||||
/* Return pointer to first occurence of string t *
|
||||
* in string s. Return NULL if not present. */
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_STRSTR
|
||||
|
||||
/**/
|
||||
char *
|
||||
strstr(const char *s, const char *t)
|
||||
{
|
||||
const char *p1, *p2;
|
||||
|
||||
for (; *s; s++) {
|
||||
for (p1 = s, p2 = t; *p2; p1++, p2++)
|
||||
if (*p1 != *p2)
|
||||
break;
|
||||
if (!*p2)
|
||||
return (char *)s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_GETHOSTNAME
|
||||
|
||||
/**/
|
||||
int
|
||||
gethostname(char *name, size_t namelen)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
uname(&uts);
|
||||
if(strlen(uts.nodename) >= namelen) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
strcpy(name, uts.nodename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
|
||||
/**/
|
||||
int
|
||||
gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
tv->tv_usec = 0;
|
||||
tv->tv_sec = (long)time((time_t) 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
/* Provide clock time with nanoseconds */
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
zgettime(struct timespec *ts)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
struct timespec dts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &dts) < 0) {
|
||||
zwarn("unable to retrieve time: %e", errno);
|
||||
ret--;
|
||||
} else {
|
||||
ret++;
|
||||
ts->tv_sec = (time_t) dts.tv_sec;
|
||||
ts->tv_nsec = (long) dts.tv_nsec;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret) {
|
||||
struct timeval dtv;
|
||||
struct timezone dtz;
|
||||
gettimeofday(&dtv, &dtz);
|
||||
ret++;
|
||||
ts->tv_sec = (time_t) dtv.tv_sec;
|
||||
ts->tv_nsec = (long) dtv.tv_usec * 1000;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* compute the difference between two calendar times */
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_DIFFTIME
|
||||
|
||||
/**/
|
||||
double
|
||||
difftime(time_t t2, time_t t1)
|
||||
{
|
||||
return ((double)t2 - (double)t1);
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_STRERROR
|
||||
extern char *sys_errlist[];
|
||||
|
||||
/* Get error message string associated with a particular *
|
||||
* error number, and returns a pointer to that string. *
|
||||
* This is not a particularly robust version of strerror. */
|
||||
|
||||
/**/
|
||||
char *
|
||||
strerror(int errnum)
|
||||
{
|
||||
return (sys_errlist[errnum]);
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
/* pathconf(_PC_PATH_MAX) is not currently useful to zsh. The value *
|
||||
* returned varies depending on a number of factors, e.g. the amount *
|
||||
* of memory available to the operating system at a given time; thus *
|
||||
* it can't be used for buffer allocation, or even as an indication *
|
||||
* of whether an attempt to use or create a given pathname may fail *
|
||||
* at any future time. *
|
||||
* *
|
||||
* The call is also permitted to fail if the argument path is not an *
|
||||
* existing directory, so even to make sense of that one must search *
|
||||
* for a valid directory somewhere in the path and adjust. Even if *
|
||||
* it succeeds, the return value is relative to the input directory, *
|
||||
* and therefore potentially relative to the length of the shortest *
|
||||
* path either to that directory or to our working directory. *
|
||||
* *
|
||||
* Finally, see the note below for glibc; detection of pathconf() is *
|
||||
* not by itself an indication that it works reliably. */
|
||||
|
||||
/* The documentation for pathconf() says something like: *
|
||||
* The limit is returned, if one exists. If the system does *
|
||||
* not have a limit for the requested resource, -1 is *
|
||||
* returned, and errno is unchanged. If there is an error, *
|
||||
* -1 is returned, and errno is set to reflect the nature of *
|
||||
* the error. *
|
||||
* *
|
||||
* System calls are not permitted to set errno to 0; but we must (or *
|
||||
* some other flag value) in order to determine that the resource is *
|
||||
* unlimited. What use is leaving errno unchanged? Instead, define *
|
||||
* a wrapper that resets errno to 0 and returns 0 for "the system *
|
||||
* does not have a limit," so that -1 always means a real error. */
|
||||
|
||||
/**/
|
||||
mod_export long
|
||||
zpathmax(char *dir)
|
||||
{
|
||||
#ifdef HAVE_PATHCONF
|
||||
long pathmax;
|
||||
|
||||
errno = 0;
|
||||
if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
|
||||
/* Some versions of glibc pathconf return a hardwired value! */
|
||||
return pathmax;
|
||||
} else if (errno == EINVAL || errno == ENOENT || errno == ENOTDIR) {
|
||||
/* Work backward to find a directory, until we run out of path. */
|
||||
char *tail = strrchr(dir, '/');
|
||||
while (tail > dir && tail[-1] == '/')
|
||||
--tail;
|
||||
if (tail > dir) {
|
||||
*tail = 0;
|
||||
pathmax = zpathmax(dir);
|
||||
*tail = '/';
|
||||
} else {
|
||||
errno = 0;
|
||||
if (tail)
|
||||
pathmax = pathconf("/", _PC_PATH_MAX);
|
||||
else
|
||||
pathmax = pathconf(".", _PC_PATH_MAX);
|
||||
}
|
||||
if (pathmax > 0) {
|
||||
long taillen = (tail ? strlen(tail) : (strlen(dir) + 1));
|
||||
if (taillen < pathmax)
|
||||
return pathmax - taillen;
|
||||
else
|
||||
errno = ENAMETOOLONG;
|
||||
}
|
||||
}
|
||||
if (errno)
|
||||
return -1;
|
||||
else
|
||||
return 0; /* pathmax should be considered unlimited */
|
||||
#else
|
||||
long dirlen = strlen(dir);
|
||||
|
||||
/* The following is wrong if dir is not an absolute path. */
|
||||
return ((long) ((dirlen >= PATH_MAX) ?
|
||||
((errno = ENAMETOOLONG), -1) :
|
||||
((errno = 0), PATH_MAX - dirlen)));
|
||||
#endif
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/**/
|
||||
#ifdef HAVE_SYSCONF
|
||||
/*
|
||||
* This is replaced by a macro from system.h if not HAVE_SYSCONF.
|
||||
* 0 is returned by sysconf if _SC_OPEN_MAX is unavailable;
|
||||
* -1 is returned on error
|
||||
*
|
||||
* Neither of these should happen, but resort to OPEN_MAX rather
|
||||
* than return 0 or -1 just in case.
|
||||
*
|
||||
* We'll limit the open maximum to ZSH_INITIAL_OPEN_MAX to
|
||||
* avoid probing ridiculous numbers of file descriptors.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export long
|
||||
zopenmax(void)
|
||||
{
|
||||
long openmax;
|
||||
|
||||
if ((openmax = sysconf(_SC_OPEN_MAX)) < 1) {
|
||||
openmax = OPEN_MAX;
|
||||
} else if (openmax > OPEN_MAX) {
|
||||
/* On some systems, "limit descriptors unlimited" or the *
|
||||
* equivalent will set openmax to a huge number. Unless *
|
||||
* there actually is a file descriptor > OPEN_MAX already *
|
||||
* open, nothing in zsh requires the true maximum, and in *
|
||||
* fact it causes inefficiency elsewhere if we report it. *
|
||||
* So, report the maximum of OPEN_MAX or the largest open *
|
||||
* descriptor (is there a better way to find that?). */
|
||||
long i, j = OPEN_MAX;
|
||||
if (openmax > ZSH_INITIAL_OPEN_MAX)
|
||||
openmax = ZSH_INITIAL_OPEN_MAX;
|
||||
for (i = j; i < openmax; i += (errno != EINTR)) {
|
||||
errno = 0;
|
||||
if (fcntl(i, F_GETFL, 0) < 0 &&
|
||||
(errno == EBADF || errno == EINTR))
|
||||
continue;
|
||||
j = i;
|
||||
}
|
||||
openmax = j;
|
||||
}
|
||||
|
||||
return (max_zsh_fd > openmax) ? max_zsh_fd : openmax;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rationalise the current directory, returning the string.
|
||||
*
|
||||
* If "d" is not NULL, it is used to store information about the
|
||||
* directory. The returned name is also present in d->dirname and is in
|
||||
* permanently allocated memory. The handling of this case depends on
|
||||
* whether the fchdir() system call is available; if it is, it is assumed
|
||||
* the caller is able to restore the current directory. On successfully
|
||||
* identifying the directory the function returns immediately rather
|
||||
* than ascending the hierarchy.
|
||||
*
|
||||
* If "d" is NULL, no assumption about the caller's behaviour is
|
||||
* made. The returned string is in heap memory. This case is
|
||||
* always handled by changing directory up the hierarchy.
|
||||
*
|
||||
* On Cygwin or other systems where USE_GETCWD is defined (at the
|
||||
* time of writing only QNX), we skip all the above and use the
|
||||
* getcwd() system call.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
zgetdir(struct dirsav *d)
|
||||
{
|
||||
char nbuf[PATH_MAX+3];
|
||||
char *buf;
|
||||
int bufsiz, pos;
|
||||
struct stat sbuf;
|
||||
ino_t pino;
|
||||
dev_t pdev;
|
||||
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
|
||||
struct dirent *de;
|
||||
DIR *dir;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
int len;
|
||||
#endif
|
||||
|
||||
buf = zhalloc(bufsiz = PATH_MAX+1);
|
||||
pos = bufsiz - 1;
|
||||
buf[pos] = '\0';
|
||||
strcpy(nbuf, "../");
|
||||
if (stat(".", &sbuf) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Record the initial inode and device */
|
||||
pino = sbuf.st_ino;
|
||||
pdev = sbuf.st_dev;
|
||||
if (d)
|
||||
d->ino = pino, d->dev = pdev;
|
||||
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
|
||||
#ifdef HAVE_FCHDIR
|
||||
else
|
||||
#endif
|
||||
holdintr();
|
||||
|
||||
for (;;) {
|
||||
/* Examine the parent of the current directory. */
|
||||
if (stat("..", &sbuf) < 0)
|
||||
break;
|
||||
|
||||
/* Inode and device of curtent directory */
|
||||
ino = pino;
|
||||
dev = pdev;
|
||||
/* Inode and device of current directory's parent */
|
||||
pino = sbuf.st_ino;
|
||||
pdev = sbuf.st_dev;
|
||||
|
||||
/* If they're the same, we've reached the root directory. */
|
||||
if (ino == pino && dev == pdev) {
|
||||
if (!buf[pos])
|
||||
buf[--pos] = '/';
|
||||
if (d) {
|
||||
#ifndef HAVE_FCHDIR
|
||||
zchdir(buf + pos);
|
||||
noholdintr();
|
||||
#endif
|
||||
return d->dirname = ztrdup(buf + pos);
|
||||
}
|
||||
zchdir(buf + pos);
|
||||
noholdintr();
|
||||
return buf + pos;
|
||||
}
|
||||
|
||||
/* Search the parent for the current directory. */
|
||||
if (!(dir = opendir("..")))
|
||||
break;
|
||||
|
||||
while ((de = readdir(dir))) {
|
||||
char *fn = de->d_name;
|
||||
/* Ignore `.' and `..'. */
|
||||
if (fn[0] == '.' &&
|
||||
(fn[1] == '\0' ||
|
||||
(fn[1] == '.' && fn[2] == '\0')))
|
||||
continue;
|
||||
#ifdef HAVE_STRUCT_DIRENT_D_STAT
|
||||
if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
|
||||
/* Found the directory we're currently in */
|
||||
strncpy(nbuf + 3, fn, PATH_MAX);
|
||||
break;
|
||||
}
|
||||
#else /* !HAVE_STRUCT_DIRENT_D_STAT */
|
||||
# ifdef HAVE_STRUCT_DIRENT_D_INO
|
||||
if (dev != pdev || (ino_t) de->d_ino == ino)
|
||||
# endif /* HAVE_STRUCT_DIRENT_D_INO */
|
||||
{
|
||||
/* Maybe found directory, need to check device & inode */
|
||||
strncpy(nbuf + 3, fn, PATH_MAX);
|
||||
lstat(nbuf, &sbuf);
|
||||
if (sbuf.st_dev == dev && sbuf.st_ino == ino)
|
||||
break;
|
||||
}
|
||||
#endif /* !HAVE_STRUCT_DIRENT_D_STAT */
|
||||
}
|
||||
closedir(dir);
|
||||
if (!de)
|
||||
break; /* Not found */
|
||||
/*
|
||||
* We get the "/" free just by copying from nbuf+2 instead
|
||||
* of nbuf+3, which is where we copied the path component.
|
||||
* This means buf[pos] is always a "/".
|
||||
*/
|
||||
len = strlen(nbuf + 2);
|
||||
pos -= len;
|
||||
while (pos <= 1) {
|
||||
char *newbuf = zhalloc(2*bufsiz);
|
||||
memcpy(newbuf + bufsiz, buf, bufsiz);
|
||||
buf = newbuf;
|
||||
pos += bufsiz;
|
||||
bufsiz *= 2;
|
||||
}
|
||||
memcpy(buf + pos, nbuf + 2, len);
|
||||
#ifdef HAVE_FCHDIR
|
||||
if (d)
|
||||
return d->dirname = ztrdup(buf + pos + 1);
|
||||
#endif
|
||||
if (chdir(".."))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the directory, if necessary.
|
||||
* We're changing back down the hierarchy, ignore the
|
||||
* "/" at buf[pos].
|
||||
*/
|
||||
if (d) {
|
||||
#ifndef HAVE_FCHDIR
|
||||
if (buf[pos])
|
||||
zchdir(buf + pos + 1);
|
||||
noholdintr();
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf[pos])
|
||||
zchdir(buf + pos + 1);
|
||||
noholdintr();
|
||||
|
||||
#else /* __CYGWIN__, USE_GETCWD cases */
|
||||
|
||||
if (!getcwd(buf, bufsiz)) {
|
||||
if (d) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (d) {
|
||||
return d->dirname = ztrdup(buf);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Something bad happened.
|
||||
* This has been seen when inside a special directory,
|
||||
* such as the Netapp .snapshot directory, that doesn't
|
||||
* appear as a directory entry in the parent directory.
|
||||
* We'll just need our best guess.
|
||||
*
|
||||
* We only get here from zgetcwd(); let that fall back to pwd.
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find the current directory.
|
||||
* If we couldn't work it out internally, fall back to getcwd().
|
||||
* If it fails, fall back to pwd; if zgetcwd() is being used
|
||||
* to set pwd, pwd should be NULL and we just return ".".
|
||||
*/
|
||||
|
||||
/**/
|
||||
char *
|
||||
zgetcwd(void)
|
||||
{
|
||||
char *ret = zgetdir(NULL);
|
||||
#ifdef HAVE_GETCWD
|
||||
if (!ret) {
|
||||
#ifdef GETCWD_CALLS_MALLOC
|
||||
char *cwd = getcwd(NULL, 0);
|
||||
if (cwd) {
|
||||
ret = dupstring(cwd);
|
||||
free(cwd);
|
||||
}
|
||||
#else
|
||||
char *cwdbuf = zalloc(PATH_MAX+1);
|
||||
ret = getcwd(cwdbuf, PATH_MAX);
|
||||
if (ret)
|
||||
ret = dupstring(ret);
|
||||
zfree(cwdbuf, PATH_MAX+1);
|
||||
#endif /* GETCWD_CALLS_MALLOC */
|
||||
}
|
||||
#endif /* HAVE_GETCWD */
|
||||
if (!ret)
|
||||
ret = unmeta(pwd);
|
||||
if (!ret)
|
||||
ret = dupstring(".");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* chdir with arbitrary long pathname. Returns 0 on success, -1 on normal *
|
||||
* failure and -2 when chdir failed and the current directory is lost.
|
||||
*
|
||||
* This is to be treated as if at system level, so dir is unmetafied but
|
||||
* terminated by a NULL.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
zchdir(char *dir)
|
||||
{
|
||||
char *s;
|
||||
int currdir = -2;
|
||||
|
||||
for (;;) {
|
||||
if (!*dir || chdir(dir) == 0) {
|
||||
#ifdef HAVE_FCHDIR
|
||||
if (currdir >= 0)
|
||||
close(currdir);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if ((errno != ENAMETOOLONG && errno != ENOMEM) ||
|
||||
strlen(dir) < PATH_MAX)
|
||||
break;
|
||||
for (s = dir + PATH_MAX - 1; s > dir && *s != '/'; s--)
|
||||
;
|
||||
if (s == dir)
|
||||
break;
|
||||
#ifdef HAVE_FCHDIR
|
||||
if (currdir == -2)
|
||||
currdir = open(".", O_RDONLY|O_NOCTTY);
|
||||
#endif
|
||||
*s = '\0';
|
||||
if (chdir(dir) < 0) {
|
||||
*s = '/';
|
||||
break;
|
||||
}
|
||||
#ifndef HAVE_FCHDIR
|
||||
currdir = -1;
|
||||
#endif
|
||||
*s = '/';
|
||||
while (*++s == '/')
|
||||
;
|
||||
dir = s;
|
||||
}
|
||||
#ifdef HAVE_FCHDIR
|
||||
if (currdir >= 0) {
|
||||
if (fchdir(currdir) < 0) {
|
||||
close(currdir);
|
||||
return -2;
|
||||
}
|
||||
close(currdir);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return currdir == -2 ? -1 : -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* How to print out a 64 bit integer. This isn't needed (1) if longs
|
||||
* are 64 bit, since ordinary %ld will work (2) if we couldn't find a
|
||||
* 64 bit type anyway.
|
||||
*/
|
||||
/**/
|
||||
#ifdef ZSH_64_BIT_TYPE
|
||||
/**/
|
||||
mod_export char *
|
||||
output64(zlong val)
|
||||
{
|
||||
static char llbuf[DIGBUFSIZE];
|
||||
convbase(llbuf, val, 0);
|
||||
return llbuf;
|
||||
}
|
||||
/**/
|
||||
#endif /* ZSH_64_BIT_TYPE */
|
||||
|
||||
/**/
|
||||
#ifndef HAVE_STRTOUL
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert a string to an unsigned long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
|
||||
/**/
|
||||
unsigned long
|
||||
strtoul(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
int base;
|
||||
{
|
||||
const char *s;
|
||||
unsigned long acc, cutoff;
|
||||
int c;
|
||||
int neg, any, cutlim;
|
||||
|
||||
/* endptr may be NULL */
|
||||
|
||||
s = nptr;
|
||||
do {
|
||||
c = (unsigned char) *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
cutoff = ULONG_MAX / (unsigned long)base;
|
||||
cutlim = (int)(ULONG_MAX % (unsigned long)base);
|
||||
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c)) {
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
} else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0)
|
||||
continue;
|
||||
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
|
||||
any = -1;
|
||||
acc = ULONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else {
|
||||
any = 1;
|
||||
acc *= (unsigned long)base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (neg && any > 0)
|
||||
acc = -acc;
|
||||
if (endptr != NULL)
|
||||
*endptr = any ? s - 1 : nptr;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* HAVE_STRTOUL */
|
||||
|
||||
/**/
|
||||
#ifdef ENABLE_UNICODE9
|
||||
#include "./wcwidth9.h"
|
||||
|
||||
/**/
|
||||
int
|
||||
u9_wcwidth(wchar_t ucs)
|
||||
{
|
||||
int w = wcwidth9(ucs);
|
||||
if (w < -1)
|
||||
return 1;
|
||||
return w;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
u9_iswprint(wint_t ucs)
|
||||
{
|
||||
if (ucs == 0)
|
||||
return 0;
|
||||
return wcwidth9(ucs) != -1;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* ENABLE_UNICODE9 */
|
||||
|
||||
/**/
|
||||
#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
|
||||
|
||||
/**/
|
||||
int
|
||||
isprint_ascii(int c)
|
||||
{
|
||||
if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
|
||||
return (c >= 0x20 && c <= 0x7e);
|
||||
else
|
||||
return isprint(c);
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* __APPLE__ && BROKEN_ISPRINT */
|
||||
6250
zmodules/Src/exec.c
6250
zmodules/Src/exec.c
File diff suppressed because it is too large
Load diff
3913
zmodules/Src/glob.c
3913
zmodules/Src/glob.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* hashtable.h - header file for hash table handling code
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Builtin function numbers; used by handler functions that handle more *
|
||||
* than one builtin. Note that builtins such as compctl, that are not *
|
||||
* overloaded, don't get a number. */
|
||||
|
||||
#define BIN_TYPESET 0
|
||||
#define BIN_BG 1
|
||||
#define BIN_FG 2
|
||||
#define BIN_JOBS 3
|
||||
#define BIN_WAIT 4
|
||||
#define BIN_DISOWN 5
|
||||
#define BIN_BREAK 6
|
||||
#define BIN_CONTINUE 7
|
||||
#define BIN_EXIT 8
|
||||
#define BIN_RETURN 9
|
||||
#define BIN_CD 10
|
||||
#define BIN_POPD 11
|
||||
#define BIN_PUSHD 12
|
||||
#define BIN_PRINT 13
|
||||
#define BIN_EVAL 14
|
||||
#define BIN_SCHED 15
|
||||
#define BIN_FC 16
|
||||
#define BIN_R 17
|
||||
#define BIN_PUSHLINE 18
|
||||
#define BIN_LOGOUT 19
|
||||
#define BIN_TEST 20
|
||||
#define BIN_BRACKET 21
|
||||
#define BIN_READONLY 22
|
||||
#define BIN_ECHO 23
|
||||
#define BIN_DISABLE 24
|
||||
#define BIN_ENABLE 25
|
||||
#define BIN_PRINTF 26
|
||||
#define BIN_COMMAND 27
|
||||
#define BIN_UNHASH 28
|
||||
#define BIN_UNALIAS 29
|
||||
#define BIN_UNFUNCTION 30
|
||||
#define BIN_UNSET 31
|
||||
|
||||
/* These currently depend on being 0 and 1. */
|
||||
#define BIN_SETOPT 0
|
||||
#define BIN_UNSETOPT 1
|
||||
1792
zmodules/Src/init.c
1792
zmodules/Src/init.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,701 +0,0 @@
|
|||
/*
|
||||
* input.c - read and store lines of input
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file deals with input buffering, supplying characters to the
|
||||
* history expansion code a character at a time. Input is stored on a
|
||||
* stack, which allows insertion of strings into the input, possibly with
|
||||
* flags marking the end of alias expansion, with minimal copying of
|
||||
* strings. The same stack is used to record the fact that the input
|
||||
* is a history or alias expansion and to store the alias while it is in use.
|
||||
*
|
||||
* Input is taken either from zle, if appropriate, or read directly from
|
||||
* the input file, or may be supplied by some other part of the shell (such
|
||||
* as `eval' or $(...) substitution). In the last case, it should be
|
||||
* supplied by pushing a new level onto the stack, via inpush(input_string,
|
||||
* flag, alias); if the current input really needs to be altered, use
|
||||
* inputsetline(input_string, flag). `Flag' can include or's of INP_FREE
|
||||
* (if the input string is to be freed when used), INP_CONT (if the input
|
||||
* is to continue onto what's already in the input queue), INP_ALIAS
|
||||
* (push supplied alias onto stack) or INP_HIST (ditto, but used to
|
||||
* mark history expansion). `alias' is ignored unless INP_ALIAS or
|
||||
* INP_HIST is supplied. INP_ALIAS is always set if INP_HIST is.
|
||||
*
|
||||
* Note that the input string is itself used as the input buffer: it is not
|
||||
* copied, nor is it every written back to, so using a constant string
|
||||
* should work. Consequently, when passing areas of memory from the heap
|
||||
* it is necessary that that heap last as long as the operation of reading
|
||||
* the string. After the string is read, the stack should be popped with
|
||||
* inpop(), which effectively flushes any unread input as well as restoring
|
||||
* the previous input state.
|
||||
*
|
||||
* The internal flags INP_ALCONT and INP_HISTCONT show that the stack
|
||||
* element was pushed by an alias or history expansion; they should not
|
||||
* be needed elsewhere.
|
||||
*
|
||||
* The global variable inalmore is set to indicate aliases should
|
||||
* continue to be expanded because the last alias expansion ended
|
||||
* in a space. It is only reset after a complete word was read
|
||||
* without expanding a new alias, in exalias().
|
||||
*
|
||||
* PWS 1996/12/10
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "zsh.mdh"
|
||||
#include "input.pro"
|
||||
|
||||
/* the shell input fd */
|
||||
|
||||
/**/
|
||||
int SHIN;
|
||||
|
||||
/* buffered shell input for non-interactive shells */
|
||||
|
||||
/**/
|
||||
FILE *bshin;
|
||||
|
||||
/* != 0 means we are reading input from a string */
|
||||
|
||||
/**/
|
||||
int strin;
|
||||
|
||||
/* total # of characters waiting to be read. */
|
||||
|
||||
/**/
|
||||
mod_export int inbufct;
|
||||
|
||||
/* the flags controlling the input routines in input.c: see INP_* in zsh.h */
|
||||
|
||||
/**/
|
||||
int inbufflags;
|
||||
|
||||
static char *inbuf; /* Current input buffer */
|
||||
static char *inbufptr; /* Pointer into input buffer */
|
||||
static char *inbufpush; /* Character at which to re-push alias */
|
||||
static int inbufleft; /* Characters left in current input
|
||||
stack element */
|
||||
|
||||
|
||||
/* Input must be stacked since the input queue is used by
|
||||
* various different parts of the shell.
|
||||
*/
|
||||
|
||||
struct instacks {
|
||||
char *buf, *bufptr;
|
||||
Alias alias;
|
||||
int bufleft, bufct, flags;
|
||||
};
|
||||
static struct instacks *instack, *instacktop;
|
||||
/*
|
||||
* Input stack size. We need to push the stack for aliases, history
|
||||
* expansion, and reading from internal strings: only if these operations
|
||||
* are nested do we need more than one extra level. Thus we shouldn't need
|
||||
* too much space as a rule. Initially, INSTACK_INITIAL is allocated; if
|
||||
* more is required, an extra INSTACK_EXPAND is added each time.
|
||||
*/
|
||||
#define INSTACK_INITIAL 4
|
||||
#define INSTACK_EXPAND 4
|
||||
|
||||
static int instacksz = INSTACK_INITIAL;
|
||||
|
||||
/* Read a line from bshin. Convert tokens and *
|
||||
* null characters to Meta c^32 character pairs. */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
shingetline(void)
|
||||
{
|
||||
char *line = NULL;
|
||||
int ll = 0;
|
||||
int c;
|
||||
char buf[BUFSIZ];
|
||||
char *p;
|
||||
int q = queue_signal_level();
|
||||
|
||||
p = buf;
|
||||
winch_unblock();
|
||||
dont_queue_signals();
|
||||
for (;;) {
|
||||
/* Can't fgets() here because we need to accept '\0' bytes */
|
||||
do {
|
||||
errno = 0;
|
||||
c = fgetc(bshin);
|
||||
} while (c < 0 && errno == EINTR);
|
||||
if (c < 0 || c == '\n') {
|
||||
winch_block();
|
||||
restore_queue_signals(q);
|
||||
if (c == '\n')
|
||||
*p++ = '\n';
|
||||
if (p > buf) {
|
||||
*p++ = '\0';
|
||||
line = zrealloc(line, ll + (p - buf));
|
||||
memcpy(line + ll, buf, p - buf);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
if (imeta(c)) {
|
||||
*p++ = Meta;
|
||||
*p++ = c ^ 32;
|
||||
} else
|
||||
*p++ = c;
|
||||
if (p >= buf + BUFSIZ - 1) {
|
||||
winch_block();
|
||||
queue_signals();
|
||||
line = zrealloc(line, ll + (p - buf) + 1);
|
||||
memcpy(line + ll, buf, p - buf);
|
||||
ll += p - buf;
|
||||
line[ll] = '\0';
|
||||
p = buf;
|
||||
winch_unblock();
|
||||
dont_queue_signals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the next character from the input.
|
||||
* Will call inputline() to get a new line where necessary.
|
||||
*/
|
||||
|
||||
/**/
|
||||
int
|
||||
ingetc(void)
|
||||
{
|
||||
int lastc = ' ';
|
||||
|
||||
if (lexstop)
|
||||
return ' ';
|
||||
for (;;) {
|
||||
if (inbufleft) {
|
||||
inbufleft--;
|
||||
inbufct--;
|
||||
if (itok(lastc = STOUC(*inbufptr++)))
|
||||
continue;
|
||||
if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n')
|
||||
lineno++;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have reached the end of input
|
||||
* (due to an error, or to reading from a single string).
|
||||
* Check the remaining characters left, since if there aren't
|
||||
* any we don't want to pop the stack---it'll mark any aliases
|
||||
* as not in use before we've finished processing.
|
||||
*/
|
||||
if (!inbufct && (strin || errflag)) {
|
||||
lexstop = 1;
|
||||
break;
|
||||
}
|
||||
/* If the next element down the input stack is a continuation of
|
||||
* this, use it.
|
||||
*/
|
||||
if (inbufflags & INP_CONT) {
|
||||
inpoptop();
|
||||
continue;
|
||||
}
|
||||
/* As a last resort, get some more input */
|
||||
if (inputline())
|
||||
break;
|
||||
}
|
||||
if (!lexstop)
|
||||
zshlex_raw_add(lastc);
|
||||
return lastc;
|
||||
}
|
||||
|
||||
/* Read a line from the current command stream and store it as input */
|
||||
|
||||
/**/
|
||||
static int
|
||||
inputline(void)
|
||||
{
|
||||
char *ingetcline, **ingetcpmptl = NULL, **ingetcpmptr = NULL;
|
||||
int context = ZLCON_LINE_START;
|
||||
|
||||
/* If reading code interactively, work out the prompts. */
|
||||
if (interact && isset(SHINSTDIN)) {
|
||||
if (!isfirstln) {
|
||||
ingetcpmptl = &prompt2;
|
||||
if (rprompt2)
|
||||
ingetcpmptr = &rprompt2;
|
||||
context = ZLCON_LINE_CONT;
|
||||
}
|
||||
else {
|
||||
ingetcpmptl = &prompt;
|
||||
if (rprompt)
|
||||
ingetcpmptr = &rprompt;
|
||||
}
|
||||
}
|
||||
if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
|
||||
/*
|
||||
* If not using zle, read the line straight from the input file.
|
||||
* Possibly we don't get the whole line at once: in that case,
|
||||
* we get another chunk with the next call to inputline().
|
||||
*/
|
||||
|
||||
if (interact && isset(SHINSTDIN)) {
|
||||
/*
|
||||
* We may still be interactive (e.g. running under emacs),
|
||||
* so output a prompt if necessary. We don't know enough
|
||||
* about the input device to be able to handle an rprompt,
|
||||
* though.
|
||||
*/
|
||||
char *pptbuf;
|
||||
int pptlen;
|
||||
pptbuf = unmetafy(promptexpand(ingetcpmptl ? *ingetcpmptl : NULL,
|
||||
0, NULL, NULL, NULL), &pptlen);
|
||||
write_loop(2, pptbuf, pptlen);
|
||||
free(pptbuf);
|
||||
}
|
||||
ingetcline = shingetline();
|
||||
} else {
|
||||
/*
|
||||
* Since we may have to read multiple lines before getting
|
||||
* a complete piece of input, we tell zle not to restore the
|
||||
* original tty settings after reading each chunk. Instead,
|
||||
* this is done when the history mechanism for the current input
|
||||
* terminates, which is not until we have the whole input.
|
||||
* This is supposed to minimise problems on systems that clobber
|
||||
* typeahead when the terminal settings are altered.
|
||||
* pws 1998/03/12
|
||||
*/
|
||||
int flags = ZLRF_HISTORY|ZLRF_NOSETTY;
|
||||
if (isset(IGNOREEOF))
|
||||
flags |= ZLRF_IGNOREEOF;
|
||||
ingetcline = zleentry(ZLE_CMD_READ, ingetcpmptl, ingetcpmptr,
|
||||
flags, context);
|
||||
histdone |= HISTFLAG_SETTY;
|
||||
}
|
||||
if (!ingetcline) {
|
||||
return lexstop = 1;
|
||||
}
|
||||
if (errflag) {
|
||||
free(ingetcline);
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return lexstop = 1;
|
||||
}
|
||||
if (isset(VERBOSE)) {
|
||||
/* Output the whole line read so far. */
|
||||
zputs(ingetcline, stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (keyboardhackchar && *ingetcline &&
|
||||
ingetcline[strlen(ingetcline) - 1] == '\n' &&
|
||||
interact && isset(SHINSTDIN) &&
|
||||
SHTTY != -1 && ingetcline[1])
|
||||
{
|
||||
char *stripptr = ingetcline + strlen(ingetcline) - 2;
|
||||
if (*stripptr == keyboardhackchar) {
|
||||
/* Junk an unwanted character at the end of the line.
|
||||
(key too close to return key) */
|
||||
int ct = 1; /* force odd */
|
||||
char *ptr;
|
||||
|
||||
if (keyboardhackchar == '\'' || keyboardhackchar == '"' ||
|
||||
keyboardhackchar == '`') {
|
||||
/*
|
||||
* for the chars above, also require an odd count before
|
||||
* junking
|
||||
*/
|
||||
for (ct = 0, ptr = ingetcline; *ptr; ptr++)
|
||||
if (*ptr == keyboardhackchar)
|
||||
ct++;
|
||||
}
|
||||
if (ct & 1) {
|
||||
stripptr[0] = '\n';
|
||||
stripptr[1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
isfirstch = 1;
|
||||
if ((inbufflags & INP_APPEND) && inbuf) {
|
||||
/*
|
||||
* We need new input but need to be able to back up
|
||||
* over the old input, so append this line.
|
||||
* Pushing the line onto the stack doesn't have the right
|
||||
* effect.
|
||||
*
|
||||
* This is quite a simple and inefficient fix, but currently
|
||||
* we only need it when backing up over a multi-line $((...
|
||||
* that turned out to be a command substitution rather than
|
||||
* a math substitution, which is a very special case.
|
||||
* So it's not worth rewriting.
|
||||
*/
|
||||
char *oinbuf = inbuf;
|
||||
int newlen = strlen(ingetcline);
|
||||
int oldlen = (int)(inbufptr - inbuf) + inbufleft;
|
||||
if (inbufflags & INP_FREE) {
|
||||
inbuf = realloc(inbuf, oldlen + newlen + 1);
|
||||
} else {
|
||||
inbuf = zalloc(oldlen + newlen + 1);
|
||||
memcpy(inbuf, oinbuf, oldlen);
|
||||
}
|
||||
inbufptr += inbuf - oinbuf;
|
||||
strcpy(inbuf + oldlen, ingetcline);
|
||||
free(ingetcline);
|
||||
inbufleft += newlen;
|
||||
inbufct += newlen;
|
||||
inbufflags |= INP_FREE;
|
||||
} else {
|
||||
/* Put this into the input channel. */
|
||||
inputsetline(ingetcline, INP_FREE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a string in the input queue:
|
||||
* inbuf is only freeable if the flags include INP_FREE.
|
||||
*/
|
||||
|
||||
/**/
|
||||
static void
|
||||
inputsetline(char *str, int flags)
|
||||
{
|
||||
queue_signals();
|
||||
|
||||
if ((inbufflags & INP_FREE) && inbuf) {
|
||||
free(inbuf);
|
||||
}
|
||||
inbuf = inbufptr = str;
|
||||
inbufleft = strlen(inbuf);
|
||||
|
||||
/*
|
||||
* inbufct must reflect the total number of characters left,
|
||||
* as it used by other parts of the shell, so we need to take account
|
||||
* of whether the input stack continues, and whether there
|
||||
* is an extra space to add on at the end.
|
||||
*/
|
||||
if (flags & INP_CONT)
|
||||
inbufct += inbufleft;
|
||||
else
|
||||
inbufct = inbufleft;
|
||||
inbufflags = flags;
|
||||
|
||||
unqueue_signals();
|
||||
}
|
||||
|
||||
/*
|
||||
* Backup one character of the input.
|
||||
* The last character can always be backed up, provided we didn't just
|
||||
* expand an alias or a history reference.
|
||||
* In fact, the character is ignored and the previous character is used.
|
||||
* (If that's wrong, the bug is in the calling code. Use the #ifdef DEBUG
|
||||
* code to check.)
|
||||
*/
|
||||
|
||||
/**/
|
||||
void
|
||||
inungetc(int c)
|
||||
{
|
||||
if (!lexstop) {
|
||||
if (inbufptr != inbuf) {
|
||||
#ifdef DEBUG
|
||||
/* Just for debugging: enable only if foul play suspected. */
|
||||
if (inbufptr[-1] != (char) c)
|
||||
fprintf(stderr, "Warning: backing up wrong character.\n");
|
||||
#endif
|
||||
/* Just decrement the pointer: if it's not the same
|
||||
* character being pushed back, we're in trouble anyway.
|
||||
*/
|
||||
inbufptr--;
|
||||
inbufct++;
|
||||
inbufleft++;
|
||||
if (((inbufflags & INP_LINENO) || !strin) && c == '\n')
|
||||
lineno--;
|
||||
}
|
||||
else if (!(inbufflags & INP_CONT)) {
|
||||
#ifdef DEBUG
|
||||
/* Just for debugging */
|
||||
fprintf(stderr, "Attempt to inungetc() at start of input.\n");
|
||||
#endif
|
||||
zerr("Garbled input at %c (binary file as commands?)", c);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* The character is being backed up from a previous input stack
|
||||
* layer. However, there was an expansion in the middle, so we
|
||||
* can't back up where we want to. Instead, we just push it
|
||||
* onto the input stack as an extra character.
|
||||
*/
|
||||
char *cback = (char *)zshcalloc(2);
|
||||
cback[0] = (char) c;
|
||||
inpush(cback, INP_FREE|INP_CONT, NULL);
|
||||
}
|
||||
/* If we are back at the start of a segment,
|
||||
* we may need to restore an alias popped from the stack.
|
||||
* Note this may be a dummy (history expansion) entry.
|
||||
*/
|
||||
if (inbufptr == inbufpush &&
|
||||
(inbufflags & (INP_ALCONT|INP_HISTCONT))) {
|
||||
/*
|
||||
* Go back up the stack over all entries which were alias
|
||||
* expansions and were pushed with nothing remaining to read.
|
||||
*/
|
||||
do {
|
||||
if (instacktop->alias)
|
||||
instacktop->alias->inuse = 1;
|
||||
instacktop++;
|
||||
} while ((instacktop->flags & (INP_ALCONT|INP_HISTCONT))
|
||||
&& !instacktop->bufleft);
|
||||
if (inbufflags & INP_HISTCONT)
|
||||
inbufflags = INP_CONT|INP_ALIAS|INP_HIST;
|
||||
else
|
||||
inbufflags = INP_CONT|INP_ALIAS;
|
||||
inbufleft = 0;
|
||||
inbuf = inbufptr = "";
|
||||
}
|
||||
zshlex_raw_back();
|
||||
}
|
||||
}
|
||||
|
||||
/* stuff a whole file into the input queue and print it */
|
||||
|
||||
/**/
|
||||
int
|
||||
stuff(char *fn)
|
||||
{
|
||||
FILE *in;
|
||||
char *buf;
|
||||
off_t len;
|
||||
|
||||
if (!(in = fopen(unmeta(fn), "r"))) {
|
||||
zerr("can't open %s", fn);
|
||||
return 1;
|
||||
}
|
||||
fseek(in, 0, 2);
|
||||
len = ftell(in);
|
||||
fseek(in, 0, 0);
|
||||
buf = (char *)zalloc(len + 1);
|
||||
if (!(fread(buf, len, 1, in))) {
|
||||
zerr("read error on %s", fn);
|
||||
fclose(in);
|
||||
zfree(buf, len + 1);
|
||||
return 1;
|
||||
}
|
||||
fclose(in);
|
||||
buf[len] = '\0';
|
||||
fwrite(buf, len, 1, stderr);
|
||||
fflush(stderr);
|
||||
inputsetline(metafy(buf, len, META_REALLOC), INP_FREE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* flush input queue */
|
||||
|
||||
/**/
|
||||
void
|
||||
inerrflush(void)
|
||||
{
|
||||
while (!lexstop && inbufct)
|
||||
ingetc();
|
||||
}
|
||||
|
||||
/* Set some new input onto a new element of the input stack */
|
||||
|
||||
/**/
|
||||
mod_export void
|
||||
inpush(char *str, int flags, Alias inalias)
|
||||
{
|
||||
if (!instack) {
|
||||
/* Initial stack allocation */
|
||||
instack = (struct instacks *)zalloc(instacksz*sizeof(struct instacks));
|
||||
instacktop = instack;
|
||||
}
|
||||
|
||||
instacktop->buf = inbuf;
|
||||
instacktop->bufptr = inbufptr;
|
||||
instacktop->bufleft = inbufleft;
|
||||
instacktop->bufct = inbufct;
|
||||
inbufflags &= ~(INP_ALCONT|INP_HISTCONT);
|
||||
if (flags & (INP_ALIAS|INP_HIST)) {
|
||||
/*
|
||||
* Text is expansion for history or alias, so continue
|
||||
* back to old level when done. Also mark stack top
|
||||
* as alias continuation so as to back up if necessary,
|
||||
* and mark alias as in use.
|
||||
*/
|
||||
flags |= INP_CONT|INP_ALIAS;
|
||||
if (flags & INP_HIST)
|
||||
instacktop->flags = inbufflags | INP_HISTCONT;
|
||||
else
|
||||
instacktop->flags = inbufflags | INP_ALCONT;
|
||||
if ((instacktop->alias = inalias))
|
||||
inalias->inuse = 1;
|
||||
} else {
|
||||
/* If we are continuing an alias expansion, record the alias
|
||||
* expansion in new set of flags (do we need this?)
|
||||
*/
|
||||
if (((instacktop->flags = inbufflags) & INP_ALIAS) &&
|
||||
(flags & INP_CONT))
|
||||
flags |= INP_ALIAS;
|
||||
}
|
||||
|
||||
instacktop++;
|
||||
if (instacktop == instack + instacksz) {
|
||||
/* Expand the stack */
|
||||
instack = (struct instacks *)
|
||||
realloc(instack,
|
||||
(instacksz + INSTACK_EXPAND)*sizeof(struct instacks));
|
||||
instacktop = instack + instacksz;
|
||||
instacksz += INSTACK_EXPAND;
|
||||
}
|
||||
/*
|
||||
* We maintain the entry above the highest one with real
|
||||
* text as a flag to inungetc() that it can stop re-pushing the stack.
|
||||
*/
|
||||
instacktop->flags = 0;
|
||||
|
||||
inbufpush = inbuf = NULL;
|
||||
|
||||
inputsetline(str, flags);
|
||||
}
|
||||
|
||||
/* Remove the top element of the stack */
|
||||
|
||||
/**/
|
||||
static void
|
||||
inpoptop(void)
|
||||
{
|
||||
if (!lexstop) {
|
||||
inbufflags &= ~(INP_ALCONT|INP_HISTCONT);
|
||||
while (inbufptr > inbuf) {
|
||||
inbufptr--;
|
||||
inbufct++;
|
||||
inbufleft++;
|
||||
/*
|
||||
* As elsewhere in input and history mechanisms:
|
||||
* unwinding aliases and unwinding history have different
|
||||
* implications as aliases are after the lexer while
|
||||
* history is before, but they're both pushed onto
|
||||
* the input stack.
|
||||
*/
|
||||
if ((inbufflags & (INP_ALIAS|INP_HIST|INP_RAW_KEEP)) == INP_ALIAS)
|
||||
zshlex_raw_back();
|
||||
}
|
||||
}
|
||||
|
||||
if (inbuf && (inbufflags & INP_FREE))
|
||||
free(inbuf);
|
||||
|
||||
instacktop--;
|
||||
|
||||
inbuf = instacktop->buf;
|
||||
inbufptr = inbufpush = instacktop->bufptr;
|
||||
inbufleft = instacktop->bufleft;
|
||||
inbufct = instacktop->bufct;
|
||||
inbufflags = instacktop->flags;
|
||||
|
||||
if (!(inbufflags & (INP_ALCONT|INP_HISTCONT)))
|
||||
return;
|
||||
|
||||
if (instacktop->alias) {
|
||||
char *t = instacktop->alias->text;
|
||||
/* a real alias: mark it as unused. */
|
||||
instacktop->alias->inuse = 0;
|
||||
if (*t && t[strlen(t) - 1] == ' ') {
|
||||
inalmore = 1;
|
||||
histbackword();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the top element of the stack and all its continuations. */
|
||||
|
||||
/**/
|
||||
mod_export void
|
||||
inpop(void)
|
||||
{
|
||||
int remcont;
|
||||
|
||||
do {
|
||||
remcont = inbufflags & INP_CONT;
|
||||
|
||||
inpoptop();
|
||||
} while (remcont);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expunge any aliases from the input stack; they shouldn't appear
|
||||
* in the history and need to be flushed explicitly when we encounter
|
||||
* an error.
|
||||
*/
|
||||
|
||||
/**/
|
||||
void
|
||||
inpopalias(void)
|
||||
{
|
||||
while (inbufflags & INP_ALIAS)
|
||||
inpoptop();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get pointer to remaining string to read.
|
||||
*/
|
||||
|
||||
/**/
|
||||
char *
|
||||
ingetptr(void)
|
||||
{
|
||||
return inbufptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the current input line, including continuations, is
|
||||
* expanding an alias. This does not detect alias expansions that
|
||||
* have been fully processed and popped from the input stack.
|
||||
* If there is an alias, the most recently expanded is returned,
|
||||
* else NULL.
|
||||
*/
|
||||
|
||||
/**/
|
||||
char *input_hasalias(void)
|
||||
{
|
||||
int flags = inbufflags;
|
||||
struct instacks *instackptr = instacktop;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(flags & INP_CONT))
|
||||
break;
|
||||
instackptr--;
|
||||
if (instackptr->alias)
|
||||
return instackptr->alias->node.nam;
|
||||
flags = instackptr->flags;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
2894
zmodules/Src/jobs.c
2894
zmodules/Src/jobs.c
File diff suppressed because it is too large
Load diff
2203
zmodules/Src/lex.c
2203
zmodules/Src/lex.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,795 +0,0 @@
|
|||
/*
|
||||
* loop.c - loop execution
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "zsh.mdh"
|
||||
#include "loop.pro"
|
||||
|
||||
/* # of nested loops we are in */
|
||||
|
||||
/**/
|
||||
int loops;
|
||||
|
||||
/* # of continue levels */
|
||||
|
||||
/**/
|
||||
mod_export int contflag;
|
||||
|
||||
/* # of break levels */
|
||||
|
||||
/**/
|
||||
mod_export int breaks;
|
||||
|
||||
/**/
|
||||
int
|
||||
execfor(Estate state, int do_exec)
|
||||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
|
||||
int last = 0;
|
||||
char *name, *str, *cond = NULL, *advance = NULL;
|
||||
zlong val = 0;
|
||||
LinkList vars = NULL, args = NULL;
|
||||
int old_simple_pline = simple_pline;
|
||||
|
||||
/* See comments in execwhile() */
|
||||
simple_pline = 1;
|
||||
|
||||
end = state->pc + WC_FOR_SKIP(code);
|
||||
|
||||
if (iscond) {
|
||||
str = dupstring(ecgetstr(state, EC_NODUP, NULL));
|
||||
singsub(&str);
|
||||
if (isset(XTRACE)) {
|
||||
char *str2 = dupstring(str);
|
||||
untokenize(str2);
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s\n", str2);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
if (!errflag) {
|
||||
matheval(str);
|
||||
}
|
||||
if (errflag) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 1;
|
||||
}
|
||||
cond = ecgetstr(state, EC_NODUP, &ctok);
|
||||
advance = ecgetstr(state, EC_NODUP, &atok);
|
||||
} else {
|
||||
vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL);
|
||||
|
||||
if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
|
||||
int htok = 0;
|
||||
|
||||
if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 0;
|
||||
}
|
||||
if (htok) {
|
||||
execsubst(args);
|
||||
if (errflag) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char **x;
|
||||
|
||||
args = newlinklist();
|
||||
for (x = pparams; *x; x++)
|
||||
addlinknode(args, dupstring(*x));
|
||||
}
|
||||
}
|
||||
|
||||
if (!args || empty(args))
|
||||
lastval = 0;
|
||||
|
||||
loops++;
|
||||
pushheap();
|
||||
cmdpush(CS_FOR);
|
||||
loop = state->pc;
|
||||
while (!last) {
|
||||
if (iscond) {
|
||||
if (ctok) {
|
||||
str = dupstring(cond);
|
||||
singsub(&str);
|
||||
} else
|
||||
str = cond;
|
||||
if (!errflag) {
|
||||
while (iblank(*str))
|
||||
str++;
|
||||
if (*str) {
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s\n", str);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
val = mathevali(str);
|
||||
} else
|
||||
val = 1;
|
||||
}
|
||||
if (errflag) {
|
||||
if (breaks)
|
||||
breaks--;
|
||||
lastval = 1;
|
||||
break;
|
||||
}
|
||||
if (!val)
|
||||
break;
|
||||
} else {
|
||||
LinkNode node;
|
||||
int count = 0;
|
||||
for (node = firstnode(vars); node; incnode(node))
|
||||
{
|
||||
name = (char *)getdata(node);
|
||||
if (!args || !(str = (char *) ugetnode(args)))
|
||||
{
|
||||
if (count) {
|
||||
str = "";
|
||||
last = 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s=%s\n", name, str);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
setsparam(name, ztrdup(str));
|
||||
count++;
|
||||
}
|
||||
if (!count)
|
||||
break;
|
||||
}
|
||||
state->pc = loop;
|
||||
execlist(state, 1, do_exec && args && empty(args));
|
||||
if (breaks) {
|
||||
breaks--;
|
||||
if (breaks || !contflag)
|
||||
break;
|
||||
contflag = 0;
|
||||
}
|
||||
if (retflag)
|
||||
break;
|
||||
if (iscond && !errflag) {
|
||||
if (atok) {
|
||||
str = dupstring(advance);
|
||||
singsub(&str);
|
||||
} else
|
||||
str = advance;
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s\n", str);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
if (!errflag)
|
||||
matheval(str);
|
||||
}
|
||||
if (errflag) {
|
||||
if (breaks)
|
||||
breaks--;
|
||||
lastval = 1;
|
||||
break;
|
||||
}
|
||||
freeheap();
|
||||
}
|
||||
popheap();
|
||||
cmdpop();
|
||||
loops--;
|
||||
simple_pline = old_simple_pline;
|
||||
state->pc = end;
|
||||
this_noerrexit = 1;
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
execselect(Estate state, UNUSED(int do_exec))
|
||||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
char *str, *s, *name;
|
||||
LinkNode n;
|
||||
int i, usezle;
|
||||
FILE *inp;
|
||||
size_t more;
|
||||
LinkList args;
|
||||
int old_simple_pline = simple_pline;
|
||||
|
||||
/* See comments in execwhile() */
|
||||
simple_pline = 1;
|
||||
|
||||
end = state->pc + WC_FOR_SKIP(code);
|
||||
name = ecgetstr(state, EC_NODUP, NULL);
|
||||
|
||||
if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
|
||||
char **x;
|
||||
|
||||
args = newlinklist();
|
||||
for (x = pparams; *x; x++)
|
||||
addlinknode(args, dupstring(*x));
|
||||
} else {
|
||||
int htok = 0;
|
||||
|
||||
if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 0;
|
||||
}
|
||||
if (htok) {
|
||||
execsubst(args);
|
||||
if (errflag) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!args || empty(args)) {
|
||||
state->pc = end;
|
||||
simple_pline = old_simple_pline;
|
||||
return 0;
|
||||
}
|
||||
loops++;
|
||||
|
||||
pushheap();
|
||||
cmdpush(CS_SELECT);
|
||||
usezle = interact && SHTTY != -1 && isset(USEZLE);
|
||||
inp = fdopen(dup(usezle ? SHTTY : 0), "r");
|
||||
more = selectlist(args, 0);
|
||||
loop = state->pc;
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
if (empty(bufstack)) {
|
||||
if (usezle) {
|
||||
int oef = errflag;
|
||||
|
||||
isfirstln = 1;
|
||||
str = zleentry(ZLE_CMD_READ, &prompt3, NULL,
|
||||
0, ZLCON_SELECT);
|
||||
if (errflag)
|
||||
str = NULL;
|
||||
/* Keep any user interrupt error status */
|
||||
errflag = oef | (errflag & ERRFLAG_INT);
|
||||
} else {
|
||||
str = promptexpand(prompt3, 0, NULL, NULL, NULL);
|
||||
zputs(str, stderr);
|
||||
free(str);
|
||||
fflush(stderr);
|
||||
str = fgets(zhalloc(256), 256, inp);
|
||||
}
|
||||
} else
|
||||
str = (char *)getlinknode(bufstack);
|
||||
if (!str && !errflag)
|
||||
setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
|
||||
if (!str || errflag) {
|
||||
if (breaks)
|
||||
breaks--;
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
goto done;
|
||||
}
|
||||
if ((s = strchr(str, '\n')))
|
||||
*s = '\0';
|
||||
if (*str)
|
||||
break;
|
||||
more = selectlist(args, more);
|
||||
}
|
||||
setsparam("REPLY", ztrdup(str));
|
||||
i = atoi(str);
|
||||
if (!i)
|
||||
str = "";
|
||||
else {
|
||||
for (i--, n = firstnode(args); n && i; incnode(n), i--);
|
||||
if (n)
|
||||
str = (char *) getdata(n);
|
||||
else
|
||||
str = "";
|
||||
}
|
||||
setsparam(name, ztrdup(str));
|
||||
state->pc = loop;
|
||||
execlist(state, 1, 0);
|
||||
freeheap();
|
||||
if (breaks) {
|
||||
breaks--;
|
||||
if (breaks || !contflag)
|
||||
break;
|
||||
contflag = 0;
|
||||
}
|
||||
if (retflag || errflag)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
cmdpop();
|
||||
popheap();
|
||||
fclose(inp);
|
||||
loops--;
|
||||
simple_pline = old_simple_pline;
|
||||
state->pc = end;
|
||||
this_noerrexit = 1;
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/* And this is used to print select lists. */
|
||||
|
||||
/**/
|
||||
size_t
|
||||
selectlist(LinkList l, size_t start)
|
||||
{
|
||||
size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
|
||||
char **arr, **ap;
|
||||
|
||||
zleentry(ZLE_CMD_TRASH);
|
||||
arr = hlinklist2array(l, 0);
|
||||
for (ap = arr; *ap; ap++)
|
||||
if (strlen(*ap) > longest)
|
||||
longest = strlen(*ap);
|
||||
t0 = ct = ap - arr;
|
||||
longest++;
|
||||
while (t0)
|
||||
t0 /= 10, longest++;
|
||||
/* to compensate for added ')' */
|
||||
fct = (zterm_columns - 1) / (longest + 3);
|
||||
if (fct == 0)
|
||||
fct = 1;
|
||||
else
|
||||
fw = (zterm_columns - 1) / fct;
|
||||
colsz = (ct + fct - 1) / fct;
|
||||
for (t1 = start; t1 != colsz && t1 - start < zterm_lines - 2; t1++) {
|
||||
ap = arr + t1;
|
||||
do {
|
||||
size_t t2 = strlen(*ap) + 2;
|
||||
int t3;
|
||||
|
||||
fprintf(stderr, "%d) %s", t3 = ap - arr + 1, *ap);
|
||||
while (t3)
|
||||
t2++, t3 /= 10;
|
||||
for (; t2 < fw; t2++)
|
||||
fputc(' ', stderr);
|
||||
for (t0 = colsz; t0 && *ap; t0--, ap++);
|
||||
}
|
||||
while (*ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
/* Below is a simple attempt at doing it the Korn Way..
|
||||
ap = arr;
|
||||
t0 = 0;
|
||||
do {
|
||||
t0++;
|
||||
fprintf(stderr,"%d) %s\n",t0,*ap);
|
||||
ap++;
|
||||
}
|
||||
while (*ap);*/
|
||||
fflush(stderr);
|
||||
|
||||
return t1 < colsz ? t1 : 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
execwhile(Estate state, UNUSED(int do_exec))
|
||||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
|
||||
int old_simple_pline = simple_pline;
|
||||
|
||||
end = state->pc + WC_WHILE_SKIP(code);
|
||||
olderrexit = noerrexit;
|
||||
oldval = 0;
|
||||
pushheap();
|
||||
cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
|
||||
loops++;
|
||||
loop = state->pc;
|
||||
|
||||
if (loop[0] == WC_END && loop[1] == WC_END) {
|
||||
|
||||
/* This is an empty loop. Make sure the signal handler sets the
|
||||
* flags and then just wait for someone hitting ^C. */
|
||||
|
||||
simple_pline = 1;
|
||||
|
||||
while (!breaks)
|
||||
;
|
||||
breaks--;
|
||||
|
||||
simple_pline = old_simple_pline;
|
||||
} else
|
||||
for (;;) {
|
||||
state->pc = loop;
|
||||
noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
|
||||
|
||||
/* In case the test condition is a functional no-op,
|
||||
* make sure signal handlers recognize ^C to end the loop. */
|
||||
simple_pline = 1;
|
||||
|
||||
execlist(state, 1, 0);
|
||||
|
||||
simple_pline = old_simple_pline;
|
||||
noerrexit = olderrexit;
|
||||
if (!((lastval == 0) ^ isuntil)) {
|
||||
if (breaks)
|
||||
breaks--;
|
||||
if (!retflag)
|
||||
lastval = oldval;
|
||||
break;
|
||||
}
|
||||
if (retflag)
|
||||
break;
|
||||
|
||||
/* In case the loop body is also a functional no-op,
|
||||
* make sure signal handlers recognize ^C as above. */
|
||||
simple_pline = 1;
|
||||
|
||||
execlist(state, 1, 0);
|
||||
|
||||
simple_pline = old_simple_pline;
|
||||
if (breaks) {
|
||||
breaks--;
|
||||
if (breaks || !contflag)
|
||||
break;
|
||||
contflag = 0;
|
||||
}
|
||||
if (errflag) {
|
||||
lastval = 1;
|
||||
break;
|
||||
}
|
||||
if (retflag)
|
||||
break;
|
||||
freeheap();
|
||||
oldval = lastval;
|
||||
}
|
||||
cmdpop();
|
||||
popheap();
|
||||
loops--;
|
||||
state->pc = end;
|
||||
this_noerrexit = 1;
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
execrepeat(Estate state, UNUSED(int do_exec))
|
||||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
int count, htok = 0;
|
||||
char *tmp;
|
||||
int old_simple_pline = simple_pline;
|
||||
|
||||
/* See comments in execwhile() */
|
||||
simple_pline = 1;
|
||||
|
||||
end = state->pc + WC_REPEAT_SKIP(code);
|
||||
|
||||
lastval = 0;
|
||||
tmp = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok)
|
||||
singsub(&tmp);
|
||||
count = mathevali(tmp);
|
||||
if (errflag)
|
||||
return 1;
|
||||
pushheap();
|
||||
cmdpush(CS_REPEAT);
|
||||
loops++;
|
||||
loop = state->pc;
|
||||
while (count-- > 0) {
|
||||
state->pc = loop;
|
||||
execlist(state, 1, 0);
|
||||
freeheap();
|
||||
if (breaks) {
|
||||
breaks--;
|
||||
if (breaks || !contflag)
|
||||
break;
|
||||
contflag = 0;
|
||||
}
|
||||
if (errflag) {
|
||||
lastval = 1;
|
||||
break;
|
||||
}
|
||||
if (retflag)
|
||||
break;
|
||||
}
|
||||
cmdpop();
|
||||
popheap();
|
||||
loops--;
|
||||
simple_pline = old_simple_pline;
|
||||
state->pc = end;
|
||||
this_noerrexit = 1;
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
execif(Estate state, int do_exec)
|
||||
{
|
||||
Wordcode end, next;
|
||||
wordcode code = state->pc[-1];
|
||||
int olderrexit, s = 0, run = 0;
|
||||
|
||||
olderrexit = noerrexit;
|
||||
end = state->pc + WC_IF_SKIP(code);
|
||||
|
||||
noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN;
|
||||
while (state->pc < end) {
|
||||
code = *state->pc++;
|
||||
if (wc_code(code) != WC_IF ||
|
||||
(run = (WC_IF_TYPE(code) == WC_IF_ELSE))) {
|
||||
if (run)
|
||||
run = 2;
|
||||
break;
|
||||
}
|
||||
next = state->pc + WC_IF_SKIP(code);
|
||||
cmdpush(s ? CS_ELIF : CS_IF);
|
||||
execlist(state, 1, 0);
|
||||
cmdpop();
|
||||
if (!lastval) {
|
||||
run = 1;
|
||||
break;
|
||||
}
|
||||
if (retflag)
|
||||
break;
|
||||
s = 1;
|
||||
state->pc = next;
|
||||
}
|
||||
|
||||
if (run) {
|
||||
/* we need to ignore lastval until we reach execcmd() */
|
||||
if (olderrexit)
|
||||
noerrexit = olderrexit;
|
||||
else if (lastval)
|
||||
noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC;
|
||||
else
|
||||
noerrexit &= ~ (NOERREXIT_EXIT | NOERREXIT_RETURN);
|
||||
cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
|
||||
execlist(state, 1, do_exec);
|
||||
cmdpop();
|
||||
} else {
|
||||
noerrexit = olderrexit;
|
||||
if (!retflag)
|
||||
lastval = 0;
|
||||
}
|
||||
state->pc = end;
|
||||
this_noerrexit = 1;
|
||||
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
execcase(Estate state, int do_exec)
|
||||
{
|
||||
Wordcode end, next;
|
||||
wordcode code = state->pc[-1];
|
||||
char *word, *pat;
|
||||
int npat, save, nalts, ialt, patok, anypatok;
|
||||
Patprog *spprog, pprog;
|
||||
|
||||
end = state->pc + WC_CASE_SKIP(code);
|
||||
|
||||
word = ecgetstr(state, EC_DUP, NULL);
|
||||
singsub(&word);
|
||||
untokenize(word);
|
||||
anypatok = 0;
|
||||
|
||||
cmdpush(CS_CASE);
|
||||
while (state->pc < end) {
|
||||
code = *state->pc++;
|
||||
if (wc_code(code) != WC_CASE)
|
||||
break;
|
||||
|
||||
save = 0;
|
||||
next = state->pc + WC_CASE_SKIP(code);
|
||||
nalts = *state->pc++;
|
||||
ialt = patok = 0;
|
||||
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "case %s (", word);
|
||||
}
|
||||
|
||||
while (!patok && nalts) {
|
||||
npat = state->pc[1];
|
||||
spprog = state->prog->pats + npat;
|
||||
pprog = NULL;
|
||||
pat = NULL;
|
||||
|
||||
queue_signals();
|
||||
|
||||
if (isset(XTRACE)) {
|
||||
int htok = 0;
|
||||
pat = dupstring(ecrawstr(state->prog, state->pc, &htok));
|
||||
if (htok)
|
||||
singsub(&pat);
|
||||
|
||||
if (ialt++)
|
||||
fprintf(stderr, " | ");
|
||||
quote_tokenized_output(pat, xtrerr);
|
||||
}
|
||||
|
||||
if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
|
||||
pprog = *spprog;
|
||||
|
||||
if (!pprog) {
|
||||
if (!pat) {
|
||||
char *opat;
|
||||
int htok = 0;
|
||||
|
||||
pat = dupstring(opat = ecrawstr(state->prog,
|
||||
state->pc, &htok));
|
||||
if (htok)
|
||||
singsub(&pat);
|
||||
save = (!(state->prog->flags & EF_HEAP) &&
|
||||
!strcmp(pat, opat) && *spprog != dummy_patprog2);
|
||||
}
|
||||
if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
|
||||
NULL)))
|
||||
zerr("bad pattern: %s", pat);
|
||||
else if (save)
|
||||
*spprog = pprog;
|
||||
}
|
||||
if (pprog && pattry(pprog, word))
|
||||
patok = anypatok = 1;
|
||||
state->pc += 2;
|
||||
nalts--;
|
||||
|
||||
unqueue_signals();
|
||||
}
|
||||
state->pc += 2 * nalts;
|
||||
if (isset(XTRACE)) {
|
||||
fprintf(xtrerr, ")\n");
|
||||
fflush(xtrerr);
|
||||
}
|
||||
if (patok) {
|
||||
execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
|
||||
do_exec));
|
||||
while (!retflag && wc_code(code) == WC_CASE &&
|
||||
WC_CASE_TYPE(code) == WC_CASE_AND && state->pc < end) {
|
||||
state->pc = next;
|
||||
code = *state->pc++;
|
||||
next = state->pc + WC_CASE_SKIP(code);
|
||||
nalts = *state->pc++;
|
||||
state->pc += 2 * nalts;
|
||||
execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
|
||||
do_exec));
|
||||
}
|
||||
if (WC_CASE_TYPE(code) != WC_CASE_TESTAND)
|
||||
break;
|
||||
}
|
||||
state->pc = next;
|
||||
}
|
||||
cmdpop();
|
||||
|
||||
state->pc = end;
|
||||
|
||||
if (!anypatok)
|
||||
lastval = 0;
|
||||
this_noerrexit = 1;
|
||||
|
||||
return lastval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Errflag from `try' block, may be reset in `always' block.
|
||||
* Accessible from an integer parameter, so needs to be a zlong.
|
||||
*/
|
||||
|
||||
/**/
|
||||
zlong
|
||||
try_errflag = -1;
|
||||
|
||||
/**
|
||||
* Corresponding interrupt error status form `try' block.
|
||||
*/
|
||||
|
||||
/**/
|
||||
zlong
|
||||
try_interrupt = -1;
|
||||
|
||||
/**/
|
||||
zlong
|
||||
try_tryflag = 0;
|
||||
|
||||
/**/
|
||||
int
|
||||
exectry(Estate state, int do_exec)
|
||||
{
|
||||
Wordcode end, always;
|
||||
int endval;
|
||||
int save_retflag, save_breaks, save_contflag;
|
||||
zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
|
||||
|
||||
end = state->pc + WC_TRY_SKIP(state->pc[-1]);
|
||||
always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
|
||||
state->pc++;
|
||||
pushheap();
|
||||
cmdpush(CS_CURSH);
|
||||
|
||||
/* The :try clause */
|
||||
save_try_tryflag = try_tryflag;
|
||||
try_tryflag = 1;
|
||||
|
||||
execlist(state, 1, do_exec);
|
||||
|
||||
try_tryflag = save_try_tryflag;
|
||||
|
||||
/* Don't record errflag here, may be reset. However, */
|
||||
/* endval should show failure when there is an error. */
|
||||
endval = lastval ? lastval : errflag;
|
||||
|
||||
freeheap();
|
||||
|
||||
cmdpop();
|
||||
cmdpush(CS_ALWAYS);
|
||||
|
||||
/* The always clause. */
|
||||
save_try_errflag = try_errflag;
|
||||
save_try_interrupt = try_interrupt;
|
||||
try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
|
||||
try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0);
|
||||
/* We need to reset all errors to allow the block to execute */
|
||||
errflag = 0;
|
||||
save_retflag = retflag;
|
||||
retflag = 0;
|
||||
save_breaks = breaks;
|
||||
breaks = 0;
|
||||
save_contflag = contflag;
|
||||
contflag = 0;
|
||||
|
||||
state->pc = always;
|
||||
execlist(state, 1, do_exec);
|
||||
|
||||
if (try_errflag)
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
else
|
||||
errflag &= ~ERRFLAG_ERROR;
|
||||
if (try_interrupt)
|
||||
errflag |= ERRFLAG_INT;
|
||||
else
|
||||
errflag &= ~ERRFLAG_INT;
|
||||
try_errflag = save_try_errflag;
|
||||
try_interrupt = save_try_interrupt;
|
||||
if (!retflag)
|
||||
retflag = save_retflag;
|
||||
if (!breaks)
|
||||
breaks = save_breaks;
|
||||
if (!contflag)
|
||||
contflag = save_contflag;
|
||||
|
||||
cmdpop();
|
||||
popheap();
|
||||
state->pc = end;
|
||||
|
||||
return endval;
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
#
|
||||
# makepro.awk - generate prototype lists
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
aborting = 0
|
||||
|
||||
# arg 1 is the name of the file to process
|
||||
# arg 2 is the name of the subdirectory it is in
|
||||
if(ARGC != 3) {
|
||||
aborting = 1
|
||||
exit 1
|
||||
}
|
||||
name = ARGV[1]
|
||||
gsub(/^.*\//, "", name)
|
||||
gsub(/\.c$/, "", name)
|
||||
name = ARGV[2] "_" name
|
||||
gsub(/\//, "_", name)
|
||||
ARGC--
|
||||
|
||||
printf "E#ifndef have_%s_globals\n", name
|
||||
printf "E#define have_%s_globals\n", name
|
||||
printf "E\n"
|
||||
}
|
||||
|
||||
# all relevant declarations are preceded by "/**/" on a line by itself
|
||||
|
||||
/^\/\*\*\/$/ {
|
||||
# The declaration is on following lines. The interesting part might
|
||||
# be terminated by a `{' (`int foo(void) { }' or `int bar[] = {')
|
||||
# or `;' (`int x;').
|
||||
line = ""
|
||||
isfunc = 0
|
||||
while(1) {
|
||||
if(getline <= 0) {
|
||||
aborting = 1
|
||||
exit 1
|
||||
}
|
||||
if (line == "" && $0 ~ /^[ \t]*#/) {
|
||||
# Directly after the /**/ was a preprocessor line.
|
||||
# Spit it out and re-start the outer loop.
|
||||
printf "E%s\n", $0
|
||||
printf "L%s\n", $0
|
||||
next
|
||||
}
|
||||
gsub(/\t/, " ")
|
||||
line = line " " $0
|
||||
gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line)
|
||||
if(line ~ /\/\*/)
|
||||
continue
|
||||
# If it is a function definition, note so.
|
||||
if(line ~ /\) *(VA_DCL )*[{].*$/) #}
|
||||
isfunc = 1
|
||||
if(sub(/ *[{;].*$/, "", line)) #}
|
||||
break
|
||||
}
|
||||
if (!match(line, /VA_ALIST/)) {
|
||||
# Put spaces around each identifier.
|
||||
while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) ||
|
||||
match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/))
|
||||
line = substr(line, 1, RSTART) " " substr(line, RSTART+1)
|
||||
}
|
||||
# Separate declarations into a type and a list of declarators.
|
||||
# In each declarator, "@{" and "@}" are used in place of parens to
|
||||
# mark function parameter lists, and "@!" is used in place of commas
|
||||
# in parameter lists. "@<" and "@>" are used in place of
|
||||
# non-parameter list parens.
|
||||
gsub(/ _ +/, " _ ", line)
|
||||
while(1) {
|
||||
if(isfunc && match(line, /\([^()]*\)$/))
|
||||
line = substr(line, 1, RSTART-1) " _ (" substr(line, RSTART) ")"
|
||||
else if(match(line, / _ \(\([^,()]*,/))
|
||||
line = substr(line, 1, RSTART+RLENGTH-2) "@!" substr(line, RSTART+RLENGTH)
|
||||
else if(match(line, / _ \(\([^,()]*\)\)/))
|
||||
line = substr(line, 1, RSTART-1) "@{" substr(line, RSTART+5, RLENGTH-7) "@}" substr(line, RSTART+RLENGTH)
|
||||
else if(match(line, /\([^,()]*\)/))
|
||||
line = substr(line, 1, RSTART-1) "@<" substr(line, RSTART+1, RLENGTH-2) "@>" substr(line, RSTART+RLENGTH)
|
||||
else
|
||||
break
|
||||
}
|
||||
sub(/^ */, "", line)
|
||||
match(line, /^((const|enum|mod_export|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/)
|
||||
dtype = substr(line, 1, RLENGTH)
|
||||
sub(/ *$/, "", dtype)
|
||||
if(" " dtype " " ~ / static /)
|
||||
locality = "L"
|
||||
else
|
||||
locality = "E"
|
||||
exported = " " dtype " " ~ / mod_export /
|
||||
line = substr(line, RLENGTH+1) ","
|
||||
# Handle each declarator.
|
||||
if (match(line, /VA_ALIST/)) {
|
||||
# Already has VARARGS handling.
|
||||
|
||||
# Put parens etc. back
|
||||
gsub(/@[{]/, "((", line)
|
||||
gsub(/@}/, "))", line)
|
||||
gsub(/@</, "(", line)
|
||||
gsub(/@>/, ")", line)
|
||||
gsub(/@!/, ",", line)
|
||||
sub(/,$/, ";", line)
|
||||
gsub(/mod_export/, "mod_import_function", dtype)
|
||||
gsub(/VA_ALIST/, "VA_ALIST_PROTO", line)
|
||||
sub(/ VA_DCL/, "", line)
|
||||
|
||||
if(locality ~ /E/)
|
||||
dtype = "extern " dtype
|
||||
|
||||
if (match(line, /[_0-9A-Za-z]+\(VA_ALIST/))
|
||||
dnam = substr(line, RSTART, RLENGTH-9)
|
||||
|
||||
# If this is exported, add it to the exported symbol list.
|
||||
if (exported)
|
||||
printf "X%s\n", dnam
|
||||
|
||||
printf "%s%s %s\n", locality, dtype, line
|
||||
} else {
|
||||
while(match(line, /^[^,]*,/)) {
|
||||
# Separate out the name from the declarator. Use "@+" and "@-"
|
||||
# to bracket the name within the declarator. Strip off any
|
||||
# initialiser.
|
||||
dcltor = substr(line, 1, RLENGTH-1)
|
||||
line = substr(line, RLENGTH+1)
|
||||
sub(/\=.*$/, "", dcltor)
|
||||
match(dcltor, /^([^_0-9A-Za-z]| const )*/)
|
||||
dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1)
|
||||
match(dcltor, /^.*@\+[_0-9A-Za-z]+/)
|
||||
dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1)
|
||||
dnam = dcltor
|
||||
sub(/^.*@\+/, "", dnam)
|
||||
sub(/@-.*$/, "", dnam)
|
||||
|
||||
# Put parens etc. back
|
||||
gsub(/@[{]/, " _((", dcltor)
|
||||
gsub(/@}/, "))", dcltor)
|
||||
gsub(/@</, "(", dcltor)
|
||||
gsub(/@>/, ")", dcltor)
|
||||
gsub(/@!/, ",", dcltor)
|
||||
|
||||
# If this is exported, add it to the exported symbol list.
|
||||
if(exported)
|
||||
printf "X%s\n", dnam
|
||||
|
||||
# Format the declaration for output
|
||||
dcl = dtype " " dcltor ";"
|
||||
if(locality ~ /E/)
|
||||
dcl = "extern " dcl
|
||||
if(isfunc)
|
||||
gsub(/ mod_export /, " mod_import_function ", dcl)
|
||||
else
|
||||
gsub(/ mod_export /, " mod_import_variable ", dcl)
|
||||
gsub(/@[+-]/, "", dcl)
|
||||
gsub(/ +/, " ", dcl)
|
||||
while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
|
||||
dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
|
||||
printf "%s%s\n", locality, dcl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if(aborting)
|
||||
exit 1
|
||||
printf "E\n"
|
||||
printf "E#endif /* !have_%s_globals */\n", name
|
||||
}
|
||||
1899
zmodules/Src/mem.c
1899
zmodules/Src/mem.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,116 +0,0 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# mkbltnmlst.sh: generate boot code for linked-in modules
|
||||
#
|
||||
# Written by Andrew Main
|
||||
#
|
||||
|
||||
srcdir=${srcdir-`echo $0|sed 's%/[^/][^/]*$%%'`}
|
||||
test "x$srcdir" = "x$0" && srcdir=.
|
||||
test "x$srcdir" = "x" && srcdir=.
|
||||
CFMOD=${CFMOD-$srcdir/../config.modules}
|
||||
|
||||
bin_mods="`grep ' link=static' $CFMOD | sed -e '/^#/d' \
|
||||
-e 's/ .*/ /' -e 's/^name=/ /'`"
|
||||
|
||||
x_mods="`grep ' load=yes' $CFMOD | sed -e '/^#/d' -e '/ link=no/d' \
|
||||
-e 's/ .*/ /' -e 's/^name=/ /'`"
|
||||
|
||||
trap "rm -f $1; exit 1" 1 2 15
|
||||
|
||||
exec > $1
|
||||
|
||||
for x_mod in $x_mods; do
|
||||
modfile="`grep '^name='$x_mod' ' $CFMOD | sed -e 's/^.* modfile=//' \
|
||||
-e 's/ .*//'`"
|
||||
if test "x$modfile" = x; then
|
||||
echo >&2 "WARNING: no name for \`$x_mod' in $CFMOD (ignored)"
|
||||
continue
|
||||
fi
|
||||
case "$bin_mods" in
|
||||
*" $x_mod "*)
|
||||
echo "/* linked-in known module \`$x_mod' */"
|
||||
linked=yes
|
||||
;;
|
||||
*)
|
||||
echo "#ifdef DYNAMIC"
|
||||
echo "/* non-linked-in known module \`$x_mod' */"
|
||||
linked=no
|
||||
esac
|
||||
unset moddeps autofeatures autofeatures_emu
|
||||
. $srcdir/../$modfile
|
||||
if test "x$autofeatures" != x; then
|
||||
if test "x$autofeatures_emu" != x; then
|
||||
echo " {"
|
||||
echo " char *zsh_features[] = { "
|
||||
for feature in $autofeatures; do
|
||||
echo " \"$feature\","
|
||||
done
|
||||
echo " NULL"
|
||||
echo " }; "
|
||||
echo " char *emu_features[] = { "
|
||||
for feature in $autofeatures_emu; do
|
||||
echo " \"$feature\","
|
||||
done
|
||||
echo " NULL"
|
||||
echo " }; "
|
||||
echo " autofeatures(\"zsh\", \"$x_mod\","
|
||||
echo " EMULATION(EMULATE_ZSH) ? zsh_features : emu_features,"
|
||||
echo " 0, 1);"
|
||||
echo " }"
|
||||
else
|
||||
echo " if (EMULATION(EMULATE_ZSH)) {"
|
||||
echo " char *features[] = { "
|
||||
for feature in $autofeatures; do
|
||||
echo " \"$feature\","
|
||||
done
|
||||
echo " NULL"
|
||||
echo " }; "
|
||||
echo " autofeatures(\"zsh\", \"$x_mod\", features, 0, 1);"
|
||||
echo " }"
|
||||
fi
|
||||
fi
|
||||
for dep in $moddeps; do
|
||||
echo " add_dep(\"$x_mod\", \"$dep\");"
|
||||
done
|
||||
test "x$linked" = xno && echo "#endif"
|
||||
done
|
||||
|
||||
echo
|
||||
done_mods=" "
|
||||
for bin_mod in $bin_mods; do
|
||||
q_bin_mod=`echo $bin_mod | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
|
||||
modfile="`grep '^name='$bin_mod' ' $CFMOD | sed -e 's/^.* modfile=//' \
|
||||
-e 's/ .*//'`"
|
||||
echo "/* linked-in module \`$bin_mod' */"
|
||||
unset moddeps
|
||||
. $srcdir/../$modfile
|
||||
for dep in $moddeps; do
|
||||
# This assumes there are no circular dependencies in the builtin
|
||||
# modules. Better ordering of config.modules would be necessary
|
||||
# to enforce stricter dependency checking.
|
||||
case $bin_mods in
|
||||
*" $dep "*)
|
||||
echo " /* depends on \`$dep' */" ;;
|
||||
*) echo >&2 "ERROR: linked-in module \`$bin_mod' depends on \`$dep'"
|
||||
rm -f $1
|
||||
exit 1 ;;
|
||||
esac
|
||||
done
|
||||
echo " {"
|
||||
echo " extern int setup_${q_bin_mod} _((Module));"
|
||||
echo " extern int boot_${q_bin_mod} _((Module));"
|
||||
echo " extern int features_${q_bin_mod} _((Module,char***));"
|
||||
echo " extern int enables_${q_bin_mod} _((Module,int**));"
|
||||
echo " extern int cleanup_${q_bin_mod} _((Module));"
|
||||
echo " extern int finish_${q_bin_mod} _((Module));"
|
||||
echo
|
||||
echo " register_module(\"$bin_mod\","
|
||||
echo " setup_${q_bin_mod},"
|
||||
echo " features_${q_bin_mod},"
|
||||
echo " enables_${q_bin_mod},"
|
||||
echo " boot_${q_bin_mod},"
|
||||
echo " cleanup_${q_bin_mod}, finish_${q_bin_mod});"
|
||||
echo " }"
|
||||
done_mods="$done_mods$bin_mod "
|
||||
done
|
||||
|
|
@ -1,468 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# mkmakemod.sh: generate Makefile.in files for module building
|
||||
#
|
||||
# Options:
|
||||
# -m = file is already generated; only build the second stage
|
||||
# -i = do not build second stage
|
||||
#
|
||||
# Args:
|
||||
# $1 = subdirectory to look in, relative to $top_srcdir
|
||||
# $2 = final output filename, within the $1 directory
|
||||
#
|
||||
# This script must be run from the top-level build directory, and $top_srcdir
|
||||
# must be set correctly in the environment.
|
||||
#
|
||||
# This looks in $1, and uses all the *.mdd files there. Each .mdd file
|
||||
# defines one module. The .mdd file is actually a shell script, which will
|
||||
# be sourced. It may define the following shell variables:
|
||||
#
|
||||
# name name of this module
|
||||
# moddeps modules on which this module depends (default none)
|
||||
# nozshdep non-empty indicates no dependence on the `zsh/main' pseudo-module
|
||||
# alwayslink if non-empty, always link the module into the executable
|
||||
# autofeatures features defined by the module, for autoloading
|
||||
# autofeatures_emu As autofeatures, but for non-zsh emulation modes
|
||||
# objects .o files making up this module (*must* be defined)
|
||||
# proto .syms 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)
|
||||
#
|
||||
# The .mdd file may also include a Makefile.in fragment between lines
|
||||
# `:<<\Make' and `Make' -- this will be copied into Makemod.in.
|
||||
#
|
||||
# The resulting Makemod.in knows how to build each module that is defined.
|
||||
# For each module it also knows how to build a .mdh file. Each source file
|
||||
# should #include the .mdh file for the module it is a part of. The .mdh
|
||||
# file #includes the .mdh files for any module dependencies, then each of
|
||||
# $headers, and then each .epro (for global declarations). It will
|
||||
# be recreated if any of the dependency .mdh files changes, or if any of
|
||||
# $headers or $hdrdeps changes. When anything depends on it, all the .epros
|
||||
# and $otherincs will be made up to date, but the .mdh file won't actually
|
||||
# be rebuilt if those files change.
|
||||
#
|
||||
# The order of sections of the output file is thus:
|
||||
# simple generated macros
|
||||
# macros generated from *.mdd
|
||||
# included Makemod.in.in
|
||||
# rules generated from *.mdd
|
||||
# The order dependencies are basically that the generated macros are required
|
||||
# in Makemod.in.in, but some of the macros that it creates are needed in the
|
||||
# later rules.
|
||||
#
|
||||
|
||||
# sed script to normalise a pathname
|
||||
sed_normalise='
|
||||
s,^,/,
|
||||
s,$,/,
|
||||
:1
|
||||
s,/\./,/,
|
||||
t1
|
||||
:2
|
||||
s,/[^/.][^/]*/\.\./,/,
|
||||
s,/\.[^/.][^/]*/\.\./,/,
|
||||
s,/\.\.[^/][^/]*/\.\./,/,
|
||||
t2
|
||||
s,^/$,.,
|
||||
s,^/,,
|
||||
s,\(.\)/$,\1,
|
||||
'
|
||||
|
||||
# decide which stages to process
|
||||
first_stage=true
|
||||
second_stage=true
|
||||
if test ."$1" = .-m; then
|
||||
shift
|
||||
first_stage=false
|
||||
elif test ."$1" = .-i; then
|
||||
shift
|
||||
second_stage=false
|
||||
fi
|
||||
|
||||
top_srcdir=`echo $top_srcdir | sed "$sed_normalise"`
|
||||
the_subdir=$1
|
||||
the_makefile=$2
|
||||
|
||||
if $first_stage; then
|
||||
|
||||
dir_top=`echo $the_subdir | sed 's,[^/][^/]*,..,g'`
|
||||
|
||||
trap "rm -f $the_subdir/${the_makefile}.in; exit 1" 1 2 15
|
||||
echo "creating $the_subdir/${the_makefile}.in"
|
||||
exec 3>&1 >$the_subdir/${the_makefile}.in
|
||||
echo "##### ${the_makefile}.in generated automatically by mkmakemod.sh"
|
||||
echo "##### DO NOT EDIT!"
|
||||
echo
|
||||
echo "##### ===== DEFINITIONS ===== #####"
|
||||
echo
|
||||
echo "makefile = ${the_makefile}"
|
||||
echo "dir_top = ${dir_top}"
|
||||
echo "subdir = ${the_subdir}"
|
||||
echo
|
||||
|
||||
bin_mods=`grep link=static ./config.modules | \
|
||||
sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`
|
||||
dyn_mods="`grep link=dynamic ./config.modules | \
|
||||
sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`"
|
||||
module_list="${bin_mods}${dyn_mods}"
|
||||
|
||||
if grep '^#define DYNAMIC ' config.h >/dev/null; then
|
||||
is_dynamic=true
|
||||
else
|
||||
is_dynamic=false
|
||||
fi
|
||||
|
||||
here_mddnames=
|
||||
all_subdirs=
|
||||
all_modobjs=
|
||||
all_modules=
|
||||
all_mdds=
|
||||
all_mdhs=
|
||||
all_proto=
|
||||
lastsub=//
|
||||
for module in $module_list; do
|
||||
modfile="`grep '^name='$module' ' ./config.modules | \
|
||||
sed -e 's/^.* modfile=//' -e 's/ .*//'`"
|
||||
case $modfile in
|
||||
$the_subdir/$lastsub/*) ;;
|
||||
$the_subdir/*/*)
|
||||
lastsub=`echo $modfile | sed 's,^'$the_subdir'/,,;s,/[^/]*$,,'`
|
||||
case "$all_subdirs " in
|
||||
*" $lastsub "* ) ;;
|
||||
* )
|
||||
all_subdirs="$all_subdirs $lastsub"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
$the_subdir/*)
|
||||
mddname=`echo $modfile | sed 's,^.*/,,;s,\.mdd$,,'`
|
||||
here_mddnames="$here_mddnames $mddname"
|
||||
build=$is_dynamic
|
||||
case $is_dynamic@$bin_mods in
|
||||
*" $module "*)
|
||||
build=true
|
||||
all_modobjs="$all_modobjs modobjs.${mddname}" ;;
|
||||
true@*)
|
||||
all_modules="$all_modules ${mddname}.\$(DL_EXT)" ;;
|
||||
esac
|
||||
all_mdds="$all_mdds ${mddname}.mdd"
|
||||
$build && all_mdhs="$all_mdhs ${mddname}.mdh"
|
||||
$build && all_proto="$all_proto proto.${mddname}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "MODOBJS =$all_modobjs"
|
||||
echo "MODULES =$all_modules"
|
||||
echo "MDDS =$all_mdds"
|
||||
echo "MDHS =$all_mdhs"
|
||||
echo "PROTOS =$all_proto"
|
||||
echo "SUBDIRS =$all_subdirs"
|
||||
echo
|
||||
echo "ENTRYOBJ = \$(dir_src)/modentry..o"
|
||||
echo "NNTRYOBJ ="
|
||||
echo "ENTRYOPT = -emodentry"
|
||||
echo "NNTRYOPT ="
|
||||
echo
|
||||
|
||||
echo "##### ===== INCLUDING Makemod.in.in ===== #####"
|
||||
echo
|
||||
cat $top_srcdir/Src/Makemod.in.in
|
||||
echo
|
||||
|
||||
case $the_subdir in
|
||||
Src) modobjs_sed= ;;
|
||||
Src/*) modobjs_sed="| sed 's\" \" "`echo $the_subdir | sed 's,^Src/,,'`"/\"g' " ;;
|
||||
*) modobjs_sed="| sed 's\" \" ../$the_subdir/\"g' " ;;
|
||||
esac
|
||||
|
||||
other_mdhs=
|
||||
remote_mdhs=
|
||||
other_exports=
|
||||
remote_exports=
|
||||
other_modules=
|
||||
remote_modules=
|
||||
for mddname in $here_mddnames; do
|
||||
|
||||
unset name moddeps nozshdep alwayslink hasexport
|
||||
unset autofeatures autofeatures_emu
|
||||
unset objects proto headers hdrdeps otherincs
|
||||
. $top_srcdir/$the_subdir/${mddname}.mdd
|
||||
q_name=`echo $name | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
|
||||
test -n "${moddeps+set}" || moddeps=
|
||||
test -n "$nozshdep" || moddeps="$moddeps zsh/main"
|
||||
test -n "${proto+set}" ||
|
||||
proto=`echo $objects '' | sed 's,\.o ,.syms ,g'`
|
||||
|
||||
dobjects=`echo $objects '' | sed 's,\.o ,..o ,g'`
|
||||
modhdeps=
|
||||
mododeps=
|
||||
exportdeps=
|
||||
imports=
|
||||
q_moddeps=
|
||||
for dep in $moddeps; do
|
||||
depfile="`grep '^name='$dep' ' ./config.modules | \
|
||||
sed -e 's/^.* modfile=//' -e 's/ .*//'`"
|
||||
q_dep=`echo $dep | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
|
||||
q_moddeps="$q_moddeps $q_dep"
|
||||
eval `echo $depfile | sed 's,/\([^/]*\)\.mdd$,;depbase=\1,;s,^,loc=,'`
|
||||
case "$binmod" in
|
||||
*" $dep "* )
|
||||
dep=zsh/main
|
||||
;;
|
||||
esac
|
||||
|
||||
case $the_subdir in
|
||||
$loc)
|
||||
mdh="${depbase}.mdh"
|
||||
export="${depbase}.export"
|
||||
case "$dep" in
|
||||
zsh/main )
|
||||
mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
|
||||
;;
|
||||
* )
|
||||
mdll="${depbase}.\$(DL_EXT) "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
$loc/*)
|
||||
mdh="\$(dir_top)/$loc/${depbase}.mdh"
|
||||
case "$other_mdhs " in
|
||||
*" $mdh "*) ;;
|
||||
*) other_mdhs="$other_mdhs $mdh" ;;
|
||||
esac
|
||||
export="\$(dir_top)/$loc/${depbase}.export"
|
||||
case "$other_exports " in
|
||||
*" $export "*) ;;
|
||||
*) other_exports="$other_exports $export" ;;
|
||||
esac
|
||||
case "$dep" in
|
||||
zsh/main )
|
||||
mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
|
||||
;;
|
||||
* )
|
||||
mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
|
||||
;;
|
||||
esac
|
||||
case "$other_modules " in
|
||||
*" $mdll "*) ;;
|
||||
*) other_modules="$other_modules $mdll" ;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
mdh="\$(dir_top)/$loc/${depbase}.mdh"
|
||||
case "$remote_mdhs " in
|
||||
*" $mdh "*) ;;
|
||||
*) remote_mdhs="$remote_mdhs $mdh" ;;
|
||||
esac
|
||||
export="\$(dir_top)/$loc/${depbase}.export"
|
||||
case "$remote_exports " in
|
||||
*" $export "*) ;;
|
||||
*) remote_exports="$remote_exports $export" ;;
|
||||
esac
|
||||
case "$dep" in
|
||||
zsh/main )
|
||||
mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
|
||||
;;
|
||||
* )
|
||||
mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
|
||||
;;
|
||||
esac
|
||||
case "$remote_modules " in
|
||||
*" $mdll "*) ;;
|
||||
*) remote_modules="$remote_modules $mdll" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
modhdeps="$modhdeps $mdh"
|
||||
exportdeps="$exportdeps $export"
|
||||
imports="$imports \$(IMPOPT)$export"
|
||||
case "$mododeps " in
|
||||
*" $mdll "* )
|
||||
:
|
||||
;;
|
||||
* )
|
||||
mododeps="$mododeps $mdll"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "##### ===== DEPENDENCIES GENERATED FROM ${mddname}.mdd ===== #####"
|
||||
echo
|
||||
echo "MODOBJS_${mddname} = $objects"
|
||||
echo "MODDOBJS_${mddname} = $dobjects \$(@E@NTRYOBJ)"
|
||||
echo "SYMS_${mddname} = $proto"
|
||||
echo "EPRO_${mddname} = "`echo $proto '' | sed 's,\.syms ,.epro ,g'`
|
||||
echo "INCS_${mddname} = \$(EPRO_${mddname}) $otherincs"
|
||||
echo "EXPIMP_${mddname} = $imports \$(EXPOPT)$mddname.export"
|
||||
echo "NXPIMP_${mddname} ="
|
||||
echo "LINKMODS_${mddname} = $mododeps"
|
||||
echo "NOLINKMODS_${mddname} = "
|
||||
echo
|
||||
echo "proto.${mddname}: \$(EPRO_${mddname})"
|
||||
echo "\$(SYMS_${mddname}): \$(PROTODEPS)"
|
||||
echo
|
||||
echo "${mddname}.export: \$(SYMS_${mddname})"
|
||||
echo " @( echo '#!'; cat \$(SYMS_${mddname}) | sed -n '/^X/{s/^X//;p;}' | sort -u ) > \$@"
|
||||
echo
|
||||
echo "modobjs.${mddname}: \$(MODOBJS_${mddname})"
|
||||
echo " @echo '' \$(MODOBJS_${mddname}) $modobjs_sed>> \$(dir_src)/stamp-modobjs.tmp"
|
||||
echo
|
||||
if test -z "$alwayslink"; then
|
||||
case " $all_modules" in *" ${mddname}."*)
|
||||
echo "install.modules-here: install.modules.${mddname}"
|
||||
echo "uninstall.modules-here: uninstall.modules.${mddname}"
|
||||
echo
|
||||
;; esac
|
||||
instsubdir=`echo $name | sed 's,^,/,;s,/[^/]*$,,'`
|
||||
echo "install.modules.${mddname}: ${mddname}.\$(DL_EXT)"
|
||||
echo " \$(SHELL) \$(sdir_top)/mkinstalldirs \$(DESTDIR)\$(MODDIR)${instsubdir}"
|
||||
echo " \$(INSTALL_PROGRAM) \$(STRIPFLAGS) ${mddname}.\$(DL_EXT) \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
|
||||
echo
|
||||
echo "uninstall.modules.${mddname}:"
|
||||
echo " rm -f \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
|
||||
echo
|
||||
echo "${mddname}.\$(DL_EXT): \$(MODDOBJS_${mddname}) ${mddname}.export $exportdeps \$(@LINKMODS@_${mddname})"
|
||||
echo ' rm -f $@'
|
||||
echo " \$(DLLINK) \$(@E@XPIMP_$mddname) \$(@E@NTRYOPT) \$(MODDOBJS_${mddname}) \$(@LINKMODS@_${mddname}) \$(LIBS) "
|
||||
echo
|
||||
fi
|
||||
echo "${mddname}.mdhi: ${mddname}.mdhs \$(INCS_${mddname})"
|
||||
echo " @test -f \$@ || echo 'do not delete this file' > \$@"
|
||||
echo
|
||||
echo "${mddname}.mdhs: ${mddname}.mdd"
|
||||
echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
|
||||
echo " @if cmp -s ${mddname}.mdh ${mddname}.mdh.tmp; then \\"
|
||||
echo " rm -f ${mddname}.mdh.tmp; \\"
|
||||
echo " echo \"\\\`${mddname}.mdh' is up to date.\"; \\"
|
||||
echo " else \\"
|
||||
echo " mv -f ${mddname}.mdh.tmp ${mddname}.mdh; \\"
|
||||
echo " echo \"Updated \\\`${mddname}.mdh'.\"; \\"
|
||||
echo " fi"
|
||||
echo " echo 'timestamp for ${mddname}.mdh against ${mddname}.mdd' > \$@"
|
||||
echo
|
||||
echo "${mddname}.mdh: ${modhdeps} ${headers} ${hdrdeps} ${mddname}.mdhi"
|
||||
echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
|
||||
echo " @mv -f ${mddname}.mdh.tmp ${mddname}.mdh"
|
||||
echo " @echo \"Updated \\\`${mddname}.mdh'.\""
|
||||
echo
|
||||
echo "${mddname}.mdh.tmp:"
|
||||
echo " @( \\"
|
||||
echo " echo '#ifndef have_${q_name}_module'; \\"
|
||||
echo " echo '#define have_${q_name}_module'; \\"
|
||||
echo " echo; \\"
|
||||
echo " echo '# ifndef IMPORTING_MODULE_${q_name}'; \\"
|
||||
echo " if test @SHORTBOOTNAMES@ = yes; then \\"
|
||||
echo " echo '# ifndef MODULE'; \\"
|
||||
echo " fi; \\"
|
||||
echo " echo '# define boot_ boot_${q_name}'; \\"
|
||||
echo " echo '# define cleanup_ cleanup_${q_name}'; \\"
|
||||
echo " echo '# define features_ features_${q_name}'; \\"
|
||||
echo " echo '# define enables_ enables_${q_name}'; \\"
|
||||
echo " echo '# define setup_ setup_${q_name}'; \\"
|
||||
echo " echo '# define finish_ finish_${q_name}'; \\"
|
||||
echo " if test @SHORTBOOTNAMES@ = yes; then \\"
|
||||
echo " echo '# endif /* !MODULE */'; \\"
|
||||
echo " fi; \\"
|
||||
echo " echo '# endif /* !IMPORTING_MODULE_${q_name} */'; \\"
|
||||
echo " echo; \\"
|
||||
if test -n "$moddeps"; then (
|
||||
set x $q_moddeps
|
||||
echo " echo '/* Module dependencies */'; \\"
|
||||
for hdep in $modhdeps; do
|
||||
shift
|
||||
echo " echo '# define IMPORTING_MODULE_${1} 1'; \\"
|
||||
echo " echo '# include \"${hdep}\"'; \\"
|
||||
done
|
||||
echo " echo; \\"
|
||||
) fi
|
||||
if test -n "$headers"; then
|
||||
echo " echo '/* Extra headers for this module */'; \\"
|
||||
echo " for hdr in $headers; do \\"
|
||||
echo " echo '# include \"'\$\$hdr'\"'; \\"
|
||||
echo " done; \\"
|
||||
echo " echo; \\"
|
||||
fi
|
||||
if test -n "$proto"; then
|
||||
echo " echo '# undef mod_import_variable'; \\"
|
||||
echo " echo '# undef mod_import_function'; \\"
|
||||
echo " echo '# if defined(IMPORTING_MODULE_${q_name}) && defined(MODULE)'; \\"
|
||||
echo " echo '# define mod_import_variable @MOD_IMPORT_VARIABLE@'; \\"
|
||||
echo " echo '# define mod_import_function @MOD_IMPORT_FUNCTION@'; \\"
|
||||
echo " echo '# else'; \\"
|
||||
echo " echo '# define mod_import_function'; \\"
|
||||
echo " echo '# define mod_import_variable'; \\"
|
||||
echo " echo '# endif /* IMPORTING_MODULE_${q_name} && MODULE */'; \\"
|
||||
echo " for epro in \$(EPRO_${mddname}); do \\"
|
||||
echo " echo '# include \"'\$\$epro'\"'; \\"
|
||||
echo " done; \\"
|
||||
echo " echo '# undef mod_import_variable'; \\"
|
||||
echo " echo '# define mod_import_variable'; \\"
|
||||
echo " echo '# undef mod_import_variable'; \\"
|
||||
echo " echo '# define mod_import_variable'; \\"
|
||||
echo " echo '# ifndef mod_export'; \\"
|
||||
echo " echo '# define mod_export @MOD_EXPORT@'; \\"
|
||||
echo " echo '# endif /* mod_export */'; \\"
|
||||
echo " echo; \\"
|
||||
fi
|
||||
echo " echo '#endif /* !have_${q_name}_module */'; \\"
|
||||
echo " ) > \$@"
|
||||
echo
|
||||
echo "\$(MODOBJS_${mddname}) \$(MODDOBJS_${mddname}): ${mddname}.mdh"
|
||||
sed -e '/^ *: *<< *\\Make *$/,/^Make$/!d' \
|
||||
-e 's/^ *: *<< *\\Make *$//; /^Make$/d' \
|
||||
< $top_srcdir/$the_subdir/${mddname}.mdd
|
||||
echo
|
||||
|
||||
done
|
||||
|
||||
if test -n "$remote_mdhs$other_mdhs$remote_exports$other_exports$remote_modules$other_modules"; then
|
||||
echo "##### ===== DEPENDENCIES FOR REMOTE MODULES ===== #####"
|
||||
echo
|
||||
for mdh in $remote_mdhs; do
|
||||
echo "$mdh: FORCE"
|
||||
echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$mdh"
|
||||
echo
|
||||
done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
|
||||
if test -n "$other_mdhs"; then
|
||||
echo "${other_mdhs}:" | sed 's,^ ,,'
|
||||
echo " false # A. should only happen with make -n"
|
||||
echo
|
||||
fi
|
||||
for export in $remote_exports; do
|
||||
echo "$export: FORCE"
|
||||
echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$export"
|
||||
echo
|
||||
done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
|
||||
if test -n "$other_exports"; then
|
||||
echo "${other_exports}:" | sed 's,^ ,,'
|
||||
echo " false # B. should only happen with make -n"
|
||||
echo
|
||||
fi
|
||||
for mdll in $remote_modules; do
|
||||
echo "$mdll: FORCE"
|
||||
echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$mdll"
|
||||
echo
|
||||
done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
|
||||
if test -n "$other_modules"; then
|
||||
echo "${other_modules}:" | sed 's,^ ,,'
|
||||
echo " false # C. should only happen with make -n"
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "##### End of ${the_makefile}.in"
|
||||
|
||||
exec >&3 3>&-
|
||||
|
||||
fi
|
||||
|
||||
if $second_stage ; then
|
||||
trap "rm -f $the_subdir/${the_makefile}; exit 1" 1 2 15
|
||||
|
||||
${CONFIG_SHELL-/bin/sh} ./config.status \
|
||||
--file=$the_subdir/${the_makefile}:$the_subdir/${the_makefile}.in ||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,955 +0,0 @@
|
|||
/*
|
||||
* options.c - shell options
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "zsh.mdh"
|
||||
#include "options.pro"
|
||||
|
||||
/* current emulation (used to decide which set of option letters is used) */
|
||||
|
||||
/**/
|
||||
mod_export int emulation;
|
||||
|
||||
/* current sticky emulation: sticky = NULL means none */
|
||||
|
||||
/**/
|
||||
mod_export Emulation_options sticky;
|
||||
|
||||
/* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
|
||||
|
||||
/**/
|
||||
mod_export char opts[OPT_SIZE];
|
||||
|
||||
/* Option name hash table */
|
||||
|
||||
/**/
|
||||
mod_export HashTable optiontab;
|
||||
|
||||
/* The canonical option name table */
|
||||
|
||||
#define OPT_CSH EMULATE_CSH
|
||||
#define OPT_KSH EMULATE_KSH
|
||||
#define OPT_SH EMULATE_SH
|
||||
#define OPT_ZSH EMULATE_ZSH
|
||||
|
||||
#define OPT_ALL (OPT_CSH|OPT_KSH|OPT_SH|OPT_ZSH)
|
||||
#define OPT_BOURNE (OPT_KSH|OPT_SH)
|
||||
#define OPT_BSHELL (OPT_KSH|OPT_SH|OPT_ZSH)
|
||||
#define OPT_NONBOURNE (OPT_ALL & ~OPT_BOURNE)
|
||||
#define OPT_NONZSH (OPT_ALL & ~OPT_ZSH)
|
||||
|
||||
/* option is relevant to emulation */
|
||||
#define OPT_EMULATE (EMULATE_UNUSED)
|
||||
/* option should never be set by emulate() */
|
||||
#define OPT_SPECIAL (EMULATE_UNUSED<<1)
|
||||
/* option is an alias to an other option */
|
||||
#define OPT_ALIAS (EMULATE_UNUSED<<2)
|
||||
|
||||
#define defset(X, my_emulation) (!!((X)->node.flags & my_emulation))
|
||||
|
||||
/*
|
||||
* Note that option names should usually be fewer than 20 characters long
|
||||
* to avoid formatting problems.
|
||||
*/
|
||||
static struct optname optns[] = {
|
||||
{{NULL, "aliases", OPT_EMULATE|OPT_ALL}, ALIASESOPT},
|
||||
{{NULL, "aliasfuncdef", OPT_EMULATE|OPT_BOURNE}, ALIASFUNCDEF},
|
||||
{{NULL, "allexport", OPT_EMULATE}, ALLEXPORT},
|
||||
{{NULL, "alwayslastprompt", OPT_ALL}, ALWAYSLASTPROMPT},
|
||||
{{NULL, "alwaystoend", 0}, ALWAYSTOEND},
|
||||
{{NULL, "appendcreate", OPT_EMULATE|OPT_BOURNE}, APPENDCREATE},
|
||||
{{NULL, "appendhistory", OPT_ALL}, APPENDHISTORY},
|
||||
{{NULL, "autocd", OPT_EMULATE}, AUTOCD},
|
||||
{{NULL, "autocontinue", 0}, AUTOCONTINUE},
|
||||
{{NULL, "autolist", OPT_ALL}, AUTOLIST},
|
||||
{{NULL, "automenu", OPT_ALL}, AUTOMENU},
|
||||
{{NULL, "autonamedirs", 0}, AUTONAMEDIRS},
|
||||
{{NULL, "autoparamkeys", OPT_ALL}, AUTOPARAMKEYS},
|
||||
{{NULL, "autoparamslash", OPT_ALL}, AUTOPARAMSLASH},
|
||||
{{NULL, "autopushd", 0}, AUTOPUSHD},
|
||||
{{NULL, "autoremoveslash", OPT_ALL}, AUTOREMOVESLASH},
|
||||
{{NULL, "autoresume", 0}, AUTORESUME},
|
||||
{{NULL, "badpattern", OPT_EMULATE|OPT_NONBOURNE},BADPATTERN},
|
||||
{{NULL, "banghist", OPT_NONBOURNE}, BANGHIST},
|
||||
{{NULL, "bareglobqual", OPT_EMULATE|OPT_ZSH}, BAREGLOBQUAL},
|
||||
{{NULL, "bashautolist", 0}, BASHAUTOLIST},
|
||||
{{NULL, "bashrematch", 0}, BASHREMATCH},
|
||||
{{NULL, "beep", OPT_ALL}, BEEP},
|
||||
{{NULL, "bgnice", OPT_EMULATE|OPT_NONBOURNE},BGNICE},
|
||||
{{NULL, "braceccl", OPT_EMULATE}, BRACECCL},
|
||||
{{NULL, "bsdecho", OPT_EMULATE|OPT_SH}, BSDECHO},
|
||||
{{NULL, "caseglob", OPT_ALL}, CASEGLOB},
|
||||
{{NULL, "casematch", OPT_ALL}, CASEMATCH},
|
||||
{{NULL, "cbases", 0}, CBASES},
|
||||
{{NULL, "cprecedences", OPT_EMULATE|OPT_NONZSH}, CPRECEDENCES},
|
||||
{{NULL, "cdablevars", OPT_EMULATE}, CDABLEVARS},
|
||||
{{NULL, "chasedots", OPT_EMULATE}, CHASEDOTS},
|
||||
{{NULL, "chaselinks", OPT_EMULATE}, CHASELINKS},
|
||||
{{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS},
|
||||
{{NULL, "checkrunningjobs", OPT_EMULATE|OPT_ZSH}, CHECKRUNNINGJOBS},
|
||||
{{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER},
|
||||
{{NULL, "combiningchars", 0}, COMBININGCHARS},
|
||||
{{NULL, "completealiases", 0}, COMPLETEALIASES},
|
||||
{{NULL, "completeinword", 0}, COMPLETEINWORD},
|
||||
{{NULL, "continueonerror", 0}, CONTINUEONERROR},
|
||||
{{NULL, "correct", 0}, CORRECT},
|
||||
{{NULL, "correctall", 0}, CORRECTALL},
|
||||
{{NULL, "cshjunkiehistory", OPT_EMULATE|OPT_CSH}, CSHJUNKIEHISTORY},
|
||||
{{NULL, "cshjunkieloops", OPT_EMULATE|OPT_CSH}, CSHJUNKIELOOPS},
|
||||
{{NULL, "cshjunkiequotes", OPT_EMULATE|OPT_CSH}, CSHJUNKIEQUOTES},
|
||||
{{NULL, "cshnullcmd", OPT_EMULATE|OPT_CSH}, CSHNULLCMD},
|
||||
{{NULL, "cshnullglob", OPT_EMULATE|OPT_CSH}, CSHNULLGLOB},
|
||||
{{NULL, "debugbeforecmd", OPT_ALL}, DEBUGBEFORECMD},
|
||||
{{NULL, "emacs", 0}, EMACSMODE},
|
||||
{{NULL, "equals", OPT_EMULATE|OPT_ZSH}, EQUALS},
|
||||
{{NULL, "errexit", OPT_EMULATE}, ERREXIT},
|
||||
{{NULL, "errreturn", OPT_EMULATE}, ERRRETURN},
|
||||
{{NULL, "exec", OPT_ALL}, EXECOPT},
|
||||
{{NULL, "extendedglob", OPT_EMULATE}, EXTENDEDGLOB},
|
||||
{{NULL, "extendedhistory", OPT_CSH}, EXTENDEDHISTORY},
|
||||
{{NULL, "evallineno", OPT_EMULATE|OPT_ZSH}, EVALLINENO},
|
||||
{{NULL, "flowcontrol", OPT_ALL}, FLOWCONTROL},
|
||||
{{NULL, "forcefloat", 0}, FORCEFLOAT},
|
||||
{{NULL, "functionargzero", OPT_EMULATE|OPT_NONBOURNE},FUNCTIONARGZERO},
|
||||
{{NULL, "glob", OPT_EMULATE|OPT_ALL}, GLOBOPT},
|
||||
{{NULL, "globalexport", OPT_EMULATE|OPT_ZSH}, GLOBALEXPORT},
|
||||
{{NULL, "globalrcs", OPT_ALL}, GLOBALRCS},
|
||||
{{NULL, "globassign", OPT_EMULATE|OPT_CSH}, GLOBASSIGN},
|
||||
{{NULL, "globcomplete", 0}, GLOBCOMPLETE},
|
||||
{{NULL, "globdots", OPT_EMULATE}, GLOBDOTS},
|
||||
{{NULL, "globstarshort", OPT_EMULATE}, GLOBSTARSHORT},
|
||||
{{NULL, "globsubst", OPT_EMULATE|OPT_NONZSH}, GLOBSUBST},
|
||||
{{NULL, "hashcmds", OPT_ALL}, HASHCMDS},
|
||||
{{NULL, "hashdirs", OPT_ALL}, HASHDIRS},
|
||||
{{NULL, "hashexecutablesonly", 0}, HASHEXECUTABLESONLY},
|
||||
{{NULL, "hashlistall", OPT_ALL}, HASHLISTALL},
|
||||
{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER},
|
||||
{{NULL, "histbeep", OPT_ALL}, HISTBEEP},
|
||||
{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST},
|
||||
{{NULL, "histfcntllock", 0}, HISTFCNTLLOCK},
|
||||
{{NULL, "histfindnodups", 0}, HISTFINDNODUPS},
|
||||
{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS},
|
||||
{{NULL, "histignoredups", 0}, HISTIGNOREDUPS},
|
||||
{{NULL, "histignorespace", 0}, HISTIGNORESPACE},
|
||||
{{NULL, "histlexwords", 0}, HISTLEXWORDS},
|
||||
{{NULL, "histnofunctions", 0}, HISTNOFUNCTIONS},
|
||||
{{NULL, "histnostore", 0}, HISTNOSTORE},
|
||||
{{NULL, "histsubstpattern", OPT_EMULATE}, HISTSUBSTPATTERN},
|
||||
{{NULL, "histreduceblanks", 0}, HISTREDUCEBLANKS},
|
||||
{{NULL, "histsavebycopy", OPT_ALL}, HISTSAVEBYCOPY},
|
||||
{{NULL, "histsavenodups", 0}, HISTSAVENODUPS},
|
||||
{{NULL, "histverify", 0}, HISTVERIFY},
|
||||
{{NULL, "hup", OPT_EMULATE|OPT_ZSH}, HUP},
|
||||
{{NULL, "ignorebraces", OPT_EMULATE|OPT_SH}, IGNOREBRACES},
|
||||
{{NULL, "ignoreclosebraces", OPT_EMULATE}, IGNORECLOSEBRACES},
|
||||
{{NULL, "ignoreeof", 0}, IGNOREEOF},
|
||||
{{NULL, "incappendhistory", 0}, INCAPPENDHISTORY},
|
||||
{{NULL, "incappendhistorytime", 0}, INCAPPENDHISTORYTIME},
|
||||
{{NULL, "interactive", OPT_SPECIAL}, INTERACTIVE},
|
||||
{{NULL, "interactivecomments",OPT_BOURNE}, INTERACTIVECOMMENTS},
|
||||
{{NULL, "ksharrays", OPT_EMULATE|OPT_BOURNE}, KSHARRAYS},
|
||||
{{NULL, "kshautoload", OPT_EMULATE|OPT_BOURNE}, KSHAUTOLOAD},
|
||||
{{NULL, "kshglob", OPT_EMULATE|OPT_KSH}, KSHGLOB},
|
||||
{{NULL, "kshoptionprint", OPT_EMULATE|OPT_KSH}, KSHOPTIONPRINT},
|
||||
{{NULL, "kshtypeset", 0}, KSHTYPESET},
|
||||
{{NULL, "kshzerosubscript", 0}, KSHZEROSUBSCRIPT},
|
||||
{{NULL, "listambiguous", OPT_ALL}, LISTAMBIGUOUS},
|
||||
{{NULL, "listbeep", OPT_ALL}, LISTBEEP},
|
||||
{{NULL, "listpacked", 0}, LISTPACKED},
|
||||
{{NULL, "listrowsfirst", 0}, LISTROWSFIRST},
|
||||
{{NULL, "listtypes", OPT_ALL}, LISTTYPES},
|
||||
{{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS},
|
||||
{{NULL, "localloops", OPT_EMULATE}, LOCALLOOPS},
|
||||
{{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS},
|
||||
{{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS},
|
||||
{{NULL, "login", OPT_SPECIAL}, LOGINSHELL},
|
||||
{{NULL, "longlistjobs", 0}, LONGLISTJOBS},
|
||||
{{NULL, "magicequalsubst", OPT_EMULATE}, MAGICEQUALSUBST},
|
||||
{{NULL, "mailwarning", 0}, MAILWARNING},
|
||||
{{NULL, "markdirs", 0}, MARKDIRS},
|
||||
{{NULL, "menucomplete", 0}, MENUCOMPLETE},
|
||||
{{NULL, "monitor", OPT_SPECIAL}, MONITOR},
|
||||
{{NULL, "multibyte",
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
OPT_ALL
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
}, MULTIBYTE},
|
||||
{{NULL, "multifuncdef", OPT_EMULATE|OPT_ZSH}, MULTIFUNCDEF},
|
||||
{{NULL, "multios", OPT_EMULATE|OPT_ZSH}, MULTIOS},
|
||||
{{NULL, "nomatch", OPT_EMULATE|OPT_NONBOURNE},NOMATCH},
|
||||
{{NULL, "notify", OPT_ZSH}, NOTIFY},
|
||||
{{NULL, "nullglob", OPT_EMULATE}, NULLGLOB},
|
||||
{{NULL, "numericglobsort", OPT_EMULATE}, NUMERICGLOBSORT},
|
||||
{{NULL, "octalzeroes", OPT_EMULATE|OPT_SH}, OCTALZEROES},
|
||||
{{NULL, "overstrike", 0}, OVERSTRIKE},
|
||||
{{NULL, "pathdirs", OPT_EMULATE}, PATHDIRS},
|
||||
{{NULL, "pathscript", OPT_EMULATE|OPT_BOURNE}, PATHSCRIPT},
|
||||
{{NULL, "pipefail", OPT_EMULATE}, PIPEFAIL},
|
||||
{{NULL, "posixaliases", OPT_EMULATE|OPT_BOURNE}, POSIXALIASES},
|
||||
{{NULL, "posixargzero", OPT_EMULATE}, POSIXARGZERO},
|
||||
{{NULL, "posixbuiltins", OPT_EMULATE|OPT_BOURNE}, POSIXBUILTINS},
|
||||
{{NULL, "posixcd", OPT_EMULATE|OPT_BOURNE}, POSIXCD},
|
||||
{{NULL, "posixidentifiers", OPT_EMULATE|OPT_BOURNE}, POSIXIDENTIFIERS},
|
||||
{{NULL, "posixjobs", OPT_EMULATE|OPT_BOURNE}, POSIXJOBS},
|
||||
{{NULL, "posixstrings", OPT_EMULATE|OPT_BOURNE}, POSIXSTRINGS},
|
||||
{{NULL, "posixtraps", OPT_EMULATE|OPT_BOURNE}, POSIXTRAPS},
|
||||
{{NULL, "printeightbit", 0}, PRINTEIGHTBIT},
|
||||
{{NULL, "printexitvalue", 0}, PRINTEXITVALUE},
|
||||
{{NULL, "privileged", OPT_SPECIAL}, PRIVILEGED},
|
||||
{{NULL, "promptbang", OPT_KSH}, PROMPTBANG},
|
||||
{{NULL, "promptcr", OPT_ALL}, PROMPTCR},
|
||||
{{NULL, "promptpercent", OPT_NONBOURNE}, PROMPTPERCENT},
|
||||
{{NULL, "promptsp", OPT_ALL}, PROMPTSP},
|
||||
{{NULL, "promptsubst", OPT_BOURNE}, PROMPTSUBST},
|
||||
{{NULL, "pushdignoredups", OPT_EMULATE}, PUSHDIGNOREDUPS},
|
||||
{{NULL, "pushdminus", OPT_EMULATE}, PUSHDMINUS},
|
||||
{{NULL, "pushdsilent", 0}, PUSHDSILENT},
|
||||
{{NULL, "pushdtohome", OPT_EMULATE}, PUSHDTOHOME},
|
||||
{{NULL, "rcexpandparam", OPT_EMULATE}, RCEXPANDPARAM},
|
||||
{{NULL, "rcquotes", OPT_EMULATE}, RCQUOTES},
|
||||
{{NULL, "rcs", OPT_ALL}, RCS},
|
||||
{{NULL, "recexact", 0}, RECEXACT},
|
||||
{{NULL, "rematchpcre", 0}, REMATCHPCRE},
|
||||
{{NULL, "restricted", OPT_SPECIAL}, RESTRICTED},
|
||||
{{NULL, "rmstarsilent", OPT_BOURNE}, RMSTARSILENT},
|
||||
{{NULL, "rmstarwait", 0}, RMSTARWAIT},
|
||||
{{NULL, "sharehistory", OPT_KSH}, SHAREHISTORY},
|
||||
{{NULL, "shfileexpansion", OPT_EMULATE|OPT_BOURNE}, SHFILEEXPANSION},
|
||||
{{NULL, "shglob", OPT_EMULATE|OPT_BOURNE}, SHGLOB},
|
||||
{{NULL, "shinstdin", OPT_SPECIAL}, SHINSTDIN},
|
||||
{{NULL, "shnullcmd", OPT_EMULATE|OPT_BOURNE}, SHNULLCMD},
|
||||
{{NULL, "shoptionletters", OPT_EMULATE|OPT_BOURNE}, SHOPTIONLETTERS},
|
||||
{{NULL, "shortloops", OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS},
|
||||
{{NULL, "shwordsplit", OPT_EMULATE|OPT_BOURNE}, SHWORDSPLIT},
|
||||
{{NULL, "singlecommand", OPT_SPECIAL}, SINGLECOMMAND},
|
||||
{{NULL, "singlelinezle", OPT_KSH}, SINGLELINEZLE},
|
||||
{{NULL, "sourcetrace", 0}, SOURCETRACE},
|
||||
{{NULL, "sunkeyboardhack", 0}, SUNKEYBOARDHACK},
|
||||
{{NULL, "transientrprompt", 0}, TRANSIENTRPROMPT},
|
||||
{{NULL, "trapsasync", 0}, TRAPSASYNC},
|
||||
{{NULL, "typesetsilent", OPT_EMULATE|OPT_BOURNE}, TYPESETSILENT},
|
||||
{{NULL, "unset", OPT_EMULATE|OPT_BSHELL}, UNSET},
|
||||
{{NULL, "verbose", 0}, VERBOSE},
|
||||
{{NULL, "vi", 0}, VIMODE},
|
||||
{{NULL, "warncreateglobal", OPT_EMULATE}, WARNCREATEGLOBAL},
|
||||
{{NULL, "warnnestedvar", OPT_EMULATE}, WARNNESTEDVAR},
|
||||
{{NULL, "xtrace", 0}, XTRACE},
|
||||
{{NULL, "zle", OPT_SPECIAL}, USEZLE},
|
||||
{{NULL, "braceexpand", OPT_ALIAS}, /* ksh/bash */ -IGNOREBRACES},
|
||||
{{NULL, "dotglob", OPT_ALIAS}, /* bash */ GLOBDOTS},
|
||||
{{NULL, "hashall", OPT_ALIAS}, /* bash */ HASHCMDS},
|
||||
{{NULL, "histappend", OPT_ALIAS}, /* bash */ APPENDHISTORY},
|
||||
{{NULL, "histexpand", OPT_ALIAS}, /* bash */ BANGHIST},
|
||||
{{NULL, "log", OPT_ALIAS}, /* ksh */ -HISTNOFUNCTIONS},
|
||||
{{NULL, "mailwarn", OPT_ALIAS}, /* bash */ MAILWARNING},
|
||||
{{NULL, "onecmd", OPT_ALIAS}, /* bash */ SINGLECOMMAND},
|
||||
{{NULL, "physical", OPT_ALIAS}, /* ksh/bash */ CHASELINKS},
|
||||
{{NULL, "promptvars", OPT_ALIAS}, /* bash */ PROMPTSUBST},
|
||||
{{NULL, "stdin", OPT_ALIAS}, /* ksh */ SHINSTDIN},
|
||||
{{NULL, "trackall", OPT_ALIAS}, /* ksh */ HASHCMDS},
|
||||
{{NULL, "dvorak", 0}, DVORAK},
|
||||
{{NULL, NULL, 0}, 0}
|
||||
};
|
||||
|
||||
/* Option letters */
|
||||
|
||||
#define optletters (isset(SHOPTIONLETTERS) ? kshletters : zshletters)
|
||||
|
||||
#define FIRST_OPT '0'
|
||||
#define LAST_OPT 'y'
|
||||
|
||||
static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
|
||||
/* 0 */ CORRECT,
|
||||
/* 1 */ PRINTEXITVALUE,
|
||||
/* 2 */ -BADPATTERN,
|
||||
/* 3 */ -NOMATCH,
|
||||
/* 4 */ GLOBDOTS,
|
||||
/* 5 */ NOTIFY,
|
||||
/* 6 */ BGNICE,
|
||||
/* 7 */ IGNOREEOF,
|
||||
/* 8 */ MARKDIRS,
|
||||
/* 9 */ AUTOLIST,
|
||||
/* : */ 0,
|
||||
/* ; */ 0,
|
||||
/* < */ 0,
|
||||
/* = */ 0,
|
||||
/* > */ 0,
|
||||
/* ? */ 0,
|
||||
/* @ */ 0,
|
||||
/* A */ 0, /* use with set for arrays */
|
||||
/* B */ -BEEP,
|
||||
/* C */ -CLOBBER,
|
||||
/* D */ PUSHDTOHOME,
|
||||
/* E */ PUSHDSILENT,
|
||||
/* F */ -GLOBOPT,
|
||||
/* G */ NULLGLOB,
|
||||
/* H */ RMSTARSILENT,
|
||||
/* I */ IGNOREBRACES,
|
||||
/* J */ AUTOCD,
|
||||
/* K */ -BANGHIST,
|
||||
/* L */ SUNKEYBOARDHACK,
|
||||
/* M */ SINGLELINEZLE,
|
||||
/* N */ AUTOPUSHD,
|
||||
/* O */ CORRECTALL,
|
||||
/* P */ RCEXPANDPARAM,
|
||||
/* Q */ PATHDIRS,
|
||||
/* R */ LONGLISTJOBS,
|
||||
/* S */ RECEXACT,
|
||||
/* T */ CDABLEVARS,
|
||||
/* U */ MAILWARNING,
|
||||
/* V */ -PROMPTCR,
|
||||
/* W */ AUTORESUME,
|
||||
/* X */ LISTTYPES,
|
||||
/* Y */ MENUCOMPLETE,
|
||||
/* Z */ USEZLE,
|
||||
/* [ */ 0,
|
||||
/* \ */ 0,
|
||||
/* ] */ 0,
|
||||
/* ^ */ 0,
|
||||
/* _ */ 0,
|
||||
/* ` */ 0,
|
||||
/* a */ ALLEXPORT,
|
||||
/* b */ 0, /* in non-Bourne shells, end of options */
|
||||
/* c */ 0, /* command follows */
|
||||
/* d */ -GLOBALRCS,
|
||||
/* e */ ERREXIT,
|
||||
/* f */ -RCS,
|
||||
/* g */ HISTIGNORESPACE,
|
||||
/* h */ HISTIGNOREDUPS,
|
||||
/* i */ INTERACTIVE,
|
||||
/* j */ 0,
|
||||
/* k */ INTERACTIVECOMMENTS,
|
||||
/* l */ LOGINSHELL,
|
||||
/* m */ MONITOR,
|
||||
/* n */ -EXECOPT,
|
||||
/* o */ 0, /* long option name follows */
|
||||
/* p */ PRIVILEGED,
|
||||
/* q */ 0,
|
||||
/* r */ RESTRICTED,
|
||||
/* s */ SHINSTDIN,
|
||||
/* t */ SINGLECOMMAND,
|
||||
/* u */ -UNSET,
|
||||
/* v */ VERBOSE,
|
||||
/* w */ CHASELINKS,
|
||||
/* x */ XTRACE,
|
||||
/* y */ SHWORDSPLIT,
|
||||
};
|
||||
|
||||
static short kshletters[LAST_OPT - FIRST_OPT + 1] = {
|
||||
/* 0 */ 0,
|
||||
/* 1 */ 0,
|
||||
/* 2 */ 0,
|
||||
/* 3 */ 0,
|
||||
/* 4 */ 0,
|
||||
/* 5 */ 0,
|
||||
/* 6 */ 0,
|
||||
/* 7 */ 0,
|
||||
/* 8 */ 0,
|
||||
/* 9 */ 0,
|
||||
/* : */ 0,
|
||||
/* ; */ 0,
|
||||
/* < */ 0,
|
||||
/* = */ 0,
|
||||
/* > */ 0,
|
||||
/* ? */ 0,
|
||||
/* @ */ 0,
|
||||
/* A */ 0,
|
||||
/* B */ 0,
|
||||
/* C */ -CLOBBER,
|
||||
/* D */ 0,
|
||||
/* E */ 0,
|
||||
/* F */ 0,
|
||||
/* G */ 0,
|
||||
/* H */ 0,
|
||||
/* I */ 0,
|
||||
/* J */ 0,
|
||||
/* K */ 0,
|
||||
/* L */ 0,
|
||||
/* M */ 0,
|
||||
/* N */ 0,
|
||||
/* O */ 0,
|
||||
/* P */ 0,
|
||||
/* Q */ 0,
|
||||
/* R */ 0,
|
||||
/* S */ 0,
|
||||
/* T */ TRAPSASYNC,
|
||||
/* U */ 0,
|
||||
/* V */ 0,
|
||||
/* W */ 0,
|
||||
/* X */ MARKDIRS,
|
||||
/* Y */ 0,
|
||||
/* Z */ 0,
|
||||
/* [ */ 0,
|
||||
/* \ */ 0,
|
||||
/* ] */ 0,
|
||||
/* ^ */ 0,
|
||||
/* _ */ 0,
|
||||
/* ` */ 0,
|
||||
/* a */ ALLEXPORT,
|
||||
/* b */ NOTIFY,
|
||||
/* c */ 0,
|
||||
/* d */ 0,
|
||||
/* e */ ERREXIT,
|
||||
/* f */ -GLOBOPT,
|
||||
/* g */ 0,
|
||||
/* h */ 0,
|
||||
/* i */ INTERACTIVE,
|
||||
/* j */ 0,
|
||||
/* k */ 0,
|
||||
/* l */ LOGINSHELL,
|
||||
/* m */ MONITOR,
|
||||
/* n */ -EXECOPT,
|
||||
/* o */ 0,
|
||||
/* p */ PRIVILEGED,
|
||||
/* q */ 0,
|
||||
/* r */ RESTRICTED,
|
||||
/* s */ SHINSTDIN,
|
||||
/* t */ SINGLECOMMAND,
|
||||
/* u */ -UNSET,
|
||||
/* v */ VERBOSE,
|
||||
/* w */ 0,
|
||||
/* x */ XTRACE,
|
||||
/* y */ 0,
|
||||
};
|
||||
|
||||
/* Initialisation of the option name hash table */
|
||||
|
||||
/**/
|
||||
static void
|
||||
printoptionnode(HashNode hn, int set)
|
||||
{
|
||||
Optname on = (Optname) hn;
|
||||
int optno = on->optno;
|
||||
|
||||
if (optno < 0)
|
||||
optno = -optno;
|
||||
if (isset(KSHOPTIONPRINT)) {
|
||||
if (defset(on, emulation))
|
||||
printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
|
||||
else
|
||||
printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
|
||||
} else if (set == (isset(optno) ^ defset(on, emulation))) {
|
||||
if (set ^ isset(optno))
|
||||
fputs("no", stdout);
|
||||
puts(on->node.nam);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
createoptiontable(void)
|
||||
{
|
||||
Optname on;
|
||||
|
||||
optiontab = newhashtable(101, "optiontab", NULL);
|
||||
|
||||
optiontab->hash = hasher;
|
||||
optiontab->emptytable = NULL;
|
||||
optiontab->filltable = NULL;
|
||||
optiontab->cmpnodes = strcmp;
|
||||
optiontab->addnode = addhashnode;
|
||||
optiontab->getnode = gethashnode;
|
||||
optiontab->getnode2 = gethashnode2;
|
||||
optiontab->removenode = NULL;
|
||||
optiontab->disablenode = disablehashnode;
|
||||
optiontab->enablenode = enablehashnode;
|
||||
optiontab->freenode = NULL;
|
||||
optiontab->printnode = printoptionnode;
|
||||
|
||||
for (on = optns; on->node.nam; on++)
|
||||
optiontab->addnode(optiontab, on->node.nam, on);
|
||||
}
|
||||
|
||||
/* Emulation appropriate to the setemulate function */
|
||||
|
||||
static int setemulate_emulation;
|
||||
|
||||
/* Option array manipulated within the setemulate function */
|
||||
|
||||
/**/
|
||||
static char *setemulate_opts;
|
||||
|
||||
/* Setting of default options */
|
||||
|
||||
/**/
|
||||
static void
|
||||
setemulate(HashNode hn, int fully)
|
||||
{
|
||||
Optname on = (Optname) hn;
|
||||
|
||||
/* Set options: each non-special option is set according to the *
|
||||
* current emulation mode if either it is considered relevant *
|
||||
* to emulation or we are doing a full emulation (as indicated *
|
||||
* by the `fully' parameter). */
|
||||
if (!(on->node.flags & OPT_ALIAS) &&
|
||||
((fully && !(on->node.flags & OPT_SPECIAL)) ||
|
||||
(on->node.flags & OPT_EMULATE)))
|
||||
setemulate_opts[on->optno] = defset(on, setemulate_emulation);
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
installemulation(int new_emulation, char *new_opts)
|
||||
{
|
||||
setemulate_emulation = new_emulation;
|
||||
setemulate_opts = new_opts;
|
||||
scanhashtable(optiontab, 0, 0, 0, setemulate,
|
||||
!!(new_emulation & EMULATE_FULLY));
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts)
|
||||
{
|
||||
char ch = *zsh_name;
|
||||
|
||||
if (ch == 'r')
|
||||
ch = zsh_name[1];
|
||||
|
||||
/* Work out the new emulation mode */
|
||||
if (ch == 'c')
|
||||
*new_emulation = EMULATE_CSH;
|
||||
else if (ch == 'k')
|
||||
*new_emulation = EMULATE_KSH;
|
||||
else if (ch == 's' || ch == 'b')
|
||||
*new_emulation = EMULATE_SH;
|
||||
else
|
||||
*new_emulation = EMULATE_ZSH;
|
||||
|
||||
if (fully)
|
||||
*new_emulation |= EMULATE_FULLY;
|
||||
installemulation(*new_emulation, new_opts);
|
||||
|
||||
if (funcstack && funcstack->tp == FS_FUNC) {
|
||||
/*
|
||||
* We are inside a function. Decide if it's traced.
|
||||
* Pedantic note: the function in the function table isn't
|
||||
* guaranteed to be what we're executing, but it's
|
||||
* close enough.
|
||||
*/
|
||||
Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name);
|
||||
if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) {
|
||||
/* Tracing is on, so set xtrace */
|
||||
new_opts[XTRACE] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setopt, unsetopt */
|
||||
|
||||
/**/
|
||||
static void
|
||||
setoption(HashNode hn, int value)
|
||||
{
|
||||
dosetopt(((Optname) hn)->optno, value, 0, opts);
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
|
||||
{
|
||||
int action, optno, match = 0;
|
||||
|
||||
/* With no arguments or options, display options. */
|
||||
if (!*args) {
|
||||
scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* loop through command line options (begins with "-" or "+") */
|
||||
while (*args && (**args == '-' || **args == '+')) {
|
||||
action = (**args == '-') ^ isun;
|
||||
if(!args[0][1])
|
||||
*args = "--";
|
||||
while (*++*args) {
|
||||
if(**args == Meta)
|
||||
*++*args ^= 32;
|
||||
/* The pseudo-option `--' signifies the end of options. */
|
||||
if (**args == '-') {
|
||||
args++;
|
||||
goto doneoptions;
|
||||
} else if (**args == 'o') {
|
||||
if (!*++*args)
|
||||
args++;
|
||||
if (!*args) {
|
||||
zwarnnam(nam, "string expected after -o");
|
||||
inittyptab();
|
||||
return 1;
|
||||
}
|
||||
if(!(optno = optlookup(*args)))
|
||||
zwarnnam(nam, "no such option: %s", *args);
|
||||
else if(dosetopt(optno, action, 0, opts))
|
||||
zwarnnam(nam, "can't change option: %s", *args);
|
||||
break;
|
||||
} else if(**args == 'm') {
|
||||
match = 1;
|
||||
} else {
|
||||
if (!(optno = optlookupc(**args)))
|
||||
zwarnnam(nam, "bad option: -%c", **args);
|
||||
else if(dosetopt(optno, action, 0, opts))
|
||||
zwarnnam(nam, "can't change option: -%c", **args);
|
||||
}
|
||||
}
|
||||
args++;
|
||||
}
|
||||
doneoptions:
|
||||
|
||||
if (!match) {
|
||||
/* Not globbing the arguments -- arguments are simply option names. */
|
||||
while (*args) {
|
||||
if(!(optno = optlookup(*args++)))
|
||||
zwarnnam(nam, "no such option: %s", args[-1]);
|
||||
else if(dosetopt(optno, !isun, 0, opts))
|
||||
zwarnnam(nam, "can't change option: %s", args[-1]);
|
||||
}
|
||||
} else {
|
||||
/* Globbing option (-m) set. */
|
||||
while (*args) {
|
||||
Patprog pprog;
|
||||
char *s, *t;
|
||||
|
||||
t = s = dupstring(*args);
|
||||
while (*t)
|
||||
if (*t == '_')
|
||||
chuck(t);
|
||||
else {
|
||||
/* See comment in optlookup() */
|
||||
if (*t >= 'A' && *t <= 'Z')
|
||||
*t = (*t - 'A') + 'a';
|
||||
t++;
|
||||
}
|
||||
|
||||
/* Expand the current arg. */
|
||||
tokenize(s);
|
||||
if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) {
|
||||
zwarnnam(nam, "bad pattern: %s", *args);
|
||||
continue;
|
||||
}
|
||||
/* Loop over expansions. */
|
||||
scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
|
||||
setoption, !isun);
|
||||
args++;
|
||||
}
|
||||
}
|
||||
inittyptab();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Identify an option name */
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
optlookup(char const *name)
|
||||
{
|
||||
char *s, *t;
|
||||
Optname n;
|
||||
|
||||
s = t = dupstring(name);
|
||||
|
||||
/* exorcise underscores, and change to lowercase */
|
||||
while (*t)
|
||||
if (*t == '_')
|
||||
chuck(t);
|
||||
else {
|
||||
/*
|
||||
* Some locales (in particular tr_TR.UTF-8) may
|
||||
* have non-standard mappings of ASCII characters,
|
||||
* so be careful. Option names must be ASCII so
|
||||
* we don't need to be too clever.
|
||||
*/
|
||||
if (*t >= 'A' && *t <= 'Z')
|
||||
*t = (*t - 'A') + 'a';
|
||||
t++;
|
||||
}
|
||||
|
||||
/* look up name in the table */
|
||||
if (s[0] == 'n' && s[1] == 'o' &&
|
||||
(n = (Optname) optiontab->getnode(optiontab, s + 2))) {
|
||||
return -n->optno;
|
||||
} else if ((n = (Optname) optiontab->getnode(optiontab, s)))
|
||||
return n->optno;
|
||||
else
|
||||
return OPT_INVALID;
|
||||
}
|
||||
|
||||
/* Identify an option letter */
|
||||
|
||||
/**/
|
||||
int
|
||||
optlookupc(char c)
|
||||
{
|
||||
if(c < FIRST_OPT || c > LAST_OPT)
|
||||
return 0;
|
||||
|
||||
return optletters[c - FIRST_OPT];
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
restrictparam(char *nam)
|
||||
{
|
||||
Param pm = (Param) paramtab->getnode(paramtab, nam);
|
||||
|
||||
if (pm) {
|
||||
pm->node.flags |= PM_SPECIAL | PM_RESTRICTED;
|
||||
return;
|
||||
}
|
||||
createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED);
|
||||
}
|
||||
|
||||
/* list of restricted parameters which are not otherwise special */
|
||||
static char *rparams[] = {
|
||||
"SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH",
|
||||
"LD_PRELOAD", "LD_AOUT_PRELOAD", NULL
|
||||
};
|
||||
|
||||
/* Set or unset an option, as a result of user request. The option *
|
||||
* number may be negative, indicating that the sense is reversed *
|
||||
* from the usual meaning of the option. */
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
dosetopt(int optno, int value, int force, char *new_opts)
|
||||
{
|
||||
if(!optno)
|
||||
return -1;
|
||||
if(optno < 0) {
|
||||
optno = -optno;
|
||||
value = !value;
|
||||
}
|
||||
if (optno == RESTRICTED) {
|
||||
if (isset(RESTRICTED))
|
||||
return value ? 0 : -1;
|
||||
if (value) {
|
||||
char **s;
|
||||
|
||||
for (s = rparams; *s; s++)
|
||||
restrictparam(*s);
|
||||
}
|
||||
} else if(!force && optno == EXECOPT && !value && interact) {
|
||||
/* cannot set noexec when interactive */
|
||||
return -1;
|
||||
} else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
|
||||
optno == SINGLECOMMAND)) {
|
||||
if (new_opts[optno] == value)
|
||||
return 0;
|
||||
/* it is not permitted to change the value of these options */
|
||||
return -1;
|
||||
} else if(!force && optno == USEZLE && value) {
|
||||
/* we require a terminal in order to use ZLE */
|
||||
if(!interact || SHTTY == -1 || !shout)
|
||||
return -1;
|
||||
} else if(optno == PRIVILEGED && !value) {
|
||||
/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
|
||||
#ifdef HAVE_SETUID
|
||||
int ignore_err;
|
||||
errno = 0;
|
||||
/*
|
||||
* Set the GID first as if we set the UID to non-privileged it
|
||||
* might be impossible to restore the GID.
|
||||
*
|
||||
* Some OSes (possibly no longer around) have been known to
|
||||
* fail silently the first time, so we attempt the change twice.
|
||||
* If it fails we are guaranteed to pick this up the second
|
||||
* time, so ignore the first time.
|
||||
*
|
||||
* Some versions of gcc make it hard to ignore the results the
|
||||
* first time, hence the following. (These are probably not
|
||||
* systems that require the doubled calls.)
|
||||
*/
|
||||
ignore_err = setgid(getgid());
|
||||
(void)ignore_err;
|
||||
ignore_err = setuid(getuid());
|
||||
(void)ignore_err;
|
||||
if (setgid(getgid())) {
|
||||
zwarn("failed to change group ID: %e", errno);
|
||||
return -1;
|
||||
} else if (setuid(getuid())) {
|
||||
zwarn("failed to change user ID: %e", errno);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
zwarn("setuid not available");
|
||||
return -1;
|
||||
#endif /* not HAVE_SETUID */
|
||||
#ifdef JOB_CONTROL
|
||||
} else if (!force && optno == MONITOR && value) {
|
||||
if (new_opts[optno] == value)
|
||||
return 0;
|
||||
if (SHTTY != -1) {
|
||||
origpgrp = GETPGRP();
|
||||
acquire_pgrp();
|
||||
} else
|
||||
return -1;
|
||||
#else
|
||||
} else if(optno == MONITOR && value) {
|
||||
return -1;
|
||||
#endif /* not JOB_CONTROL */
|
||||
#ifdef GETPWNAM_FAKED
|
||||
} else if(optno == CDABLEVARS && value) {
|
||||
return -1;
|
||||
#endif /* GETPWNAM_FAKED */
|
||||
} else if ((optno == EMACSMODE || optno == VIMODE) && value) {
|
||||
if (sticky && sticky->emulation)
|
||||
return -1;
|
||||
zleentry(ZLE_CMD_SET_KEYMAP, optno);
|
||||
new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
|
||||
} else if (optno == SUNKEYBOARDHACK) {
|
||||
/* for backward compatibility */
|
||||
keyboardhackchar = (value ? '`' : '\0');
|
||||
}
|
||||
new_opts[optno] = value;
|
||||
if (optno == BANGHIST || optno == SHINSTDIN)
|
||||
inittyptab();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to get value for special parameter `-' */
|
||||
|
||||
/**/
|
||||
char *
|
||||
dashgetfn(UNUSED(Param pm))
|
||||
{
|
||||
static char buf[LAST_OPT - FIRST_OPT + 2];
|
||||
char *val = buf;
|
||||
int i;
|
||||
|
||||
for(i = 0; i <= LAST_OPT - FIRST_OPT; i++) {
|
||||
int optno = optletters[i];
|
||||
if(optno && ((optno > 0) ? isset(optno) : unset(-optno)))
|
||||
*val++ = FIRST_OPT + i;
|
||||
}
|
||||
*val = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* print options for set -o/+o */
|
||||
|
||||
/**/
|
||||
void
|
||||
printoptionstates(int hadplus)
|
||||
{
|
||||
scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionnodestate, hadplus);
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
printoptionnodestate(HashNode hn, int hadplus)
|
||||
{
|
||||
Optname on = (Optname) hn;
|
||||
int optno = on->optno;
|
||||
|
||||
if (hadplus) {
|
||||
printf("set %co %s%s\n",
|
||||
defset(on, emulation) != isset(optno) ? '-' : '+',
|
||||
defset(on, emulation) ? "no" : "",
|
||||
on->node.nam);
|
||||
} else {
|
||||
if (defset(on, emulation))
|
||||
printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
|
||||
else
|
||||
printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print option list for --help */
|
||||
|
||||
/**/
|
||||
void
|
||||
printoptionlist(void)
|
||||
{
|
||||
short *lp;
|
||||
char c;
|
||||
|
||||
printf("\nNamed options:\n");
|
||||
scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
|
||||
printf("\nOption aliases:\n");
|
||||
scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
|
||||
printf("\nOption letters:\n");
|
||||
for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
|
||||
if(!*lp)
|
||||
continue;
|
||||
printf(" -%c ", c);
|
||||
printoptionlist_printequiv(*lp);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
printoptionlist_printoption(HashNode hn, UNUSED(int ignored))
|
||||
{
|
||||
Optname on = (Optname) hn;
|
||||
|
||||
if(on->node.flags & OPT_ALIAS) {
|
||||
printf(" --%-19s ", on->node.nam);
|
||||
printoptionlist_printequiv(on->optno);
|
||||
} else
|
||||
printf(" --%s\n", on->node.nam);
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
printoptionlist_printequiv(int optno)
|
||||
{
|
||||
int isneg = optno < 0;
|
||||
|
||||
optno *= (isneg ? -1 : 1);
|
||||
printf(" equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam);
|
||||
}
|
||||
|
||||
/**/
|
||||
static char *print_emulate_opts;
|
||||
|
||||
/**/
|
||||
static void
|
||||
print_emulate_option(HashNode hn, int fully)
|
||||
{
|
||||
Optname on = (Optname) hn;
|
||||
|
||||
if (!(on->node.flags & OPT_ALIAS) &&
|
||||
((fully && !(on->node.flags & OPT_SPECIAL)) ||
|
||||
(on->node.flags & OPT_EMULATE)))
|
||||
{
|
||||
if (!print_emulate_opts[on->optno])
|
||||
fputs("no", stdout);
|
||||
puts(on->node.nam);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* List the settings of options associated with an emulation
|
||||
*/
|
||||
|
||||
/**/
|
||||
void list_emulate_options(char *cmdopts, int fully)
|
||||
{
|
||||
print_emulate_opts = cmdopts;
|
||||
scanhashtable(optiontab, 1, 0, 0, print_emulate_option, fully);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
3977
zmodules/Src/parse.c
3977
zmodules/Src/parse.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* prototypes.h - prototypes header file
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_STDLIB_H
|
||||
char *malloc _((size_t));
|
||||
char *realloc _((void *, size_t));
|
||||
char *calloc _((size_t, size_t));
|
||||
#endif
|
||||
|
||||
#if !(defined(USES_TERMCAP_H) || defined(USES_TERM_H))
|
||||
/*
|
||||
* These prototypes are only used where we don't have the
|
||||
* headers. In some cases they need tweaking.
|
||||
* TBD: we'd much prefer to get hold of the header where
|
||||
* these are defined.
|
||||
*/
|
||||
#ifdef _AIX
|
||||
#define TC_CONST const
|
||||
#else
|
||||
#define TC_CONST
|
||||
#endif
|
||||
extern int tgetent _((char *bp, TC_CONST char *name));
|
||||
extern int tgetnum _((char *id));
|
||||
extern int tgetflag _((char *id));
|
||||
extern char *tgetstr _((char *id, char **area));
|
||||
extern int tputs _((TC_CONST char *cp, int affcnt, int (*outc) (int)));
|
||||
#undef TC_CONST
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some systems that do have termcap headers nonetheless don't
|
||||
* declare tgoto, so we detect if that is missing separately.
|
||||
*/
|
||||
#ifdef TGOTO_PROTO_MISSING
|
||||
char *tgoto(const char *cap, int col, int row);
|
||||
#endif
|
||||
|
||||
/* MISSING PROTOTYPES FOR VARIOUS OPERATING SYSTEMS */
|
||||
|
||||
#if defined(__hpux) && defined(_HPUX_SOURCE) && !defined(_XPG4_EXTENDED)
|
||||
# define SELECT_ARG_2_T int *
|
||||
#else
|
||||
# define SELECT_ARG_2_T fd_set *
|
||||
#endif
|
||||
|
||||
#ifdef __osf__
|
||||
char *mktemp _((char *));
|
||||
#endif
|
||||
|
||||
#if defined(__osf__) && defined(__alpha) && defined(__GNUC__)
|
||||
/* Digital cc does not need these prototypes, gcc does need them */
|
||||
# ifndef HAVE_IOCTL_PROTO
|
||||
int ioctl _((int d, unsigned long request, void *argp));
|
||||
# endif
|
||||
# ifndef HAVE_MKNOD_PROTO
|
||||
int mknod _((const char *pathname, int mode, dev_t device));
|
||||
# endif
|
||||
int nice _((int increment));
|
||||
int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout));
|
||||
#endif
|
||||
|
||||
#if defined(DGUX) && defined(__STDC__)
|
||||
/* Just plain missing. */
|
||||
extern int getrlimit _((int resource, struct rlimit *rlp));
|
||||
extern int setrlimit _((int resource, const struct rlimit *rlp));
|
||||
extern int getrusage _((int who, struct rusage *rusage));
|
||||
extern int gettimeofday _((struct timeval *tv, struct timezone *tz));
|
||||
extern int wait3 _((union wait *wait_status, int options, struct rusage *rusage));
|
||||
extern int getdomainname _((char *name, int maxlength));
|
||||
extern int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout));
|
||||
#endif /* DGUX and __STDC__ */
|
||||
|
||||
#ifdef __NeXT__
|
||||
extern pid_t getppid(void);
|
||||
#endif
|
||||
|
||||
#if defined(__sun__) && !defined(__SVR4) /* SunOS */
|
||||
extern char *strerror _((int errnum));
|
||||
#endif
|
||||
|
||||
/**************************************************/
|
||||
/*** prototypes for functions built in compat.c ***/
|
||||
#ifndef HAVE_STRSTR
|
||||
extern char *strstr _((const char *s, const char *t));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETHOSTNAME
|
||||
extern int gethostname _((char *name, size_t namelen));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
extern int gettimeofday _((struct timeval *tv, struct timezone *tz));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DIFFTIME
|
||||
extern double difftime _((time_t t2, time_t t1));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
extern char *strerror _((int errnum));
|
||||
#endif
|
||||
|
||||
/*** end of prototypes for functions in compat.c ***/
|
||||
/***************************************************/
|
||||
|
||||
#ifndef HAVE_MEMMOVE
|
||||
extern void bcopy _((const void *, void *, size_t));
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* signals.h - header file for signals handling code
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SIGNAL_HANDTYPE void (*)_((int))
|
||||
|
||||
#ifndef HAVE_KILLPG
|
||||
# define killpg(pgrp,sig) kill(-(pgrp),sig)
|
||||
#endif
|
||||
|
||||
#define SIGZERR (SIGCOUNT+1)
|
||||
#define SIGDEBUG (SIGCOUNT+2)
|
||||
#define VSIGCOUNT (SIGCOUNT+3)
|
||||
#define SIGEXIT 0
|
||||
|
||||
#ifdef SV_BSDSIG
|
||||
# define SV_INTERRUPT SV_BSDSIG
|
||||
#endif
|
||||
|
||||
/* If not a POSIX machine, then we create our *
|
||||
* own POSIX style signal sets functions. */
|
||||
#ifndef POSIX_SIGNALS
|
||||
# define sigemptyset(s) (*(s) = 0)
|
||||
# if NSIG == 32
|
||||
# define sigfillset(s) (*(s) = ~(sigset_t)0, 0)
|
||||
# else
|
||||
# define sigfillset(s) (*(s) = (1 << NSIG) - 1, 0)
|
||||
# endif
|
||||
# define sigaddset(s,n) (*(s) |= (1 << ((n) - 1)), 0)
|
||||
# define sigdelset(s,n) (*(s) &= ~(1 << ((n) - 1)), 0)
|
||||
# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0)
|
||||
#endif /* ifndef POSIX_SIGNALS */
|
||||
|
||||
#define child_block() signal_block(sigchld_mask)
|
||||
#define child_unblock() signal_unblock(sigchld_mask)
|
||||
|
||||
#ifdef SIGWINCH
|
||||
# define winch_block() signal_block(signal_mask(SIGWINCH))
|
||||
# define winch_unblock() signal_unblock(signal_mask(SIGWINCH))
|
||||
#else
|
||||
# define winch_block() 0
|
||||
# define winch_unblock() 0
|
||||
#endif
|
||||
|
||||
/* ignore a signal */
|
||||
#define signal_ignore(S) signal(S, SIG_IGN)
|
||||
|
||||
/* return a signal to it default action */
|
||||
#define signal_default(S) signal(S, SIG_DFL)
|
||||
|
||||
/* Use a circular queue to save signals caught during *
|
||||
* critical sections of code. You call queue_signals to *
|
||||
* start queueing, and unqueue_signals to process the *
|
||||
* queue and stop queueing. Since the kernel doesn't *
|
||||
* queue signals, it is probably overkill for zsh to do *
|
||||
* this, but it shouldn't hurt anything to do it anyway. */
|
||||
|
||||
#define MAX_QUEUE_SIZE 128
|
||||
|
||||
#define run_queued_signals() do { \
|
||||
while (queue_front != queue_rear) { /* while signals in queue */ \
|
||||
sigset_t oset; \
|
||||
queue_front = (queue_front + 1) % MAX_QUEUE_SIZE; \
|
||||
oset = signal_setmask(signal_mask_queue[queue_front]); \
|
||||
zhandler(signal_queue[queue_front]); /* handle queued signal */ \
|
||||
signal_setmask(oset); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define queue_signals() (queue_in++, queueing_enabled++)
|
||||
|
||||
#define unqueue_signals() do { \
|
||||
DPUTS(!queueing_enabled, "BUG: unqueue_signals called but not queueing"); \
|
||||
--queue_in; \
|
||||
if (!--queueing_enabled) run_queued_signals(); \
|
||||
} while (0)
|
||||
|
||||
#define dont_queue_signals() do { \
|
||||
queue_in = queueing_enabled; \
|
||||
queueing_enabled = 0; \
|
||||
run_queued_signals(); \
|
||||
} while (0)
|
||||
|
||||
#define restore_queue_signals(q) do { \
|
||||
DPUTS2(queueing_enabled && queue_in != q, \
|
||||
"BUG: q = %d != queue_in = %d", q, queue_in); \
|
||||
queue_in = (queueing_enabled = (q)); \
|
||||
} while (0)
|
||||
|
||||
#else /* !DEBUG */
|
||||
|
||||
#define queue_signals() (queueing_enabled++)
|
||||
|
||||
#define unqueue_signals() do { \
|
||||
if (!--queueing_enabled) run_queued_signals(); \
|
||||
} while (0)
|
||||
|
||||
#define dont_queue_signals() do { \
|
||||
queueing_enabled = 0; \
|
||||
run_queued_signals(); \
|
||||
} while (0)
|
||||
|
||||
#define restore_queue_signals(q) (queueing_enabled = (q))
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define queue_signal_level() queueing_enabled
|
||||
|
||||
#ifdef BSD_SIGNALS
|
||||
#define signal_block(S) sigblock(S)
|
||||
#else
|
||||
extern sigset_t signal_block _((sigset_t));
|
||||
#endif /* BSD_SIGNALS */
|
||||
|
||||
extern sigset_t signal_unblock _((sigset_t));
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# This is an awk script which finds out what the possibilities for
|
||||
# the signal names are, and dumps them out so that cpp can turn them
|
||||
# into numbers. Since we don't need to decide here what the
|
||||
# real signals are, we can afford to be generous about definitions,
|
||||
# in case the definitions are in terms of other definitions.
|
||||
# However, we need to avoid definitions with parentheses, which will
|
||||
# mess up the syntax.
|
||||
BEGIN { printf "#include <signal.h>\n\n" }
|
||||
|
||||
/^[\t ]*#[\t ]*define[\t _]*SIG[A-Z][A-Z0-9]*[\t ][\t ]*[^(\t ]/ {
|
||||
sigindex = index($0, "SIG")
|
||||
sigtail = substr($0, sigindex, 80)
|
||||
split(sigtail, tmp)
|
||||
signam = substr(tmp[1], 4, 20)
|
||||
if (substr($0, sigindex-1, 1) == "_")
|
||||
printf("XXNAMES XXSIG%s _SIG%s\n", signam, signam)
|
||||
else
|
||||
printf("XXNAMES XXSIG%s SIG%s\n", signam, signam)
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
#
|
||||
# {g,n}awk script to generate signames.c
|
||||
# This version relies on the previous output of the preprocessor
|
||||
# on sigtmp.c, sigtmp.out, which is in turn generated by signames1.awk.
|
||||
#
|
||||
# NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
|
||||
# Without 0 + hacks some nawks compare numbers as strings
|
||||
#
|
||||
/^[\t ]*XXNAMES XXSIG[A-Z][A-Z0-9]*[\t ][\t ]*[1-9][0-9]*/ {
|
||||
sigindex = index($0, "SIG")
|
||||
sigtail = substr($0, sigindex, 80)
|
||||
split(sigtail, tmp)
|
||||
signam = substr(tmp[1], 4, 20)
|
||||
signum = tmp[2]
|
||||
if (signam == "CHLD" && sig[signum] == "CLD") sig[signum] = ""
|
||||
if (signam == "POLL" && sig[signum] == "IO") sig[signum] = ""
|
||||
if (sig[signum] == "") {
|
||||
sig[signum] = signam
|
||||
if (0 + max < 0 + signum && signum < 60)
|
||||
max = signum
|
||||
if (signam == "ABRT") { msg[signum] = "abort" }
|
||||
if (signam == "ALRM") { msg[signum] = "alarm" }
|
||||
if (signam == "BUS") { msg[signum] = "bus error" }
|
||||
if (signam == "CHLD") { msg[signum] = "death of child" }
|
||||
if (signam == "CLD") { msg[signum] = "death of child" }
|
||||
if (signam == "CONT") { msg[signum] = "continued" }
|
||||
if (signam == "EMT") { msg[signum] = "EMT instruction" }
|
||||
if (signam == "FPE") { msg[signum] = "floating point exception" }
|
||||
if (signam == "HUP") { msg[signum] = "hangup" }
|
||||
if (signam == "ILL") { msg[signum] = "illegal hardware instruction" }
|
||||
if (signam == "INFO") { msg[signum] = "status request from keyboard" }
|
||||
if (signam == "INT") { msg[signum] = "interrupt" }
|
||||
if (signam == "IO") { msg[signum] = "i/o ready" }
|
||||
if (signam == "IOT") { msg[signum] = "IOT instruction" }
|
||||
if (signam == "KILL") { msg[signum] = "killed" }
|
||||
if (signam == "LOST") { msg[signum] = "resource lost" }
|
||||
if (signam == "PIPE") { msg[signum] = "broken pipe" }
|
||||
if (signam == "POLL") { msg[signum] = "pollable event occurred" }
|
||||
if (signam == "PROF") { msg[signum] = "profile signal" }
|
||||
if (signam == "PWR") { msg[signum] = "power fail" }
|
||||
if (signam == "QUIT") { msg[signum] = "quit" }
|
||||
if (signam == "SEGV") { msg[signum] = "segmentation fault" }
|
||||
if (signam == "SYS") { msg[signum] = "invalid system call" }
|
||||
if (signam == "TERM") { msg[signum] = "terminated" }
|
||||
if (signam == "TRAP") { msg[signum] = "trace trap" }
|
||||
if (signam == "URG") { msg[signum] = "urgent condition" }
|
||||
if (signam == "USR1") { msg[signum] = "user-defined signal 1" }
|
||||
if (signam == "USR2") { msg[signum] = "user-defined signal 2" }
|
||||
if (signam == "VTALRM") { msg[signum] = "virtual time alarm" }
|
||||
if (signam == "WINCH") { msg[signum] = "window size changed" }
|
||||
if (signam == "XCPU") { msg[signum] = "cpu limit exceeded" }
|
||||
if (signam == "XFSZ") { msg[signum] = "file size limit exceeded" }
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
ps = "%s"
|
||||
ifdstr = sprintf("# ifdef USE_SUSPENDED\n\t%csuspended%s%c,\n%s else\n\t%cstopped%s%c,\n# endif\n", 34, ps, 34, "#", 34, ps, 34)
|
||||
|
||||
printf "/** signames.c **/\n"
|
||||
printf "/** architecture-customized signames.c for zsh **/\n"
|
||||
printf "\n"
|
||||
printf "#define SIGCOUNT\t%d\n", max
|
||||
printf "\n"
|
||||
printf "#include %czsh.mdh%c\n", 34, 34
|
||||
printf "\n"
|
||||
printf "/**/\n"
|
||||
printf "#define sigmsg(sig) ((sig) <= SIGCOUNT ? sig_msg[sig]"
|
||||
printf " : %c%s%c)", 34, "unknown signal", 34
|
||||
printf "\n"
|
||||
printf "/**/\n"
|
||||
printf "mod_export char *sig_msg[SIGCOUNT+2] = {\n"
|
||||
printf "\t%c%s%c,\n", 34, "done", 34
|
||||
|
||||
for (i = 1; i <= 0 + max; i++)
|
||||
if (msg[i] == "") {
|
||||
if (sig[i] == "")
|
||||
printf("\t%c%c,\n", 34, 34)
|
||||
else if (sig[i] == "STOP")
|
||||
printf ifdstr, " (signal)", " (signal)"
|
||||
else if (sig[i] == "TSTP")
|
||||
printf ifdstr, "", ""
|
||||
else if (sig[i] == "TTIN")
|
||||
printf ifdstr, " (tty input)", " (tty input)"
|
||||
else if (sig[i] == "TTOU")
|
||||
printf ifdstr, " (tty output)", " (tty output)"
|
||||
else
|
||||
printf("\t%cSIG%s%c,\n", 34, sig[i], 34)
|
||||
} else
|
||||
printf("\t%c%s%c,\n", 34, msg[i], 34)
|
||||
print "\tNULL"
|
||||
print "};"
|
||||
print ""
|
||||
print "/**/"
|
||||
printf "char *sigs[SIGCOUNT+4] = {\n"
|
||||
printf("\t%cEXIT%c,\n", 34, 34)
|
||||
for (i = 1; i <= 0 + max; i++)
|
||||
if (sig[i] == "")
|
||||
printf("\t%c%d%c,\n", 34, i, 34)
|
||||
else
|
||||
printf("\t%c%s%c,\n", 34, sig[i], 34)
|
||||
printf("\t%cZERR%c,\n", 34, 34)
|
||||
printf("\t%cDEBUG%c,\n", 34, 34)
|
||||
print "\tNULL"
|
||||
print "};"
|
||||
}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
* string.c - string manipulation
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 2000 Peter Stephenson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Peter Stephenson or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Peter Stephenson and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Peter Stephenson and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Peter Stephenson and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*/
|
||||
|
||||
#include "zsh.mdh"
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
dupstring(const char *s)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
t = (char *) zhalloc(strlen((char *)s) + 1);
|
||||
strcpy(t, s);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Duplicate string on heap when length is known */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
dupstring_wlen(const char *s, unsigned len)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
t = (char *) zhalloc(len + 1);
|
||||
memcpy(t, s, len);
|
||||
t[len] = '\0';
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Duplicate string on heap, returning length of string */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
dupstring_glen(const char *s, unsigned *len_ret)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
t = (char *) zhalloc((*len_ret = strlen((char *)s)) + 1);
|
||||
strcpy(t, s);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
ztrdup(const char *s)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
t = (char *)zalloc(strlen((char *)s) + 1);
|
||||
strcpy(t, s);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
/**/
|
||||
mod_export wchar_t *
|
||||
wcs_ztrdup(const wchar_t *s)
|
||||
{
|
||||
wchar_t *t;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
t = (wchar_t *)zalloc(sizeof(wchar_t) * (wcslen((wchar_t *)s) + 1));
|
||||
wcscpy(t, s);
|
||||
return t;
|
||||
}
|
||||
/**/
|
||||
#endif /* MULTIBYTE_SUPPORT */
|
||||
|
||||
|
||||
/* concatenate s1, s2, and s3 in dynamically allocated buffer */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
tricat(char const *s1, char const *s2, char const *s3)
|
||||
{
|
||||
/* This version always uses permanently-allocated space. */
|
||||
char *ptr;
|
||||
size_t l1 = strlen(s1);
|
||||
size_t l2 = strlen(s2);
|
||||
|
||||
ptr = (char *)zalloc(l1 + l2 + strlen(s3) + 1);
|
||||
strcpy(ptr, s1);
|
||||
strcpy(ptr + l1, s2);
|
||||
strcpy(ptr + l1 + l2, s3);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
zhtricat(char const *s1, char const *s2, char const *s3)
|
||||
{
|
||||
char *ptr;
|
||||
size_t l1 = strlen(s1);
|
||||
size_t l2 = strlen(s2);
|
||||
|
||||
ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
|
||||
strcpy(ptr, s1);
|
||||
strcpy(ptr + l1, s2);
|
||||
strcpy(ptr + l1 + l2, s3);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* concatenate s1 and s2 in dynamically allocated buffer */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
dyncat(const char *s1, const char *s2)
|
||||
{
|
||||
/* This version always uses space from the current heap. */
|
||||
char *ptr;
|
||||
size_t l1 = strlen(s1);
|
||||
|
||||
ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
|
||||
strcpy(ptr, s1);
|
||||
strcpy(ptr + l1, s2);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
bicat(const char *s1, const char *s2)
|
||||
{
|
||||
/* This version always uses permanently-allocated space. */
|
||||
char *ptr;
|
||||
size_t l1 = strlen(s1);
|
||||
|
||||
ptr = (char *)zalloc(l1 + strlen(s2) + 1);
|
||||
strcpy(ptr, s1);
|
||||
strcpy(ptr + l1, s2);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* like dupstring(), but with a specified length */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
dupstrpfx(const char *s, int len)
|
||||
{
|
||||
char *r = zhalloc(len + 1);
|
||||
|
||||
memcpy(r, s, len);
|
||||
r[len] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
ztrduppfx(const char *s, int len)
|
||||
{
|
||||
/* This version always uses permanently-allocated space. */
|
||||
char *r = zalloc(len + 1);
|
||||
|
||||
memcpy(r, s, len);
|
||||
r[len] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Append a string to an allocated string, reallocating to make room. */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
appstr(char *base, char const *append)
|
||||
{
|
||||
return strcat(realloc(base, strlen(base) + strlen(append) + 1), append);
|
||||
}
|
||||
|
||||
/* Return a pointer to the last character of a string,
|
||||
unless the string is empty. */
|
||||
|
||||
/**/
|
||||
mod_export char *
|
||||
strend(char *str)
|
||||
{
|
||||
if (*str == '\0')
|
||||
return str;
|
||||
return str + strlen (str) - 1;
|
||||
}
|
||||
7520
zmodules/Src/utils.c
7520
zmodules/Src/utils.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,18 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.export
|
||||
so_locations
|
||||
*.pro
|
||||
*.epro
|
||||
*.syms
|
||||
*.o
|
||||
*.o.c
|
||||
*.so
|
||||
*.mdh
|
||||
*.mdhi
|
||||
*.mdhs
|
||||
*.mdh.tmp
|
||||
*.swp
|
||||
errnames.c errcount.h
|
||||
*.dll
|
||||
curses_keys.h
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
set ai
|
||||
set sw=4
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +0,0 @@
|
|||
name=zdharma/zinit
|
||||
link=dynamic
|
||||
load=no
|
||||
|
||||
autofeatures=""
|
||||
|
||||
objects="zinit.o"
|
||||
3305
zmodules/Src/zsh.h
3305
zmodules/Src/zsh.h
File diff suppressed because it is too large
Load diff
|
|
@ -1,147 +0,0 @@
|
|||
name=zsh/main
|
||||
link=static
|
||||
load=yes
|
||||
# load=static should replace use of alwayslink
|
||||
functions='Functions/Chpwd/* Functions/Exceptions/* Functions/Math/* Functions/Misc/* Functions/MIME/* Functions/Prompts/* Functions/VCS_Info/* Functions/VCS_Info/Backends/*'
|
||||
|
||||
nozshdep=1
|
||||
alwayslink=1
|
||||
|
||||
# autofeatures not specified because of alwayslink
|
||||
|
||||
objects="signames.o builtin.o module.o lex.o exec.o mem.o \
|
||||
string.o parse.o hashtable.o init.o input.o loop.o utils.o params.o options.o \
|
||||
signals.o pattern.o prompt.o compat.o jobs.o glob.o"
|
||||
|
||||
headers="../config.h zsh_system.h zsh.h sigcount.h signals.h \
|
||||
prototypes.h hashtable.h ztype.h"
|
||||
hdrdeps="zshcurses.h zshterm.h"
|
||||
|
||||
:<<\Make
|
||||
@CONFIG_MK@
|
||||
|
||||
# If we're using gcc as the preprocessor, get rid of the additional
|
||||
# lines generated by the preprocessor as they can confuse the script.
|
||||
# We don't need these in other cases either, but can't necessarily rely
|
||||
# on the option to remove them being the same.
|
||||
signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
|
||||
$(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
|
||||
case "`$(CPP) --version </dev/null 2>&1`" in \
|
||||
*"Free Software Foundation"*) \
|
||||
$(CPP) -P sigtmp.c >sigtmp.out;; \
|
||||
*) \
|
||||
$(CPP) sigtmp.c >sigtmp.out;; \
|
||||
esac
|
||||
$(AWK) -f $(sdir)/signames2.awk sigtmp.out > $@
|
||||
rm -f sigtmp.c sigtmp.out
|
||||
|
||||
sigcount.h: signames.c
|
||||
grep 'define.*SIGCOUNT' signames.c > $@
|
||||
|
||||
init.o: bltinmods.list zshpaths.h zshxmods.h
|
||||
|
||||
init.o params.o parse.o: version.h
|
||||
|
||||
params.o: patchlevel.h
|
||||
|
||||
version.h: $(sdir_top)/Config/version.mk zshcurses.h zshterm.h
|
||||
echo '#define ZSH_VERSION "'$(VERSION)'"' > $@
|
||||
|
||||
patchlevel.h: FORCE
|
||||
@if [ -f $(sdir)/$@.release ]; then \
|
||||
cp -f $(sdir)/$@.release $@; \
|
||||
else \
|
||||
echo '#define ZSH_PATCHLEVEL "'`cd $(sdir) && git describe --tags --long`'"' > $@.tmp; \
|
||||
cmp $@ $@.tmp >/dev/null 2>&1 && rm -f $@.tmp || mv $@.tmp $@; \
|
||||
fi
|
||||
FORCE:
|
||||
|
||||
zshcurses.h: ../config.h
|
||||
@if test x$(ZSH_CURSES_H) != x; then \
|
||||
echo "#include <$(ZSH_CURSES_H)>" >zshcurses.h; \
|
||||
else \
|
||||
echo >zshcurses.h; \
|
||||
fi
|
||||
|
||||
zshterm.h: ../config.h
|
||||
@if test x$(ZSH_TERM_H) != x; then \
|
||||
echo "#include <$(ZSH_TERM_H)>" >zshterm.h; \
|
||||
else \
|
||||
echo >zshterm.h; \
|
||||
fi
|
||||
|
||||
zshpaths.h: Makemod $(CONFIG_INCS)
|
||||
@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
|
||||
@if test x$(sitescriptdir) != xno; then \
|
||||
echo '#define SITESCRIPT_DIR "'$(sitescriptdir)'"' >> zshpaths.h.tmp; \
|
||||
fi
|
||||
@if test x$(scriptdir) != xno; then \
|
||||
echo '#define SCRIPT_DIR "'$(scriptdir)'"' >> zshpaths.h.tmp; \
|
||||
fi
|
||||
@if test x$(sitefndir) != xno; then \
|
||||
echo '#define SITEFPATH_DIR "'$(sitefndir)'"' >> zshpaths.h.tmp; \
|
||||
fi
|
||||
@if test x$(fixed_sitefndir) != x; then \
|
||||
echo '#define FIXED_FPATH_DIR "'$(fixed_sitefndir)'"' >> zshpaths.h.tmp; \
|
||||
fi
|
||||
@if test x$(fndir) != xno; then \
|
||||
echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
|
||||
if test x$(FUNCTIONS_SUBDIRS) != x && \
|
||||
test x$(FUNCTIONS_SUBDIRS) != xno; then \
|
||||
fpath_tmp="`grep ' functions=.' \
|
||||
$(dir_top)/config.modules | sed -e '/^#/d' -e '/ link=no/d' \
|
||||
-e 's/^.* functions=//'`"; \
|
||||
fpath_tmp=`for f in $$fpath_tmp; do \
|
||||
echo $$f | sed -e 's%^Functions/%%' -e 's%/[^/]*$$%%' -e 's%/\*%%'; \
|
||||
done | grep -v Scripts | sort | uniq`; \
|
||||
fpath_tmp=`echo $$fpath_tmp | sed 's/ /\", \"/g'`; \
|
||||
echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }" \
|
||||
>>zshpaths.h.tmp; \
|
||||
fi; \
|
||||
fi
|
||||
@if test x$(additionalfpath) != x; then \
|
||||
fpath_tmp="`echo $(additionalfpath) | sed -e 's:,:\", \":g'`"; \
|
||||
echo "#define ADDITIONAL_FPATH { \"$$fpath_tmp\" }" >> zshpaths.h.tmp; \
|
||||
fi
|
||||
@if cmp -s zshpaths.h zshpaths.h.tmp; then \
|
||||
rm -f zshpaths.h.tmp; \
|
||||
echo "\`zshpaths.h' is up to date." ; \
|
||||
else \
|
||||
mv -f zshpaths.h.tmp zshpaths.h; \
|
||||
echo "Updated \`zshpaths.h'." ; \
|
||||
fi
|
||||
|
||||
bltinmods.list: modules.stamp mkbltnmlst.sh $(dir_top)/config.modules
|
||||
srcdir='$(sdir)' CFMOD='$(dir_top)/config.modules' \
|
||||
$(SHELL) $(sdir)/mkbltnmlst.sh $@
|
||||
|
||||
zshxmods.h: $(dir_top)/config.modules
|
||||
@echo "Creating \`$@'."
|
||||
@( \
|
||||
for q_mod in `grep ' load=yes' $(dir_top)/config.modules | \
|
||||
grep ' link=static' | sed -e '/^#/d' -e 's/ .*//' \
|
||||
-e 's/^name=//' -e 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`; do \
|
||||
test x$q_mod = xzshQsmain && continue; \
|
||||
echo "#define LINKED_XMOD_$$q_mod 1"; \
|
||||
done; \
|
||||
for q_mod in `grep ' load=yes' $(dir_top)/config.modules | \
|
||||
grep ' link=dynamic' | sed -e '/^#/d' -e 's/ .*//' \
|
||||
-e 's/^name=//' -e 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`; do \
|
||||
test x$q_mod = x && continue; \
|
||||
echo "#ifdef DYNAMIC"; \
|
||||
echo "# define UNLINKED_XMOD_$$q_mod 1"; \
|
||||
echo "#endif"; \
|
||||
done; \
|
||||
) > $@
|
||||
|
||||
clean-here: clean.zsh
|
||||
clean.zsh:
|
||||
rm -f sigcount.h signames.c bltinmods.list version.h zshpaths.h zshxmods.h
|
||||
|
||||
# This is not properly part of this module, but it is built as if it were.
|
||||
main.o: main.c zsh.mdh main.epro
|
||||
$(CC) -c -I. -I$(sdir_top)/Src $(CPPFLAGS) $(DEFS) $(CFLAGS) -o $@ $(sdir)/main.c
|
||||
|
||||
main.syms: $(PROTODEPS)
|
||||
proto.zsh: main.epro
|
||||
Make
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// Use this file as follows
|
||||
//
|
||||
// myapp.exe : myapp.o myapp.res
|
||||
// gcc -mwindows myapp.o myapp.res -o $@
|
||||
//
|
||||
// myapp.res : myapp.rc resource.h
|
||||
// windres $< -O coff -o $@
|
||||
IDR_MAINFRAME ICON DISCARDABLE "zsh.ico"
|
||||
|
|
@ -1,900 +0,0 @@
|
|||
/*
|
||||
* system.h - system configuration header file
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Setting _XPG_IV here is actually wrong and is not needed
|
||||
* with currently supported versions (5.43C20 and above)
|
||||
*/
|
||||
#ifdef sinix
|
||||
# define _XPG_IV 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux) || defined(__GNU__) || defined(__GLIBC__) || defined(LIBC_MUSL) || defined(__CYGWIN__)
|
||||
/*
|
||||
* Turn on numerous extensions.
|
||||
* This is in order to get the functions for manipulating /dev/ptmx.
|
||||
*/
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
#ifdef LIBC_MUSL
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
|
||||
/* NeXT has half-implemented POSIX support *
|
||||
* which currently fools configure */
|
||||
#ifdef __NeXT__
|
||||
# undef HAVE_TERMIOS_H
|
||||
# undef HAVE_SYS_UTSNAME_H
|
||||
#endif
|
||||
|
||||
#ifndef ZSH_NO_XOPEN
|
||||
# ifdef ZSH_CURSES_SOURCE
|
||||
# define _XOPEN_SOURCE_EXTENDED 1
|
||||
# else
|
||||
# ifdef MULTIBYTE_SUPPORT
|
||||
/*
|
||||
* Needed for wcwidth() which is part of XSI.
|
||||
* Various other uses of the interface mean we can't get away with just
|
||||
* _XOPEN_SOURCE.
|
||||
*/
|
||||
# define _XOPEN_SOURCE_EXTENDED 1
|
||||
# endif /* MULTIBYTE_SUPPORT */
|
||||
# endif /* ZSH_CURSES_SOURCE */
|
||||
#endif /* ZSH_NO_XOPEN */
|
||||
|
||||
/*
|
||||
* Solaris by default zeroes all elements of the tm structure in
|
||||
* strptime(). Unfortunately that gives us no way of telling whether
|
||||
* the tm_isdst element has been set from the input pattern. If it
|
||||
* hasn't we want it to be -1 (undetermined) on input to mktime(). So
|
||||
* we stop strptime() zeroing the struct tm and instead set all the
|
||||
* elements ourselves.
|
||||
*
|
||||
* This is likely to be harmless everywhere else.
|
||||
*/
|
||||
#define _STRPTIME_DONTZERO
|
||||
|
||||
#ifdef PROTOTYPES
|
||||
# define _(Args) Args
|
||||
#else
|
||||
# define _(Args) ()
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ALLOCA
|
||||
# define alloca zhalloc
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# else
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
# pragma alloca
|
||||
# else
|
||||
# ifndef alloca
|
||||
char *alloca _((size_t));
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* libc.h in an optional package for Debian Linux is broken (it
|
||||
* defines dup() as a synonym for dup2(), which has a different
|
||||
* number of arguments), so just include it for next.
|
||||
*/
|
||||
#ifdef __NeXT__
|
||||
# ifdef HAVE_LIBC_H
|
||||
# include <libc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
/*
|
||||
* Seen on Solaris 8 with gcc: stddef defines offsetof, which clashes
|
||||
* with system.h's definition of the symbol unless we include this
|
||||
* first. Otherwise, this will be hooked in by wchar.h, too late
|
||||
* for comfort.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
# include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GRP_H
|
||||
# include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else /* !HAVE_DIRENT_H */
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# ifdef HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# ifdef HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
# define dirent direct
|
||||
# undef HAVE_STRUCT_DIRENT_D_INO
|
||||
# undef HAVE_STRUCT_DIRENT_D_STAT
|
||||
# ifdef HAVE_STRUCT_DIRECT_D_INO
|
||||
# define HAVE_STRUCT_DIRENT_D_INO HAVE_STRUCT_DIRECT_D_INO
|
||||
# endif
|
||||
# ifdef HAVE_STRUCT_DIRECT_D_STAT
|
||||
# define HAVE_STRUCT_DIRENT_D_STAT HAVE_STRUCT_DIRECT_D_STAT
|
||||
# endif
|
||||
#endif /* !HAVE_DIRENT_H */
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# ifdef ZSH_MEM
|
||||
/* malloc and calloc are macros in GNU's stdlib.h unless the
|
||||
* the __MALLOC_0_RETURNS_NULL macro is defined */
|
||||
# define __MALLOC_0_RETURNS_NULL
|
||||
# endif
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stuff with variable arguments. We use definitions to make the
|
||||
* same code work with varargs (the original K&R-style, just to
|
||||
* be maximally compatible) and stdarg (which all modern systems
|
||||
* should have).
|
||||
*
|
||||
* Ideally this should somehow be merged with the tricks performed
|
||||
* with "_" in makepro.awk, but I don't understand makepro.awk.
|
||||
* Currently we simply rely on the fact that makepro.awk has been
|
||||
* hacked to leave alone argument lists that already contains VA_ALIST
|
||||
* except for removing the VA_DCL and turning VA_ALIST into VA_ALIST_PROTO.
|
||||
*/
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
# define VA_ALIST1(x) x, ...
|
||||
# define VA_ALIST2(x,y) x, y, ...
|
||||
# define VA_ALIST_PROTO1(x) VA_ALIST1(x)
|
||||
# define VA_ALIST_PROTO2(x,y) VA_ALIST2(x,y)
|
||||
# define VA_DCL
|
||||
# define VA_DEF_ARG(x)
|
||||
# define VA_START(ap,x) va_start(ap, x)
|
||||
# define VA_GET_ARG(ap,x,t)
|
||||
#else
|
||||
# if HAVE_VARARGS_H
|
||||
# include <varargs.h>
|
||||
# define VA_ALIST1(x) va_alist
|
||||
# define VA_ALIST2(x,y) va_alist
|
||||
/*
|
||||
* In prototypes, assume K&R form and remove the variable list.
|
||||
* This is about the best we can do without second-guessing the way
|
||||
* varargs works on this system. The _ trick should be able to
|
||||
* do this for us but we've turned it off here.
|
||||
*/
|
||||
# define VA_ALIST_PROTO1(x)
|
||||
# define VA_ALIST_PROTO2(x,y)
|
||||
# define VA_DCL va_dcl
|
||||
# define VA_DEF_ARG(x) x
|
||||
# define VA_START(ap,x) va_start(ap);
|
||||
# define VA_GET_ARG(ap,x,t) (x = va_arg(ap, t))
|
||||
# else
|
||||
# error "Your system has neither stdarg.h or varargs.h."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
#else
|
||||
# ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is needed by some old SCO unices */
|
||||
#if !defined(HAVE_STRUCT_TIMEZONE) && !defined(ZSH_OOT_MODULE)
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Used to provide compatibility with clock_gettime() */
|
||||
#if !defined(HAVE_STRUCT_TIMESPEC) && !defined(ZSH_OOT_MODULE)
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* There's more than one non-standard way to get at this data */
|
||||
#if !defined(HAVE_STRUCT_DIRENT_D_INO) && defined(HAVE_STRUCT_DIRENT_D_STAT)
|
||||
# define d_ino d_stat.st_ino
|
||||
# define HAVE_STRUCT_DIRENT_D_INO HAVE_STRUCT_DIRENT_D_STAT
|
||||
#endif /* !HAVE_STRUCT_DIRENT_D_INO && HAVE_STRUCT_DIRENT_D_STAT */
|
||||
|
||||
/* Sco needs the following include for struct utimbuf *
|
||||
* which is strange considering we do not use that *
|
||||
* anywhere in the code */
|
||||
#ifdef __sco
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif /* not STDC_HEADERS and HAVE_MEMORY_H */
|
||||
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
# include <strings.h>
|
||||
/* memory.h and strings.h conflict on some systems. */
|
||||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_STACK_ALLOCATION
|
||||
#ifdef HAVE_VARIABLE_LENGTH_ARRAYS
|
||||
# define VARARR(X,Y,Z) X (Y)[Z]
|
||||
#else
|
||||
# define VARARR(X,Y,Z) X *(Y) = (X *) alloca(sizeof(X) * (Z))
|
||||
#endif
|
||||
#else
|
||||
# define VARARR(X,Y,Z) X *(Y) = (X *) zhalloc(sizeof(X) * (Z))
|
||||
#endif
|
||||
|
||||
/* we should handle unlimited sizes from pathconf(_PC_PATH_MAX) */
|
||||
/* but this is too much trouble */
|
||||
#ifndef PATH_MAX
|
||||
# ifdef MAXPATHLEN
|
||||
# define PATH_MAX MAXPATHLEN
|
||||
# else
|
||||
# ifdef _POSIX_PATH_MAX
|
||||
# define PATH_MAX _POSIX_PATH_MAX
|
||||
# else
|
||||
/* so we will just pick something */
|
||||
# define PATH_MAX 1024
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The number of file descriptors we'll allocate initially.
|
||||
* We will reallocate later if necessary.
|
||||
*/
|
||||
#define ZSH_INITIAL_OPEN_MAX 64
|
||||
#ifndef OPEN_MAX
|
||||
# ifdef NOFILE
|
||||
# define OPEN_MAX NOFILE
|
||||
# else
|
||||
/* so we will just pick something */
|
||||
# define OPEN_MAX ZSH_INITIAL_OPEN_MAX
|
||||
# endif
|
||||
#endif
|
||||
#ifndef HAVE_SYSCONF
|
||||
# define zopenmax() ((long) (OPEN_MAX > ZSH_INITIAL_OPEN_MAX ? \
|
||||
ZSH_INITIAL_OPEN_MAX : OPEN_MAX))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
/* The following will only be defined if <sys/wait.h> is POSIX. *
|
||||
* So we don't have to worry about union wait. But some machines *
|
||||
* (NeXT) include <sys/wait.h> from other include files, so we *
|
||||
* need to undef and then redefine the wait macros if <sys/wait.h> *
|
||||
* is not POSIX. */
|
||||
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#else
|
||||
# undef WIFEXITED
|
||||
# undef WEXITSTATUS
|
||||
# undef WIFSIGNALED
|
||||
# undef WTERMSIG
|
||||
# undef WCOREDUMP
|
||||
# undef WIFSTOPPED
|
||||
# undef WSTOPSIG
|
||||
#endif
|
||||
|
||||
/* missing macros for wait/waitpid/wait3 */
|
||||
#ifndef WIFEXITED
|
||||
# define WIFEXITED(X) (((X)&0377)==0)
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(X) (((X)>>8)&0377)
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(X) (((X)&0377)!=0&&((X)&0377)!=0177)
|
||||
#endif
|
||||
#ifndef WTERMSIG
|
||||
# define WTERMSIG(X) ((X)&0177)
|
||||
#endif
|
||||
#ifndef WCOREDUMP
|
||||
# define WCOREDUMP(X) ((X)&0200)
|
||||
#endif
|
||||
#ifndef WIFSTOPPED
|
||||
# define WIFSTOPPED(X) (((X)&0377)==0177)
|
||||
#endif
|
||||
#ifndef WSTOPSIG
|
||||
# define WSTOPSIG(X) (((X)>>8)&0377)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# ifndef TIME_H_SELECT_H_CONFLICTS
|
||||
# include <sys/select.h>
|
||||
# endif
|
||||
#elif defined(SELECT_IN_SYS_SOCKET_H)
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(HAVE_SELECT)
|
||||
/*
|
||||
* Prefer select() to poll() on MacOS X since poll() is known
|
||||
* to be problematic in 10.4
|
||||
*/
|
||||
#undef HAVE_POLL
|
||||
#undef HAVE_POLL_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_FILIO_H
|
||||
# include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
# ifdef __sco
|
||||
/* termios.h includes sys/termio.h instead of sys/termios.h; *
|
||||
* hence the declaration for struct termios is missing */
|
||||
# include <sys/termios.h>
|
||||
# else
|
||||
# include <termios.h>
|
||||
# endif
|
||||
# ifdef _POSIX_VDISABLE
|
||||
# define VDISABLEVAL _POSIX_VDISABLE
|
||||
# else
|
||||
# define VDISABLEVAL 0
|
||||
# endif
|
||||
# define HAS_TIO 1
|
||||
#else /* not TERMIOS */
|
||||
# ifdef HAVE_TERMIO_H
|
||||
# include <termio.h>
|
||||
# define VDISABLEVAL -1
|
||||
# define HAS_TIO 1
|
||||
# else /* not TERMIOS and TERMIO */
|
||||
# include <sgtty.h>
|
||||
# endif /* HAVE_TERMIO_H */
|
||||
#endif /* HAVE_TERMIOS_H */
|
||||
|
||||
#if defined(GWINSZ_IN_SYS_IOCTL) || defined(IOCTL_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef WINSIZE_IN_PTEM
|
||||
# include <sys/stream.h>
|
||||
# include <sys/ptem.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UTSNAME_H
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WORDCHARS "*?_-.[]~=/&;!#$%^(){}<>"
|
||||
#define DEFAULT_TIMEFMT "%J %U user %S system %P cpu %*E total"
|
||||
|
||||
/* Posix getpgrp takes no argument, while the BSD version *
|
||||
* takes the process ID as an argument */
|
||||
#ifdef GETPGRP_VOID
|
||||
# define GETPGRP() getpgrp()
|
||||
#else
|
||||
# define GETPGRP() getpgrp(0)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETLOGIN
|
||||
# define getlogin() cuserid(NULL)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETPGID
|
||||
# define setpgrp setpgid
|
||||
#endif
|
||||
|
||||
/* can we set the user/group id of a process */
|
||||
|
||||
#ifndef HAVE_SETUID
|
||||
# ifdef HAVE_SETREUID
|
||||
# define setuid(X) setreuid(X,X)
|
||||
# define setgid(X) setregid(X,X)
|
||||
# define HAVE_SETUID
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* can we set the effective user/group id of a process */
|
||||
|
||||
#ifndef HAVE_SETEUID
|
||||
# ifdef HAVE_SETREUID
|
||||
# define seteuid(X) setreuid(-1,X)
|
||||
# define setegid(X) setregid(-1,X)
|
||||
# define HAVE_SETEUID
|
||||
# else
|
||||
# ifdef HAVE_SETRESUID
|
||||
# define seteuid(X) setresuid(-1,X,-1)
|
||||
# define setegid(X) setresgid(-1,X,-1)
|
||||
# define HAVE_SETEUID
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
# include <sys/resource.h>
|
||||
# if defined(__hpux) && !defined(RLIMIT_CPU)
|
||||
/* HPUX does have the BSD rlimits in the kernel. Officially they are *
|
||||
* unsupported but quite a few of them like RLIMIT_CORE seem to work. *
|
||||
* All the following are in the <sys/resource.h> but made visible *
|
||||
* only for the kernel. */
|
||||
# define RLIMIT_CPU 0
|
||||
# define RLIMIT_FSIZE 1
|
||||
# define RLIMIT_DATA 2
|
||||
# define RLIMIT_STACK 3
|
||||
# define RLIMIT_CORE 4
|
||||
# define RLIMIT_RSS 5
|
||||
# define RLIMIT_NOFILE 6
|
||||
# define RLIMIT_OPEN_MAX RLIMIT_NOFILE
|
||||
# define RLIM_NLIMITS 7
|
||||
# define RLIM_INFINITY 0x7fffffff
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* we use the SVR4 constant instead of the BSD one */
|
||||
#if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
|
||||
# define RLIMIT_NOFILE RLIMIT_OFILE
|
||||
#endif
|
||||
#if !defined(RLIMIT_VMEM) && defined(RLIMIT_AS)
|
||||
# define RLIMIT_VMEM RLIMIT_AS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
# include <sys/capability.h>
|
||||
#endif
|
||||
|
||||
/* DIGBUFSIZ is the length of a buffer which can hold the -LONG_MAX-1 *
|
||||
* (or with ZSH_64_BIT_TYPE maybe -LONG_LONG_MAX-1) *
|
||||
* converted to printable decimal form including the sign and the *
|
||||
* terminating null character. Below 0.30103 > lg 2. *
|
||||
* BDIGBUFSIZE is for a number converted to printable binary form. */
|
||||
#define DIGBUFSIZE ((int)(((sizeof(zlong) * 8) - 1) * 30103/100000) + 3)
|
||||
#define BDIGBUFSIZE ((int)((sizeof(zlong) * 8) + 4))
|
||||
|
||||
/* If your stat macros are broken, we will *
|
||||
* just undefine them. */
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISDIR
|
||||
# undef S_ISDOOR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISMPB
|
||||
# undef S_ISMPC
|
||||
# undef S_ISNWK
|
||||
# undef S_ISOFD
|
||||
# undef S_ISOFL
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif /* STAT_MACROS_BROKEN. */
|
||||
|
||||
/* If you are missing the stat macros, we *
|
||||
* define our own */
|
||||
|
||||
#ifndef S_IFMT
|
||||
# define S_IFMT 0170000
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISDOOR) && defined(S_IFDOOR) /* Solaris */
|
||||
# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
#endif
|
||||
#if !defined(S_ISMPC) && defined(S_IFMPC) /* V7 */
|
||||
# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
#if !defined(S_ISOFD) && defined(S_IFOFD) /* Cray */
|
||||
# define S_ISOFD(m) (((m) & S_IFMT) == S_IFOFD)
|
||||
#endif
|
||||
#if !defined(S_ISOFL) && defined(S_IFOFL) /* Cray */
|
||||
# define S_ISOFL(m) (((m) & S_IFMT) == S_IFOFL)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
|
||||
/* We will pretend to have all file types on any system. */
|
||||
|
||||
#ifndef S_ISBLK
|
||||
# define S_ISBLK(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISCHR
|
||||
# define S_ISCHR(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISDOOR
|
||||
# define S_ISDOOR(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISFIFO
|
||||
# define S_ISFIFO(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISLNK
|
||||
# define S_ISLNK(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISMPB
|
||||
# define S_ISMPB(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISMPC
|
||||
# define S_ISMPC(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISNWK
|
||||
# define S_ISNWK(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISOFD
|
||||
# define S_ISOFD(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISOFL
|
||||
# define S_ISOFL(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(m) ((void)(m), 0)
|
||||
#endif
|
||||
#ifndef S_ISSOCK
|
||||
# define S_ISSOCK(m) ((void)(m), 0)
|
||||
#endif
|
||||
|
||||
/* file mode permission bits */
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 04000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 02000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 01000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 00400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 00200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 00100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 00040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 00020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 00010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 00004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 00002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 00001
|
||||
#endif
|
||||
#ifndef S_IRWXU
|
||||
# define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
|
||||
#endif
|
||||
#ifndef S_IRWXG
|
||||
# define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP)
|
||||
#endif
|
||||
#ifndef S_IRWXO
|
||||
# define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH)
|
||||
#endif
|
||||
#ifndef S_IRUGO
|
||||
# define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
|
||||
#endif
|
||||
#ifndef S_IWUGO
|
||||
# define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
|
||||
#endif
|
||||
#ifndef S_IXUGO
|
||||
# define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LSTAT
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_READLINK
|
||||
# define readlink(PATH, BUF, BUFSZ) \
|
||||
((void)(PATH), (void)(BUF), (void)(BUFSZ), errno = ENOSYS, -1)
|
||||
#endif
|
||||
|
||||
#ifndef F_OK /* missing macros for access() */
|
||||
# define F_OK 0
|
||||
# define X_OK 1
|
||||
# define W_OK 2
|
||||
# define R_OK 4
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LCHOWN
|
||||
# define lchown chown
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
# define memcpy memmove
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMMOVE
|
||||
# ifndef memmove
|
||||
static char *zmmv;
|
||||
# define memmove(dest, src, len) (bcopy((src), zmmv = (dest), (len)), zmmv)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof(TYPE, MEM) ((char *)&((TYPE *)0)->MEM - (char *)(TYPE *)0)
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
|
||||
/*
|
||||
* We always need setenv and unsetenv in pairs, because
|
||||
* we don't know how to do memory management on the values set.
|
||||
*/
|
||||
#if defined(HAVE_SETENV) && defined(HAVE_UNSETENV) && !defined(__APPLE__)
|
||||
# define USE_SET_UNSET_ENV
|
||||
#endif
|
||||
|
||||
|
||||
/* These variables are sometimes defined in, *
|
||||
* and needed by, the termcap library. */
|
||||
#if MUST_DEFINE_OSPEED
|
||||
extern char PC, *BC, *UP;
|
||||
extern short ospeed;
|
||||
#endif
|
||||
|
||||
#ifndef O_NOCTTY
|
||||
# define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
#ifdef _LARGEFILE_SOURCE
|
||||
#ifdef HAVE_FSEEKO
|
||||
#define fseek fseeko
|
||||
#endif
|
||||
#ifdef HAVE_FTELLO
|
||||
#define ftell ftello
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Can't support job control without working tcsetgrp() */
|
||||
#ifdef BROKEN_TCSETPGRP
|
||||
#undef JOB_CONTROL
|
||||
#endif /* BROKEN_TCSETPGRP */
|
||||
|
||||
#ifdef BROKEN_KILL_ESRCH
|
||||
#undef ESRCH
|
||||
#define ESRCH EINVAL
|
||||
#endif /* BROKEN_KILL_ESRCH */
|
||||
|
||||
/* Can we do locale stuff? */
|
||||
#undef USE_LOCALE
|
||||
#if defined(CONFIG_LOCALE) && defined(HAVE_SETLOCALE) && defined(LC_ALL)
|
||||
# define USE_LOCALE 1
|
||||
#endif /* CONFIG_LOCALE && HAVE_SETLOCALE && LC_ALL */
|
||||
|
||||
#ifndef MAILDIR_SUPPORT
|
||||
#define mailstat(X,Y) stat(X,Y)
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
# include <sys/cygwin.h>
|
||||
# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
|
||||
#else
|
||||
# define IS_DIRSEP(c) ((c) == '/')
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (!defined(__APPLE__) || defined(__clang__))
|
||||
/* Does the OS X port of gcc still gag on __attribute__? */
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
#else
|
||||
#define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The MULTIBYTE_SUPPORT configure-define specifies that we want to enable
|
||||
* complete Unicode conversion between wide characters and multibyte strings.
|
||||
*/
|
||||
#if defined MULTIBYTE_SUPPORT \
|
||||
|| (defined HAVE_WCHAR_H && defined HAVE_WCTOMB && defined __STDC_ISO_10646__)
|
||||
/*
|
||||
* If MULTIBYTE_SUPPORT is not defined, these includes provide a subset of
|
||||
* Unicode support that makes the \u and \U printf escape sequences work.
|
||||
*/
|
||||
|
||||
#if defined(__hpux) && !defined(_INCLUDE__STDC_A1_SOURCE)
|
||||
#define _INCLUDE__STDC_A1_SOURCE
|
||||
#endif
|
||||
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
# include <langinfo.h>
|
||||
# ifdef HAVE_ICONV
|
||||
# include <iconv.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INITGROUPS) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_INITGROUPS
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETGRGID) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_GETGRGID
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETGRNAM) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_GETGRNAM
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETPWENT) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_GETPWENT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETPWNAM) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_GETPWNAM
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETPWUID) && !defined(DISABLE_DYNAMIC_NSS)
|
||||
# define USE_GETPWUID
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
|
||||
# define GET_ST_ATIME_NSEC(st) (st).st_atim.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
|
||||
# define GET_ST_ATIME_NSEC(st) (st).st_atimespec.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_ATIMENSEC
|
||||
# define GET_ST_ATIME_NSEC(st) (st).st_atimensec
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
# define GET_ST_MTIME_NSEC(st) (st).st_mtim.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
# define GET_ST_MTIME_NSEC(st) (st).st_mtimespec.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
# define GET_ST_MTIME_NSEC(st) (st).st_mtimensec
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
|
||||
# define GET_ST_CTIME_NSEC(st) (st).st_ctim.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_CTIMESPEC_TV_NSEC
|
||||
# define GET_ST_CTIME_NSEC(st) (st).st_ctimespec.tv_nsec
|
||||
#elif HAVE_STRUCT_STAT_ST_CTIMENSEC
|
||||
# define GET_ST_CTIME_NSEC(st) (st).st_ctimensec
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_TGETENT) && !defined(ZSH_NO_TERM_HANDLING)
|
||||
# if defined(ZSH_HAVE_CURSES_H) && defined(ZSH_HAVE_TERM_H)
|
||||
# define USES_TERM_H 1
|
||||
# else
|
||||
# ifdef HAVE_TERMCAP_H
|
||||
# define USES_TERMCAP_H 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef USES_TERM_H
|
||||
# ifdef HAVE_TERMIO_H
|
||||
# include <termio.h>
|
||||
# endif
|
||||
# ifdef ZSH_HAVE_CURSES_H
|
||||
# include "zshcurses.h"
|
||||
# endif
|
||||
# include "zshterm.h"
|
||||
# else
|
||||
# ifdef USES_TERMCAP_H
|
||||
# include <termcap.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SRAND_DETERMINISTIC
|
||||
# define srand srand_deterministic
|
||||
#endif
|
||||
|
||||
#ifdef ZSH_VALGRIND
|
||||
# include "valgrind/valgrind.h"
|
||||
# include "valgrind/memcheck.h"
|
||||
#endif
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* ztype.h - character classification macros
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1992-1997 Paul Falstad
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Paul Falstad and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#define IDIGIT (1 << 0)
|
||||
#define IALNUM (1 << 1)
|
||||
#define IBLANK (1 << 2)
|
||||
#define INBLANK (1 << 3)
|
||||
#define ITOK (1 << 4)
|
||||
#define ISEP (1 << 5)
|
||||
#define IALPHA (1 << 6)
|
||||
#define IIDENT (1 << 7)
|
||||
#define IUSER (1 << 8)
|
||||
#define ICNTRL (1 << 9)
|
||||
#define IWORD (1 << 10)
|
||||
#define ISPECIAL (1 << 11)
|
||||
#define IMETA (1 << 12)
|
||||
#define IWSEP (1 << 13)
|
||||
#define INULL (1 << 14)
|
||||
#define IPATTERN (1 << 15)
|
||||
#define zistype(X,Y) (typtab[STOUC(X)] & Y)
|
||||
#define idigit(X) zistype(X,IDIGIT)
|
||||
#define ialnum(X) zistype(X,IALNUM)
|
||||
#define iblank(X) zistype(X,IBLANK) /* blank, not including \n */
|
||||
#define inblank(X) zistype(X,INBLANK) /* blank or \n */
|
||||
#define itok(X) zistype(X,ITOK)
|
||||
#define isep(X) zistype(X,ISEP)
|
||||
#define ialpha(X) zistype(X,IALPHA)
|
||||
#define iident(X) zistype(X,IIDENT)
|
||||
#define iuser(X) zistype(X,IUSER) /* username char */
|
||||
#define icntrl(X) zistype(X,ICNTRL)
|
||||
#define iword(X) zistype(X,IWORD)
|
||||
#define ispecial(X) zistype(X,ISPECIAL)
|
||||
#define imeta(X) zistype(X,IMETA)
|
||||
#define iwsep(X) zistype(X,IWSEP)
|
||||
#define inull(X) zistype(X,INULL)
|
||||
#define ipattern(X) zistype(X,IPATTERN)
|
||||
|
||||
/*
|
||||
* Bit flags for typtab_flags --- preserved after
|
||||
* shell initialisation.
|
||||
*/
|
||||
#define ZTF_INIT (0x0001) /* One-off initialisation done */
|
||||
#define ZTF_INTERACT (0x0002) /* Shell interative and reading from stdin */
|
||||
#define ZTF_SP_COMMA (0x0004) /* Treat comma as a special characters */
|
||||
#define ZTF_BANGCHAR (0x0008) /* Treat bangchar as a special character */
|
||||
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
#define WC_ZISTYPE(X,Y) wcsitype((X),(Y))
|
||||
# ifdef ENABLE_UNICODE9
|
||||
# define WC_ISPRINT(X) u9_iswprint(X)
|
||||
# else
|
||||
# define WC_ISPRINT(X) iswprint(X)
|
||||
# endif
|
||||
#else
|
||||
#define WC_ZISTYPE(X,Y) zistype((X),(Y))
|
||||
#define WC_ISPRINT(X) isprint(X)
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
|
||||
#define ZISPRINT(c) isprint_ascii(c)
|
||||
#else
|
||||
#define ZISPRINT(c) isprint(c)
|
||||
#endif
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Makefile
|
||||
*.tmp
|
||||
*.swp
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -1,790 +0,0 @@
|
|||
#
|
||||
# This file contains tests corresponding to the `Shell Grammar' texinfo node.
|
||||
#
|
||||
|
||||
%prep
|
||||
|
||||
mkdir basic.tmp && cd basic.tmp
|
||||
|
||||
touch foo bar
|
||||
echo "'" >unmatched_quote.txt
|
||||
|
||||
%test
|
||||
#
|
||||
# Tests for `Simple Commands and Pipelines'
|
||||
#
|
||||
|
||||
# Test skipping early to ensure we run the remainder...
|
||||
if [[ -n $ZTST_test_skip ]]; then
|
||||
ZTST_skip="Test system verification for skipping"
|
||||
else
|
||||
print "This is standard output"
|
||||
print "This is standard error" >&2
|
||||
false
|
||||
fi
|
||||
1:Test skipping if ZTST_test_skip is set
|
||||
>This is standard output
|
||||
?This is standard error
|
||||
|
||||
echo foo | cat | sed 's/foo/bar/'
|
||||
0:Basic pipeline handling
|
||||
>bar
|
||||
|
||||
false | true
|
||||
0:Exit status of pipeline with builtins (true)
|
||||
|
||||
true | false
|
||||
1:Exit status of pipeline with builtins (false)
|
||||
|
||||
false
|
||||
$nonexistent_variable
|
||||
0:Executing command that evaluates to empty resets status
|
||||
|
||||
false
|
||||
sleep 1 &
|
||||
print $?
|
||||
# a tidy test is a happy test
|
||||
wait $!
|
||||
0:Starting background command resets status
|
||||
>0
|
||||
|
||||
false
|
||||
. /dev/null
|
||||
0:Sourcing empty file resets status
|
||||
|
||||
fn() { local foo; read foo; print $foo; }
|
||||
coproc fn
|
||||
print -p coproc test output
|
||||
read -p bar
|
||||
print $bar
|
||||
0:Basic coprocess handling
|
||||
>coproc test output
|
||||
|
||||
true | false && print true || print false
|
||||
0:Basic sublist (i)
|
||||
>false
|
||||
|
||||
false | true && print true || print false
|
||||
0:Basic sublist (ii)
|
||||
>true
|
||||
|
||||
(cd /NonExistentDirectory >&/dev/null) || print false
|
||||
0:Basic subshell list with error
|
||||
>false
|
||||
|
||||
{ cd /NonExistentDirectory >&/dev/null } || print false
|
||||
0:Basic current shell list with error
|
||||
>false
|
||||
|
||||
#
|
||||
# Tests for `Precommand Modifiers'
|
||||
#
|
||||
- $ZTST_testdir/../Src/zsh -fc "[[ \$0 = \"-$ZTST_testdir/../Src/zsh\" ]]"
|
||||
0:`-' precommand modifier
|
||||
|
||||
echo f*
|
||||
noglob echo f*
|
||||
0:`noglob' precommand modifier
|
||||
>foo
|
||||
>f*
|
||||
|
||||
(exec /bin/sh; echo bar)
|
||||
0:`exec' precommand modifier
|
||||
|
||||
(exec -l $ZTST_testdir/../Src/zsh -fc 'echo $0' | sed 's%/.*/%%' )
|
||||
0:`exec' with -l option
|
||||
>-zsh
|
||||
|
||||
(exec -a /bin/SPLATTER /bin/sh -c 'echo $0')
|
||||
0:`exec' with -a option
|
||||
>/bin/SPLATTER
|
||||
|
||||
(exec -a/bin/SPLOOSH /bin/sh -c 'echo $0')
|
||||
0:`exec' with -a option, no space
|
||||
>/bin/SPLOOSH
|
||||
|
||||
(export FOO=bar; exec -c /bin/sh -c 'echo x${FOO}x')
|
||||
0:`exec' with -c option
|
||||
>xx
|
||||
|
||||
cat() { echo Function cat executed; }
|
||||
command cat && unfunction cat
|
||||
0:`command' precommand modifier
|
||||
<External command cat executed
|
||||
>External command cat executed
|
||||
|
||||
command -pv cat
|
||||
command -pv echo
|
||||
command -p -V cat
|
||||
command -p -V -- echo
|
||||
0:command -p in combination
|
||||
*>*/cat
|
||||
>echo
|
||||
>cat is /*/cat
|
||||
>echo is a shell builtin
|
||||
|
||||
cd() { echo Not cd at all; }
|
||||
builtin cd . && unfunction cd
|
||||
0:`builtin' precommand modifier
|
||||
|
||||
#
|
||||
# Tests for `Complex Commands'
|
||||
#
|
||||
|
||||
if true; then
|
||||
print true-1
|
||||
elif true; then
|
||||
print true-2
|
||||
else
|
||||
print false
|
||||
fi
|
||||
0:`if ...' (i)
|
||||
>true-1
|
||||
|
||||
if false; then
|
||||
print true-1
|
||||
elif true; then
|
||||
print true-2
|
||||
else
|
||||
print false
|
||||
fi
|
||||
0:`if ...' (ii)
|
||||
>true-2
|
||||
|
||||
if false; then
|
||||
print true-1
|
||||
elif false; then
|
||||
print true-2
|
||||
else
|
||||
print false
|
||||
fi
|
||||
0:`if ...' (iii)
|
||||
>false
|
||||
|
||||
if true;
|
||||
:
|
||||
fi
|
||||
1d:`if ...' (iv)
|
||||
?(eval):3: parse error near `fi'
|
||||
|
||||
for name in word to term; do
|
||||
print $name
|
||||
done
|
||||
0:`for' loop
|
||||
>word
|
||||
>to
|
||||
>term
|
||||
|
||||
for name
|
||||
in word to term; do
|
||||
print $name
|
||||
done
|
||||
0:`for' loop with newline before in keyword
|
||||
>word
|
||||
>to
|
||||
>term
|
||||
|
||||
for (( name = 0; name < 3; name++ )); do
|
||||
print $name
|
||||
done
|
||||
0:arithmetic `for' loop
|
||||
>0
|
||||
>1
|
||||
>2
|
||||
|
||||
for (( $(true); ; )); do break; done
|
||||
for (( ; $(true); )); do break; done
|
||||
for (( ; ; $(true) )); do break; done
|
||||
for (( ; $((1)); )); do break; done
|
||||
0:regression test, nested cmdsubst in arithmetic `for' loop
|
||||
|
||||
for keyvar valvar in key1 val1 key2 val2; do
|
||||
print key=$keyvar val=$valvar
|
||||
done
|
||||
0:enhanced `for' syntax with two loop variables
|
||||
>key=key1 val=val1
|
||||
>key=key2 val=val2
|
||||
|
||||
for keyvar valvar stuffvar in keyA valA stuffA keyB valB stuffB; do
|
||||
print key=$keyvar val=$valvar stuff=$stuffvar
|
||||
done
|
||||
0:enhanced `for' syntax with three loop variables
|
||||
>key=keyA val=valA stuff=stuffA
|
||||
>key=keyB val=valB stuff=stuffB
|
||||
|
||||
for in in in in in stop; do
|
||||
print in=$in
|
||||
done
|
||||
0:compatibility of enhanced `for' syntax with standard syntax
|
||||
>in=in
|
||||
>in=in
|
||||
>in=in
|
||||
>in=stop
|
||||
|
||||
name=0
|
||||
while (( name < 3 )); do
|
||||
print $name
|
||||
(( name++ ))
|
||||
done
|
||||
0:`while' loop
|
||||
>0
|
||||
>1
|
||||
>2
|
||||
|
||||
name=0
|
||||
until (( name == 3 )); do
|
||||
print $name
|
||||
(( name++ ))
|
||||
done
|
||||
0:`until' loop
|
||||
>0
|
||||
>1
|
||||
>2
|
||||
|
||||
repeat 3 do
|
||||
echo over and over
|
||||
done
|
||||
0:`repeat' loop
|
||||
>over and over
|
||||
>over and over
|
||||
>over and over
|
||||
|
||||
word=Trinity
|
||||
case $word in
|
||||
Michaelmas) print 0
|
||||
;;
|
||||
Hilary) print 1
|
||||
;;
|
||||
Trinity) print 2
|
||||
;;
|
||||
*) print 3
|
||||
;;
|
||||
esac
|
||||
0:`case', old syntax
|
||||
>2
|
||||
|
||||
word=Trinity
|
||||
case $word in
|
||||
(Michaelmas) print 0
|
||||
;;
|
||||
(Hilary) print 1
|
||||
;;
|
||||
(Trinity) print 2
|
||||
;;
|
||||
(*) print 3
|
||||
;;
|
||||
esac
|
||||
0:`case', new syntax
|
||||
>2
|
||||
|
||||
word=Hilary
|
||||
case $word in
|
||||
(Michaelmas) print 0
|
||||
;;
|
||||
(Hilary) print 1
|
||||
;&
|
||||
(Trinity) print 2
|
||||
;&
|
||||
(*) print 3
|
||||
;;
|
||||
esac
|
||||
0:`case', new syntax, cascaded
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
|
||||
case whatever in
|
||||
(*) print yeah, right ;&
|
||||
esac
|
||||
print but well
|
||||
0:'case', redundant final ";&"
|
||||
>yeah, right
|
||||
>but well
|
||||
|
||||
## Select now reads from stdin if the shell is not interactive.
|
||||
## Its own output goes to stderr.
|
||||
(COLUMNS=80 LINES=3
|
||||
PS3="input> "
|
||||
select name in one two three; do
|
||||
print $name
|
||||
done)
|
||||
0:`select' loop
|
||||
<2
|
||||
?1) one 2) two 3) three
|
||||
?input> input>
|
||||
>two
|
||||
|
||||
function name1 name2 () { print This is $0; }
|
||||
name2
|
||||
name1 name2() { print This is still $0; }
|
||||
name2
|
||||
0:`function' keyword
|
||||
>This is name2
|
||||
>This is still name2
|
||||
|
||||
(time cat) >&/dev/null
|
||||
0:`time' keyword (status only)
|
||||
|
||||
if [[ -f foo && -d . && -n $ZTST_testdir ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
0:basic [[ ... ]] test
|
||||
|
||||
#
|
||||
# Current shell execution with try/always form.
|
||||
# We put those with errors in subshells so that any unhandled error doesn't
|
||||
# propagate.
|
||||
#
|
||||
|
||||
{
|
||||
print The try block.
|
||||
} always {
|
||||
print The always block.
|
||||
}
|
||||
print After the always block.
|
||||
0:Basic `always' syntax
|
||||
>The try block.
|
||||
>The always block.
|
||||
>After the always block.
|
||||
|
||||
({
|
||||
print Position one.
|
||||
print ${*this is an error*}
|
||||
print Position two.
|
||||
} always {
|
||||
if (( TRY_BLOCK_ERROR )); then
|
||||
print An error occurred.
|
||||
else
|
||||
print No error occurred.
|
||||
fi
|
||||
}
|
||||
print Position three)
|
||||
1:Always block with error not reset
|
||||
>Position one.
|
||||
>An error occurred.
|
||||
?(eval):3: bad substitution
|
||||
|
||||
({
|
||||
print Stelle eins.
|
||||
print ${*voici une erreur}
|
||||
print Posizione due.
|
||||
} always {
|
||||
if (( TRY_BLOCK_ERROR )); then
|
||||
print Erratum factum est. Retro ponetur.
|
||||
(( TRY_BLOCK_ERROR = 0 ))
|
||||
else
|
||||
print unray touay foay anguageslay
|
||||
fi
|
||||
}
|
||||
print Status after always block is $?.)
|
||||
0:Always block with error reset
|
||||
>Stelle eins.
|
||||
>Erratum factum est. Retro ponetur.
|
||||
>Status after always block is 1.
|
||||
?(eval):3: bad substitution
|
||||
|
||||
fn() { { return } always { echo always 1 }; echo not executed }
|
||||
fn
|
||||
fn() { { echo try 2 } always { return }; echo not executed }
|
||||
fn
|
||||
0:Always block interaction with return
|
||||
>always 1
|
||||
>try 2
|
||||
|
||||
# Outputting of structures from the wordcode is distinctly non-trivial,
|
||||
# we probably ought to have more like the following...
|
||||
fn1() { { echo foo; } }
|
||||
fn2() { { echo foo; } always { echo bar; } }
|
||||
fn3() { ( echo foo; ) }
|
||||
functions fn1 fn2 fn3
|
||||
0:Output of syntactic structures with and without always blocks
|
||||
>fn1 () {
|
||||
> {
|
||||
> echo foo
|
||||
> }
|
||||
>}
|
||||
>fn2 () {
|
||||
> {
|
||||
> echo foo
|
||||
> } always {
|
||||
> echo bar
|
||||
> }
|
||||
>}
|
||||
>fn3 () {
|
||||
> (
|
||||
> echo foo
|
||||
> )
|
||||
>}
|
||||
|
||||
|
||||
#
|
||||
# Tests for `Alternate Forms For Complex Commands'
|
||||
#
|
||||
|
||||
if (true) { print true-1 } elif (true) { print true-2 } else { print false }
|
||||
if (false) { print true-1 } elif (true) { print true-2 } else { print false }
|
||||
if (false) { print true-1 } elif (false) { print true-2 } else { print false }
|
||||
0:Alternate `if' with braces
|
||||
>true-1
|
||||
>true-2
|
||||
>false
|
||||
|
||||
if { true } print true
|
||||
if { false } print false
|
||||
0:Short form of `if'
|
||||
>true
|
||||
|
||||
eval "if"
|
||||
1:Short form of `if' can't be too short
|
||||
?(eval):1: parse error near `if'
|
||||
|
||||
for name ( word1 word2 word3 ) print $name
|
||||
0:Form of `for' with parentheses.
|
||||
>word1
|
||||
>word2
|
||||
>word3
|
||||
|
||||
for name in alpha beta gamma; print $name
|
||||
0:Short form of `for'
|
||||
>alpha
|
||||
>beta
|
||||
>gamma
|
||||
|
||||
for (( val = 2; val < 10; val *= val )) print $val
|
||||
0:Short arithmetic `for'
|
||||
>2
|
||||
>4
|
||||
|
||||
foreach name ( verbiage words periphrasis )
|
||||
print $name
|
||||
end
|
||||
0:Csh-like `for'
|
||||
>verbiage
|
||||
>words
|
||||
>periphrasis
|
||||
|
||||
# see comment with braces used in if loops
|
||||
val=0;
|
||||
while (( val < 2 )) { print $((val++)); }
|
||||
0:Alternative `while'
|
||||
>0
|
||||
>1
|
||||
|
||||
val=2;
|
||||
until (( val == 0 )) { print $((val--)); }
|
||||
0:Alternative `until'
|
||||
>2
|
||||
>1
|
||||
|
||||
repeat 3 print Hip hip hooray
|
||||
0:Short `repeat'
|
||||
>Hip hip hooray
|
||||
>Hip hip hooray
|
||||
>Hip hip hooray
|
||||
|
||||
case bravo {
|
||||
(alpha) print schmalpha
|
||||
;;
|
||||
(bravo) print schmavo
|
||||
;;
|
||||
(charlie) print schmarlie
|
||||
;;
|
||||
}
|
||||
0:`case' with braces
|
||||
>schmavo
|
||||
|
||||
for word in artichoke bladderwort chrysanthemum Zanzibar
|
||||
case $word in
|
||||
(*der*) print $word contains the forbidden incantation der
|
||||
;;
|
||||
(a*) print $word begins with a
|
||||
;&
|
||||
([[:upper:]]*) print $word either begins with a or an upper case letter
|
||||
;|
|
||||
([[:lower:]]*) print $word begins with a lower case letter
|
||||
;|
|
||||
(*e*) print $word contains an e
|
||||
;;
|
||||
esac
|
||||
0:`case' with mixed ;& and ;|
|
||||
>artichoke begins with a
|
||||
>artichoke either begins with a or an upper case letter
|
||||
>artichoke begins with a lower case letter
|
||||
>artichoke contains an e
|
||||
>bladderwort contains the forbidden incantation der
|
||||
>chrysanthemum begins with a lower case letter
|
||||
>chrysanthemum contains an e
|
||||
>Zanzibar either begins with a or an upper case letter
|
||||
|
||||
print -u $ZTST_fd 'This test hangs the shell when it fails...'
|
||||
name=0
|
||||
# The number 4375 here is chosen to produce more than 16384 bytes of output
|
||||
while (( name < 4375 )); do
|
||||
print -n $name
|
||||
(( name++ ))
|
||||
done < /dev/null | { read name; print done }
|
||||
0:Bug regression: `while' loop with redirection and pipeline
|
||||
>done
|
||||
|
||||
# This used to be buggy and print X at the end of each iteration.
|
||||
for f in 1 2 3 4; do
|
||||
print $f || break
|
||||
done && print X
|
||||
0:Handling of ||'s and &&'s with a for loop in between
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
>4
|
||||
>X
|
||||
|
||||
# Same bug for &&, used to print `no' at the end of each iteration
|
||||
for f in 1 2 3 4; do
|
||||
false && print strange
|
||||
done || print no
|
||||
0:Handling of &&'s and ||'s with a for loop in between
|
||||
>no
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f unmatched_quote.txt
|
||||
1:Parse error with file causes non-zero exit status
|
||||
?unmatched_quote.txt:2: unmatched '
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f <unmatched_quote.txt
|
||||
1:Parse error on standard input causes non-zero exit status
|
||||
?zsh: unmatched '
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -c "'"
|
||||
1:Parse error on inline command causes non-zero exit status
|
||||
?zsh:1: unmatched '
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f NonExistentScript
|
||||
127q:Non-existent script causes exit status 127
|
||||
?$ZTST_testdir/../Src/zsh: can't open input file: NonExistentScript
|
||||
|
||||
(setopt nonomatch
|
||||
# use this to get stuff at start of line
|
||||
contents=$'# comment \'\necho value #with " stuff\n# comment\n#comment
|
||||
echo not#comment\n'
|
||||
eval 'VAR=$('"$contents"')'
|
||||
print -l $VAR)
|
||||
0:comments within $(...)
|
||||
>value
|
||||
>not#comment
|
||||
|
||||
. ./nonexistent
|
||||
127: Attempt to "." non-existent file.
|
||||
?(eval):.:1: no such file or directory: ./nonexistent
|
||||
|
||||
echo '[[' >bad_syntax
|
||||
. ./bad_syntax
|
||||
126: Attempt to "." file with bad syntax.
|
||||
?./bad_syntax:2: parse error near `\n'
|
||||
# `
|
||||
|
||||
echo 'false' >dot_false
|
||||
. ./dot_false
|
||||
print $?
|
||||
echo 'true' >dot_true
|
||||
. ./dot_true
|
||||
print $?
|
||||
0:Last status of successfully executed "." file is retained
|
||||
>1
|
||||
>0
|
||||
|
||||
echo 'echo $?' >dot_status
|
||||
false
|
||||
. ./dot_status
|
||||
0:"." file sees status from previous command
|
||||
>1
|
||||
|
||||
mkdir test_path_script
|
||||
print "#!/bin/sh\necho Found the script." >test_path_script/myscript
|
||||
chmod u+x test_path_script/myscript
|
||||
path=($PWD/test_path_script $path)
|
||||
export PATH
|
||||
$ZTST_testdir/../Src/zsh -f -o pathscript myscript
|
||||
0:PATHSCRIPT option
|
||||
>Found the script.
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f myscript
|
||||
127q:PATHSCRIPT option not used.
|
||||
?$ZTST_testdir/../Src/zsh: can't open input file: myscript
|
||||
# '
|
||||
|
||||
$ZTST_testdir/../Src/zsh -fc 'echo $0; echo $1' myargzero myargone
|
||||
0:$0 is traditionally if bizarrely set to the first argument with -c
|
||||
>myargzero
|
||||
>myargone
|
||||
|
||||
(setopt shglob
|
||||
eval '
|
||||
if ! (echo success1); then echo failure1; fi
|
||||
if !(echo success2); then echo failure2; fi
|
||||
print -l one two | while(read foo)do(print read it)done
|
||||
')
|
||||
0:Parentheses in shglob
|
||||
>success1
|
||||
>success2
|
||||
>read it
|
||||
>read it
|
||||
|
||||
(
|
||||
mywrap() { echo BEGIN; true; echo END }
|
||||
mytest() { { exit 3 } always { mywrap }; print Exited before this }
|
||||
mytest
|
||||
print Exited before this, too
|
||||
)
|
||||
3:Exit and always block with functions: simple
|
||||
>BEGIN
|
||||
>END
|
||||
|
||||
(
|
||||
mytrue() { echo mytrue; return 0 }
|
||||
mywrap() { echo BEGIN; mytrue; echo END }
|
||||
mytest() { { exit 4 } always { mywrap }; print Exited before this }
|
||||
mytest
|
||||
print Exited before this, too
|
||||
)
|
||||
4:Exit and always block with functions: nested
|
||||
>BEGIN
|
||||
>mytrue
|
||||
>END
|
||||
|
||||
(emulate sh -c '
|
||||
fn() {
|
||||
case $1 in
|
||||
( one | two | three )
|
||||
print Matched $1
|
||||
;;
|
||||
( fo* | fi* | si* )
|
||||
print Pattern matched $1
|
||||
;;
|
||||
( []x | a[b]* )
|
||||
print Character class matched $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
'
|
||||
which fn
|
||||
fn one
|
||||
fn two
|
||||
fn three
|
||||
fn four
|
||||
fn five
|
||||
fn six
|
||||
fn abecedinarian
|
||||
fn xylophone)
|
||||
0: case word handling in sh emulation (SH_GLOB parentheses)
|
||||
>fn () {
|
||||
> case $1 in
|
||||
> (one | two | three) print Matched $1 ;;
|
||||
> (fo* | fi* | si*) print Pattern matched $1 ;;
|
||||
> ([]x | a[b]*) print Character class matched $1 ;;
|
||||
> esac
|
||||
>}
|
||||
>Matched one
|
||||
>Matched two
|
||||
>Matched three
|
||||
>Pattern matched four
|
||||
>Pattern matched five
|
||||
>Pattern matched six
|
||||
>Character class matched abecedinarian
|
||||
|
||||
case grumph in
|
||||
( no | (grumph) )
|
||||
print 1 OK
|
||||
;;
|
||||
esac
|
||||
case snruf in
|
||||
( fleer | (|snr(|[au]f)) )
|
||||
print 2 OK
|
||||
;;
|
||||
esac
|
||||
0: case patterns within words
|
||||
>1 OK
|
||||
>2 OK
|
||||
|
||||
case horrible in
|
||||
([a-m])(|[n-z])rr(|ib(um|le|ah)))
|
||||
print It worked
|
||||
;;
|
||||
esac
|
||||
case "a string with separate words" in
|
||||
(*with separate*))
|
||||
print That worked, too
|
||||
;;
|
||||
esac
|
||||
0:Unbalanced parentheses and spaces with zsh pattern
|
||||
>It worked
|
||||
>That worked, too
|
||||
|
||||
case horrible in
|
||||
(([a-m])(|[n-z])rr(|ib(um|le|ah)))
|
||||
print It worked
|
||||
;;
|
||||
esac
|
||||
case "a string with separate words" in
|
||||
(*with separate*)
|
||||
print That worked, too
|
||||
;;
|
||||
esac
|
||||
0:Balanced parentheses and spaces with zsh pattern
|
||||
>It worked
|
||||
>That worked, too
|
||||
|
||||
fn() {
|
||||
typeset ac_file="the else branch"
|
||||
case $ac_file in
|
||||
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
|
||||
*.* ) break;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
print Stuff here
|
||||
}
|
||||
which fn
|
||||
fn
|
||||
0:Long case with parsed alternatives turned back into text
|
||||
>fn () {
|
||||
> typeset ac_file="the else branch"
|
||||
> case $ac_file in
|
||||
> (*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj) ;;
|
||||
> (*.*) break ;;
|
||||
> (*) ;;
|
||||
> esac
|
||||
> print Stuff here
|
||||
>}
|
||||
>Stuff here
|
||||
|
||||
(exit 37)
|
||||
case $? in
|
||||
(37) echo $?
|
||||
;;
|
||||
esac
|
||||
0:case retains exit status for execution of cases
|
||||
>37
|
||||
|
||||
false
|
||||
case stuff in
|
||||
(nomatch) foo
|
||||
;;
|
||||
esac
|
||||
echo $?
|
||||
0:case sets exit status to zero if no patterns are matched
|
||||
>0
|
||||
|
||||
case match in
|
||||
(match) true; false; (exit 37)
|
||||
;;
|
||||
esac
|
||||
echo $?
|
||||
0:case keeps exit status of last command executed in compound-list
|
||||
>37
|
||||
|
||||
x=1
|
||||
x=2 | echo $x
|
||||
echo $x
|
||||
0:Assignment-only current shell commands in LHS of pipelin
|
||||
>1
|
||||
>1
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
# To get the "command not found" message when aliasing is suppressed
|
||||
# we need, er, a command that isn't found.
|
||||
# The other aliases are only ever used as aliases.
|
||||
|
||||
%prep
|
||||
alias ThisCommandDefinitelyDoesNotExist=echo
|
||||
|
||||
alias -g bar=echo
|
||||
|
||||
alias '\bar=echo'
|
||||
|
||||
%test
|
||||
ThisCommandDefinitelyDoesNotExist ThisCommandDefinitelyDoesNotExist
|
||||
0:Basic aliasing
|
||||
>ThisCommandDefinitelyDoesNotExist
|
||||
|
||||
bar bar
|
||||
0:Global aliasing
|
||||
>echo
|
||||
|
||||
\ThisCommandDefinitelyDoesNotExist ThisCommandDefinitelyDoesNotExist
|
||||
127:Not aliasing
|
||||
?(eval):1: command not found: ThisCommandDefinitelyDoesNotExist
|
||||
|
||||
\bar \bar
|
||||
0:Aliasing with a backslash
|
||||
>bar
|
||||
|
||||
(alias '!=echo This command has the argument'
|
||||
eval 'print Without
|
||||
! true'
|
||||
setopt posixaliases
|
||||
eval 'print With
|
||||
! true')
|
||||
1:POSIX_ALIASES option
|
||||
>Without
|
||||
>This command has the argument true
|
||||
>With
|
||||
|
||||
print -u $ZTST_fd 'This test hangs the shell when it fails...'
|
||||
alias cat='LC_ALL=C cat'
|
||||
cat <(echo foo | cat)
|
||||
0:Alias expansion works at the end of parsed strings
|
||||
>foo
|
||||
|
||||
alias -g '&&=(){ return $?; } && '
|
||||
alias not_the_print_command=print
|
||||
eval 'print This is output
|
||||
&& print And so is this
|
||||
&& { print And this too; false; }
|
||||
&& print But not this
|
||||
&& print Nor this
|
||||
true
|
||||
&& not_the_print_command And aliases are expanded'
|
||||
0:We can now alias special tokens. Woo hoo.
|
||||
>This is output
|
||||
>And so is this
|
||||
>And this too
|
||||
>And aliases are expanded
|
||||
|
||||
$ZTST_testdir/../Src/zsh -fis <<<'
|
||||
unsetopt PROMPT_SP
|
||||
PROMPT="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
|
||||
exec 2>&1
|
||||
alias \{=echo
|
||||
{ begin
|
||||
{end
|
||||
fc -l -2' 2>/dev/null
|
||||
0:Aliasing reserved tokens
|
||||
>begin
|
||||
>end
|
||||
*>*5*{ begin
|
||||
*>*6*{end
|
||||
|
||||
$ZTST_testdir/../Src/zsh -fis <<<'
|
||||
unsetopt PROMPT_SP
|
||||
PROMPT="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
|
||||
exec 2>&1
|
||||
alias -g S=\"
|
||||
echo S a string S "
|
||||
fc -l -1' 2>/dev/null
|
||||
0:Global aliasing quotes
|
||||
> a string S
|
||||
*>*5*echo S a string S "
|
||||
# "
|
||||
# Note there is a trailing space on the "> a string S " line
|
||||
|
||||
(
|
||||
unalias -a
|
||||
alias
|
||||
)
|
||||
0:unalias -a
|
||||
|
||||
alias -s foo=print
|
||||
type bar.foo; type -w bar.foo
|
||||
unalias -as
|
||||
0:unalias -as
|
||||
>foo is a suffix alias for print
|
||||
>foo: suffix alias
|
||||
|
||||
aliases[x=y]=z
|
||||
alias -L | grep x=y
|
||||
echo $pipestatus[1]
|
||||
0:printing invalid aliases warns
|
||||
>0
|
||||
?(eval):2: invalid alias 'x=y' encountered while printing aliases
|
||||
# Currently, 'alias -L' returns 0 in this case. Perhaps it should return 1.
|
||||
|
||||
alias -s mysuff='print -r "You said it.";'
|
||||
eval 'thingummy.mysuff'
|
||||
127:No endless loop with suffix alias in command position
|
||||
>You said it.
|
||||
?(eval):1: command not found: thingummy.mysuff
|
||||
|
||||
alias +x; alias -z
|
||||
1:error message has the correct sign
|
||||
?(eval):alias:1: bad option: +x
|
||||
?(eval):alias:1: bad option: -z
|
||||
|
||||
# Usual issue that aliases aren't expanded until we
|
||||
# trigger a new parse...
|
||||
(alias badalias=notacommand
|
||||
eval 'badalias() { print does not work; }')
|
||||
1:ALIAS_FUNC_DEF off by default.
|
||||
?(eval):1: defining function based on alias `badalias'
|
||||
?(eval):1: parse error near `()'
|
||||
|
||||
(alias goodalias=isafunc
|
||||
setopt ALIAS_FUNC_DEF
|
||||
eval 'goodalias() { print does now work; }'
|
||||
isafunc)
|
||||
0:ALIAS_FUNC_DEF causes the icky behaviour to be avaliable
|
||||
>does now work
|
||||
|
||||
(alias thisisokthough='thisworks() { print That worked; }'
|
||||
eval thisisokthough
|
||||
thisworks)
|
||||
0:NO_ALIAS_FUNC_DEF works if the alias is a complete definition
|
||||
>That worked
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
%test
|
||||
print 'single quotes' "double quotes" `echo backquotes`
|
||||
0:Simple use of quotes
|
||||
>single quotes double quotes backquotes
|
||||
|
||||
foo=text
|
||||
print -r '$foo\\\' "$foo\$foo\\\"\``echo bar`\`\"" `print -r $foo\\\``
|
||||
0:Quoting inside quotes
|
||||
>$foo\\\ text$foo\"`bar`" text`
|
||||
|
||||
print -r $'\'ut queant laxis\'\n"resonare fibris"'
|
||||
0:$'-style quotes
|
||||
>'ut queant laxis'
|
||||
>"resonare fibris"
|
||||
|
||||
print -r $'\'a \\\' is \'a backslash\' is \'a \\\''
|
||||
0:$'-style quotes with backslashed backslashes
|
||||
>'a \' is 'a backslash' is 'a \'
|
||||
|
||||
chars=$(print -r $'BS\\MBS\M-\\')
|
||||
for (( i = 1; i <= $#chars; i++ )); do
|
||||
char=$chars[$i]
|
||||
print $(( [#16] #char ))
|
||||
done
|
||||
0:$'-style quote with metafied backslash
|
||||
>16#42
|
||||
>16#53
|
||||
>16#5C
|
||||
>16#4D
|
||||
>16#42
|
||||
>16#53
|
||||
>16#DC
|
||||
|
||||
print -r ''''
|
||||
setopt rcquotes
|
||||
# We need to set rcquotes here for the next example since it is
|
||||
# needed while parsing.
|
||||
0:No RC_QUOTES with single quotes
|
||||
>
|
||||
|
||||
print -r ''''
|
||||
unsetopt rcquotes
|
||||
0:Yes RC_QUOTES with single quotes
|
||||
>'
|
||||
# ' Deconfuse Emacs quoting rules
|
||||
|
||||
print '<\u0041>'
|
||||
printf '%s\n' $'<\u0042>'
|
||||
print '<\u0043>'
|
||||
printf '%s\n' $'<\u0044>'
|
||||
0:\u in both print and printf
|
||||
><A>
|
||||
><B>
|
||||
><C>
|
||||
><D>
|
||||
|
||||
null1="$(print -r a$'b\0c'd)"
|
||||
null2="$(setopt posixstrings; print -r a$'b\0c'd)"
|
||||
for string in $null1 $null2; do
|
||||
print ":"
|
||||
for (( i = 1; i <= $#string; i++ )); do
|
||||
char=$string[$i]
|
||||
print $(( [#16] #char ))
|
||||
done
|
||||
done
|
||||
0:Embedded null characters in $'...' strings.
|
||||
>:
|
||||
>16#61
|
||||
>16#62
|
||||
>16#0
|
||||
>16#63
|
||||
>16#64
|
||||
>:
|
||||
>16#61
|
||||
>16#62
|
||||
>16#64
|
||||
|
||||
() { print $# } '' "" $''
|
||||
0:$'' should not be elided, in common with other empty quotes
|
||||
>3
|
||||
|
|
@ -1,588 +0,0 @@
|
|||
# Tests corresponding to the `Redirection' texinfo node.
|
||||
|
||||
%prep
|
||||
mkdir redir.tmp && cd redir.tmp
|
||||
|
||||
myfd=99
|
||||
(echo >&$myfd) 2>msg
|
||||
bad_fd_msg="${$(<msg)##*:}"
|
||||
|
||||
%test
|
||||
|
||||
print 'This is file redir' >redir && cat redir
|
||||
0:'>' and '<' redirection
|
||||
>This is file redir
|
||||
|
||||
rm -f redir
|
||||
print 'This is still file redir' <>redir >&0 && cat <>redir
|
||||
0:'<>' redirection
|
||||
>This is still file redir
|
||||
|
||||
rm -f redir
|
||||
print 'With a bar' >|redir && cat redir
|
||||
0:'>|' redirection
|
||||
>With a bar
|
||||
|
||||
rm -f redir
|
||||
print 'With a bang' >!redir && cat redir
|
||||
0:'>!' redirection
|
||||
>With a bang
|
||||
|
||||
rm -f redir
|
||||
print 'Line 1' >>redir && print 'Line 2' >>redir && cat redir
|
||||
0:'>>' redirection
|
||||
>Line 1
|
||||
>Line 2
|
||||
|
||||
rm -f redir
|
||||
print 'Line a' >>|redir && print 'Line b' >>!redir
|
||||
0:'>>|' and '>>!' redirection
|
||||
|
||||
foo=bar
|
||||
cat <<' HERE'
|
||||
$foo
|
||||
HERE
|
||||
eval "$(print 'cat <<HERE\n$foo\nHERE')"
|
||||
0:Here-documents
|
||||
> $foo
|
||||
>bar
|
||||
|
||||
cat <<-HERE
|
||||
# note tabs at the start of the following lines
|
||||
$foo$foo
|
||||
HERE
|
||||
0:Here-documents stripping tabs
|
||||
>barbar
|
||||
|
||||
cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" #
|
||||
# tabs again. sorry about the max miller.
|
||||
Here's a funny thing. Here is a funny thing.
|
||||
I went home last night. There's a funny thing.
|
||||
Man walks into a $foo. Ouch, it's an iron $foo.
|
||||
$HERE `$(THERE) `$((AND)) \EVERYWHERE
|
||||
0:Here-documents don't perform shell expansion on the initial word
|
||||
>Here's a funny thing. Here is a funny thing.
|
||||
>I went home last night. There's a funny thing.
|
||||
>Man walks into a $foo. Ouch, it's an iron $foo.
|
||||
|
||||
cat <<-$'\x45\x4e\x44\t\x44\x4f\x43'
|
||||
# tabs again
|
||||
This message is unfathomable.
|
||||
END DOC
|
||||
0:Here-documents do perform $'...' expansion on the initial word
|
||||
>This message is unfathomable.
|
||||
|
||||
cat <<<"This is a line with a $foo in it"
|
||||
0:'<<<' redirection
|
||||
>This is a line with a bar in it
|
||||
|
||||
cat <<<$'a\nb\nc'
|
||||
0:here-strings with $'...' quoting
|
||||
>a
|
||||
>b
|
||||
>c
|
||||
|
||||
# The following tests check that output of parsed here-documents works.
|
||||
# This isn't completely trivial because we convert the here-documents
|
||||
# internally to here-strings. So we check again that we can output
|
||||
# the reevaluated here-strings correctly. Hence there are three slightly
|
||||
# different stages. We don't care how the output actually looks, so
|
||||
# we don't test that.
|
||||
heretest() {
|
||||
print First line
|
||||
cat <<-HERE
|
||||
$foo$foo met celeste 'but with extra' "stuff to test quoting"
|
||||
HERE
|
||||
print Last line
|
||||
}
|
||||
heretest
|
||||
eval "$(functions heretest)"
|
||||
heretest
|
||||
eval "$(functions heretest)"
|
||||
heretest
|
||||
0:Re-evaluation of function output with here document, unquoted
|
||||
>First line
|
||||
>barbar met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
>First line
|
||||
>barbar met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
>First line
|
||||
>barbar met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
|
||||
heretest() {
|
||||
print First line
|
||||
cat <<' HERE'
|
||||
$foo$foo met celeste 'but with extra' "stuff to test quoting"
|
||||
HERE
|
||||
print Last line
|
||||
}
|
||||
heretest
|
||||
eval "$(functions heretest)"
|
||||
heretest
|
||||
eval "$(functions heretest)"
|
||||
heretest
|
||||
0:Re-evaluation of function output with here document, quoted
|
||||
>First line
|
||||
> $foo$foo met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
>First line
|
||||
> $foo$foo met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
>First line
|
||||
> $foo$foo met celeste 'but with extra' "stuff to test quoting"
|
||||
>Last line
|
||||
|
||||
read -r line <<' HERE'
|
||||
HERE
|
||||
1:No input, not even newline, from empty here document.
|
||||
|
||||
#
|
||||
# exec tests: perform these in subshells so if they fail the
|
||||
# shell won't exit.
|
||||
#
|
||||
(exec 3>redir && print hello >&3 && print goodbye >&3 && cat redir)
|
||||
0:'>&' redirection
|
||||
>hello
|
||||
>goodbye
|
||||
|
||||
(exec 3<redir && read foo <&3 && print $foo && read foo <&3 && print $foo)
|
||||
0:'<&' redirection
|
||||
>hello
|
||||
>goodbye
|
||||
|
||||
({exec 3<&- } 2>/dev/null
|
||||
exec 3<&-
|
||||
read foo <&-)
|
||||
1:'<&-' redirection with numeric fd (no error message on failure)
|
||||
|
||||
(exec {varid}<&0
|
||||
exec {varid}<&-
|
||||
print About to close a second time >&2
|
||||
read {varid}<&-)
|
||||
1:'<&-' redirection with fd in variable (error message on failure)
|
||||
?About to close a second time
|
||||
*?\(eval\):*: failed to close file descriptor *
|
||||
|
||||
print foo >&-
|
||||
0:'>&-' redirection
|
||||
|
||||
(exec >&-
|
||||
print foo)
|
||||
0:'>&-' with attempt to use closed fd
|
||||
*?\(eval\):2: write error:*
|
||||
|
||||
fn() { local foo; read foo; print $foo; }
|
||||
coproc fn
|
||||
print test output >&p
|
||||
read bar <&p
|
||||
print $bar
|
||||
0:'>&p' and '<&p' redirection
|
||||
>test output
|
||||
|
||||
( print Output; print Error >& 2 ) >&errout && cat errout
|
||||
0:'>&FILE' handling
|
||||
>Output
|
||||
>Error
|
||||
|
||||
rm -f errout
|
||||
( print Output2; print Error2 >& 2 ) &>errout && cat errout
|
||||
0:'&>FILE' handling
|
||||
>Output2
|
||||
>Error2
|
||||
|
||||
rm -f errout
|
||||
( print Output3; print Error3 >& 2 ) >&|errout && cat errout
|
||||
( print Output4; print Error4 >& 2 ) >&!errout && cat errout
|
||||
( print Output5; print Error5 >& 2 ) &>|errout && cat errout
|
||||
( print Output6; print Error6 >& 2 ) &>!errout &&
|
||||
( print Output7; print Error7 >& 2 ) >>&errout &&
|
||||
( print Output8; print Error8 >& 2 ) &>>errout &&
|
||||
( print Output9; print Error9 >& 2 ) >>&|errout &&
|
||||
( print Output10; print Error10 >& 2 ) &>>|errout &&
|
||||
( print Output11; print Error11 >& 2 ) >>&!errout &&
|
||||
( print Output12; print Error12 >& 2 ) &>>!errout && cat errout
|
||||
0:'>&|', '>&!', '&>|', '&>!' redirection
|
||||
>Output3
|
||||
>Error3
|
||||
>Output4
|
||||
>Error4
|
||||
>Output5
|
||||
>Error5
|
||||
>Output6
|
||||
>Error6
|
||||
>Output7
|
||||
>Error7
|
||||
>Output8
|
||||
>Error8
|
||||
>Output9
|
||||
>Error9
|
||||
>Output10
|
||||
>Error10
|
||||
>Output11
|
||||
>Error11
|
||||
>Output12
|
||||
>Error12
|
||||
|
||||
rm -f errout
|
||||
( print Output; print Error 1>&2 ) 1>errout 2>&1 && cat errout
|
||||
0:'Combining > with >& (1)'
|
||||
>Output
|
||||
>Error
|
||||
|
||||
rm -f errout
|
||||
( print Output; print Error 1>&2 ) 2>&1 1>errout && print errout: &&
|
||||
cat errout
|
||||
0:'Combining > with >& (2)'
|
||||
>Error
|
||||
>errout:
|
||||
>Output
|
||||
|
||||
rm -f errout
|
||||
print doo be doo be doo >foo >bar
|
||||
print "foo: $(<foo)\nbar: $(<bar)"
|
||||
0:2-file multio
|
||||
>foo: doo be doo be doo
|
||||
>bar: doo be doo be doo
|
||||
|
||||
rm -f foo bar
|
||||
print dont be dont be dont >foo | sed 's/dont/wont/g' >bar
|
||||
0:setup file+pipe multio
|
||||
|
||||
print "foo: $(<foo)\nbar: $(<bar)"
|
||||
0:read file+pipe multio
|
||||
>foo: dont be dont be dont
|
||||
>bar: wont be wont be wont
|
||||
|
||||
rm -f *
|
||||
touch out1 out2
|
||||
print All files >*
|
||||
print *
|
||||
print "out1: $(<out1)\nout2: $(<out2)"
|
||||
0:multio with globbing
|
||||
>out1 out2
|
||||
>out1: All files
|
||||
>out2: All files
|
||||
|
||||
print This is out1 >out1
|
||||
print This is out2 >out2
|
||||
0:setup multio for input
|
||||
|
||||
# Currently, <out{1,2} doesn't work: this is a bug.
|
||||
cat <out*
|
||||
0:read multio input
|
||||
>This is out1
|
||||
>This is out2
|
||||
|
||||
cat out1 | sed s/out/bout/ <out2
|
||||
0:read multio input with pipe
|
||||
>This is bout1
|
||||
>This is bout2
|
||||
|
||||
unset NULLCMD
|
||||
>out1
|
||||
1:null redir with NULLCMD unset
|
||||
?(eval):2: redirection with no command
|
||||
|
||||
echo this should still work >out1
|
||||
print "$(<out1)"
|
||||
0:null redir in $(...) with NULLCMD unset
|
||||
>this should still work
|
||||
|
||||
READNULLCMD=cat
|
||||
print cat input >out1
|
||||
<out1
|
||||
1:READNULLCMD with NULLCMD unset
|
||||
?(eval):3: redirection with no command
|
||||
|
||||
NULLCMD=:
|
||||
>out1
|
||||
[[ ! -s out1 ]] || print out1 is not empty
|
||||
0:null redir with NULLCMD=:
|
||||
<input
|
||||
|
||||
print cat input >out1
|
||||
<out1
|
||||
0:READNULLCMD
|
||||
>cat input
|
||||
|
||||
NULLCMD=cat
|
||||
>out1
|
||||
cat out1
|
||||
0:null redir with NULLCMD=cat
|
||||
<input
|
||||
>input
|
||||
|
||||
(myfd=
|
||||
exec {myfd}>logfile
|
||||
if [[ -z $myfd ]]; then
|
||||
print "Ooops, failed to set myfd to a file descriptor." >&2
|
||||
else
|
||||
print This is my logfile. >&$myfd
|
||||
print Examining contents of logfile...
|
||||
cat logfile
|
||||
fi)
|
||||
0:Using {fdvar}> syntax to open a new file descriptor
|
||||
>Examining contents of logfile...
|
||||
>This is my logfile.
|
||||
|
||||
(setopt noclobber
|
||||
exec {myfd}>logfile2
|
||||
echo $myfd
|
||||
exec {myfd}>logfile3) | read myfd
|
||||
(( ! ${pipestatus[1]} ))
|
||||
1q:NO_CLOBBER prevents overwriting parameter with allocated fd
|
||||
?(eval):4: can't clobber parameter myfd containing file descriptor $myfd
|
||||
|
||||
(setopt noclobber
|
||||
exec {myfd}>logfile2b
|
||||
print First open >&$myfd
|
||||
rm -f logfile2b # prevent normal file no_clobberation
|
||||
myotherfd="${myfd}+0"
|
||||
exec {myotherfd}>logfile2b
|
||||
print Overwritten >&$myotherfd)
|
||||
cat logfile2b
|
||||
0:NO_CLOBBER doesn't complain about any other expression
|
||||
>Overwritten
|
||||
|
||||
(exec {myfd}>logfile4
|
||||
echo $myfd
|
||||
exec {myfd}>&-
|
||||
print This message should disappear >&$myfd) | read myfd
|
||||
(( ! ${pipestatus[1]} ))
|
||||
1q:Closing file descriptor using brace syntax
|
||||
?(eval):4: $myfd:$bad_fd_msg
|
||||
|
||||
typeset -r myfd
|
||||
echo This should not appear {myfd}>nologfile
|
||||
1:Error opening file descriptor using readonly variable
|
||||
?(eval):2: can't allocate file descriptor to readonly parameter myfd
|
||||
|
||||
(typeset +r myfd
|
||||
exec {myfd}>newlogfile
|
||||
typeset -r myfd
|
||||
exec {myfd}>&-)
|
||||
1:Error closing file descriptor using readonly variable
|
||||
?(eval):4: can't close file descriptor from readonly parameter myfd
|
||||
|
||||
# This tests the here-string to filename optimisation; we can't
|
||||
# test that it's actually being optimised, but we can test that it
|
||||
# still works.
|
||||
cat =(<<<$'This string has been replaced\nby a file containing it.\n')
|
||||
0:Optimised here-string to filename
|
||||
>This string has been replaced
|
||||
>by a file containing it.
|
||||
|
||||
print This f$'\x69'le contains d$'\x61'ta. >redirfile
|
||||
print redirection:
|
||||
cat<redirfile>outfile
|
||||
print output:
|
||||
cat outfile
|
||||
print append:
|
||||
cat>>outfile<redirfile
|
||||
print more output:
|
||||
cat outfile
|
||||
0:Parsing of redirection operators (no space required before operators)
|
||||
>redirection:
|
||||
>output:
|
||||
>This file contains data.
|
||||
>append:
|
||||
>more output:
|
||||
>This file contains data.
|
||||
>This file contains data.
|
||||
|
||||
$ZTST_testdir/../Src/zsh -fc 'exec >/nonexistent/nonexistent
|
||||
echo output'
|
||||
0:failed exec redir, no POSIX_BUILTINS
|
||||
>output
|
||||
?zsh:1: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
|
||||
exec >/nonexistent/nonexistent
|
||||
echo output'
|
||||
1:failed exec redir, POSIX_BUILTINS
|
||||
?zsh:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
|
||||
set >/nonexistent/nonexistent
|
||||
echo output'
|
||||
1:failed special builtin redir, POSIX_BUILTINS
|
||||
?zsh:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
|
||||
command set >/nonexistent/nonexistent
|
||||
echo output'
|
||||
0:failed special builtin redir with command prefix, POSIX_BUILTINS
|
||||
>output
|
||||
?zsh:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
|
||||
echo >/nonexistent/nonexistent
|
||||
echo output'
|
||||
0:failed unspecial builtin redir, POSIX_BUILTINS
|
||||
>output
|
||||
?zsh:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
|
||||
. /nonexistent/nonexistent
|
||||
echo output'
|
||||
1:failed dot, POSIX_BUILTINS
|
||||
?zsh:.:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -c '
|
||||
. /nonexistent/nonexistent
|
||||
echo output'
|
||||
0:failed dot, NO_POSIX_BUILTINS
|
||||
>output
|
||||
?zsh:.:2: no such file or directory: /nonexistent/nonexistent
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
|
||||
readonly foo
|
||||
foo=bar set output
|
||||
echo output'
|
||||
0:failed assignment on posix special, CONTINUE_ON_ERROR
|
||||
>output
|
||||
?zsh: read-only variable: foo
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f <<<'
|
||||
readonly foo
|
||||
foo=bar set output
|
||||
echo output'
|
||||
1:failed assignment on posix special, NO_CONTINUE_ON_ERROR
|
||||
?zsh: read-only variable: foo
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
|
||||
readonly foo
|
||||
foo=bar echo output
|
||||
echo output'
|
||||
0:failed assignment on non-posix-special, CONTINUE_ON_ERROR
|
||||
>output
|
||||
?zsh: read-only variable: foo
|
||||
|
||||
[</dev/null ]
|
||||
1:check behaviour with square brackets
|
||||
|
||||
print any old rubbish >input1
|
||||
() {
|
||||
local var
|
||||
read var
|
||||
print I just read $var
|
||||
} <input1 >output1
|
||||
print Nothing output yet
|
||||
cat output1
|
||||
0:anonymous function redirections are applied immediately
|
||||
>Nothing output yet
|
||||
>I just read any old rubbish
|
||||
|
||||
redirfn() {
|
||||
local var
|
||||
read var
|
||||
print I want to tell you about $var
|
||||
print Also, this might be an error >&2
|
||||
} <input2 >output2 2>&1
|
||||
print something I heard on the radio >input2
|
||||
redirfn
|
||||
print No output until after this
|
||||
cat output2
|
||||
0:redirections with normal function definition
|
||||
>No output until after this
|
||||
>I want to tell you about something I heard on the radio
|
||||
>Also, this might be an error
|
||||
|
||||
which redirfn
|
||||
0:text output of function with redirections
|
||||
>redirfn () {
|
||||
> local var
|
||||
> read var
|
||||
> print I want to tell you about $var
|
||||
> print Also, this might be an error >&2
|
||||
>} < input2 > output2 2>&1
|
||||
|
||||
1func 2func 3func() { print Ich heisse $0 } >output3
|
||||
for i in 1 2 3; do
|
||||
f=${i}func
|
||||
print Running $f
|
||||
$f
|
||||
cat output3
|
||||
unfunction $f
|
||||
done
|
||||
0:multiply named functions with redirection
|
||||
>Running 1func
|
||||
>Ich heisse 1func
|
||||
>Running 2func
|
||||
>Ich heisse 2func
|
||||
>Running 3func
|
||||
>Ich heisse 3func
|
||||
|
||||
redirfn2() { print The latest output; } >&3
|
||||
redirfn2 3>output4
|
||||
print No output yet
|
||||
cat output4
|
||||
0:Redirections in both function definition and command line
|
||||
>No output yet
|
||||
>The latest output
|
||||
|
||||
# This relies on the fact that the test harness always loads
|
||||
# the zsh/parameter module.
|
||||
print $functions[redirfn]
|
||||
0:Output from $functions[] for definition with redirection
|
||||
>{
|
||||
> local var
|
||||
> read var
|
||||
> print I want to tell you about $var
|
||||
> print Also, this might be an error >&2
|
||||
>} < input2 > output2 2>&1
|
||||
|
||||
noredirfn() { print This rather boring function has no redirection.; }
|
||||
print $functions[noredirfn]
|
||||
0:Output from $functions[] for definition with no redirection
|
||||
> print This rather boring function has no redirection.
|
||||
|
||||
(x=43
|
||||
x=$(print This should appear, really >&2; print Not used) exec >test.log
|
||||
print x=$x)
|
||||
cat test.log
|
||||
0:Assignment with exec used for redirection: no POSIX_BUILTINS
|
||||
>x=43
|
||||
?This should appear, really
|
||||
|
||||
(setopt POSIX_BUILTINS
|
||||
x=45
|
||||
x=$(print This should appear, too >&2; print And this) exec >test.log
|
||||
print x=$x)
|
||||
cat test.log
|
||||
0:Assignment with exec used for redirection: POSIX_BUILTINS
|
||||
>x=And this
|
||||
?This should appear, too
|
||||
|
||||
fn-two-heres() {
|
||||
# tabs below
|
||||
cat <<-x <<-y
|
||||
foo
|
||||
x
|
||||
bar
|
||||
y
|
||||
}
|
||||
which -x2 fn-two-heres
|
||||
fn-two-heres
|
||||
eval "$(which -x2 fn-two-heres)"
|
||||
fn-two-heres
|
||||
print $functions[fn-two-heres]
|
||||
0:Two here-documents in a line are shown correctly.
|
||||
>fn-two-heres () {
|
||||
> cat <<x <<y
|
||||
>foo
|
||||
>x
|
||||
>bar
|
||||
>y
|
||||
>}
|
||||
>foo
|
||||
>bar
|
||||
>foo
|
||||
>bar
|
||||
> cat <<x <<y
|
||||
>foo
|
||||
>x
|
||||
>bar
|
||||
>y
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
%prep
|
||||
|
||||
storepath=($path)
|
||||
|
||||
mkdir command.tmp command.tmp/dir1 command.tmp/dir2
|
||||
|
||||
cd command.tmp
|
||||
|
||||
print '#!/bin/sh\necho This is top' >tstcmd
|
||||
|
||||
print '#!/bin/sh\necho This is dir1' >dir1/tstcmd
|
||||
|
||||
print '#!/bin/sh\necho This is dir2' >dir2/tstcmd
|
||||
|
||||
chmod 755 tstcmd dir1/tstcmd dir2/tstcmd
|
||||
|
||||
%test
|
||||
./tstcmd
|
||||
0:./prog execution
|
||||
>This is top
|
||||
|
||||
path=($ZTST_testdir/command.tmp/dir1
|
||||
$ZTST_testdir/command.tmp/dir2
|
||||
.)
|
||||
tstcmd
|
||||
path=($storepath)
|
||||
0:path (1)
|
||||
>This is dir1
|
||||
|
||||
path=(. command.tmp/dir{1,2})
|
||||
tstcmd
|
||||
path=($storepath)
|
||||
0:path (2)
|
||||
>This is top
|
||||
|
||||
functst() { print $# arguments:; print -l $*; }
|
||||
functst "Eines Morgens" "als Gregor Samsa"
|
||||
functst ""
|
||||
functst "aus unrühigen Träumen erwachte"
|
||||
foo="fand er sich in seinem Bett"
|
||||
bar=
|
||||
rod="zu einem ungeheuren Ungeziefer verwandelt."
|
||||
functst $foo $bar $rod
|
||||
# set up alias for next test
|
||||
alias foo='print This is alias one'
|
||||
0:function argument passing
|
||||
>2 arguments:
|
||||
>Eines Morgens
|
||||
>als Gregor Samsa
|
||||
>1 arguments:
|
||||
>
|
||||
>1 arguments:
|
||||
>aus unrühigen Träumen erwachte
|
||||
>2 arguments:
|
||||
>fand er sich in seinem Bett
|
||||
>zu einem ungeheuren Ungeziefer verwandelt.
|
||||
|
||||
alias foo='print This is alias two'
|
||||
fn() { foo; }
|
||||
fn
|
||||
0:Aliases in functions
|
||||
>This is alias one
|
||||
|
||||
foo='Global foo'
|
||||
traptst() { local foo="Local foo"; trap 'print $foo' EXIT; }
|
||||
traptst
|
||||
0:EXIT trap environment
|
||||
>Global foo
|
||||
|
||||
functst() { return 0; print Ha ha; return 1; }
|
||||
functst
|
||||
0:return (1)
|
||||
|
||||
functst() { return 1; print Ho ho; return 0; }
|
||||
functst
|
||||
1:return (2)
|
||||
|
||||
unfunction functst
|
||||
fpath=(.)
|
||||
print "print This is functst." >functst
|
||||
autoload functst
|
||||
functst
|
||||
0:autoloading (1)
|
||||
>This is functst.
|
||||
|
||||
unfunction functst
|
||||
print "functst() { print This, too, is functst; }; print Hello." >functst
|
||||
typeset -fu functst
|
||||
functst
|
||||
functst
|
||||
0:autoloading with initialization
|
||||
>Hello.
|
||||
>This, too, is functst
|
||||
|
||||
unfunction functst
|
||||
print "print Yet another version" >functst
|
||||
functst() { autoload -X; }
|
||||
functst
|
||||
0:autoloading via -X
|
||||
>Yet another version
|
||||
|
||||
chpwd() { print Changed to $PWD; }
|
||||
cd .
|
||||
unfunction chpwd
|
||||
0q:chpwd
|
||||
>Changed to $ZTST_testdir/command.tmp
|
||||
|
||||
chpwd() { print chpwd: changed to $PWD; }
|
||||
chpwdfn1() { print chpwdfn1: changed to $PWD; }
|
||||
chpwdfn2() { print chpwdfn2: changed to $PWD; }
|
||||
chpwd_functions=(chpwdfn1 '' chpwdnonexistentfn chpwdfn2)
|
||||
cd .
|
||||
unfunction chpwd
|
||||
unset chpwd_functions
|
||||
0q:chpwd_functions
|
||||
>chpwd: changed to $ZTST_testdir/command.tmp
|
||||
>chpwdfn1: changed to $ZTST_testdir/command.tmp
|
||||
>chpwdfn2: changed to $ZTST_testdir/command.tmp
|
||||
|
||||
# Hard to test periodic, precmd and preexec non-interactively.
|
||||
|
||||
fn() { TRAPEXIT() { print Exit; }; }
|
||||
fn
|
||||
0:TRAPEXIT
|
||||
>Exit
|
||||
|
||||
unsetopt DEBUG_BEFORE_CMD
|
||||
unfunction fn
|
||||
print 'TRAPDEBUG() {
|
||||
print Line $LINENO
|
||||
}
|
||||
:
|
||||
unfunction TRAPDEBUG
|
||||
' > fn
|
||||
autoload fn
|
||||
fn
|
||||
rm fn
|
||||
0:TRAPDEBUG
|
||||
>Line 1
|
||||
>Line 1
|
||||
|
||||
unsetopt DEBUG_BEFORE_CMD
|
||||
unfunction fn
|
||||
print 'trap '\''print Line $LINENO'\'' DEBUG
|
||||
:
|
||||
trap - DEBUG
|
||||
' > fn
|
||||
autoload fn
|
||||
fn
|
||||
rm fn
|
||||
0:trap DEBUG
|
||||
>Line 1
|
||||
>Line 2
|
||||
|
||||
TRAPZERR() { print Command failed; }
|
||||
true
|
||||
false
|
||||
true
|
||||
false
|
||||
unfunction TRAPZERR
|
||||
0:TRAPZERR
|
||||
>Command failed
|
||||
>Command failed
|
||||
|
||||
trap 'print Command failed again.' ZERR
|
||||
true
|
||||
false
|
||||
true
|
||||
false
|
||||
trap - ZERR
|
||||
0:trap ZERR
|
||||
>Command failed again.
|
||||
>Command failed again.
|
||||
|
||||
false
|
||||
sleep 1000 &
|
||||
print $?
|
||||
kill $!
|
||||
0:Status reset by starting a backgrounded command
|
||||
>0
|
||||
|
||||
{ setopt MONITOR } 2>/dev/null
|
||||
[[ -o MONITOR ]] || print -u $ZTST_fd 'Unable to change MONITOR option'
|
||||
repeat 2048; do (return 2 |
|
||||
return 1 |
|
||||
while true; do
|
||||
false
|
||||
break
|
||||
done;
|
||||
print "${pipestatus[@]}")
|
||||
ZTST_hashmark
|
||||
done | sort | uniq -c | sed 's/^ *//'
|
||||
0:Check whether '$pipestatus[]' behaves.
|
||||
>2048 2 1 0
|
||||
F:This test checks for a bug in '$pipestatus[]' handling. If it breaks then
|
||||
F:the bug is still there or it reappeared. See workers-29973 for details.
|
||||
|
||||
{ setopt MONITOR } 2>/dev/null
|
||||
externFunc() { awk >/dev/null 2>&1; true; }
|
||||
false | true | false | true | externFunc
|
||||
echo $pipestatus
|
||||
0:Check $pipestatus with a known difficult case
|
||||
>1 0 1 0 0
|
||||
F:This similar test was triggering a reproducible failure with pipestatus.
|
||||
|
||||
{ unsetopt MONITOR } 2>/dev/null
|
||||
coproc { read -et 5 || { print -u $ZTST_fd KILLED; kill -HUP -$$ } }
|
||||
print -u $ZTST_fd 'This test takes 5 seconds to fail...'
|
||||
{ printf "%d\n" {1..20000} } 2>/dev/null | ( read -e )
|
||||
hang(){ printf "%d\n" {2..20000} | cat }; hang 2>/dev/null | ( read -e )
|
||||
print -p done
|
||||
read -et 6 -p
|
||||
0:Bug regression: piping a shell construct to an external process may hang
|
||||
>1
|
||||
>2
|
||||
>done
|
||||
F:This test checks for a file descriptor leak that could cause the left
|
||||
F:side of a pipe to block on write after the right side has exited
|
||||
|
||||
{ setopt MONITOR } 2>/dev/null
|
||||
if [[ -o MONITOR ]]
|
||||
then
|
||||
( while :; do print "This is a line"; done ) | () : &
|
||||
sleep 1
|
||||
jobs -l
|
||||
else
|
||||
print -u $ZTST_fd "Skipping pipe leak test, requires MONITOR option"
|
||||
print "[0] 0 0"
|
||||
fi
|
||||
0:Bug regression: piping to anonymous function; piping to backround function
|
||||
*>\[<->\] <-> <->
|
||||
F:This test checks for two different bugs, a parser segfault piping to an
|
||||
F:anonymous function, and a descriptor leak when backgrounding a pipeline
|
||||
|
||||
print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir
|
||||
autoload -Uk autoload_redir
|
||||
autoload_redir
|
||||
print No output yet
|
||||
cat autoload.log
|
||||
functions autoload_redir
|
||||
0:
|
||||
>No output yet
|
||||
>Autoloaded ksh style
|
||||
>autoload_redir () {
|
||||
> print Autoloaded ksh style
|
||||
>} > autoload.log
|
||||
|
||||
# This tests that we record the status of processes that have already exited
|
||||
# for when we wait for them.
|
||||
#
|
||||
# Actually, we don't guarantee here that the jobs have already exited, but
|
||||
# the order of the waits means it's highly likely we do need to recall a
|
||||
# previous status, barring accidents which shouldn't happen very often. In
|
||||
# other words, we rely on the test working repeatedly rather than just
|
||||
# once. The monitor option is irrelevant to the logic, so we'll make
|
||||
# our job easier by turning it off.
|
||||
{ unsetopt MONITOR } 2>/dev/null
|
||||
(exit 1) &
|
||||
one=$!
|
||||
(exit 2) &
|
||||
two=$!
|
||||
(exit 3) &
|
||||
three=$!
|
||||
wait $three
|
||||
print $?
|
||||
wait $two
|
||||
print $?
|
||||
wait $one
|
||||
print $?
|
||||
0:The status of recently exited background jobs is recorded
|
||||
>3
|
||||
>2
|
||||
>1
|
||||
|
||||
# Regression test for workers/34060 (patch in 34065)
|
||||
setopt ERR_EXIT NULL_GLOB
|
||||
if false; then :; else echo if:$?; fi
|
||||
if false; then :; else for x in _*_; do :; done; echo for:$?; fi
|
||||
0:False "if" condition handled correctly by "for" loops with ERR_EXIT
|
||||
>if:1
|
||||
>for:0
|
||||
|
||||
# Regression test for workers/34065 (uses setopt from preceding test)
|
||||
select x; do :; done; echo $?
|
||||
select x in; do :; done; echo $?
|
||||
select x in _*_; do :; done; echo $?
|
||||
unsetopt ERR_EXIT NULL_GLOB
|
||||
0:The status of "select" is zero when the loop body does not execute
|
||||
>0
|
||||
>0
|
||||
>0
|
||||
|
||||
# Regression test for workers/36392
|
||||
print -u $ZTST_fd 'This test takes 3 seconds and hangs the shell when it fails...'
|
||||
callfromchld() { true && { print CHLD } }
|
||||
TRAPCHLD() { callfromchld }
|
||||
sleep 2 & sleep 3; print OK
|
||||
0:Background job exit does not affect reaping foreground job
|
||||
>CHLD
|
||||
>OK
|
||||
|
||||
# Regression test for workers/39839 and workers/39844
|
||||
() { if return 11; then :; fi }; echo $?
|
||||
() { while return 13; do :; done }; echo $?
|
||||
() { until return 17; do :; done }; echo $?
|
||||
() { until false; do return 19; done }; echo $?
|
||||
0:"return" in "if" or "while" conditional
|
||||
>11
|
||||
>13
|
||||
>17
|
||||
>19
|
||||
|
||||
|
|
@ -1,631 +0,0 @@
|
|||
# Tests of parameter assignments
|
||||
|
||||
%prep
|
||||
mkdir assign.tmp && cd assign.tmp
|
||||
|
||||
touch tmpfile1 tmpfile2
|
||||
|
||||
%test
|
||||
|
||||
typeset -A assoc
|
||||
assoc=(one 1 two 2 odd)
|
||||
1:assign to association with odd no. of values
|
||||
?(eval):2: bad set of key/value pairs for associative array
|
||||
|
||||
# tests of array element assignment
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1]=42
|
||||
print $array
|
||||
0:Replacement of array element
|
||||
>42 2 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1]=(42 43)
|
||||
print $array
|
||||
0:Replacement of array element with array
|
||||
>42 43 2 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1,2]=(42 43)
|
||||
print $array
|
||||
0:Replacement of start of array
|
||||
>42 43 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1,4]=(42 43)
|
||||
print $array
|
||||
0:Replacement of start of array with shorter slice
|
||||
>42 43 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1,6]=(42 43)
|
||||
print $array
|
||||
0:Replacement of array by extending slice
|
||||
>42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[3]=(42 43)
|
||||
print $array
|
||||
0:Replacement of middle element with array
|
||||
>1 2 42 43 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[3,4]=(42 43 44)
|
||||
print $array
|
||||
0:Replacement of slice in middle
|
||||
>1 2 42 43 44 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[7,8]=(42 43)
|
||||
print $array
|
||||
# check that [6] was left empty...
|
||||
array[6]=41
|
||||
print $array
|
||||
0:Appending by replacing elements off the end
|
||||
>1 2 3 4 5 42 43
|
||||
>1 2 3 4 5 41 42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-1]=42
|
||||
print $array
|
||||
0:Replacement of last element of array, negative indices
|
||||
>1 2 3 4 42
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-1]=(42 43)
|
||||
print $array
|
||||
0:Replacement of last element of array with array, negative indices
|
||||
>1 2 3 4 42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-3,-2]=(42 43 44)
|
||||
print $array
|
||||
0:Replacement of middle of array, negative indices
|
||||
>1 2 42 43 44 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-5,-1]=(42 43)
|
||||
print $array
|
||||
0:Replacement of entire array, negative indices
|
||||
>42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-7,-1]=(42 43)
|
||||
print $array
|
||||
0:Replacement of more than entire array, negative indices
|
||||
>42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-7]=42
|
||||
print $array
|
||||
0:Replacement of element off start of array.
|
||||
>42 1 2 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-7]=42
|
||||
array[-6]=43
|
||||
print $array
|
||||
0:Replacement off start doesn't leave gaps. Hope this is right.
|
||||
>43 1 2 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[1,-1]=(42 43)
|
||||
print $array
|
||||
array[-3,3]=(1 2 3 4 5)
|
||||
print $array
|
||||
0:Replacement of entire array, mixed indices
|
||||
>42 43
|
||||
>1 2 3 4 5
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[-7,7]=(42 43)
|
||||
print $array
|
||||
0:Replacement of more than entire array, mixed indices
|
||||
>42 43
|
||||
|
||||
array=(1 2 3 4 5)
|
||||
array[3,-2]=(42 43 44)
|
||||
print $array
|
||||
array[-3,5]=(100 99)
|
||||
print $array
|
||||
0:Replacement of slice in middle, mixed indices
|
||||
>1 2 42 43 44 5
|
||||
>1 2 42 100 99 5
|
||||
|
||||
# tests of var+=scalar
|
||||
|
||||
s+=foo
|
||||
echo $s
|
||||
0:append scalar to unset scalar
|
||||
>foo
|
||||
|
||||
s=foo
|
||||
s+=bar
|
||||
echo $s
|
||||
0:append to scalar
|
||||
>foobar
|
||||
|
||||
set -- a b c
|
||||
2+=end
|
||||
echo $2
|
||||
0:append to positional parameter
|
||||
>bend
|
||||
|
||||
a=(first second)
|
||||
a+=last
|
||||
print -l $a
|
||||
0:add scalar to array
|
||||
>first
|
||||
>second
|
||||
>last
|
||||
|
||||
setopt ksharrays
|
||||
a=(first second)
|
||||
a+=last
|
||||
print -l $a
|
||||
unsetopt ksharrays
|
||||
0:add scalar to array with ksharrays set
|
||||
>firstlast
|
||||
|
||||
a=(1 2)
|
||||
a[@]+=3
|
||||
print -l $a
|
||||
0:add scalar to array with alternate syntax
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
|
||||
integer i=10
|
||||
i+=20
|
||||
(( i == 30 ))
|
||||
0:add to integer
|
||||
|
||||
float f=3.4
|
||||
f+=2.3
|
||||
printf "%g\n" f
|
||||
0:add to float
|
||||
>5.7
|
||||
|
||||
typeset -A hash
|
||||
hash=(one 1)
|
||||
hash+=string
|
||||
[[ $hash[@] == string ]]
|
||||
0:add scalar to association
|
||||
|
||||
# tests of var+=(array)
|
||||
|
||||
unset a
|
||||
a+=(1 2 3)
|
||||
print -l $a
|
||||
0:add array to unset parameter
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
|
||||
a=(a)
|
||||
a+=(b)
|
||||
print -l $a
|
||||
0:add array to existing array
|
||||
>a
|
||||
>b
|
||||
|
||||
s=foo
|
||||
s+=(bar)
|
||||
print -l $s
|
||||
0:add array to scalar
|
||||
>foo
|
||||
>bar
|
||||
|
||||
integer i=1
|
||||
i+=(2 3)
|
||||
print -l $i
|
||||
0:add array to integer
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
|
||||
float f=2.5
|
||||
f+=(3.5 4.5)
|
||||
printf '%g\n' $f
|
||||
0:add array to float
|
||||
>2.5
|
||||
>3.5
|
||||
>4.5
|
||||
|
||||
typeset -A h
|
||||
h+=(a 1 b 2)
|
||||
print -l $h
|
||||
0:add to empty association
|
||||
>1
|
||||
>2
|
||||
|
||||
typeset -A h
|
||||
h=(a 1)
|
||||
h+=(b 2 c 3)
|
||||
print -l $h
|
||||
0:add to association
|
||||
>1
|
||||
>2
|
||||
>3
|
||||
|
||||
typeset -A h
|
||||
h=(a 1 b 2)
|
||||
h+=()
|
||||
print -l $h
|
||||
0:add empty array to association
|
||||
>1
|
||||
>2
|
||||
|
||||
# tests of var[range]+=scalar
|
||||
|
||||
s=sting
|
||||
s[2]+=art
|
||||
echo $s
|
||||
0:insert scalar inside another
|
||||
>starting
|
||||
|
||||
s=inert
|
||||
s[-4]+=s
|
||||
echo $s
|
||||
0:insert scalar inside another with negative index
|
||||
>insert
|
||||
|
||||
s=append
|
||||
s[2,6]+=age
|
||||
echo $s
|
||||
0:append scalar to scalar using a range
|
||||
>appendage
|
||||
|
||||
s=123456789
|
||||
s[3,-5]+=X
|
||||
echo $s
|
||||
0:insert scalar inside another, specifying a slice
|
||||
>12345X6789
|
||||
|
||||
a=(a b c)
|
||||
a[2]+=oo
|
||||
echo $a
|
||||
0:append to array element
|
||||
>a boo c
|
||||
|
||||
a=(a b c d)
|
||||
a[-2]+=ool
|
||||
echo $a
|
||||
0:append to array element with negative index
|
||||
>a b cool d
|
||||
|
||||
a=(a b c d)
|
||||
a[2,-1]+=oom
|
||||
echo $a
|
||||
0:append to array element, specifying a slice
|
||||
>a b c doom
|
||||
|
||||
setopt ksharrays
|
||||
a=(a b c d)
|
||||
a[0]+=0
|
||||
echo $a
|
||||
unsetopt ksharrays
|
||||
0:append to array element with ksharrays set
|
||||
>a0
|
||||
|
||||
typeset -A h
|
||||
h=(one foo)
|
||||
h[one]+=bar
|
||||
echo $h
|
||||
0:append to association element
|
||||
>foobar
|
||||
|
||||
typeset -A h
|
||||
h[foo]+=bar
|
||||
echo ${(kv)h}
|
||||
0:append to non-existent association element
|
||||
>foo bar
|
||||
|
||||
typeset -A h
|
||||
h=(one a two b three c four d)
|
||||
h[(I)*o*]+=append
|
||||
1:attempt to append to slice of association
|
||||
?(eval):3: h: attempt to set slice of associative array
|
||||
|
||||
integer i=123
|
||||
i[2]+=6
|
||||
1:attempt to add to indexed integer variable
|
||||
?(eval):2: attempt to add to slice of a numeric variable
|
||||
|
||||
float f=1234.5
|
||||
f[2,4]+=3
|
||||
1:attempt to add to slice of float variable
|
||||
?(eval):2: attempt to add to slice of a numeric variable
|
||||
|
||||
unset u
|
||||
u[3]+=third
|
||||
echo $u[1]:$u[3]
|
||||
0:append to unset variable with index
|
||||
>:third
|
||||
|
||||
# tests of var[range]+=(array)
|
||||
|
||||
a=(1 2 3)
|
||||
a[2]+=(a b)
|
||||
echo $a
|
||||
0:insert array inside another
|
||||
>1 2 a b 3
|
||||
|
||||
a=(a b c)
|
||||
a[-1]+=(d)
|
||||
echo $a
|
||||
0:append to array using negative index
|
||||
>a b c d
|
||||
|
||||
a=(1 2 3 4)
|
||||
a[-1,-3]+=(x)
|
||||
echo $a
|
||||
0:insert array using negative range
|
||||
>1 2 x 3 4
|
||||
|
||||
s=string
|
||||
s[2]+=(a b)
|
||||
1:attempt to insert array into string
|
||||
?(eval):2: s: attempt to assign array value to non-array
|
||||
|
||||
integer i=365
|
||||
i[2]+=(1 2)
|
||||
1:attempt to insert array into string
|
||||
?(eval):2: i: attempt to assign array value to non-array
|
||||
|
||||
typeset -A h
|
||||
h=(a 1)
|
||||
h[a]+=(b 2)
|
||||
1:attempt to append array to hash element
|
||||
?(eval):3: h: attempt to set slice of associative array
|
||||
|
||||
unset u
|
||||
u[-34,-2]+=(a z)
|
||||
echo $u
|
||||
0:add array to indexed unset variable
|
||||
>a z
|
||||
|
||||
repeat 10 PATH=. echo hello
|
||||
0:saving and restoring of exported special parameters
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
>hello
|
||||
|
||||
repeat 10 FOO=BAR BAR=FOO echo $FOO $BAR
|
||||
0:save and restore multiple variables around builtin
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
|
||||
call() { print $HELLO; }
|
||||
export HELLO=world
|
||||
call
|
||||
HELLO=universe call
|
||||
call
|
||||
HELLO=${HELLO}liness call
|
||||
call
|
||||
unset HELLO
|
||||
0:save and restore when using original value in temporary
|
||||
>world
|
||||
>universe
|
||||
>world
|
||||
>worldliness
|
||||
>world
|
||||
|
||||
(integer i n x
|
||||
float f
|
||||
setopt globassign
|
||||
i=tmpfile1
|
||||
n=tmpf*
|
||||
x=*2
|
||||
f=2+2
|
||||
typeset -p i n x f)
|
||||
0:GLOB_ASSIGN with numeric types
|
||||
>typeset -i i=0
|
||||
>typeset -a n=( tmpfile1 tmpfile2 )
|
||||
>typeset x=tmpfile2
|
||||
>typeset -E f=4.000000000e+00
|
||||
|
||||
setopt globassign
|
||||
foo=tmpf*
|
||||
print $foo
|
||||
unsetopt globassign
|
||||
foo=tmpf*
|
||||
print $foo
|
||||
0:GLOB_ASSIGN option
|
||||
>tmpfile1 tmpfile2
|
||||
>tmpf*
|
||||
|
||||
(setopt globassign
|
||||
typeset -A foo
|
||||
touch gatest1 gatest2
|
||||
foo=(gatest*)
|
||||
print ${(t)foo}
|
||||
rm -rf gatest*)
|
||||
0:GLOB_ASSIGN doesn't monkey with type if not scalar assignment.
|
||||
>association-local
|
||||
|
||||
A=(first second)
|
||||
A="${A[*]}" /bin/sh -c 'echo $A'
|
||||
print -l "${A[@]}"
|
||||
0:command execution with assignments shadowing array parameter
|
||||
>first second
|
||||
>first
|
||||
>second
|
||||
|
||||
setopt ksharrays
|
||||
A=(first second)
|
||||
A="${A[*]}" /bin/sh -c 'echo $A'
|
||||
print -l "${A[@]}"
|
||||
unsetopt ksharrays
|
||||
0:command execution with assignments shadowing array parameter with ksharrays
|
||||
>first second
|
||||
>first
|
||||
>second
|
||||
|
||||
typeset -aU unique_array=(first second)
|
||||
unique_array[1]=second
|
||||
print $unique_array
|
||||
0:assignment to unique array
|
||||
>second
|
||||
|
||||
typeset -a array=(first)
|
||||
array[1,3]=(FIRST)
|
||||
print $array
|
||||
0:slice beyond length of array
|
||||
>FIRST
|
||||
|
||||
# tests of string assignments
|
||||
|
||||
a="abc"
|
||||
a[1]=x
|
||||
print $a
|
||||
0:overwrite first character in string
|
||||
>xbc
|
||||
|
||||
a="abc"
|
||||
a[2]="x"
|
||||
print $a
|
||||
0:overwrite middle character in string
|
||||
>axc
|
||||
|
||||
a="abc"
|
||||
a[3]="x"
|
||||
print $a
|
||||
0:overwrite last character in string
|
||||
>abx
|
||||
|
||||
a="abc"
|
||||
a[-1]="x"
|
||||
print $a
|
||||
0:overwrite -1 character in string
|
||||
>abx
|
||||
|
||||
a="abc"
|
||||
a[-2]="x"
|
||||
print $a
|
||||
0:overwrite -2 character (middle) in string
|
||||
>axc
|
||||
|
||||
a="ab"
|
||||
a[-2]="x"
|
||||
print $a
|
||||
0:overwrite -2 character (first) in string
|
||||
>xb
|
||||
|
||||
a="abc"
|
||||
a[-3]="x"
|
||||
print $a
|
||||
0:overwrite -3 character (first) in string
|
||||
>xbc
|
||||
|
||||
a="abc"
|
||||
a[-4]="x"
|
||||
print $a
|
||||
0:overwrite -4 character (before first) in string
|
||||
>xabc
|
||||
|
||||
a="abc"
|
||||
a[-5]="x"
|
||||
print $a
|
||||
0:overwrite -5 character (before-before first) in string
|
||||
>xabc
|
||||
|
||||
a="abc"
|
||||
a[-4,0]="x"
|
||||
print $a
|
||||
0:overwrite [-4,0] characters (before first) in string
|
||||
>xabc
|
||||
|
||||
a="abc"
|
||||
a[-4,-4]="x"
|
||||
print $a
|
||||
0:overwrite [-4,-4] character (before first) in string
|
||||
>xabc
|
||||
|
||||
a="abc"
|
||||
a[-40,-30]="x"
|
||||
print $a
|
||||
0:overwrite [-40,-30] characters (far before first) in string
|
||||
>xabc
|
||||
|
||||
a="abc"
|
||||
a[-40,1]="x"
|
||||
print $a
|
||||
0:overwrite [-40,1] characters in short string
|
||||
>xbc
|
||||
|
||||
a="abc"
|
||||
a[-40,40]="x"
|
||||
print $a
|
||||
0:overwrite [-40,40] characters in short string
|
||||
>x
|
||||
|
||||
a="abc"
|
||||
a[2,40]="x"
|
||||
print $a
|
||||
0:overwrite [2,40] characters in short string
|
||||
>ax
|
||||
|
||||
a="abc"
|
||||
a[2,-1]="x"
|
||||
print $a
|
||||
0:overwrite [2,-1] characters in short string
|
||||
>ax
|
||||
|
||||
a="abc"
|
||||
a[-2,-1]="x"
|
||||
print $a
|
||||
0:overwrite [-2,-1] characters in short string
|
||||
>ax
|
||||
|
||||
a="a"
|
||||
a[-1]="xx"
|
||||
print $a
|
||||
0:overwrite [-1] character with "xx"
|
||||
>xx
|
||||
|
||||
a="a"
|
||||
a[-2]="xx"
|
||||
print $a
|
||||
0:overwrite [-2] character (before first) with "xx"
|
||||
>xxa
|
||||
|
||||
a="a"
|
||||
a[2]="xx"
|
||||
print $a
|
||||
0:overwrite [2] character (after last) with "xx"
|
||||
>axx
|
||||
|
||||
a=""
|
||||
a[1]="xx"
|
||||
print $a
|
||||
0:overwrite [1] character (string: "") with "xx"
|
||||
>xx
|
||||
|
||||
a=""
|
||||
a[-1]="xx"
|
||||
print $a
|
||||
0:overwrite [-1] character (string: "") with "xx"
|
||||
>xx
|
||||
|
||||
a=""
|
||||
a[2]="xx"
|
||||
print $a
|
||||
0:overwrite [2] character (string: "") with "xx"
|
||||
>xx
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
# Test control commands for loops and functions.
|
||||
|
||||
%test
|
||||
|
||||
fn3() { return $1; print Error }
|
||||
fn2() { fn3 $1 }
|
||||
fn() {
|
||||
print start $1
|
||||
fn2 $1
|
||||
return
|
||||
print Error
|
||||
}
|
||||
for val in -1 0 1 255; do
|
||||
fn $val; print $?
|
||||
done
|
||||
0:Passing of return values back through functions
|
||||
>start -1
|
||||
>-1
|
||||
>start 0
|
||||
>0
|
||||
>start 1
|
||||
>1
|
||||
>start 255
|
||||
>255
|
||||
|
||||
$ZTST_testdir/../Src/zsh -fc 'fn() {
|
||||
continue
|
||||
}
|
||||
fn'
|
||||
1:continue outside loop
|
||||
?fn:continue:1: not in while, until, select, or repeat loop
|
||||
|
||||
for outer in 0 1 2 3; do
|
||||
print outer $outer
|
||||
for inner in 0 1 2 3; do
|
||||
print inner $inner
|
||||
continue $(( (outer & 1) ? 2 : 1 ))
|
||||
print error
|
||||
done
|
||||
print outer end
|
||||
done
|
||||
0:continue with valid argument
|
||||
>outer 0
|
||||
>inner 0
|
||||
>inner 1
|
||||
>inner 2
|
||||
>inner 3
|
||||
>outer end
|
||||
>outer 1
|
||||
>inner 0
|
||||
>outer 2
|
||||
>inner 0
|
||||
>inner 1
|
||||
>inner 2
|
||||
>inner 3
|
||||
>outer end
|
||||
>outer 3
|
||||
>inner 0
|
||||
|
||||
for outer in 0 1; do
|
||||
continue 0
|
||||
print -- $outer got here, status $?
|
||||
done
|
||||
1:continue error case 0
|
||||
?(eval):continue:2: argument is not positive: 0
|
||||
|
||||
for outer in 0 1; do
|
||||
continue -1
|
||||
print -- $outer got here, status $?
|
||||
done
|
||||
1:continue error case -1
|
||||
?(eval):continue:2: argument is not positive: -1
|
||||
|
||||
fn() {
|
||||
break
|
||||
}
|
||||
for outer in 0 1; do
|
||||
print $outer
|
||||
fn
|
||||
done
|
||||
0:break from within function (this is a feature, I disovered)
|
||||
>0
|
||||
|
||||
for outer in 0 1 2 3; do
|
||||
print outer $outer
|
||||
for inner in 0 1 2 3; do
|
||||
print inner $inner
|
||||
break $(( (outer & 1) ? 2 : 1 ))
|
||||
print error
|
||||
done
|
||||
print outer end
|
||||
done
|
||||
0:break with valid argument
|
||||
>outer 0
|
||||
>inner 0
|
||||
>outer end
|
||||
>outer 1
|
||||
>inner 0
|
||||
|
||||
for outer in 0 1; do
|
||||
break 0
|
||||
print -- $outer got here, status $?
|
||||
done
|
||||
1:break error case 0
|
||||
?(eval):break:2: argument is not positive: 0
|
||||
|
||||
for outer in 0 1; do
|
||||
break -1
|
||||
print -- $outer got here, status $?
|
||||
done
|
||||
1:break error case -1
|
||||
?(eval):break:2: argument is not positive: -1
|
||||
|
||||
false
|
||||
for x in; do
|
||||
print nothing executed
|
||||
done
|
||||
0:Status 0 from for with explicit empty list
|
||||
|
||||
set --
|
||||
false
|
||||
for x; do
|
||||
print nothing executed
|
||||
done
|
||||
0:Status 0 from for with implicit empty list
|
||||
|
||||
(exit 2)
|
||||
for x in 1 2; do
|
||||
print $?
|
||||
done
|
||||
0:Status from previous command propagated into for loop
|
||||
>2
|
||||
>0
|
||||
|
||||
false
|
||||
for x in $(echo 1 2; (exit 3)); do
|
||||
print $?
|
||||
done
|
||||
0:Status from expansion propagated into for loop
|
||||
>3
|
||||
>0
|
||||
|
||||
false
|
||||
for x in $(exit 4); do
|
||||
print not executed
|
||||
done
|
||||
0:Status from expansion not propagated after unexecuted for loop
|
||||
|
||||
false
|
||||
for x in NonExistentFilePrefix*(N); do
|
||||
print not executed, either
|
||||
done
|
||||
0:Status from before for loop not propagated if empty after expansion
|
||||
|
||||
for x in $(echo 1; false); do
|
||||
done
|
||||
0:Status reset by empty list in for loop
|
||||
|
||||
false
|
||||
for x in $(echo 1; false); do
|
||||
echo $?
|
||||
(exit 4)
|
||||
done
|
||||
4:Last status from loop body is kept even with other funny business going on
|
||||
>1
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
# This file serves as a model for how to write tests, so is more heavily
|
||||
# commented than the others. All tests are run in the Test subdirectory
|
||||
# of the distribution, which must be writable. They should end with
|
||||
# the suffix `.ztst': this is not required by the test harness itself,
|
||||
# but it is needed by the Makefile to run all the tests.
|
||||
|
||||
# Blank lines with no other special meaning (e.g. separating chunks of
|
||||
# code) and all those with a `#' in the first column are ignored.
|
||||
|
||||
# All section names start with a % in the first column. The names
|
||||
# must be in the expected order, though not all sections are required.
|
||||
# The sections are %prep (preparatory setup: code executed should return
|
||||
# status 0, but no other tests are performed), %test (the main tests), and
|
||||
# %clean (to cleanup: the code is simply unconditionally executed).
|
||||
#
|
||||
# Literal shell code to be evaluated must be indented with any number
|
||||
# of spaces and/or tabs, to differentiate it from tags with a special
|
||||
# meaning to the test harness. Note that this is true even in sections
|
||||
# where there are no such tags. Also note that file descriptor 9
|
||||
# is reserved for input from the test script, and file descriptor 8
|
||||
# preserves the original stdout. Option settings are preserved between the
|
||||
# execution of different code chunks; initially, all standard zsh options
|
||||
# (the effect of `emulate -R zsh') are set.
|
||||
|
||||
%prep
|
||||
# This optional section prepares the test, creating directories and files
|
||||
# and so on. Chunks of code are separated by blank lines (which is not
|
||||
# necessary before the end of the section); each chunk of code is evaluated
|
||||
# in one go and must return status 0, or the preparation is deemed to have
|
||||
# failed and the test ends with an appropriate error message. Standard
|
||||
# output from this section is redirected to /dev/null, but standard error
|
||||
# is not redirected.
|
||||
#
|
||||
# Tests should use subdirectories ending in `.tmp'. These will be
|
||||
# removed with all the contents even if the test is aborted.
|
||||
mkdir cdtst.tmp cdtst.tmp/real cdtst.tmp/sub
|
||||
|
||||
ln -s ../real cdtst.tmp/sub/fake
|
||||
|
||||
setopt chaselinks
|
||||
cd .
|
||||
unsetopt chaselinks
|
||||
mydir=$PWD
|
||||
|
||||
%test
|
||||
# This is where the tests are run. It consists of blocks separated
|
||||
# by blank lines. Each block has the same format and there may be any
|
||||
# number of them. It consists of indented code, plus optional sets of lines
|
||||
# beginning '<', '>' and '?' which may appear in any order. These correspond
|
||||
# to stdin (fed to the code), stdout (compared with code output) and
|
||||
# stderr (compared with code error output) respectively. These subblocks
|
||||
# may occur in any order, but the natural one is: code, stdin, stdout,
|
||||
# stderr.
|
||||
#
|
||||
# The rules for '<', '>' and '?' lines are the same: only the first
|
||||
# character is stripped (with the excpetion for '*' noted below), with
|
||||
# subsequent whitespace being significant; lines are not subject to any
|
||||
# substitution unless the `q' flag (see below) is set.
|
||||
#
|
||||
# Each line of a '>' and '?' chunk may be preceded by a '*', so the line
|
||||
# starts '*>' or '*?'. This signifies that for any line with '*' in front
|
||||
# the actual output should be pattern matched against the corresponding
|
||||
# lines in the test output. Each line following '>' or '?' must be a
|
||||
# valid pattern, so characters special to patterns such as parentheses
|
||||
# must be quoted with a backslash. The EXTENDED_GLOB option is used for
|
||||
# all such patterns.
|
||||
#
|
||||
# Each chunk of indented code is to be evaluated in one go and is to
|
||||
# be followed by a line starting (in the first column) with
|
||||
# the expected status returned by the code when run, or - if it is
|
||||
# irrelevant. An optional set of single-letter flags follows the status
|
||||
# or -. The following are understood:
|
||||
# . d Don't diff stdout against the expected stdout.
|
||||
# D Don't diff stderr against the expected stderr.
|
||||
# q All redirection lines given in the test script (not the lines
|
||||
# actually produced by the test) are subject to ordinary quoted shell
|
||||
# expansion (i.e. not globbing).
|
||||
# This can be followed by a `:' and a message describing the
|
||||
# test, which will be printed if the test fails, along with a
|
||||
# description of the failure that occurred. The `:' and message are
|
||||
# optional, but highly recommended.
|
||||
# Hence a complete status line looks something like:
|
||||
# 0dDq:Checking whether the world will end with a bang or a whimper
|
||||
#
|
||||
# If either or both of the '>' and '?' sets of lines is absent, it is
|
||||
# assumed the corresponding output should be empty and it is an error if it
|
||||
# is not. If '<' is empty, stdin is an empty (but opened) file.
|
||||
#
|
||||
# It is also possible to add lines in the redirection section beginning
|
||||
# with `F:'. The remaining text on all such lines will be concatenated
|
||||
# (with newlines in between) and displayed in the event of an error.
|
||||
# This text is useful for explaining certain frequent errors, for example
|
||||
# ones which may arise from the environment rather than from the shell
|
||||
# itself. (The example below isn't particularly useful as errors with
|
||||
# `cd' are unusual.)
|
||||
#
|
||||
# A couple of features aren't used in this file, but are usefuil in cases
|
||||
# where features may not be available so should not be tested. They boh
|
||||
# take the form of variables. Note that to keep the test framework simple
|
||||
# there is no magic in setting the variables: the chunk of code being
|
||||
# executed needs to avoid executing any test code by appropriate structure
|
||||
# (typically "if"). In both cases, the value of the variable is output
|
||||
# as a warning that the test was skipped.
|
||||
# ZTST_unimplemented: Set this in the %prep phase if the entire test file
|
||||
# is to be skipped.
|
||||
# ZTST_skip: Set this in any test case if that single test case is to be
|
||||
# skipped. Testing resumes at the next test case in the same file.
|
||||
cd cdtst.tmp/sub/fake &&
|
||||
pwd &&
|
||||
print $PWD
|
||||
0q:Preserving symbolic links in the current directory string
|
||||
>$mydir/cdtst.tmp/sub/fake
|
||||
>$mydir/cdtst.tmp/sub/fake
|
||||
F:This test shouldn't really fail. The fact that it has indicates
|
||||
F:something is broken. But you already knew that.
|
||||
|
||||
cd ../../.. &&
|
||||
pwd &&
|
||||
print $PWD
|
||||
0q:Changing directory up through symbolic links without following them
|
||||
>$mydir
|
||||
>$mydir
|
||||
|
||||
setopt chaselinks
|
||||
cd cdtst.tmp/sub/fake &&
|
||||
pwd &&
|
||||
print $PWD
|
||||
0q:Resolving symbolic links with chaselinks set
|
||||
>$mydir/cdtst.tmp/real
|
||||
>$mydir/cdtst.tmp/real
|
||||
|
||||
ln -s nonexistent link_to_nonexistent
|
||||
pwd1=$(pwd -P)
|
||||
cd -s link_to_nonexistent
|
||||
pwd2=$(pwd -P)
|
||||
[[ $pwd1 = $pwd2 ]] || print "Ooops, changed to directory '$pwd2'"
|
||||
0:
|
||||
?(eval):cd:3: not a directory: link_to_nonexistent
|
||||
|
||||
%clean
|
||||
# This optional section cleans up after the test, if necessary,
|
||||
# e.g. killing processes etc. This is in addition to the removal of *.tmp
|
||||
# subdirectories. This is essentially like %prep, except that status
|
||||
# return values are ignored.
|
||||
|
|
@ -1,723 +0,0 @@
|
|||
# There are certain usages of typeset and its synonyms that it is not
|
||||
# possible to test here, because they must appear at the top level and
|
||||
# everything that follows is processed by an "eval" within a function.
|
||||
|
||||
# Equivalences:
|
||||
# declare typeset
|
||||
# export typeset -xg
|
||||
# float typeset -E
|
||||
# functions typeset -f
|
||||
# integer typeset -i
|
||||
# local typeset +g -m approximately
|
||||
# readonly typeset -r
|
||||
|
||||
# Tested elsewhere:
|
||||
# Equivalence of autoload and typeset -fu A05execution
|
||||
# Associative array creation & assignment D04parameter, D06subscript
|
||||
# Effects of GLOBAL_EXPORT E01options
|
||||
# Function tracing (typeset -ft) E02xtrace
|
||||
|
||||
# Not yet tested:
|
||||
# Assorted illegal flag combinations
|
||||
|
||||
%prep
|
||||
## Do not remove the next line, it's used by V10private.ztst
|
||||
# test_zsh_param_private
|
||||
|
||||
mkdir typeset.tmp && cd typeset.tmp
|
||||
|
||||
setopt noglob
|
||||
|
||||
scalar=scalar
|
||||
array=(a r r a y)
|
||||
|
||||
scope00() {
|
||||
typeset scalar
|
||||
scalar=local
|
||||
typeset -a array
|
||||
array=(l o c a l)
|
||||
print $scalar $array
|
||||
}
|
||||
scope01() {
|
||||
local scalar
|
||||
scalar=local
|
||||
local -a array
|
||||
array=(l o c a l)
|
||||
print $scalar $array
|
||||
}
|
||||
scope02() {
|
||||
declare scalar
|
||||
scalar=local
|
||||
declare -a array
|
||||
array=(l o c a l)
|
||||
print $scalar $array
|
||||
}
|
||||
scope10() {
|
||||
export outer=outer
|
||||
/bin/sh -fc 'echo $outer'
|
||||
}
|
||||
scope11() {
|
||||
typeset -x outer=outer
|
||||
/bin/sh -fc 'echo $outer'
|
||||
}
|
||||
scope12() {
|
||||
local -x outer=inner
|
||||
/bin/sh -fc 'echo $outer'
|
||||
}
|
||||
scope13() {
|
||||
local -xT OUTER outer
|
||||
outer=(i n n e r)
|
||||
/bin/sh -fc 'echo $OUTER'
|
||||
}
|
||||
|
||||
# Bug? `typeset -h' complains that ! # $ * - ? @ are not identifiers.
|
||||
stress00() {
|
||||
typeset -h +g -m [[:alpha:]_]*
|
||||
unset -m [[:alpha:]_]*
|
||||
typeset +m [[:alpha:]_]*
|
||||
}
|
||||
|
||||
%test
|
||||
|
||||
typeset +m scalar array
|
||||
0:Report types of parameters with typeset +m
|
||||
>scalar
|
||||
>array array
|
||||
|
||||
scope00
|
||||
print $scalar $array
|
||||
0:Simple local declarations
|
||||
>local l o c a l
|
||||
>scalar a r r a y
|
||||
|
||||
scope01
|
||||
print $scalar $array
|
||||
0:Equivalence of local and typeset in functions
|
||||
>local l o c a l
|
||||
>scalar a r r a y
|
||||
|
||||
scope02
|
||||
print $scalar $array
|
||||
0:Basic equivalence of declare and typeset
|
||||
>local l o c a l
|
||||
>scalar a r r a y
|
||||
|
||||
declare +m scalar
|
||||
0:declare previously lacked -m/+m options
|
||||
>scalar
|
||||
|
||||
scope10
|
||||
print $outer
|
||||
0:Global export
|
||||
>outer
|
||||
>outer
|
||||
|
||||
scope11
|
||||
print $outer
|
||||
0:Equivalence of export and typeset -x
|
||||
>outer
|
||||
>outer
|
||||
|
||||
scope12
|
||||
print $outer
|
||||
0:Local export
|
||||
>inner
|
||||
>outer
|
||||
|
||||
float f=3.14159
|
||||
typeset +m f
|
||||
float -E3 f
|
||||
print $f
|
||||
float -F f
|
||||
print $f
|
||||
0:Floating point, adding a precision, and fixed point
|
||||
>float local f
|
||||
>3.14e+00
|
||||
>3.142
|
||||
|
||||
integer i=3.141
|
||||
typeset +m i
|
||||
integer -i2 i
|
||||
print $i
|
||||
0:Integer and changing the base
|
||||
>integer local i
|
||||
>2#11
|
||||
|
||||
float -E3 f=3.141
|
||||
typeset +m f
|
||||
integer -i2 f
|
||||
typeset +m f
|
||||
print $f
|
||||
0:Conversion of floating point to integer
|
||||
>float local f
|
||||
>integer 2 local f
|
||||
>2#11
|
||||
|
||||
typeset -f
|
||||
0q:Equivalence of functions and typeset -f
|
||||
>$(functions)
|
||||
|
||||
readonly r=success
|
||||
print $r
|
||||
r=failure
|
||||
1:Readonly declaration
|
||||
>success
|
||||
?(eval):3: read-only variable: r
|
||||
|
||||
typeset r=success
|
||||
readonly r
|
||||
print $r
|
||||
r=failure
|
||||
1:Convert to readonly
|
||||
>success
|
||||
?(eval):4: read-only variable: r
|
||||
|
||||
typeset -gU array
|
||||
print $array
|
||||
0:Uniquified arrays and non-local scope
|
||||
>a r y
|
||||
|
||||
typeset -T SCALAR=l:o:c:a:l array
|
||||
print $array
|
||||
typeset -U SCALAR
|
||||
print $SCALAR $array
|
||||
0:Tied parameters and uniquified colon-arrays
|
||||
>l o c a l
|
||||
>l:o:c:a l o c a
|
||||
|
||||
(setopt NO_multibyte cbases
|
||||
LC_ALL=C 2>/dev/null
|
||||
typeset -T SCALAR=$'l\x83o\x83c\x83a\x83l' array $'\x83'
|
||||
print $array
|
||||
typeset -U SCALAR
|
||||
for (( i = 1; i <= ${#SCALAR}; i++ )); do
|
||||
char=$SCALAR[i]
|
||||
print $(( [#16] #char ))
|
||||
done
|
||||
print $array)
|
||||
0:Tied parameters and uniquified arrays with meta-character as separator
|
||||
>l o c a l
|
||||
>0x6C
|
||||
>0x83
|
||||
>0x6F
|
||||
>0x83
|
||||
>0x63
|
||||
>0x83
|
||||
>0x61
|
||||
>l o c a
|
||||
|
||||
typeset -T SCALAR=$'l\000o\000c\000a\000l' array $'\000'
|
||||
typeset -U SCALAR
|
||||
print $array
|
||||
[[ $SCALAR == $'l\000o\000c\000a' ]]
|
||||
0:Tied parameters and uniquified arrays with NUL-character as separator
|
||||
>l o c a
|
||||
|
||||
typeset -T SCALAR array
|
||||
typeset +T SCALAR
|
||||
1:Untying is prohibited
|
||||
?(eval):typeset:2: use unset to remove tied variables
|
||||
|
||||
OUTER=outer
|
||||
scope13
|
||||
print $OUTER
|
||||
0:Export of tied parameters
|
||||
>i:n:n:e:r
|
||||
>outer
|
||||
|
||||
typeset -TU MORESTUFF=here-we-go-go-again morestuff '-'
|
||||
print -l $morestuff
|
||||
0:Tied arrays with separator specified
|
||||
>here
|
||||
>we
|
||||
>go
|
||||
>again
|
||||
|
||||
typeset -T THIS will not work
|
||||
1:Tied array syntax
|
||||
?(eval):typeset:1: too many arguments for -T
|
||||
|
||||
local array[2]=x
|
||||
1:Illegal local array element assignment
|
||||
?(eval):local:1: array[2]: can't create local array elements
|
||||
|
||||
local -a array
|
||||
typeset array[1]=a array[2]=b array[3]=c
|
||||
print $array
|
||||
0:Legal local array element assignment
|
||||
>a b c
|
||||
|
||||
local -A assoc
|
||||
local b=1 ;: to stomp assoc[1] if assoc[b] is broken
|
||||
typeset assoc[1]=a assoc[b]=2 assoc[3]=c
|
||||
print $assoc[1] $assoc[b] $assoc[3]
|
||||
0:Legal local associative array element assignment
|
||||
>a 2 c
|
||||
|
||||
local scalar scalar[1]=a scalar[2]=b scalar[3]=c
|
||||
print $scalar
|
||||
0:Local scalar subscript assignment
|
||||
>abc
|
||||
|
||||
typeset -L 10 fools
|
||||
for fools in " once" "twice" " thrice" " oops too long here"; do
|
||||
print "'$fools'"
|
||||
done
|
||||
0:Left justification of scalars
|
||||
>'once '
|
||||
>'twice '
|
||||
>'thrice '
|
||||
>'oops too l'
|
||||
|
||||
typeset -L 10 -F 3 foolf
|
||||
for foolf in 1.3 4.6 -2.987 -4.91031; do
|
||||
print "'$foolf'"
|
||||
done
|
||||
0:Left justification of floating point
|
||||
>'1.300 '
|
||||
>'4.600 '
|
||||
>'-2.987 '
|
||||
>'-4.910 '
|
||||
|
||||
typeset -L 10 -Z foolzs
|
||||
for foolzs in 001.3 04.6 -2.987 -04.91231; do
|
||||
print "'$foolzs'"
|
||||
done
|
||||
0:Left justification of scalars with zero suppression
|
||||
>'1.3 '
|
||||
>'4.6 '
|
||||
>'-2.987 '
|
||||
>'-04.91231 '
|
||||
|
||||
typeset -R 10 foors
|
||||
for foors in short longer even-longer; do
|
||||
print "'$foors'"
|
||||
done
|
||||
0:Right justification of scalars
|
||||
>' short'
|
||||
>' longer'
|
||||
>'ven-longer'
|
||||
|
||||
typeset -Z 10 foozs
|
||||
for foozs in 42 -42 " 43" " -43"; do
|
||||
print "'$foozs'"
|
||||
done
|
||||
0:Right justification of scalars with zeroes
|
||||
>'0000000042'
|
||||
>' -42'
|
||||
>' 000000043'
|
||||
>' -43'
|
||||
|
||||
integer -Z 10 foozi
|
||||
for foozi in 42 -42 " 43" " -43"; do
|
||||
print "'$foozi'"
|
||||
done
|
||||
0:Right justification of integers with zero, no initial base
|
||||
>'0000000042'
|
||||
>'-000000042'
|
||||
>'0000000043'
|
||||
>'-000000043'
|
||||
# In case you hadn't twigged, the spaces are absorbed in the initial
|
||||
# math evaluation, so don't get through.
|
||||
|
||||
unsetopt cbases
|
||||
integer -Z 10 -i 16 foozi16
|
||||
for foozi16 in 42 -42 " 43" " -43"; do
|
||||
print "'$foozi16'"
|
||||
done
|
||||
0:Right justification of integers with zero, base 16, C_BASES off
|
||||
>'16#000002A'
|
||||
>'-16#00002A'
|
||||
>'16#000002B'
|
||||
>'-16#00002B'
|
||||
|
||||
setopt cbases
|
||||
integer -Z 10 -i 16 foozi16c
|
||||
for foozi16c in 42 -42 " 43" " -43"; do
|
||||
print "'$foozi16c'"
|
||||
done
|
||||
0:Right justification of integers with zero, base 16, C_BASES on
|
||||
>'0x0000002A'
|
||||
>'-0x000002A'
|
||||
>'0x0000002B'
|
||||
>'-0x000002B'
|
||||
|
||||
setopt cbases
|
||||
integer -Z 10 -i 16 foozi16c
|
||||
for foozi16c in 0x1234 -0x1234; do
|
||||
for (( i = 1; i <= 5; i++ )); do
|
||||
print "'${foozi16c[i,11-i]}'"
|
||||
done
|
||||
print "'${foozi16c[-2]}'"
|
||||
done
|
||||
0:Extracting substrings from padded integers
|
||||
>'0x00001234'
|
||||
>'x0000123'
|
||||
>'000012'
|
||||
>'0001'
|
||||
>'00'
|
||||
>'3'
|
||||
>'-0x0001234'
|
||||
>'0x000123'
|
||||
>'x00012'
|
||||
>'0001'
|
||||
>'00'
|
||||
>'3'
|
||||
|
||||
typeset -F 3 -Z 10 foozf
|
||||
for foozf in 3.14159 -3.14159 4 -4; do
|
||||
print "'$foozf'"
|
||||
done
|
||||
0:Right justification of fixed point numbers with zero
|
||||
>'000003.142'
|
||||
>'-00003.142'
|
||||
>'000004.000'
|
||||
>'-00004.000'
|
||||
|
||||
stress00
|
||||
print $scalar $array
|
||||
0q:Stress test: all parameters are local and unset, using -m
|
||||
>scalar a r y
|
||||
|
||||
local parentenv=preserved
|
||||
fn() {
|
||||
typeset -h +g -m \*
|
||||
unset -m \*
|
||||
integer i=9
|
||||
float -H f=9
|
||||
declare -t scalar
|
||||
declare -H -a array
|
||||
typeset
|
||||
typeset +
|
||||
}
|
||||
fn
|
||||
echo $parentenv
|
||||
0:Parameter hiding and tagging, printing types and values
|
||||
>array local array
|
||||
>float local f
|
||||
>integer local i=9
|
||||
>local tagged scalar=''
|
||||
>array local array
|
||||
>float local f
|
||||
>integer local i
|
||||
>local tagged scalar
|
||||
>preserved
|
||||
|
||||
export ENVFOO=bar
|
||||
print ENVFOO in environment
|
||||
env | grep '^ENVFOO'
|
||||
print Changing ENVFOO
|
||||
ENVFOO="not bar any more"
|
||||
env | grep '^ENVFOO'
|
||||
unset ENVFOO
|
||||
print ENVFOO no longer in environment
|
||||
env | grep '^ENVFOO'
|
||||
1:Adding and removing values to and from the environment
|
||||
>ENVFOO in environment
|
||||
>ENVFOO=bar
|
||||
>Changing ENVFOO
|
||||
>ENVFOO=not bar any more
|
||||
>ENVFOO no longer in environment
|
||||
|
||||
(export FOOENV=BAR
|
||||
env | grep '^FOOENV'
|
||||
print Exec
|
||||
exec $ZTST_testdir/../Src/zsh -fc '
|
||||
print Unset
|
||||
unset FOOENV
|
||||
env | grep "^FOOENV"')
|
||||
1:Can unset environment variables after exec
|
||||
>FOOENV=BAR
|
||||
>Exec
|
||||
>Unset
|
||||
|
||||
local case1=upper
|
||||
typeset -u case1
|
||||
print $case1
|
||||
upper="VALUE OF \$UPPER"
|
||||
print ${(P)case1}
|
||||
0:Upper case conversion, does not apply to values used internally
|
||||
>UPPER
|
||||
>VALUE OF $UPPER
|
||||
|
||||
local case2=LOWER
|
||||
typeset -l case2
|
||||
print $case2
|
||||
LOWER="value of \$lower"
|
||||
print ${(P)case2}
|
||||
0:Lower case conversion, does not apply to values used internally
|
||||
>lower
|
||||
>value of $lower
|
||||
|
||||
typeset -a array
|
||||
array=(foo bar)
|
||||
fn() { typeset -p array nonexistent; }
|
||||
fn
|
||||
1:declare -p shouldn't create scoped values
|
||||
>typeset -g -a array=( foo bar )
|
||||
?fn:typeset: no such variable: nonexistent
|
||||
|
||||
unsetopt typesetsilent
|
||||
silent1(){ typeset -g silence; }
|
||||
silent2(){ local silence; silent1; }
|
||||
silent2
|
||||
0:typeset -g should be silent even without TYPESET_SILENT
|
||||
|
||||
typeset -T TIED_SCALAR tied_array
|
||||
TIED_SCALAR=foo:bar
|
||||
print $tied_array
|
||||
typeset -T TIED_SCALAR=goo:car tied_array
|
||||
print $tied_array
|
||||
typeset -T TIED_SCALAR tied_array=(poo par)
|
||||
print $TIED_SCALAR
|
||||
0:retying arrays to same array works
|
||||
>foo bar
|
||||
>goo car
|
||||
>poo:par
|
||||
|
||||
(
|
||||
setopt POSIXBUILTINS
|
||||
readonly pbro
|
||||
print ${+pbro} >&2
|
||||
(typeset -g pbro=3)
|
||||
(pbro=4)
|
||||
readonly -p pbro >&2 # shows up as "readonly" although unset
|
||||
typeset -gr pbro # idempotent (no error)...
|
||||
print ${+pbro} >&2 # ...so still readonly...
|
||||
typeset -g +r pbro # ...can't turn it off
|
||||
)
|
||||
1:readonly with POSIX_BUILTINS
|
||||
?0
|
||||
?(eval):5: read-only variable: pbro
|
||||
?(eval):6: read-only variable: pbro
|
||||
?typeset -g -r pbro
|
||||
?0
|
||||
?(eval):10: read-only variable: pbro
|
||||
|
||||
readonly foo=bar novalue
|
||||
readonly -p
|
||||
0:readonly -p output (no readonly specials)
|
||||
>typeset -r foo=bar
|
||||
>typeset -r novalue=''
|
||||
|
||||
local -a a1 a2
|
||||
local -r r1=yes r2=no
|
||||
a1=(one two) a2=(three four)
|
||||
readonly a1
|
||||
typeset -pm 'a[12]'
|
||||
typeset -pm 'r[12]'
|
||||
0:readonly -p output
|
||||
>typeset -ar a1=( one two )
|
||||
>typeset -a a2=( three four )
|
||||
>typeset -r r1=yes
|
||||
>typeset -r r2=no
|
||||
|
||||
one=hidden two=hidden three=hidden four=hidden five=hidden
|
||||
fn() {
|
||||
local bleugh="four=vier"
|
||||
typeset -R10 one=eins two=(zwei dio) three $bleugh five=(cinq cinque)
|
||||
three=drei
|
||||
print -l $one $two $three $four $five
|
||||
}
|
||||
fn
|
||||
print -l $one $two $three $four $five
|
||||
0:typeset reserved word interface: basic
|
||||
> eins
|
||||
>zwei
|
||||
>dio
|
||||
> drei
|
||||
> vier
|
||||
>cinq
|
||||
>cinque
|
||||
>hidden
|
||||
>hidden
|
||||
>hidden
|
||||
>hidden
|
||||
>hidden
|
||||
|
||||
(
|
||||
setopt glob
|
||||
mkdir -p arrayglob
|
||||
touch arrayglob/{one,two,three,four,five,six,seven}
|
||||
fn() {
|
||||
typeset array=(arrayglob/[tf]*)
|
||||
print -l ${array:t}
|
||||
#
|
||||
typeset {first,second,third}=the_same_value array=(
|
||||
extends
|
||||
over
|
||||
multiple
|
||||
lines
|
||||
)
|
||||
print -l $first $second $third "$array"
|
||||
#
|
||||
integer i=$(echo 1 + 2 + 3 + 4)
|
||||
print $i
|
||||
#
|
||||
# only noted by accident this was broken..
|
||||
# we need to turn off special recognition
|
||||
# of assignments within assignments...
|
||||
typeset careful=( i=1 j=2 k=3 )
|
||||
print -l $careful
|
||||
}
|
||||
fn
|
||||
)
|
||||
0:typeset reserved word, more complicated cases
|
||||
>five
|
||||
>four
|
||||
>three
|
||||
>two
|
||||
>the_same_value
|
||||
>the_same_value
|
||||
>the_same_value
|
||||
>extends over multiple lines
|
||||
>10
|
||||
>i=1
|
||||
>j=2
|
||||
>k=3
|
||||
|
||||
(
|
||||
# reserved word is recognised at parsing.
|
||||
# yes, this is documented.
|
||||
# anyway, that means we need to
|
||||
# re-eval the function...
|
||||
fn='
|
||||
fn() {
|
||||
typeset foo=`echo one word=two`
|
||||
print $foo
|
||||
print $word
|
||||
}
|
||||
'
|
||||
print reserved
|
||||
eval $fn; fn
|
||||
print builtin
|
||||
disable -r typeset
|
||||
eval $fn; fn
|
||||
enable -r typeset
|
||||
disable typeset
|
||||
print reserved
|
||||
eval $fn; fn
|
||||
)
|
||||
0:reserved word and builtin interfaces
|
||||
>reserved
|
||||
>one word=two
|
||||
>
|
||||
>builtin
|
||||
>one
|
||||
>two
|
||||
>reserved
|
||||
>one word=two
|
||||
>
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt typeset_silent
|
||||
local k
|
||||
typeset -A hash=(k1 v1 k2 v2)
|
||||
typeset foo=word array=(more than one word)
|
||||
for k in ${(ko)hash}; do
|
||||
print $k $hash[$k]
|
||||
done
|
||||
print -l $foo $array
|
||||
typeset -A hash
|
||||
typeset foo array
|
||||
for k in ${(ko)hash}; do
|
||||
print $k $hash[$k]
|
||||
done
|
||||
print -l $foo $array
|
||||
typeset hash=(k3 v3 k4 v4) array=(odd number here)
|
||||
for k in ${(ko)hash}; do
|
||||
print $k $hash[$k]
|
||||
done
|
||||
print -l $array
|
||||
}
|
||||
fn
|
||||
0:typeset preserves existing variable types
|
||||
>k1 v1
|
||||
>k2 v2
|
||||
>word
|
||||
>more
|
||||
>than
|
||||
>one
|
||||
>word
|
||||
>k1 v1
|
||||
>k2 v2
|
||||
>word
|
||||
>more
|
||||
>than
|
||||
>one
|
||||
>word
|
||||
>k3 v3
|
||||
>k4 v4
|
||||
>odd
|
||||
>number
|
||||
>here
|
||||
|
||||
fn() { typeset foo bar thing=this stuff=(that other) more=woevva; }
|
||||
which -x2 fn
|
||||
fn2() { typeset assignfirst=(why not); }
|
||||
which -x2 fn2
|
||||
0:text output from typeset
|
||||
>fn () {
|
||||
> typeset foo bar thing=this stuff=(that other) more=woevva
|
||||
>}
|
||||
>fn2 () {
|
||||
> typeset assignfirst=(why not)
|
||||
>}
|
||||
|
||||
fn() {
|
||||
typeset array=()
|
||||
print ${(t)array} ${#array}
|
||||
typeset gnothergarray=() gnothergarray[1]=yes gnothergarray[2]=no
|
||||
print -l ${(t)gnothergarray} $gnothergarray
|
||||
}
|
||||
fn
|
||||
0:can set empty array
|
||||
>array-local 0
|
||||
>array-local
|
||||
>yes
|
||||
>no
|
||||
|
||||
array=(nothing to see here)
|
||||
fn() {
|
||||
typeset array=(one two three four five)
|
||||
typeset array[2,4]=(umm er)
|
||||
print ${#array} $array
|
||||
typeset array[2,3]=()
|
||||
print ${#array} $array
|
||||
}
|
||||
fn
|
||||
print ${#array} $array
|
||||
0:can update array slices in typeset
|
||||
>4 one umm er five
|
||||
>2 one five
|
||||
>4 nothing to see here
|
||||
|
||||
array=(no really nothing here)
|
||||
fn() {
|
||||
typeset array=() array[2]=two array[4]=four
|
||||
typeset -p array
|
||||
typeset array=() array[3]=three array[1]=one
|
||||
typeset -p array
|
||||
}
|
||||
fn
|
||||
print $array
|
||||
0:setting empty array in typeset
|
||||
>typeset -a array=( '' two '' four )
|
||||
>typeset -a array=( one '' three )
|
||||
>no really nothing here
|
||||
|
||||
readonly isreadonly=yes
|
||||
typeset isreadonly=still
|
||||
1:typeset returns status 1 if setting readonly variable
|
||||
?(eval):2: read-only variable: isreadonly
|
||||
|
||||
if (( UID )); then
|
||||
UID=$((UID+1)) date; echo "Status is printed, $?"
|
||||
else
|
||||
ZTST_skip="cannot test setuid error when tests run as superuser"
|
||||
fi
|
||||
0:when cannot change UID, the command isn't run
|
||||
# 'date' did not run.
|
||||
>Status is printed, 1
|
||||
*?*: failed to change user ID: *
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
# Tests for the echo, print, printf and pushln builtins
|
||||
|
||||
# Tested elsewhere:
|
||||
# Use of print -p to output to coprocess A01grammar
|
||||
# Prompt expansion with print -P D01prompt
|
||||
# -l, -r, -R and -n indirectly tested in various places
|
||||
|
||||
# Not yet tested:
|
||||
# echo and pushln
|
||||
# print's -b -c -s -z -N options
|
||||
|
||||
|
||||
%test
|
||||
|
||||
print -D "${HOME:-~}"
|
||||
0:replace directory name
|
||||
>~
|
||||
|
||||
print -u2 'error message'
|
||||
0:output to file-descriptor
|
||||
?error message
|
||||
|
||||
print -o foo bar Baz
|
||||
0:argument sorting
|
||||
>Baz bar foo
|
||||
|
||||
print -f
|
||||
1:print -f needs a format specified
|
||||
?(eval):print:1: argument expected: -f
|
||||
|
||||
print -Of '%s\n' foo bar baz
|
||||
0:reverse argument sorting
|
||||
>foo
|
||||
>baz
|
||||
>bar
|
||||
|
||||
# some locales force case-insensitive sorting
|
||||
(LC_ALL=C; print -o a B c)
|
||||
0:case-sensitive argument sorting
|
||||
>B a c
|
||||
|
||||
(LC_ALL=C; print -io a B c)
|
||||
0:case-insensitive argument sorting
|
||||
>a B c
|
||||
|
||||
print -m '[0-9]' one 2 three 4 five 6
|
||||
0:removal of non-matching arguments
|
||||
>2 4 6
|
||||
|
||||
printf '%s\n' string
|
||||
0:test s format specifier
|
||||
>string
|
||||
|
||||
printf '%b' '\t\\\n'
|
||||
0:test b format specifier
|
||||
> \
|
||||
|
||||
printf '%q\n' '=a=b \ c!'
|
||||
0: test q format specifier
|
||||
>\=a=b\ \\\ c!
|
||||
|
||||
printf '%c\n' char
|
||||
0:test c format specifier
|
||||
>c
|
||||
|
||||
printf '%.10e%n\n' 1 count >/dev/null
|
||||
printf '%d\n' $count
|
||||
0:test n format specifier
|
||||
>16
|
||||
|
||||
printf '%5b%n\n' abc count >/dev/null; echo $count
|
||||
0:check count of width-specified %b
|
||||
>5
|
||||
|
||||
printf '%s!%5b!\n' abc
|
||||
0:ensure width is applied to empty param
|
||||
>abc! !
|
||||
|
||||
printf '%d %d\n' 123.45 678 90.1
|
||||
0:test d format specifier
|
||||
>123 678
|
||||
>90 0
|
||||
|
||||
printf '%g %g\n' 123.45 678 90.1
|
||||
0:test g format specifier
|
||||
>123.45 678
|
||||
>90.1 0
|
||||
|
||||
print -f 'arg: %b\n' -C2 '\x41' '\x42' '\x43'
|
||||
0:override -C when -f was given
|
||||
>arg: A
|
||||
>arg: B
|
||||
>arg: C
|
||||
|
||||
# Is anyone not using ASCII
|
||||
printf '%d\n' \'A
|
||||
0:initial quote to get numeric value of character with int
|
||||
>65
|
||||
|
||||
printf '%.1E\n' \'B
|
||||
0:initial quote to get numeric value of character with double
|
||||
>6.6E+01
|
||||
|
||||
printf '%x\n' $(printf '"\xf0')
|
||||
0:numeric value of high numbered character
|
||||
>f0
|
||||
|
||||
printf '\x25s\n' arg
|
||||
0:using \x25 to print a literal % in format
|
||||
>%s
|
||||
|
||||
printf '%3c\n' c
|
||||
0:width specified in format specifier
|
||||
> c
|
||||
|
||||
printf '%.4s\n' chopped
|
||||
0:precision specified in format specifier
|
||||
>chop
|
||||
|
||||
printf '%*.*f\n' 6 2 10.2
|
||||
0:width/precision specified in arguments
|
||||
> 10.20
|
||||
|
||||
printf '%z'
|
||||
1:use of invalid directive
|
||||
?(eval):printf:1: %z: invalid directive
|
||||
|
||||
printf '%d\n' 3a
|
||||
1:bad arithmetic expression
|
||||
?(eval):1: bad math expression: operator expected at `a'
|
||||
>0
|
||||
|
||||
printf '%12$s' 1 2 3
|
||||
1:out of range argument specifier
|
||||
?(eval):printf:1: 12: argument specifier out of range
|
||||
|
||||
printf '%2$s\n' 1 2 3
|
||||
1:out of range argument specifier on format reuse
|
||||
?(eval):printf:1: 2: argument specifier out of range
|
||||
>2
|
||||
|
||||
printf '%*0$d'
|
||||
1:out of range argument specifier on width
|
||||
?(eval):printf:1: 0: argument specifier out of range
|
||||
|
||||
print -m -f 'format - %s.\n' 'z' a b c
|
||||
0:format not printed if no arguments left after -m removal
|
||||
|
||||
print -f 'format - %s%b.\n'
|
||||
0:format printed despite lack of arguments
|
||||
>format - .
|
||||
|
||||
printf 'x%4sx\n'
|
||||
0:with no arguments empty string where string needed
|
||||
>x x
|
||||
|
||||
printf '%d\n'
|
||||
0:with no arguments, zero used where number needed
|
||||
>0
|
||||
|
||||
printf '%s\t%c:%#x%%\n' one a 1 two b 2 three c 3
|
||||
0:multiple arguments with format reused
|
||||
>one a:0x1%
|
||||
>two b:0x2%
|
||||
>three c:0x3%
|
||||
|
||||
printf '%d%n' 123 val val val > /dev/null
|
||||
printf '%d\n' val
|
||||
0:%n count zeroed on format reuse
|
||||
>1
|
||||
|
||||
# this may fill spec string with '%0'+- #*.*lld\0' - 14 characters
|
||||
printf '%1$0'"'+- #-08.5dx\n" 123
|
||||
0:maximal length format specification
|
||||
>+00123 x
|
||||
|
||||
printf "x:%-20s:y\n" fubar
|
||||
0:left-justification of string
|
||||
>x:fubar :y
|
||||
|
||||
printf '%*smorning\n' -5 good
|
||||
0:negative width specified
|
||||
>good morning
|
||||
|
||||
printf '%.*g\n' -1 .1
|
||||
0:negative precision specified
|
||||
>0.1
|
||||
|
||||
printf '%2$s %1$d\n' 1 2
|
||||
0:specify argument to output explicitly
|
||||
>2 1
|
||||
|
||||
printf '%3$.*1$d\n' 4 0 3
|
||||
0:specify output and precision arguments explicitly
|
||||
>0003
|
||||
|
||||
printf '%2$d%1$d\n' 1 2 3 4
|
||||
0:reuse format where arguments are explicitly specified
|
||||
>21
|
||||
>43
|
||||
|
||||
printf '%1$*2$d' 1 2 3 4 5 6 7 8 9 10; echo .EoL.
|
||||
0:reuse of specified arguments
|
||||
> 1 3 5 7 9.EoL.
|
||||
|
||||
echo -n 'Now is the time'; echo .EoL.
|
||||
0:testing -n with echo
|
||||
>Now is the time.EoL.
|
||||
|
||||
printf '%1$0+.3d\n' 3
|
||||
0:flags mixed with specified argument
|
||||
>+003
|
||||
|
||||
# Test the parsing of the \c escape.
|
||||
|
||||
echo '1 2!\c3 4' a b c d; echo .EoL.
|
||||
0:Truncating first echo arg using backslash-c
|
||||
>1 2!.EoL.
|
||||
|
||||
echo a b '1 2?\c5 6' c d; echo .EoL.
|
||||
0:Truncating third echo arg using backslash-c
|
||||
>a b 1 2?.EoL.
|
||||
|
||||
printf '1 2!\c3 4'; echo .EoL.
|
||||
0:Truncating printf literal using backslash-c
|
||||
>1 2!.EoL.
|
||||
|
||||
printf '%s %b!\c%s %s' 1 2 3 4 5 6 7 8 9; echo .EoL.
|
||||
0:Truncating printf format using backslash-c
|
||||
>1 2!.EoL.
|
||||
|
||||
printf '%s %b!\c%s %s' '1\c' '2\n\c' 3 4 5 6 7 8 9
|
||||
0:Truncating printf early %b arg using backslash-c
|
||||
>1\c 2
|
||||
|
||||
printf '%b %b\n' 1 2 3 4 '5\c' 6 7 8 9; echo .EoL.
|
||||
0:Truncating printf late %b arg using backslash-c
|
||||
>1 2
|
||||
>3 4
|
||||
>5.EoL.
|
||||
|
||||
# The following usage, as stated in the manual, is not recommended and the
|
||||
# results are undefined. Tests are here anyway to ensure some form of
|
||||
# half-sane behaviour.
|
||||
|
||||
printf '%2$s %s %3$s\n' Morning Good World
|
||||
0:mixed style of argument selection
|
||||
>Good Morning World
|
||||
|
||||
printf '%*1$.*d\n' 1 2
|
||||
0:argument specified for width only
|
||||
>00
|
||||
|
||||
print -f '%*.*1$d\n' 1 2 3
|
||||
0:argument specified for precision only
|
||||
>2
|
||||
>000
|
||||
|
||||
printf -- '%s\n' str
|
||||
0:initial `--' ignored to satisfy POSIX
|
||||
>str
|
||||
|
||||
printf '%'
|
||||
1:nothing after % in format specifier
|
||||
?(eval):printf:1: %: invalid directive
|
||||
|
||||
printf $'%\0'
|
||||
1:explicit null after % in format specifier
|
||||
?(eval):printf:1: %: invalid directive
|
||||
|
||||
printf '%b\n' '\0123'
|
||||
0:printf handles \0... octal escapes in replacement text
|
||||
>S
|
||||
|
||||
print -lO $'a' $'a\0' $'a\0b' $'a\0b\0' $'a\0b\0a' $'a\0b\0b' $'a\0c' |
|
||||
while read -r line; do
|
||||
for (( i = 1; i <= ${#line}; i++ )); do
|
||||
foo=$line[i]
|
||||
printf "%02x" $(( #foo ))
|
||||
done
|
||||
print
|
||||
done
|
||||
0:sorting with embedded nulls
|
||||
>610063
|
||||
>6100620062
|
||||
>6100620061
|
||||
>61006200
|
||||
>610062
|
||||
>6100
|
||||
>61
|
||||
|
||||
foo=$'one\ttwo\tthree\tfour\n'
|
||||
foo+=$'\tone\ttwo\tthree\tfour\n'
|
||||
foo+=$'\t\tone\t\ttwo\t\tthree\t\tfour'
|
||||
print -x4 $foo
|
||||
print -X4 $foo
|
||||
0:Tab expansion by print
|
||||
>one two three four
|
||||
> one two three four
|
||||
> one two three four
|
||||
>one two three four
|
||||
> one two three four
|
||||
> one two three four
|
||||
|
||||
unset foo
|
||||
print -v foo once more
|
||||
typeset -p foo
|
||||
printf -v foo "%s\0%s-" into the breach
|
||||
typeset -p foo
|
||||
0:print and printf into a variable
|
||||
>typeset -g foo='once more'
|
||||
>typeset -g foo=$'into\C-@the-breach\C-@-'
|
||||
|
||||
typeset -a foo
|
||||
print -f '%2$d %4s' -v foo one 1 two 2 three 3
|
||||
typeset -p foo
|
||||
0:printf into an array variable
|
||||
>typeset -a foo=( '1 one' '2 two' '3 three' )
|
||||
|
||||
typeset -a foo
|
||||
print -f '%s' -v foo string
|
||||
typeset -p foo
|
||||
0:printf to an array variable without format string reuse
|
||||
>typeset foo=string
|
||||
|
||||
printf -
|
||||
printf - -
|
||||
printf --
|
||||
printf -- -
|
||||
printf -- --
|
||||
printf -x -v foo
|
||||
# Final print for newline on stdout
|
||||
print
|
||||
0:regression test of printf with assorted ambiguous options or formats
|
||||
>------x
|
||||
?(eval):printf:3: not enough arguments
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
# Tests for the read builtin
|
||||
|
||||
# Tested elsewhere:
|
||||
# reading from a coprocess A01grammar, A04redirect
|
||||
|
||||
# Not tested:
|
||||
# -c/-l/-n (options for compctl functions)
|
||||
# -q/-s (needs a tty)
|
||||
|
||||
%test
|
||||
|
||||
read <<<'hello world'
|
||||
print $REPLY
|
||||
0:basic read command
|
||||
>hello world
|
||||
|
||||
read -A <<<'hello world'
|
||||
print $reply[2]
|
||||
0:array read
|
||||
>world
|
||||
|
||||
read -k3 -u0 <<<foo:bar
|
||||
print $REPLY
|
||||
0:read specified number of chars
|
||||
>foo
|
||||
|
||||
for char in y Y n N X $'\n'; do
|
||||
read -q -u0 <<<$char
|
||||
print $?
|
||||
done
|
||||
0:read yes or no, default no
|
||||
>0
|
||||
>0
|
||||
>1
|
||||
>1
|
||||
>1
|
||||
>1
|
||||
|
||||
read -d: <<<foo:bar
|
||||
print $REPLY
|
||||
0:read up to delimiter
|
||||
>foo
|
||||
|
||||
print foo:bar|IFS=: read -A
|
||||
print $reply
|
||||
0:use different, IFS separator to array
|
||||
>foo bar
|
||||
|
||||
print -z hello world; read -z
|
||||
print $REPLY
|
||||
0:read from editor buffer stack
|
||||
>hello world
|
||||
|
||||
unset REPLY
|
||||
read -E <<<hello
|
||||
print $REPLY
|
||||
0:read with echoing and assigning
|
||||
>hello
|
||||
>hello
|
||||
|
||||
unset REPLY
|
||||
read -e <<<hello
|
||||
print $REPLY
|
||||
0:read with echoing but assigning disabled
|
||||
>hello
|
||||
>
|
||||
|
||||
read -e -t <<<hello
|
||||
0:read with test first
|
||||
>hello
|
||||
|
||||
SECONDS=0
|
||||
read -e -t 5 <<<hello
|
||||
print $SECONDS
|
||||
0:read with timeout (no waiting should occur)
|
||||
>hello
|
||||
>0
|
||||
|
||||
print -n 'Testing the\0null hypothesis\0' |
|
||||
while read -d $'\0' line; do print $line; done
|
||||
0:read with null delimiter
|
||||
>Testing the
|
||||
>null hypothesis
|
||||
|
||||
# Note that trailing NULLs are not stripped even if they are in
|
||||
# $IFS; only whitespace characters contained in $IFS are stripped.
|
||||
print -n $'Aaargh, I hate nulls.\0\0\0' | read line
|
||||
print ${#line}
|
||||
0:read with trailing metafied characters
|
||||
>24
|
||||
|
||||
(typeset -r foo
|
||||
read foo) <<<bar
|
||||
1:return status on failing to set parameter
|
||||
?(eval):2: read-only variable: foo
|
||||
|
||||
read -AE array <<<'one two three'
|
||||
print ${(j.:.)array}
|
||||
0:Behaviour of -A and -E combination
|
||||
>one
|
||||
>two
|
||||
>three
|
||||
>one:two:three
|
||||
|
||||
array=()
|
||||
read -Ae array <<<'four five six'
|
||||
print ${(j.:.)array}
|
||||
0:Behaviour of -A and -e combination
|
||||
>four
|
||||
>five
|
||||
>six
|
||||
>
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Tests for the eval builtin.
|
||||
# This is quite short; eval is widely tested throughout the test suite
|
||||
# and its basic behaviour is fairly straightforward.
|
||||
|
||||
%prep
|
||||
|
||||
cmd='print $?'
|
||||
|
||||
%test
|
||||
|
||||
false
|
||||
eval $cmd
|
||||
0:eval retains value of $?
|
||||
>1
|
||||
|
||||
# no point getting worked up over what the error message is...
|
||||
./command_not_found 2>/dev/null
|
||||
eval $cmd
|
||||
0:eval after command not found
|
||||
>127
|
||||
|
||||
# trick the test system
|
||||
sp=
|
||||
false
|
||||
eval "
|
||||
$sp
|
||||
$sp
|
||||
$sp
|
||||
"
|
||||
0:eval with empty command resets the status
|
||||
|
||||
false
|
||||
eval
|
||||
0:eval with empty command resets the status
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# Tests of fc command
|
||||
%prep
|
||||
|
||||
mkdir fc.tmp
|
||||
cd fc.tmp
|
||||
print 'fc -l foo' >fcl
|
||||
|
||||
%test
|
||||
$ZTST_testdir/../Src/zsh -f ./fcl
|
||||
1:Checking that fc -l foo doesn't core dump when history is empty
|
||||
?./fcl:fc:1: event not found: foo
|
||||
|
||||
PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< $'fc -p /dev/null 0 0\n:'
|
||||
0:Checking that fc -p doesn't core dump when history size is zero
|
||||
*?*%*
|
||||
|
||||
PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null a 0'
|
||||
1:Checking that fc -p rejects non-integer history size
|
||||
*?*% fc: HISTSIZE must be an integer
|
||||
*?*%*
|
||||
|
||||
PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null 0 a'
|
||||
1:Checking that fc -p rejects non-integer history save size
|
||||
*?*% fc: SAVEHIST must be an integer
|
||||
*?*%*
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
# Test the "emulate" builtin and related functions.
|
||||
|
||||
%prep
|
||||
|
||||
isset() {
|
||||
print -n "${1}: "
|
||||
if [[ -o $1 ]]; then print yes; else print no; fi
|
||||
}
|
||||
showopts() {
|
||||
# Set for Bourne shell emulation
|
||||
isset shwordsplit
|
||||
# Set in native mode and unless "emulate -R" is in use
|
||||
isset banghist
|
||||
}
|
||||
cshowopts() {
|
||||
showopts
|
||||
# Show a csh option, too
|
||||
isset cshnullglob
|
||||
}
|
||||
|
||||
%test
|
||||
|
||||
(print Before
|
||||
showopts
|
||||
fn() {
|
||||
emulate sh
|
||||
}
|
||||
fn
|
||||
print After
|
||||
showopts)
|
||||
0:Basic use of emulate
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>After
|
||||
>shwordsplit: yes
|
||||
>banghist: yes
|
||||
|
||||
fn() {
|
||||
emulate -L sh
|
||||
print During
|
||||
showopts
|
||||
}
|
||||
print Before
|
||||
showopts
|
||||
fn
|
||||
print After
|
||||
showopts
|
||||
0:Use of emulate -L
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>During
|
||||
>shwordsplit: yes
|
||||
>banghist: yes
|
||||
>After
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
|
||||
(print Before
|
||||
showopts
|
||||
emulate -R sh
|
||||
print After
|
||||
showopts)
|
||||
0:Use of emulate -R
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>After
|
||||
>shwordsplit: yes
|
||||
>banghist: no
|
||||
|
||||
print Before
|
||||
showopts
|
||||
emulate sh -c 'print During; showopts'
|
||||
print After
|
||||
showopts
|
||||
0:Use of emulate -c
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>During
|
||||
>shwordsplit: yes
|
||||
>banghist: yes
|
||||
>After
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
|
||||
print Before
|
||||
showopts
|
||||
emulate -R sh -c 'print During; showopts'
|
||||
print After
|
||||
showopts
|
||||
0:Use of emulate -R -c
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>During
|
||||
>shwordsplit: yes
|
||||
>banghist: no
|
||||
>After
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
|
||||
print Before
|
||||
showopts
|
||||
emulate -R sh -c 'shshowopts() { showopts; }'
|
||||
print After definition
|
||||
showopts
|
||||
print In sticky emulation
|
||||
shshowopts
|
||||
print After sticky emulation
|
||||
showopts
|
||||
0:Basic sticky function emulation
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>After definition
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>In sticky emulation
|
||||
>shwordsplit: yes
|
||||
>banghist: no
|
||||
>After sticky emulation
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
|
||||
print Before
|
||||
cshowopts
|
||||
emulate -R sh -c 'shshowopts() { cshowopts; }'
|
||||
emulate csh -c 'cshshowopts() {
|
||||
cshowopts
|
||||
print In nested sh emulation
|
||||
shshowopts
|
||||
}'
|
||||
print After definition
|
||||
cshowopts
|
||||
print In sticky csh emulation
|
||||
cshshowopts
|
||||
print After sticky emulation
|
||||
cshowopts
|
||||
0:Basic sticky function emulation
|
||||
>Before
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>cshnullglob: no
|
||||
>After definition
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>cshnullglob: no
|
||||
>In sticky csh emulation
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>cshnullglob: yes
|
||||
>In nested sh emulation
|
||||
>shwordsplit: yes
|
||||
>banghist: no
|
||||
>cshnullglob: no
|
||||
>After sticky emulation
|
||||
>shwordsplit: no
|
||||
>banghist: yes
|
||||
>cshnullglob: no
|
||||
|
||||
isalp() { if [[ -o alwayslastprompt ]]; then print on; else print off; fi; }
|
||||
emulate sh -c 'shfunc_inner() { setopt alwayslastprompt; }'
|
||||
emulate csh -c 'cshfunc_inner() { setopt alwayslastprompt; }'
|
||||
emulate sh -c 'shfunc_outer() {
|
||||
unsetopt alwayslastprompt;
|
||||
shfunc_inner;
|
||||
isalp
|
||||
unsetopt alwayslastprompt
|
||||
cshfunc_inner
|
||||
isalp
|
||||
}'
|
||||
shfunc_outer
|
||||
0:Sticky emulation not triggered if sticky emulation unchanged
|
||||
>on
|
||||
>off
|
||||
|
||||
(
|
||||
setopt ignorebraces
|
||||
emulate zsh -o extendedglob -c '
|
||||
[[ -o ignorebraces ]] || print "Yay, ignorebraces was reset"
|
||||
[[ -o extendedglob ]] && print "Yay, extendedglob is set"
|
||||
'
|
||||
)
|
||||
0:emulate -c with options
|
||||
>Yay, ignorebraces was reset
|
||||
>Yay, extendedglob is set
|
||||
|
||||
(
|
||||
setopt ignorebraces
|
||||
emulate zsh -o extendedglob
|
||||
[[ -o ignorebraces ]] || print "Yay, ignorebraces is no longer set"
|
||||
[[ -o extendedglob ]] && print "Yay, extendedglob is set"
|
||||
)
|
||||
0:emulate with options but no -c
|
||||
>Yay, ignorebraces is no longer set
|
||||
>Yay, extendedglob is set
|
||||
|
||||
emulate zsh -o fixallmybugs 'print This was executed, bad'
|
||||
1:emulate -c with incorrect options
|
||||
?(eval):emulate:1: no such option: fixallmybugs
|
||||
|
||||
emulate zsh -c '
|
||||
func() { [[ -o extendedglob ]] || print extendedglob is off }
|
||||
'
|
||||
func
|
||||
emulate zsh -o extendedglob -c '
|
||||
func() { [[ -o extendedglob ]] && print extendedglob is on }
|
||||
'
|
||||
func
|
||||
0:options specified alongside emulation are also sticky
|
||||
>extendedglob is off
|
||||
>extendedglob is on
|
||||
|
||||
emulate zsh -o extendedglob -c '
|
||||
func_inner() { setopt nobareglobqual }
|
||||
'
|
||||
emulate zsh -o extendedglob -c '
|
||||
func_outer() {
|
||||
func_inner
|
||||
[[ -o bareglobqual ]] || print bareglobqual was turned off
|
||||
[[ -o extendedglob ]] && print extendedglob is on, though
|
||||
}
|
||||
'
|
||||
[[ -o extendedglob ]] || print extendedglob is initially off
|
||||
func_outer
|
||||
0:options propagate between identical emulations
|
||||
>extendedglob is initially off
|
||||
>bareglobqual was turned off
|
||||
>extendedglob is on, though
|
||||
|
||||
emulate zsh -o extendedglob -c '
|
||||
func_inner() { setopt nobareglobqual }
|
||||
'
|
||||
emulate zsh -o extendedglob -o cbases -c '
|
||||
func_outer() {
|
||||
func_inner
|
||||
[[ -o bareglobqual ]] && print bareglobqual is still on
|
||||
[[ -o extendedglob ]] && print extendedglob is on, too
|
||||
}
|
||||
'
|
||||
[[ -o extendedglob ]] || print extendedglob is initially off
|
||||
func_outer
|
||||
0:options do not propagate between different emulations
|
||||
>extendedglob is initially off
|
||||
>bareglobqual is still on
|
||||
>extendedglob is on, too
|
||||
|
||||
emulate sh -c '[[ a == a ]]'
|
||||
0:regression test for POSIX_ALIASES reserved words
|
||||
F:Some reserved tokens are handled in alias expansion
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# Test the shift builtin.
|
||||
|
||||
%test
|
||||
|
||||
set -- one two three four five six seven eight nine ten
|
||||
shift
|
||||
print $*
|
||||
shift 2
|
||||
print $*
|
||||
shift -p 3
|
||||
print $*
|
||||
shift -p
|
||||
print $*
|
||||
0:shifting positional parameters
|
||||
>two three four five six seven eight nine ten
|
||||
>four five six seven eight nine ten
|
||||
>four five six seven
|
||||
>four five six
|
||||
|
||||
array=(yan tan tether mether pip azer sezar akker conter dick)
|
||||
shift 2 array
|
||||
print $array
|
||||
shift array
|
||||
print $array
|
||||
shift -p 3 array
|
||||
print $array
|
||||
shift -p array
|
||||
print $array
|
||||
0:shifting array
|
||||
>tether mether pip azer sezar akker conter dick
|
||||
>mether pip azer sezar akker conter dick
|
||||
>mether pip azer sezar
|
||||
>mether pip azer
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# The hash builtin is most used for the command hash table, which is
|
||||
# populated automatically. This is therefore highly system specific,
|
||||
# so mostly we'll test with the directory hash table: the logic is
|
||||
# virtually identical but with the different table, and furthermore
|
||||
# the shell doesn't care whether the directory exists unless you refer
|
||||
# to it in a context that needs one.
|
||||
|
||||
%prep
|
||||
populate_hash() {
|
||||
hash -d one=/first/directory
|
||||
hash -d two=/directory/the/second
|
||||
hash -d three=/noch/ein/verzeichnis
|
||||
hash -d four=/bored/with/this/now
|
||||
}
|
||||
|
||||
%test
|
||||
|
||||
hash -d
|
||||
0:Directory hash initially empty
|
||||
|
||||
populate_hash
|
||||
hash -d
|
||||
0:Populating directory hash and output with sort
|
||||
>four=/bored/with/this/now
|
||||
>one=/first/directory
|
||||
>three=/noch/ein/verzeichnis
|
||||
>two=/directory/the/second
|
||||
|
||||
hash -rd
|
||||
hash -d
|
||||
0:Empty hash
|
||||
|
||||
populate_hash
|
||||
hash -d
|
||||
0:Refill hash
|
||||
>four=/bored/with/this/now
|
||||
>one=/first/directory
|
||||
>three=/noch/ein/verzeichnis
|
||||
>two=/directory/the/second
|
||||
|
||||
hash -dL
|
||||
0:hash -L option
|
||||
>hash -d four=/bored/with/this/now
|
||||
>hash -d one=/first/directory
|
||||
>hash -d three=/noch/ein/verzeichnis
|
||||
>hash -d two=/directory/the/second
|
||||
|
||||
hash -dm 't*'
|
||||
0:hash -m option
|
||||
>three=/noch/ein/verzeichnis
|
||||
>two=/directory/the/second
|
||||
|
||||
hash -d five=/yet/more six=/here/we/go seven=/not/yet/eight
|
||||
hash -d
|
||||
0:Multiple assignments
|
||||
>five=/yet/more
|
||||
>four=/bored/with/this/now
|
||||
>one=/first/directory
|
||||
>seven=/not/yet/eight
|
||||
>six=/here/we/go
|
||||
>three=/noch/ein/verzeichnis
|
||||
>two=/directory/the/second
|
||||
|
||||
hash -d one two three
|
||||
0:Multiple arguments with no assignment not in verbose mode
|
||||
|
||||
hash -vd one two three
|
||||
0:Multiple arguments with no assignment in verbose mode
|
||||
>one=/first/directory
|
||||
>two=/directory/the/second
|
||||
>three=/noch/ein/verzeichnis
|
||||
|
||||
hash -d t-t=/foo
|
||||
i="~t-t"
|
||||
print ~t-t/bar
|
||||
print ${~i}/rab
|
||||
0:Dashes are untokenized in directory hash names
|
||||
>/foo/bar
|
||||
>/foo/rab
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
# Tests corresponding to the texinfo node `Arithmetic Evaluation'
|
||||
|
||||
%test
|
||||
|
||||
integer light there
|
||||
(( light = 42 )) &&
|
||||
let 'there = light' &&
|
||||
print $(( there ))
|
||||
0:basic integer arithmetic
|
||||
>42
|
||||
|
||||
float light there
|
||||
integer rnd
|
||||
(( light = 3.1415 )) &&
|
||||
let 'there = light' &&
|
||||
print -- $(( rnd = there * 10000 ))
|
||||
# save rounding problems by converting to integer
|
||||
0:basic floating point arithmetic
|
||||
>31415
|
||||
|
||||
integer rnd
|
||||
(( rnd = ((29.1 % 13.0 * 10) + 0.5) ))
|
||||
print $rnd
|
||||
0:Test floating point modulo function
|
||||
>31
|
||||
|
||||
print $(( 0x10 + 0X01 + 2#1010 ))
|
||||
0:base input
|
||||
>27
|
||||
|
||||
float light
|
||||
(( light = 4 ))
|
||||
print $light
|
||||
typeset -F light
|
||||
print $light
|
||||
0:conversion to float
|
||||
>4.000000000e+00
|
||||
>4.0000000000
|
||||
|
||||
integer i
|
||||
(( i = 32.5 ))
|
||||
print $i
|
||||
0:conversion to int
|
||||
>32
|
||||
|
||||
integer i
|
||||
(( i = 4 - - 3 * 7 << 1 & 7 ^ 1 | 16 ** 2 ))
|
||||
print $i
|
||||
0:precedence (arithmetic)
|
||||
>1591
|
||||
|
||||
fn() {
|
||||
setopt localoptions c_precedences
|
||||
integer i
|
||||
(( i = 4 - - 3 * 7 << 1 & 7 ^ 1 | 16 ** 2 ))
|
||||
print $i
|
||||
}
|
||||
fn
|
||||
0:precedence (arithmetic, with C_PRECEDENCES)
|
||||
>259
|
||||
|
||||
print $(( 1 < 2 || 2 < 2 && 3 > 4 ))
|
||||
0:precedence (logical)
|
||||
>1
|
||||
|
||||
print $(( 1 + 4 ? 3 + 2 ? 4 + 3 ? 5 + 6 ? 4 * 8 : 0 : 0 : 0 : 0 ))
|
||||
0:precedence (ternary)
|
||||
>32
|
||||
|
||||
print $(( 3 ? 2 ))
|
||||
1:parsing ternary (1)
|
||||
?(eval):1: bad math expression: ':' expected
|
||||
|
||||
print $(( 3 ? 2 : 1 : 4 ))
|
||||
1:parsing ternary (2)
|
||||
?(eval):1: bad math expression: ':' without '?'
|
||||
|
||||
print $(( 0, 4 ? 3 : 1, 5 ))
|
||||
0:comma operator
|
||||
>5
|
||||
|
||||
foo=000
|
||||
print $(( ##A + ##\C-a + #foo + $#foo ))
|
||||
0:#, ## and $#
|
||||
>117
|
||||
|
||||
print $((##))
|
||||
1:## without following character
|
||||
?(eval):1: bad math expression: character missing after ##
|
||||
|
||||
print $((## ))
|
||||
0:## followed by a space
|
||||
>32
|
||||
|
||||
integer i
|
||||
(( i = 3 + 5 * 1.75 ))
|
||||
print $i
|
||||
0:promotion to float
|
||||
>11
|
||||
|
||||
typeset x &&
|
||||
(( x = 3.5 )) &&
|
||||
print $x &&
|
||||
(( x = 4 )) &&
|
||||
print $x
|
||||
0:use of scalars to store integers and floats
|
||||
>3.5
|
||||
>4
|
||||
|
||||
(( newarray[unsetvar] = 1 ))
|
||||
2:error using unset variable as index
|
||||
?(eval):1: newarray: assignment to invalid subscript range
|
||||
|
||||
integer setvar=1
|
||||
(( newarray[setvar]++ ))
|
||||
(( newarray[setvar]++ ))
|
||||
print ${(t)newarray} ${#newarray} ${newarray[1]}
|
||||
0:setting array elements in math context
|
||||
>array 1 2
|
||||
|
||||
xarr=()
|
||||
(( xarr = 3 ))
|
||||
print ${(t)xarr} $xarr
|
||||
0:converting type from array
|
||||
>integer 3
|
||||
|
||||
print $(( 13 = 42 ))
|
||||
1:bad lvalue
|
||||
?(eval):1: bad math expression: lvalue required
|
||||
|
||||
x=/bar
|
||||
(( x = 32 ))
|
||||
print $x
|
||||
0:assigning to scalar which contains non-math string
|
||||
>32
|
||||
|
||||
print $(( ))
|
||||
0:empty math parse e.g. $(( )) acts like a zero
|
||||
>0
|
||||
|
||||
print $(( a = ))
|
||||
1:empty assignment
|
||||
?(eval):1: bad math expression: operand expected at end of string
|
||||
|
||||
print $(( 3, ))
|
||||
1:empty right hand of comma
|
||||
?(eval):1: bad math expression: operand expected at end of string
|
||||
|
||||
print $(( 3,,4 ))
|
||||
1:empty middle of comma
|
||||
?(eval):1: bad math expression: operand expected at `,4 '
|
||||
|
||||
print $(( (3 + 7, 4), 5 ))
|
||||
0:commas and parentheses, part 1
|
||||
>5
|
||||
|
||||
print $(( 5, (3 + 7, 4) ))
|
||||
0:commas and parentheses, part 1
|
||||
>4
|
||||
|
||||
print $(( 07.5 ))
|
||||
(setopt octalzeroes; print $(( 09.5 )))
|
||||
0:leading zero doesn't affect floating point
|
||||
>7.5
|
||||
>9.5
|
||||
|
||||
(setopt octalzeroes; print $(( 09 )))
|
||||
1:octalzeroes rejects invalid constants
|
||||
?(eval):1: bad math expression: operator expected at `9 '
|
||||
|
||||
(setopt octalzeroes; print $(( 08#77 )))
|
||||
0:octalzeroes doesn't affect bases
|
||||
>63
|
||||
|
||||
print $(( 36#z ))
|
||||
0:bases up to 36 work
|
||||
>35
|
||||
|
||||
print $(( 37#z ))
|
||||
1:bases beyond 36 don't work
|
||||
?(eval):1: invalid base (must be 2 to 36 inclusive): 37
|
||||
|
||||
print $(( 3 + "fail" ))
|
||||
1:parse failure in arithmetic
|
||||
?(eval):1: bad math expression: operand expected at `"fail" '
|
||||
|
||||
alias 3=echo
|
||||
print $(( 3 + "OK"); echo "Worked")
|
||||
0:not a parse failure because not arithmetic
|
||||
>+ OK Worked
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
print $(( [#16] 255 ))
|
||||
print $(( [##16] 255 ))
|
||||
setopt cbases
|
||||
print $(( [#16] 255 ))
|
||||
print $(( [##16] 255 ))
|
||||
}
|
||||
fn
|
||||
0:doubled # in base removes radix
|
||||
>16#FF
|
||||
>FF
|
||||
>0xFF
|
||||
>FF
|
||||
|
||||
array=(1)
|
||||
x=0
|
||||
(( array[++x]++ ))
|
||||
print $x
|
||||
print $#array
|
||||
print $array
|
||||
0:no double increment for subscript
|
||||
>1
|
||||
>1
|
||||
>2
|
||||
|
||||
# This is a bit naughty... the value of array
|
||||
# isn't well defined since there's no sequence point
|
||||
# between the increments of x, however we just want
|
||||
# to be sure that in this case, unlike the above,
|
||||
# x does get incremented twice.
|
||||
x=0
|
||||
array=(1 2)
|
||||
(( array[++x] = array[++x] + 1 ))
|
||||
print $x
|
||||
0:double increment for repeated expression
|
||||
>2
|
||||
|
||||
# Floating point. Default precision should take care of rounding errors.
|
||||
print $(( 1_0.000_000e0_1 ))
|
||||
# Integer.
|
||||
print $(( 0x_ff_ff_ ))
|
||||
# _ are parts of variable names that don't start with a digit
|
||||
__myvar__=42
|
||||
print $(( __myvar__ + $__myvar__ ))
|
||||
# _ is not part of variable name that does start with a digit
|
||||
# (which are substituted before math eval)
|
||||
set -- 6
|
||||
print $(( $1_000_000 ))
|
||||
# Underscores in expressions with no whitespace
|
||||
print $(( 3_000_+4_000_/2 ))
|
||||
# Underscores may appear in the base descriptor, for what it's worth...
|
||||
print $(( 1_6_#f_f_ ))
|
||||
0:underscores in math constants
|
||||
>100.
|
||||
>65535
|
||||
>84
|
||||
>6000000
|
||||
>5000
|
||||
>255
|
||||
|
||||
# Force floating point.
|
||||
for expr in "3/4" "0x100/0x200" "0x30/0x10"; do
|
||||
print $(( $expr ))
|
||||
setopt force_float
|
||||
print $(( $expr ))
|
||||
unsetopt force_float
|
||||
done
|
||||
0:Forcing floating point constant evaluation, or not.
|
||||
>0
|
||||
>0.75
|
||||
>0
|
||||
>0.5
|
||||
>3
|
||||
>3.
|
||||
|
||||
print $(( 0x30 + 0.5 ))
|
||||
print $(( 077 + 0.5 ))
|
||||
(setopt octalzeroes; print $(( 077 + 0.5 )) )
|
||||
0:Mixed float and non-decimal integer constants
|
||||
>48.5
|
||||
>77.5
|
||||
>63.5
|
||||
|
||||
underscore_integer() {
|
||||
setopt cbases localoptions
|
||||
print $(( [#_] 1000000 ))
|
||||
print $(( [#16_] 65536 ))
|
||||
print $(( [#16_4] 65536 * 32768 ))
|
||||
}
|
||||
underscore_integer
|
||||
0:Grouping output with underscores: integers
|
||||
>1_000_000
|
||||
>0x10_000
|
||||
>0x8000_0000
|
||||
|
||||
print $(( [#_] (5. ** 10) / 16. ))
|
||||
0:Grouping output with underscores: floating point
|
||||
>610_351.562_5
|
||||
|
||||
env SHLVL=1+RANDOM $ZTST_testdir/../Src/zsh -f -c 'print $SHLVL'
|
||||
0:Imported integer functions are not evaluated
|
||||
>2
|
||||
|
||||
print $(( 0b0 + 0b1 + 0b11 + 0b110 ))
|
||||
0:Binary input
|
||||
>10
|
||||
|
||||
print $(( 0b2 ))
|
||||
1:Binary numbers don't tend to have 2's in
|
||||
?(eval):1: bad math expression: operator expected at `2 '
|
||||
# ` for emacs shell mode
|
||||
|
||||
integer varassi
|
||||
print $(( varassi = 5.5 / 2.0 ))
|
||||
print $varassi
|
||||
0:Integer variable assignment converts result to integer
|
||||
>2
|
||||
>2
|
||||
# It's hard to test for integer to float.
|
||||
|
||||
integer ff1=3 ff2=4
|
||||
print $(( ff1/ff2 ))
|
||||
setopt force_float
|
||||
print $(( ff1/ff2 ))
|
||||
unsetopt force_float
|
||||
0:Variables are forced to floating point where necessary
|
||||
# 0.75 is exactly representable, don't expect rounding error.
|
||||
>0
|
||||
>0.75
|
||||
|
||||
# The following tests for a bug that only happens when
|
||||
# backing up over input read a line at a time, so we'll
|
||||
# read the input from stdin.
|
||||
$ZTST_testdir/../Src/zsh -f <<<'
|
||||
print $((echo first command
|
||||
); echo second command)
|
||||
print third command
|
||||
'
|
||||
0:Backing up a line of input when finding out it's not arithmetic
|
||||
>first command second command
|
||||
>third command
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f <<<'
|
||||
print $((3 +
|
||||
4))
|
||||
print next line
|
||||
'
|
||||
0:Not needing to back up a line when reading multiline arithmetic
|
||||
>7
|
||||
>next line
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f <<<'
|
||||
print $((case foo in
|
||||
bar)
|
||||
echo not this no, no
|
||||
;;
|
||||
foo)
|
||||
echo yes, this one
|
||||
;;
|
||||
esac)
|
||||
print after case in subshell)
|
||||
'
|
||||
0:Non-arithmetic subst with command subsitution parse from hell
|
||||
>yes, this one after case in subshell
|
||||
|
||||
print "a$((echo one subst)
|
||||
(echo two subst))b"
|
||||
0:Another tricky case that is actually a command substitution
|
||||
>aone subst
|
||||
>two substb
|
||||
|
||||
print "x$((echo one frob); (echo two frob))y"
|
||||
0:Same on a single line
|
||||
>xone frob
|
||||
>two froby
|
||||
|
||||
# This case actually only works by accident: if it wasn't for the
|
||||
# unbalanced parenthesis this would be a valid math substitution.
|
||||
# Hence it's definitely not recommended code. However, it does give
|
||||
# the algorithm an extra check.
|
||||
print $((case foo in
|
||||
foo)
|
||||
print Worked OK
|
||||
;;
|
||||
esac))
|
||||
0:Would-be math expansion with extra parenthesis making it a cmd subst
|
||||
>Worked OK
|
||||
|
||||
(setopt extendedglob
|
||||
set -- 32.463
|
||||
print ${$(( $1 * 100 ))%%.[0-9]#})
|
||||
0:Arithmetic substitution nested in parameter substitution
|
||||
>3246
|
||||
|
||||
print $((`:`))
|
||||
0:Null string in arithmetic evaluation after command substitution
|
||||
>0
|
||||
|
||||
print $(( 1 + $(( 2 + 3 )) ))
|
||||
print $(($((3+4))))
|
||||
print $((1*$((2*$((3))*4))*5))
|
||||
0:Nested math substitutions. Yes, I know, very useful.
|
||||
>6
|
||||
>7
|
||||
>120
|
||||
|
||||
foo="(1)"
|
||||
print $((foo))
|
||||
print $(($foo))
|
||||
print $(((2)))
|
||||
foo="3)"
|
||||
(print $((foo))) 2>&1
|
||||
(print $(($foo))) 2>&1
|
||||
1: Good and bad trailing parentheses
|
||||
>1
|
||||
>1
|
||||
>2
|
||||
>(eval):6: bad math expression: unexpected ')'
|
||||
>(eval):7: bad math expression: unexpected ')'
|
||||
|
||||
unset number
|
||||
(( number = 3 ))
|
||||
print ${(t)number}
|
||||
unset number
|
||||
(setopt posix_identifiers
|
||||
(( number = 3 ))
|
||||
print ${(t)number})
|
||||
0:type of variable when created in arithmetic context
|
||||
>integer
|
||||
>scalar
|
||||
|
|
@ -1,448 +0,0 @@
|
|||
# Tests corresponding to the texinfo node `Conditional Expressions'
|
||||
|
||||
%prep
|
||||
|
||||
umask 077
|
||||
|
||||
mkdir cond.tmp
|
||||
|
||||
cd cond.tmp
|
||||
|
||||
typeset -gi isnfs
|
||||
[[ "$(find . -prune -fstype nfs 2>/dev/null)" == "." ]] && isnfs=1
|
||||
if (( isnfs )) &&
|
||||
(cd -q ${ZTST_tmp} >/dev/null 2>&1 &&
|
||||
[[ "$(find . -prune -fstype nfs 2>/dev/null)" != "." ]]); then
|
||||
filetmpprefix=${ZTST_tmp}/condtest-$$-
|
||||
isnfs=0
|
||||
else
|
||||
filetmpprefix=
|
||||
fi
|
||||
newnewnew=${filetmpprefix}newnewnew
|
||||
unmodified=${filetmpprefix}unmodified
|
||||
zlnfs=${filetmpprefix}zlnfs
|
||||
|
||||
touch $unmodified
|
||||
|
||||
touch zerolength
|
||||
chgrp $EGID zerolength
|
||||
|
||||
touch $zlnfs
|
||||
chgrp $EGID $zlnfs
|
||||
|
||||
print 'Garbuglio' >nonzerolength
|
||||
|
||||
mkdir modish
|
||||
chgrp $EGID modish
|
||||
|
||||
chmod 7710 modish # g+xs,u+s,+t
|
||||
chmod g+s modish # two lines combined work around chmod bugs
|
||||
|
||||
touch unmodish
|
||||
chmod 000 unmodish
|
||||
|
||||
print 'MZ' > cmd.exe
|
||||
chmod +x cmd.exe
|
||||
%test
|
||||
|
||||
[[ -a zerolength && ! -a nonexistent ]]
|
||||
0:-a cond
|
||||
|
||||
# Find a block special file system. This is a little tricky.
|
||||
block=$(find /dev(|ices)/ -type b -print)
|
||||
if [[ -n $block ]]; then
|
||||
[[ -b $block[(f)1] && ! -b zerolength ]]
|
||||
else
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ -b blockdevice ]] (no devices found)'
|
||||
[[ ! -b zerolength ]]
|
||||
fi
|
||||
0D:-b cond
|
||||
|
||||
# Use hardcoded /dev/tty because globbing inside /dev fails on Cygwin
|
||||
char=/dev/tty
|
||||
[[ -c $char && ! -c $zerolength ]]
|
||||
0:-c cond
|
||||
|
||||
[[ -d . && ! -d zerolength ]]
|
||||
0:-d cond
|
||||
|
||||
[[ -e zerolength && ! -e nonexistent ]]
|
||||
0:-e cond
|
||||
|
||||
if [[ -n $block ]]; then
|
||||
[[ -f zerolength && ! -f cond && ! -f $char && ! -f $block[(f)1] && ! -f . ]]
|
||||
else
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ -f blockdevice ]] (no devices found)'
|
||||
[[ -f zerolength && ! -f cond && ! -f $char && ! -f . ]]
|
||||
fi
|
||||
0:-f cond
|
||||
|
||||
[[ -g modish && ! -g zerolength ]]
|
||||
0:-g cond
|
||||
|
||||
ln -s zerolength link
|
||||
[[ -h link && ! -h zerolength ]]
|
||||
0:-h cond
|
||||
|
||||
[[ -k modish && ! -k zerolength ]]
|
||||
0:-k cond
|
||||
|
||||
foo=foo
|
||||
bar=
|
||||
[[ -n $foo && ! -n $bar && ! -n '' ]]
|
||||
0:-n cond
|
||||
|
||||
[[ -o rcs && ! -o norcs && -o noerrexit && ! -o errexit ]]
|
||||
0:-o cond
|
||||
|
||||
if ! grep '#define HAVE_FIFOS' $ZTST_testdir/../config.h; then
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ -p pipe ]] (FIFOs not supported)'
|
||||
[[ ! -p zerolength ]]
|
||||
else
|
||||
if whence mkfifo && mkfifo pipe || mknod pipe p; then
|
||||
[[ -p pipe && ! -p zerolength ]]
|
||||
else
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ -p pipe ]] (cannot create FIFO)'
|
||||
[[ ! -p zerolength ]]
|
||||
fi
|
||||
fi
|
||||
0dD:-p cond
|
||||
|
||||
if (( EUID == 0 )); then
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ ! -r file ]] (root reads anything)'
|
||||
[[ -r zerolength && -r unmodish ]]
|
||||
elif [[ $OSTYPE = cygwin ]]; then
|
||||
print -u$ZTST_fd 'Warning: Not testing [[ ! -r file ]]
|
||||
(all files created by user may be readable)'
|
||||
[[ -r zerolength ]]
|
||||
else
|
||||
[[ -r zerolength && ! -r unmodish ]]
|
||||
fi
|
||||
0:-r cond
|
||||
|
||||
[[ -s nonzerolength && ! -s zerolength ]]
|
||||
0:-s cond
|
||||
|
||||
# no simple way of guaranteeing test for -t
|
||||
|
||||
[[ -u modish && ! -u zerolength ]]
|
||||
0:-u cond
|
||||
|
||||
[[ -x cmd.exe && ! -x zerolength ]]
|
||||
0:-x cond
|
||||
|
||||
[[ -z $bar && -z '' && ! -z $foo ]]
|
||||
0:-z cond
|
||||
|
||||
[[ -L link && ! -L zerolength ]]
|
||||
0:-L cond
|
||||
|
||||
# hard to guarantee a file not owned by current uid
|
||||
[[ -O zerolength ]]
|
||||
0:-O cond
|
||||
|
||||
[[ -G zerolength ]]
|
||||
0:-G cond
|
||||
|
||||
# can't be bothered with -S
|
||||
|
||||
if [[ ${mtab::="$({mount || /sbin/mount || /usr/sbin/mount} 2>/dev/null)"} = *[(]?*[)] ]]; then
|
||||
print -u $ZTST_fd 'This test takes two seconds...'
|
||||
else
|
||||
unmodified_ls="$(ls -lu $unmodified)"
|
||||
print -u $ZTST_fd 'This test takes up to 60 seconds...'
|
||||
fi
|
||||
sleep 2
|
||||
touch $newnewnew
|
||||
if [[ $OSTYPE == "cygwin" ]]; then
|
||||
ZTST_skip="[[ -N file ]] not supported on Cygwin"
|
||||
elif (( isnfs )); then
|
||||
ZTST_skip="[[ -N file ]] not supported with NFS"
|
||||
elif { (( ! $+unmodified_ls )) &&
|
||||
cat $unmodified &&
|
||||
{ df -k -- ${$(print -r -- "$mtab" |
|
||||
awk '/noatime/ {print $1,$3}'):-""} | tr -s ' ' |
|
||||
fgrep -- "$(df -k . | tail -1 | tr -s ' ')" } >&/dev/null } ||
|
||||
{ (( $+unmodified_ls )) && SECONDS=0 &&
|
||||
! until (( SECONDS >= 58 )); do
|
||||
ZTST_hashmark; sleep 2; cat $unmodified
|
||||
[[ $unmodified_ls != "$(ls -lu $unmodified)" ]] && break
|
||||
done }; then
|
||||
ZTST_skip="[[ -N file ]] not supported with noatime file system"
|
||||
else
|
||||
[[ -N $newnewnew && ! -N $unmodified ]]
|
||||
fi
|
||||
0:-N cond
|
||||
F:This test can fail on NFS-mounted filesystems as the access and
|
||||
F:modification times are not updated separately. The test will fail
|
||||
F:on HFS+ (Apple Mac OS X default) filesystems because access times
|
||||
F:are not recorded. Also, Linux ext3 filesystems may be mounted
|
||||
F:with the noatime option which does not update access times.
|
||||
F:Failures in these cases do not indicate a problem in the shell.
|
||||
|
||||
[[ $newnewnew -nt $zlnfs && ! ($unmodified -nt $zlnfs) ]]
|
||||
0:-nt cond
|
||||
|
||||
[[ $zlnfs -ot $newnewnew && ! ($zlnfs -ot $unmodified) ]]
|
||||
0:-ot cond
|
||||
|
||||
[[ link -ef zerolength && ! (link -ef nonzerolength) ]]
|
||||
0:-ef cond
|
||||
|
||||
[[ foo = foo && foo != bar && foo == foo && foo != '' ]]
|
||||
0:=, == and != conds
|
||||
|
||||
[[ bar < foo && foo > bar ]]
|
||||
0:< and > conds
|
||||
|
||||
[[ $(( 3 + 4 )) -eq 0x07 && $(( 5 * 2 )) -ne 0x10 ]]
|
||||
0:-eq and -ne conds
|
||||
|
||||
[[ 3 -lt 04 && 05 -gt 2 ]]
|
||||
0:-lt and -gt conds
|
||||
|
||||
[[ 3 -le 3 && ! (4 -le 3) ]]
|
||||
0:-le cond
|
||||
|
||||
[[ 3 -ge 3 && ! (3 -ge 4) ]]
|
||||
0:-ge cond
|
||||
|
||||
[[ 1 -lt 2 || 2 -lt 2 && 3 -gt 4 ]]
|
||||
0:|| and && in conds
|
||||
|
||||
if ! grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h; then
|
||||
print -u$ZTST_fd "Warning: not testing [[ -e /dev/fd/0 ]] (/dev/fd not supported)"
|
||||
true
|
||||
else
|
||||
[[ -e /dev/fd/0 ]]
|
||||
fi
|
||||
0dD:/dev/fd support in conds handled by access
|
||||
|
||||
if ! grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h; then
|
||||
print -u$ZTST_fd "Warning: not testing [[ -O /dev/fd/0 ]] (/dev/fd not supported)"
|
||||
true
|
||||
else
|
||||
[[ -O /dev/fd/0 ]]
|
||||
fi
|
||||
0dD:/dev/fd support in conds handled by stat
|
||||
|
||||
[[ ( -z foo && -z foo ) || -z foo ]]
|
||||
1:complex conds with skipping
|
||||
|
||||
[ '' != bar -a '' = '' ]
|
||||
0:strings with `[' builtin
|
||||
|
||||
[ `echo 0` -lt `echo 1` ]
|
||||
0:substitution in `[' builtin
|
||||
|
||||
[ -n foo scrimble ]
|
||||
2:argument checking for [ builtin
|
||||
?(eval):[:1: too many arguments
|
||||
|
||||
test -n foo scramble
|
||||
2:argument checking for test builtin
|
||||
?(eval):test:1: too many arguments
|
||||
|
||||
[ -n foo scrimble scromble ]
|
||||
2:argument checking for [ builtin
|
||||
?(eval):[:1: too many arguments
|
||||
|
||||
test -n foo scramble scrumble
|
||||
2:argument checking for test builtin
|
||||
?(eval):test:1: too many arguments
|
||||
|
||||
[ -n foo -a -n bar scrimble ]
|
||||
2:argument checking for [ builtin
|
||||
?(eval):[:1: too many arguments
|
||||
|
||||
test -n foo -a -z "" scramble
|
||||
2:argument checking for test builtin
|
||||
?(eval):test:1: too many arguments
|
||||
|
||||
fn() {
|
||||
# careful: first file must exist to trigger bug
|
||||
[[ -e $unmodified ]] || print Where\'s my file\?
|
||||
[[ $unmodified -nt NonExistentFile ]]
|
||||
print status = $?
|
||||
}
|
||||
fn
|
||||
0:-nt shouldn't abort on non-existent files
|
||||
>status = 1
|
||||
|
||||
str='string' empty=''
|
||||
[[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]]
|
||||
0:-v cond
|
||||
|
||||
arr=( 1 2 3 4 ) empty=()
|
||||
[[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] &&
|
||||
-v arr[(i)3] && ! -v arr[(i)x] &&
|
||||
! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] &&
|
||||
! -v arr[3]extra && -v empty && ! -v empty[1] ]]
|
||||
0:-v cond with array
|
||||
|
||||
typeset -A assoc=( key val num 4 )
|
||||
[[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] &&
|
||||
! -v assoc[x] && ! -v assoc[key][1] ]]
|
||||
0:-v cond with association
|
||||
|
||||
() { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg ''
|
||||
0:-v cond with positional parameters
|
||||
|
||||
# core dumps on failure
|
||||
if zmodload zsh/regex 2>/dev/null; then
|
||||
echo >regex_test.sh 'if [[ $# = 1 ]]; then
|
||||
if [[ $1 =~ /?[^/]+:[0-9]+:$ ]]; then
|
||||
:
|
||||
fi
|
||||
fi
|
||||
exit 0'
|
||||
$ZTST_testdir/../Src/zsh -f ./regex_test.sh
|
||||
fi
|
||||
0:regex tests shouldn't crash
|
||||
|
||||
if zmodload zsh/regex 2>/dev/null; then
|
||||
( # subshell in case coredump test failed
|
||||
string="this has stuff in it"
|
||||
bad_regex=0
|
||||
if [[ $string =~ "h([a-z]*) s([a-z]*) " ]]; then
|
||||
if [[ "$MATCH $MBEGIN $MEND" != "has stuff 6 15" ]]; then
|
||||
print -r "regex variables MATCH MBEGIN MEND:
|
||||
'$MATCH $MBEGIN $MEND'
|
||||
should be:
|
||||
'has stuff 6 15'"
|
||||
bad_regex=1
|
||||
else
|
||||
results=("as 7 8" "tuff 11 14")
|
||||
for i in 1 2; do
|
||||
if [[ "$match[$i] $mbegin[$i] $mend[$i]" != $results[i] ]]; then
|
||||
print -r "regex variables match[$i] mbegin[$i] mend[$i]:
|
||||
'$match[$i] $mbegin[$i] $mend[$i]'
|
||||
should be
|
||||
'$results[$i]'"
|
||||
bad_regex=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
(( bad_regex )) || print OK
|
||||
else
|
||||
print -r "regex failed to match '$string'"
|
||||
fi
|
||||
)
|
||||
else
|
||||
# if it didn't load, tough, but not a test error
|
||||
ZTST_skip="regexp library not found."
|
||||
fi
|
||||
0:MATCH, MBEGIN, MEND, match, mbegin, mend
|
||||
>OK
|
||||
|
||||
if zmodload zsh/regex 2>/dev/null; then
|
||||
( # subshell because regex module may dump core, see above
|
||||
if [[ a =~ a && b == b ]]; then
|
||||
print OK
|
||||
else
|
||||
print "regex =~ inverted following test"
|
||||
fi
|
||||
)
|
||||
else
|
||||
# not a test error
|
||||
ZTST_skip="regexp library not found."
|
||||
fi
|
||||
0:regex infix operator should not invert following conditions
|
||||
>OK
|
||||
|
||||
[[ -fail badly ]]
|
||||
2:Error message for unknown prefix condition
|
||||
?(eval):1: unknown condition: -fail
|
||||
|
||||
[[ really -fail badly ]]
|
||||
2:Error message for unknown infix condition
|
||||
?(eval):1: unknown condition: -fail
|
||||
|
||||
crashme() {
|
||||
if [[ $1 =~ ^http:* ]]
|
||||
then
|
||||
url=${1#*=}
|
||||
fi
|
||||
}
|
||||
which crashme
|
||||
0:Regression test for examining code with regular expression match
|
||||
>crashme () {
|
||||
> if [[ $1 =~ ^http:* ]]
|
||||
> then
|
||||
> url=${1#*=}
|
||||
> fi
|
||||
>}
|
||||
|
||||
weirdies=(
|
||||
'! -a !'
|
||||
'! -o !'
|
||||
'! -a'
|
||||
'! -o'
|
||||
'! -a ! -a !'
|
||||
'! = !'
|
||||
'! !'
|
||||
'= -a o'
|
||||
'! = -a o')
|
||||
for w in $weirdies; do
|
||||
eval test $w
|
||||
print $?
|
||||
done
|
||||
0:test compatability weirdness: treat ! as a string sometimes
|
||||
>0
|
||||
>0
|
||||
>1
|
||||
>0
|
||||
>0
|
||||
>0
|
||||
>1
|
||||
>0
|
||||
>1
|
||||
|
||||
foo=''
|
||||
[[ $foo ]] || print foo is empty
|
||||
foo=full
|
||||
[[ $foo ]] && print foo is full
|
||||
0:bash compatibility with single [[ ... ]] argument
|
||||
>foo is empty
|
||||
>foo is full
|
||||
|
||||
test -z \( || print Not zero 1
|
||||
test -z \< || print Not zero 2
|
||||
test -n \( && print Not zero 3
|
||||
test -n \) && print Not zero 4
|
||||
[ -n \> ] && print Not zero 5
|
||||
[ -n \! ] && print Not zero 6
|
||||
0:test with two arguments and a token
|
||||
>Not zero 1
|
||||
>Not zero 2
|
||||
>Not zero 3
|
||||
>Not zero 4
|
||||
>Not zero 5
|
||||
>Not zero 6
|
||||
|
||||
[ '(' = ')' ] || print OK 1
|
||||
[ '((' = '))' ] || print OK 2
|
||||
[ '(' = '(' ] && print OK 3
|
||||
[ '(' non-empty-string ')' ] && echo OK 4
|
||||
[ '(' '' ')' ] || echo OK 5
|
||||
0:yet more old-fashioned test fix ups: prefer comparison to parentheses
|
||||
>OK 1
|
||||
>OK 2
|
||||
>OK 3
|
||||
>OK 4
|
||||
>OK 5
|
||||
|
||||
fn() { [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]] }
|
||||
which -x2 fn
|
||||
0: = and == appear as input
|
||||
>fn () {
|
||||
> [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]]
|
||||
>}
|
||||
|
||||
%clean
|
||||
# This works around a bug in rm -f in some versions of Cygwin
|
||||
chmod 644 unmodish
|
||||
for tmpfile in $newnewnew $unmodified $zlnfs; do
|
||||
[[ -f $tmpfile ]] && rm -f $tmpfile
|
||||
done
|
||||
|
|
@ -1,761 +0,0 @@
|
|||
# Tests for both trap builtin and TRAP* functions.
|
||||
|
||||
%prep
|
||||
|
||||
setopt localtraps
|
||||
mkdir traps.tmp && cd traps.tmp
|
||||
|
||||
%test
|
||||
|
||||
fn1() {
|
||||
trap 'print EXIT1' EXIT
|
||||
fn2() { trap 'print EXIT2' EXIT; }
|
||||
fn2
|
||||
}
|
||||
fn1
|
||||
0:Nested `trap ... EXIT'
|
||||
>EXIT2
|
||||
>EXIT1
|
||||
|
||||
fn1() {
|
||||
TRAPEXIT() { print EXIT1; }
|
||||
fn2() { TRAPEXIT() { print EXIT2; }; }
|
||||
fn2
|
||||
}
|
||||
fn1
|
||||
0: Nested TRAPEXIT
|
||||
>EXIT2
|
||||
>EXIT1
|
||||
|
||||
fn1() {
|
||||
trap 'print EXIT1' EXIT
|
||||
fn2() { trap - EXIT; }
|
||||
fn2
|
||||
}
|
||||
fn1
|
||||
0:Nested `trap - EXIT' on `trap ... EXIT'
|
||||
>EXIT1
|
||||
|
||||
fn1() {
|
||||
TRAPEXIT() { print EXIT1; }
|
||||
fn2() { trap - EXIT; }
|
||||
fn2
|
||||
}
|
||||
fn1
|
||||
0:Nested `trap - EXIT' on `TRAPEXIT'
|
||||
>EXIT1
|
||||
|
||||
# We can't test an EXIT trap for the shell as a whole, because
|
||||
# we're inside a function scope which we don't leave when the
|
||||
# subshell exits. Not sure if that's the correct behaviour, but
|
||||
# it's sort of consistent.
|
||||
( fn1() { trap 'print Function 1 going' EXIT; exit; print Not reached; }
|
||||
fn2() { trap 'print Function 2 going' EXIT; fn1; print Not reached; }
|
||||
fn2
|
||||
)
|
||||
0:EXIT traps on functions when exiting from function
|
||||
>Function 1 going
|
||||
>Function 2 going
|
||||
|
||||
# $ZTST_exe is relative to the parent directory.
|
||||
# We ought to fix this in ztst.zsh...
|
||||
(cd ..
|
||||
$ZTST_exe -fc 'TRAPEXIT() { print Exited.; }')
|
||||
0:EXIT traps on a script
|
||||
>Exited.
|
||||
|
||||
trap -
|
||||
trap
|
||||
trap int INT
|
||||
trap sigterm SIGTERM
|
||||
trap quit 3
|
||||
trap
|
||||
0: Outputting traps correctly
|
||||
>trap -- int INT
|
||||
>trap -- quit QUIT
|
||||
>trap -- sigterm TERM
|
||||
|
||||
fn1() {
|
||||
trap -
|
||||
trap
|
||||
trap 'print INT1' INT
|
||||
fn2() { trap 'print INT2' INT; trap; }
|
||||
trap
|
||||
fn2
|
||||
trap
|
||||
}
|
||||
fn1
|
||||
0: Nested `trap ... INT', not triggered
|
||||
>trap -- 'print INT1' INT
|
||||
>trap -- 'print INT2' INT
|
||||
>trap -- 'print INT1' INT
|
||||
|
||||
fn1() {
|
||||
trap -
|
||||
trap
|
||||
TRAPINT() { print INT1; }
|
||||
fn2() { TRAPINT() { print INT2; }; trap; }
|
||||
trap
|
||||
fn2
|
||||
trap
|
||||
}
|
||||
fn1
|
||||
0: Nested TRAPINT, not triggered
|
||||
>TRAPINT () {
|
||||
> print INT1
|
||||
>}
|
||||
>TRAPINT () {
|
||||
> print INT2
|
||||
>}
|
||||
>TRAPINT () {
|
||||
> print INT1
|
||||
>}
|
||||
|
||||
fn1() {
|
||||
trap -
|
||||
trap 'print INT1' INT
|
||||
fn2() { trap - INT; trap; }
|
||||
trap
|
||||
fn2
|
||||
trap
|
||||
}
|
||||
fn1
|
||||
0: Nested `trap - INT' on untriggered `trap ... INT'
|
||||
>trap -- 'print INT1' INT
|
||||
>trap -- 'print INT1' INT
|
||||
|
||||
# Testing the triggering of traps here is very unpleasant.
|
||||
# The delays are attempts to avoid race conditions, though there is
|
||||
# no guarantee that they will work. Note the subtlety that the
|
||||
# `sleep' in the function which receives the trap does *not* get the
|
||||
# signal, only the parent shell, which is waiting for a SIGCHILD.
|
||||
# (At least, that's what I think is happening.) Thus we have to wait at
|
||||
# least the full two seconds to make sure we have got the output from the
|
||||
# execution of the trap.
|
||||
|
||||
print -u $ZTST_fd 'This test takes at least three seconds...'
|
||||
fn1() {
|
||||
trap 'print TERM1' TERM
|
||||
fn2() { trap 'print TERM2; return 1' TERM; sleep 2; }
|
||||
fn2 &
|
||||
sleep 1
|
||||
kill -TERM $!
|
||||
sleep 2
|
||||
}
|
||||
fn1
|
||||
0: Nested `trap ... TERM', triggered on inner loop
|
||||
>TERM2
|
||||
|
||||
print -u $ZTST_fd 'This test, too, takes at least three seconds...'
|
||||
fn1() {
|
||||
trap 'print TERM1; return 1' TERM
|
||||
fn2() { trap 'print TERM2; return 1' TERM; }
|
||||
fn2
|
||||
sleep 2
|
||||
}
|
||||
fn1 &
|
||||
sleep 1
|
||||
kill -TERM $!
|
||||
sleep 2
|
||||
0: Nested `trap ... TERM', triggered on outer loop
|
||||
>TERM1
|
||||
|
||||
TRAPZERR() { print error activated; }
|
||||
fn() { print start of fn; false; print end of fn; }
|
||||
fn
|
||||
fn() {
|
||||
setopt localoptions localtraps
|
||||
unfunction TRAPZERR
|
||||
print start of fn
|
||||
false
|
||||
print end of fn
|
||||
}
|
||||
fn
|
||||
unfunction TRAPZERR
|
||||
print finish
|
||||
0: basic localtraps handling
|
||||
>start of fn
|
||||
>error activated
|
||||
>end of fn
|
||||
>start of fn
|
||||
>end of fn
|
||||
>finish
|
||||
|
||||
TRAPZERR() { print 'ERR-or!'; }
|
||||
f() { print f; false; }
|
||||
t() { print t; }
|
||||
f
|
||||
f && t
|
||||
t && f && true
|
||||
t && f
|
||||
testunset() {
|
||||
setopt localtraps
|
||||
unset -f TRAPZERR
|
||||
print testunset
|
||||
false
|
||||
true
|
||||
}
|
||||
testunset
|
||||
f
|
||||
print status $?
|
||||
unfunction TRAPZERR
|
||||
0: more sophisticated error trapping
|
||||
>f
|
||||
>ERR-or!
|
||||
>f
|
||||
>t
|
||||
>f
|
||||
>t
|
||||
>f
|
||||
>ERR-or!
|
||||
>testunset
|
||||
>f
|
||||
>ERR-or!
|
||||
>status 1
|
||||
|
||||
f() {
|
||||
setopt localtraps
|
||||
TRAPWINCH() { print "Window changed. That wrecked the test."; }
|
||||
}
|
||||
f
|
||||
f
|
||||
functions TRAPWINCH
|
||||
1:Unsetting ordinary traps with localtraps.
|
||||
|
||||
#
|
||||
# Returns from within traps are a perennial problem.
|
||||
# The following two apply to returns in and around standard
|
||||
# ksh-style traps. The intention is that a return value from
|
||||
# within the function is preserved (i.e. statuses set by the trap
|
||||
# are ignored) unless the trap explicitly executes `return', which makes
|
||||
# it return from the enclosing function.
|
||||
#
|
||||
fn() { trap 'true' EXIT; return 1; }
|
||||
fn
|
||||
1: ksh-style EXIT traps preserve return value
|
||||
|
||||
inner() { trap 'return 3' EXIT; return 2; }
|
||||
outer() { inner; return 1; }
|
||||
outer
|
||||
3: ksh-style EXIT traps can force return status of enclosing function
|
||||
|
||||
# Autoloaded traps are horrid, but unfortunately people expect
|
||||
# them to work if we support them.
|
||||
echo "print Running exit trap" >TRAPEXIT
|
||||
${${ZTST_exe##[^/]*}:-$ZTST_testdir/$ZTST_exe} -fc '
|
||||
fpath=(. $fpath)
|
||||
autoload TRAPEXIT
|
||||
print "Exiting, attempt 1"
|
||||
exit
|
||||
print "What?"
|
||||
'
|
||||
${${ZTST_exe##[^/]*}:-$ZTST_testdir/$ZTST_exe} -fc '
|
||||
fpath=(. $fpath)
|
||||
autoload TRAPEXIT;
|
||||
fn() { print Some function }
|
||||
fn
|
||||
print "Exiting, attempt 2"
|
||||
exit
|
||||
'
|
||||
0: autoloaded TRAPEXIT (exit status > 128 indicates an old bug is back)
|
||||
>Exiting, attempt 1
|
||||
>Running exit trap
|
||||
>Some function
|
||||
>Exiting, attempt 2
|
||||
>Running exit trap
|
||||
|
||||
print -u $ZTST_fd Another test that takes three seconds
|
||||
gotsig=0
|
||||
signal_handler() {
|
||||
echo "parent received signal"
|
||||
gotsig=1
|
||||
}
|
||||
child() {
|
||||
sleep 1
|
||||
echo "child sending signal"
|
||||
kill -15 $parentpid
|
||||
sleep 2
|
||||
echo "child exiting"
|
||||
exit 33
|
||||
}
|
||||
parentpid=$$
|
||||
child &
|
||||
childpid=$!
|
||||
trap signal_handler 15
|
||||
echo "parent waiting"
|
||||
wait $childpid
|
||||
cstatus=$?
|
||||
echo "wait #1 finished, gotsig=$gotsig, status=$cstatus"
|
||||
gotsig=0
|
||||
wait $childpid
|
||||
cstatus=$?
|
||||
echo "wait #2 finished, gotsig=$gotsig, status=$cstatus"
|
||||
0:waiting for trapped signal
|
||||
>parent waiting
|
||||
>child sending signal
|
||||
>parent received signal
|
||||
>wait #1 finished, gotsig=1, status=143
|
||||
>child exiting
|
||||
>wait #2 finished, gotsig=0, status=33
|
||||
|
||||
fn1() {
|
||||
setopt errexit
|
||||
trap 'echo error1' ZERR
|
||||
false
|
||||
print Shouldn\'t get here 1a
|
||||
}
|
||||
fn2() {
|
||||
setopt errexit
|
||||
trap 'echo error2' ZERR
|
||||
return 1
|
||||
print Shouldn\'t get here 2a
|
||||
}
|
||||
fn3() {
|
||||
setopt errexit
|
||||
TRAPZERR() { echo error3; }
|
||||
false
|
||||
print Shouldn\'t get here 3a
|
||||
}
|
||||
fn4() {
|
||||
setopt errexit
|
||||
TRAPZERR() { echo error4; }
|
||||
return 1
|
||||
print Shouldn\'t get here 4a
|
||||
}
|
||||
(fn1; print Shouldn\'t get here 1b)
|
||||
(fn2; print Shouldn\'t get here 2b)
|
||||
(fn3; print Shouldn\'t get here 3b)
|
||||
(fn4; print Shouldn\'t get here 4b)
|
||||
1: Combination of ERR_EXIT and ZERR trap
|
||||
>error1
|
||||
>error2
|
||||
>error3
|
||||
>error4
|
||||
|
||||
fn1() { TRAPZERR() { print trap; return 42; }; false; print Broken; }
|
||||
(fn1)
|
||||
print Working $?
|
||||
0: Force return of containing function from TRAPZERR.
|
||||
>trap
|
||||
>Working 42
|
||||
|
||||
fn2() { trap 'print trap; return 42' ZERR; false; print Broken }
|
||||
(fn2)
|
||||
print Working $?
|
||||
0: Return with non-zero status triggered from within trap '...' ZERR.
|
||||
>trap
|
||||
>Working 42
|
||||
|
||||
fn3() { TRAPZERR() { print trap; return 0; }; false; print OK this time; }
|
||||
(fn3)
|
||||
print Working $?
|
||||
0: Normal return from TRAPZERR.
|
||||
>trap
|
||||
>OK this time
|
||||
>Working 0
|
||||
|
||||
fn4() { trap 'print trap; return 0' ZERR; false; print Broken; }
|
||||
(fn4)
|
||||
print Working $?
|
||||
0: Return with zero status triggered from within trap '...' ZERR.
|
||||
>trap
|
||||
>Working 0
|
||||
|
||||
{ trap 'echo This subshell is exiting' EXIT; } | cat
|
||||
0: EXIT trap set in current shell at left of pipeline
|
||||
>This subshell is exiting
|
||||
|
||||
( trap 'echo This subshell is also exiting' EXIT; ) | cat
|
||||
0: EXIT trap set in subshell at left of pipeline
|
||||
>This subshell is also exiting
|
||||
|
||||
( trap 'echo Should only appear once at the end' EXIT
|
||||
( : trap reset here ) | cat
|
||||
: trap not reset but not part of shell command list | cat
|
||||
echo nothing after this should appear $( : trap reset here too)
|
||||
)
|
||||
0: EXIT trap set in subshell reset in subsubshell
|
||||
>nothing after this should appear
|
||||
>Should only appear once at the end
|
||||
|
||||
echo $( trap 'echo command substitution exited' EXIT )
|
||||
0: EXIT trap set in command substitution
|
||||
>command substitution exited
|
||||
|
||||
(cd ..; $ZTST_exe -fc 'setopt posixtraps;
|
||||
TRAPEXIT() { print Exited; }
|
||||
fn1() { trap; }
|
||||
setopt localtraps # should be ignored by EXIT
|
||||
fn2() { TRAPEXIT() { print No, really exited; } }
|
||||
fn1
|
||||
fn2
|
||||
fn1')
|
||||
0:POSIX_TRAPS option
|
||||
>TRAPEXIT () {
|
||||
> print Exited
|
||||
>}
|
||||
>TRAPEXIT () {
|
||||
> print No, really exited
|
||||
>}
|
||||
>No, really exited
|
||||
|
||||
(cd ..; $ZTST_exe -fc 'unsetopt posixtraps;
|
||||
echo start program
|
||||
emulate sh -c '\''testfn() {
|
||||
echo start function
|
||||
set -o | grep posixtraps
|
||||
trap "echo EXIT TRAP TRIGGERED" EXIT
|
||||
echo end function
|
||||
}'\''
|
||||
testfn
|
||||
echo program continuing
|
||||
echo end of program')
|
||||
0:POSIX_TRAPS effect on EXIT trap is sticky
|
||||
>start program
|
||||
>start function
|
||||
>noposixtraps off
|
||||
>end function
|
||||
>program continuing
|
||||
>end of program
|
||||
>EXIT TRAP TRIGGERED
|
||||
|
||||
(cd ..; $ZTST_exe -fc '
|
||||
echo entering program
|
||||
emulate sh -c '\''trap "echo POSIX exit trap triggered" EXIT'\''
|
||||
fn() {
|
||||
trap "echo native zsh function-local exit trap triggered" EXIT
|
||||
echo entering native zsh function
|
||||
}
|
||||
fn
|
||||
echo exiting program
|
||||
')
|
||||
0:POSIX EXIT trap can have nested native mode EXIT trap
|
||||
>entering program
|
||||
>entering native zsh function
|
||||
>native zsh function-local exit trap triggered
|
||||
>exiting program
|
||||
>POSIX exit trap triggered
|
||||
|
||||
(cd ..; $ZTST_exe -fc '
|
||||
echo entering program
|
||||
emulate sh -c '\''spt() { trap "echo POSIX exit trap triggered" EXIT; }'\''
|
||||
fn() {
|
||||
trap "echo native zsh function-local exit trap triggered" EXIT
|
||||
echo entering native zsh function
|
||||
}
|
||||
spt
|
||||
fn
|
||||
echo exiting program
|
||||
')
|
||||
0:POSIX EXIT trap not replaced if defined within function
|
||||
>entering program
|
||||
>entering native zsh function
|
||||
>native zsh function-local exit trap triggered
|
||||
>exiting program
|
||||
>POSIX exit trap triggered
|
||||
|
||||
(set -e
|
||||
printf "a\nb\n" | while read line
|
||||
do
|
||||
[[ $line = a* ]] || continue
|
||||
((ctr++))
|
||||
[[ $line = foo ]]
|
||||
done
|
||||
echo "ctr = $ctr"
|
||||
)
|
||||
1:ERREXIT in loop with simple commands
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
if false; then
|
||||
false
|
||||
print No.
|
||||
else
|
||||
print Oh, yes
|
||||
fi
|
||||
}
|
||||
fn
|
||||
0:ERR_RETURN not triggered in if condition
|
||||
>Oh, yes
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
if true; then
|
||||
false
|
||||
print No.
|
||||
else
|
||||
print No, no.
|
||||
fi
|
||||
}
|
||||
fn
|
||||
1:ERR_RETURN in "if"
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
if false; then
|
||||
print No.
|
||||
else
|
||||
false
|
||||
print No, no.
|
||||
fi
|
||||
}
|
||||
fn
|
||||
1:ERR_RETURN in "else" branch (regression test)
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f =(<<<"
|
||||
if false; then
|
||||
:
|
||||
else
|
||||
if [[ -n '' ]]; then
|
||||
a=2
|
||||
fi
|
||||
print Yes
|
||||
fi
|
||||
")
|
||||
0:ERR_RETURN when false "if" is the first statement in an "else" (regression)
|
||||
>Yes
|
||||
F:Must be tested with a top-level script rather than source or function
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
print before
|
||||
false
|
||||
print after
|
||||
}
|
||||
fn
|
||||
1:ERR_RETURN, basic case
|
||||
>before
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
print before
|
||||
! true
|
||||
! false
|
||||
print after
|
||||
}
|
||||
fn
|
||||
0:ERR_RETURN with "!"
|
||||
>before
|
||||
>after
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
print before
|
||||
! true
|
||||
! false
|
||||
false
|
||||
print after
|
||||
}
|
||||
fn
|
||||
1:ERR_RETURN with "!" and a following false
|
||||
>before
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
print before
|
||||
! if true; then
|
||||
false
|
||||
fi
|
||||
print after
|
||||
}
|
||||
fn
|
||||
0:ERR_RETURN with "!" suppressed inside complex structure
|
||||
>before
|
||||
>after
|
||||
|
||||
fn() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
print before
|
||||
if true; then
|
||||
false
|
||||
fi
|
||||
print after
|
||||
}
|
||||
fn
|
||||
1:ERR_RETURN with no "!" suppression (control case)
|
||||
>before
|
||||
|
||||
(setopt err_return
|
||||
fn() {
|
||||
print before-in
|
||||
false && false
|
||||
}
|
||||
print before-out
|
||||
fn
|
||||
print after-out
|
||||
)
|
||||
1:ERR_RETURN with "&&" in function (regression test)
|
||||
>before-out
|
||||
>before-in
|
||||
|
||||
(setopt err_return
|
||||
fn() {
|
||||
print before-in
|
||||
false && false
|
||||
print after-in
|
||||
}
|
||||
print before-out
|
||||
fn
|
||||
print after-out
|
||||
)
|
||||
0:ERR_RETURN not triggered on LHS of "&&" in function
|
||||
>before-out
|
||||
>before-in
|
||||
>after-in
|
||||
>after-out
|
||||
|
||||
(setopt err_return
|
||||
fn() {
|
||||
print before-in
|
||||
true && false
|
||||
print after-in
|
||||
}
|
||||
print before-out
|
||||
fn
|
||||
print after-out
|
||||
)
|
||||
1:ERR_RETURN triggered on RHS of "&&" in function
|
||||
>before-out
|
||||
>before-in
|
||||
|
||||
(setopt err_exit
|
||||
for x in y; do
|
||||
false && true
|
||||
done
|
||||
print OK
|
||||
)
|
||||
0:ERR_EXIT not triggered by status 1 at end of for
|
||||
>OK
|
||||
|
||||
(setopt err_exit
|
||||
integer x=0
|
||||
while (( ! x++ )); do
|
||||
false && true
|
||||
done
|
||||
print OK
|
||||
)
|
||||
0:ERR_EXIT not triggered by status 1 at end of while
|
||||
>OK
|
||||
|
||||
(setopt err_exit
|
||||
repeat 1; do
|
||||
false && true
|
||||
done
|
||||
print OK
|
||||
)
|
||||
0:ERR_EXIT not triggered by status 1 at end of repeat
|
||||
>OK
|
||||
|
||||
(setopt err_exit
|
||||
if true; then
|
||||
false && true
|
||||
fi
|
||||
print OK
|
||||
)
|
||||
0:ERR_EXIT not triggered by status 1 at end of if
|
||||
>OK
|
||||
|
||||
(setopt err_exit
|
||||
{
|
||||
false && true
|
||||
}
|
||||
print OK
|
||||
)
|
||||
0:ERR_EXIT not triggered by status 1 at end of { }
|
||||
>OK
|
||||
|
||||
(setopt err_exit
|
||||
for x in y; do
|
||||
false
|
||||
done
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 within for
|
||||
|
||||
(setopt err_exit
|
||||
integer x=0
|
||||
while (( ! x++ )); do
|
||||
false
|
||||
done
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 within while
|
||||
|
||||
(setopt err_exit
|
||||
repeat 1; do
|
||||
false
|
||||
done
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 within repeat
|
||||
|
||||
(setopt err_exit
|
||||
if true; then
|
||||
false
|
||||
fi
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 within if
|
||||
|
||||
(setopt err_exit
|
||||
{
|
||||
false
|
||||
}
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 within { }
|
||||
|
||||
(setopt err_exit
|
||||
() {
|
||||
false && true
|
||||
print Still functioning
|
||||
false && true
|
||||
}
|
||||
print OK
|
||||
)
|
||||
1:ERR_EXIT triggered by status 1 at end of anon func
|
||||
>Still functioning
|
||||
|
||||
if zmodload zsh/system 2>/dev/null; then
|
||||
(
|
||||
trap 'echo TERM; exit 2' TERM
|
||||
trap 'echo EXIT' EXIT
|
||||
kill -s TERM "$sysparams[pid]"
|
||||
echo 'FATAL: we should never get here!' 1>&2
|
||||
exit 1
|
||||
)
|
||||
else
|
||||
ZTST_skip="zsh/system library not found."
|
||||
fi
|
||||
2:EXIT trap from TERM trap
|
||||
>TERM
|
||||
>EXIT
|
||||
|
||||
# Should not get "hello" in the single quotes.
|
||||
(
|
||||
trap "echo hello" EXIT;
|
||||
{ :; } | { read line; print "'$line'"; }
|
||||
)
|
||||
0:EXIT trap not called in LHS of pipeline: Shell construct on LHS
|
||||
>''
|
||||
>hello
|
||||
|
||||
(
|
||||
trap "echo hello" EXIT;
|
||||
cat </dev/null | { read line; print "'$line'"; }
|
||||
)
|
||||
0:EXIT trap not called in LHS of pipeline: External command on LHS
|
||||
>''
|
||||
>hello
|
||||
|
||||
%clean
|
||||
|
||||
rm -f TRAPEXIT
|
||||
|
|
@ -1,502 +0,0 @@
|
|||
%prep
|
||||
|
||||
mkdir funcdef.tmp
|
||||
cd funcdef.tmp
|
||||
setopt chaselinks
|
||||
cd .
|
||||
unsetopt chaselinks
|
||||
mydir=$PWD
|
||||
|
||||
%test
|
||||
|
||||
fn1() { return 1; }
|
||||
fn2() {
|
||||
fn1
|
||||
print $?
|
||||
return 2
|
||||
}
|
||||
fn2
|
||||
2:Basic status returns from functions
|
||||
>1
|
||||
|
||||
fnz() { }
|
||||
false
|
||||
fnz
|
||||
0:Empty function body resets status
|
||||
|
||||
fn3() { return 3; }
|
||||
fnstat() { print $?; }
|
||||
fn3
|
||||
fnstat
|
||||
0:Status is not reset on non-empty function body
|
||||
>3
|
||||
|
||||
function f$$ () {
|
||||
print regress expansion of function names
|
||||
}
|
||||
f$$
|
||||
0:Regression test: 'function f$$ () { ... }'
|
||||
>regress expansion of function names
|
||||
|
||||
function foo () print bar
|
||||
foo
|
||||
0:Function definition without braces
|
||||
>bar
|
||||
|
||||
functions -M m1
|
||||
m1() { (( $# )) }
|
||||
print $(( m1() ))
|
||||
print $(( m1(1) ))
|
||||
print $(( m1(1,2) ))
|
||||
0:User-defined math functions, argument handling
|
||||
>0
|
||||
>1
|
||||
>2
|
||||
|
||||
functions -M m2
|
||||
m2() {
|
||||
integer sum
|
||||
local val
|
||||
for val in $*; do
|
||||
(( sum += $val ))
|
||||
done
|
||||
}
|
||||
print $(( m2(1) ))
|
||||
print $(( m2(1,3+3,4**2) ))
|
||||
0:User-defined math functions, complex argument handling
|
||||
>1
|
||||
>23
|
||||
|
||||
functions -M m3 1 2
|
||||
m3() { (( 1 )) }
|
||||
print zero
|
||||
(print $(( m3() )))
|
||||
print one
|
||||
print $(( m3(1) ))
|
||||
print two
|
||||
print $(( m3(1,2) ))
|
||||
print three
|
||||
(print $(( m3(1,2,3) )))
|
||||
1:User-defined math functions, argument checking
|
||||
>zero
|
||||
>one
|
||||
>1
|
||||
>two
|
||||
>1
|
||||
>three
|
||||
?(eval):4: wrong number of arguments: m3()
|
||||
?(eval):10: wrong number of arguments: m3(1,2,3)
|
||||
|
||||
functions -M m4 0 0 testmathfunc
|
||||
functions -M m5 0 0 testmathfunc
|
||||
testmathfunc() {
|
||||
if [[ $0 = m4 ]]; then
|
||||
(( 4 ))
|
||||
else
|
||||
(( 5 ))
|
||||
fi
|
||||
}
|
||||
print $(( m4() ))
|
||||
print $(( m5() ))
|
||||
0:User-defined math functions, multiple interfaces
|
||||
>4
|
||||
>5
|
||||
|
||||
command_not_found_handler() {
|
||||
print "Great News! I've handled the command:"
|
||||
print "$1"
|
||||
print "with arguments:"
|
||||
print -l ${argv[2,-1]}
|
||||
}
|
||||
ACommandWhichHadBetterNotExistOnTheSystem and some "really useful" args
|
||||
0:Command not found handler, success
|
||||
>Great News! I've handled the command:
|
||||
>ACommandWhichHadBetterNotExistOnTheSystem
|
||||
>with arguments:
|
||||
>and
|
||||
>some
|
||||
>really useful
|
||||
>args
|
||||
|
||||
# ' deconfuse emacs
|
||||
|
||||
command_not_found_handler() {
|
||||
print "Your command:" >&2
|
||||
print "$1" >&2
|
||||
print "has gone down the tubes. Sorry." >&2
|
||||
return 42
|
||||
}
|
||||
ThisCommandDoesNotExistEither
|
||||
42:Command not found handler, failure
|
||||
?Your command:
|
||||
?ThisCommandDoesNotExistEither
|
||||
?has gone down the tubes. Sorry.
|
||||
|
||||
local variable=outside
|
||||
print "I am $variable"
|
||||
function {
|
||||
local variable=inside
|
||||
print "I am $variable"
|
||||
}
|
||||
print "I am $variable"
|
||||
() {
|
||||
local variable="inside again"
|
||||
print "I am $variable"
|
||||
}
|
||||
print "I am $variable"
|
||||
0:Anonymous function scope
|
||||
>I am outside
|
||||
>I am inside
|
||||
>I am outside
|
||||
>I am inside again
|
||||
>I am outside
|
||||
|
||||
integer i
|
||||
for (( i = 0; i < 10; i++ )); do function {
|
||||
case $i in
|
||||
([13579])
|
||||
print $i is odd
|
||||
;|
|
||||
([2468])
|
||||
print $i is even
|
||||
;|
|
||||
([2357])
|
||||
print $i is prime
|
||||
;;
|
||||
esac
|
||||
}; done
|
||||
0:Anonymous function with patterns in loop
|
||||
>1 is odd
|
||||
>2 is even
|
||||
>2 is prime
|
||||
>3 is odd
|
||||
>3 is prime
|
||||
>4 is even
|
||||
>5 is odd
|
||||
>5 is prime
|
||||
>6 is even
|
||||
>7 is odd
|
||||
>7 is prime
|
||||
>8 is even
|
||||
>9 is odd
|
||||
|
||||
echo stuff in file >file.in
|
||||
function {
|
||||
sed 's/stuff/rubbish/'
|
||||
} <file.in >file.out
|
||||
cat file.out
|
||||
0:Anonymous function redirection
|
||||
>rubbish in file
|
||||
|
||||
variable="Do be do"
|
||||
print $variable
|
||||
function {
|
||||
print $variable
|
||||
local variable="Da de da"
|
||||
print $variable
|
||||
function {
|
||||
print $variable
|
||||
local variable="Dum da dum"
|
||||
print $variable
|
||||
}
|
||||
print $variable
|
||||
}
|
||||
print $variable
|
||||
0:Nested anonymous functions
|
||||
>Do be do
|
||||
>Do be do
|
||||
>Da de da
|
||||
>Da de da
|
||||
>Dum da dum
|
||||
>Da de da
|
||||
>Do be do
|
||||
|
||||
() (cat $1 $2) <(print process expanded) =(print expanded to file)
|
||||
0:Process substitution with anonymous functions
|
||||
>process expanded
|
||||
>expanded to file
|
||||
|
||||
() { print This has arguments $*; } of all sorts; print After the function
|
||||
function { print More stuff $*; } and why not; print Yet more
|
||||
0:Anonymous function with arguments
|
||||
>This has arguments of all sorts
|
||||
>After the function
|
||||
>More stuff and why not
|
||||
>Yet more
|
||||
|
||||
fn() {
|
||||
(){ print Anonymous function 1 $*; } with args
|
||||
function { print Anonymous function 2 $*; } with more args
|
||||
print Following bit
|
||||
}
|
||||
functions fn
|
||||
0:Text representation of anonymous function with arguments
|
||||
>fn () {
|
||||
> () {
|
||||
> print Anonymous function 1 $*
|
||||
> } with args
|
||||
> () {
|
||||
> print Anonymous function 2 $*
|
||||
> } with more args
|
||||
> print Following bit
|
||||
>}
|
||||
|
||||
touch yes no
|
||||
() { echo $1 } (y|z)*
|
||||
(echo here)
|
||||
() { echo $* } some (y|z)*
|
||||
() { echo empty };(echo here)
|
||||
0:Anonymous function arguments and command arguments
|
||||
>yes
|
||||
>here
|
||||
>some yes
|
||||
>empty
|
||||
>here
|
||||
|
||||
if true; then f() { echo foo1; } else f() { echo bar1; } fi; f
|
||||
if false; then f() { echo foo2; } else f() { echo bar2; } fi; f
|
||||
0:Compatibility with other shells when not anonymous functions
|
||||
>foo1
|
||||
>bar2
|
||||
|
||||
(
|
||||
setopt ignorebraces
|
||||
fpath=(.)
|
||||
print "{ echo OK }\n[[ -o ignorebraces ]] || print 'ignorebraces is off'" \
|
||||
>emufunctest
|
||||
(autoload -z emufunctest; emufunctest) 2>&1
|
||||
emulate zsh -c 'autoload -Uz emufunctest'
|
||||
emufunctest
|
||||
[[ -o ignorebraces ]] && print 'ignorebraces is still on here'
|
||||
)
|
||||
0:sticky emulation applies to autoloads and autoloaded function execution
|
||||
>emufunctest:3: parse error near `\n'
|
||||
>OK
|
||||
>ignorebraces is off
|
||||
>ignorebraces is still on here
|
||||
#` (matching error message for editors parsing the file)
|
||||
|
||||
# lsfoo should not be expanded as an anonymous function argument
|
||||
alias lsfoo='This is not ls.'
|
||||
() (echo anon func; echo "$@") lsfoo
|
||||
0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway
|
||||
>anon func
|
||||
>lsfoo
|
||||
|
||||
print foo | () cat
|
||||
0:Simple anonymous function should not simplify enclosing pipeline
|
||||
>foo
|
||||
|
||||
alias fooalias=barexpansion
|
||||
funcwithalias() { echo $(fooalias); }
|
||||
functions funcwithalias
|
||||
barexpansion() { print This is the correct output.; }
|
||||
funcwithalias
|
||||
0:Alias expanded in command substitution does not appear expanded in text
|
||||
>funcwithalias () {
|
||||
> echo $(fooalias)
|
||||
>}
|
||||
>This is the correct output.
|
||||
|
||||
unfunction command_not_found_handler # amusing but unhelpful
|
||||
alias first='firstfn1 firstfn2' second='secondfn1 secondfn2'
|
||||
function first second { print This is function $0; }
|
||||
first
|
||||
second
|
||||
firstfn1
|
||||
secondfn1
|
||||
127:No alias expansion after "function" keyword
|
||||
>This is function first
|
||||
>This is function second
|
||||
?(eval):6: command not found: firstfn1
|
||||
?(eval):7: command not found: secondfn1
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
print "print oops was successfully autoloaded" >oops
|
||||
oops() { eval autoload -X }
|
||||
oops
|
||||
which -x2 oops
|
||||
)
|
||||
0:autoload containing eval
|
||||
>oops was successfully autoloaded
|
||||
>oops () {
|
||||
> print oops was successfully autoloaded
|
||||
>}
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
printf '%s\n' 'oops(){}' 'ninjas-earring(){}' 'oops "$@"' >oops
|
||||
autoload oops
|
||||
oops
|
||||
whence -v oops
|
||||
)
|
||||
0q:whence -v of zsh-style autoload
|
||||
>oops is a shell function from $mydir/oops
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
mkdir extra
|
||||
print 'print "I have been loaded by explicit path."' >extra/spec
|
||||
autoload -Uz $PWD/extra/spec
|
||||
spec
|
||||
)
|
||||
0:autoload with explicit path
|
||||
>I have been loaded by explicit path.
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
print 'print "I have been loaded by default path."' >def
|
||||
autoload -Uz $PWD/extra/def
|
||||
def
|
||||
)
|
||||
1:autoload with explicit path with function in normal path, no -d
|
||||
?(eval):5: def: function definition file not found
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
autoload -dUz $PWD/extra/def
|
||||
def
|
||||
)
|
||||
0:autoload with explicit path with function in normal path, with -d
|
||||
>I have been loaded by default path.
|
||||
|
||||
(
|
||||
cd extra
|
||||
fpath=(.)
|
||||
autoload -r spec
|
||||
cd ..
|
||||
spec
|
||||
)
|
||||
0:autoload -r
|
||||
>I have been loaded by explicit path.
|
||||
|
||||
(
|
||||
cd extra
|
||||
fpath=(.)
|
||||
autoload -r def
|
||||
cd ..
|
||||
def
|
||||
)
|
||||
0:autoload -r is permissive
|
||||
>I have been loaded by default path.
|
||||
|
||||
(
|
||||
cd extra
|
||||
fpath=(.)
|
||||
autoload -R def
|
||||
)
|
||||
1:autoload -R is not permissive
|
||||
?(eval):4: def: function definition file not found
|
||||
|
||||
(
|
||||
spec() { autoload -XUz $PWD/extra; }
|
||||
spec
|
||||
)
|
||||
0:autoload -X with path
|
||||
>I have been loaded by explicit path.
|
||||
|
||||
# The line number 1 here and in the next test seems suspect,
|
||||
# but this example proves it's not down to the new features
|
||||
# being tested here.
|
||||
(
|
||||
fpath=(.)
|
||||
cod() { autoload -XUz; }
|
||||
cod
|
||||
)
|
||||
1:autoload -X with no path, failure
|
||||
?(eval):1: cod: function definition file not found
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
def() { autoload -XUz $PWD/extra; }
|
||||
def
|
||||
)
|
||||
1:autoload -X with wrong path and no -d
|
||||
?(eval):1: def: function definition file not found
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
def() { autoload -dXUz $PWD/extra; }
|
||||
def
|
||||
)
|
||||
0:autoload -dX with path
|
||||
>I have been loaded by default path.
|
||||
|
||||
(
|
||||
fpath=(.)
|
||||
print 'loadthisfunc() { autoload -X }' >loadthisfunc_sourceme
|
||||
print 'print Function was loaded correctly.' >loadthisfunc
|
||||
source $PWD/loadthisfunc_sourceme
|
||||
loadthisfunc
|
||||
)
|
||||
0: autoload -X interaction with absolute filename used for source location
|
||||
>Function was loaded correctly.
|
||||
|
||||
(
|
||||
fpath=()
|
||||
mkdir extra2
|
||||
for f in fun2a fun2b; do
|
||||
print "print $f" >extra2/$f
|
||||
done
|
||||
repeat 3; do
|
||||
autoload $PWD/extra2/fun2{a,b} $PWD/extra/spec
|
||||
fun2a
|
||||
fun2b
|
||||
spec
|
||||
unfunction fun2a fun2b spec
|
||||
autoload $PWD/extra2/fun2{a,b} $PWD/extra/spec
|
||||
spec
|
||||
fun2b
|
||||
fun2a
|
||||
unfunction fun2a fun2b spec
|
||||
done
|
||||
)
|
||||
0: Exercise the directory name cache for autoloads
|
||||
>fun2a
|
||||
>fun2b
|
||||
>I have been loaded by explicit path.
|
||||
>I have been loaded by explicit path.
|
||||
>fun2b
|
||||
>fun2a
|
||||
>fun2a
|
||||
>fun2b
|
||||
>I have been loaded by explicit path.
|
||||
>I have been loaded by explicit path.
|
||||
>fun2b
|
||||
>fun2a
|
||||
>fun2a
|
||||
>fun2b
|
||||
>I have been loaded by explicit path.
|
||||
>I have been loaded by explicit path.
|
||||
>fun2b
|
||||
>fun2a
|
||||
|
||||
not_trashed() { print This function was not trashed; }
|
||||
autoload -Uz /foo/bar/not_trashed
|
||||
not_trashed
|
||||
0:autoload with absolute path doesn't trash loaded function
|
||||
>This function was not trashed
|
||||
|
||||
# keep spec from getting loaded in parent shell for simplicity
|
||||
(
|
||||
if whence spec; then print spec already loaded >&2; exit 1; fi
|
||||
autoload -Uz $PWD/spec
|
||||
autoload -Uz $PWD/extra/spec
|
||||
spec
|
||||
)
|
||||
0:autoload with absolute path can be overridden if not yet loaded
|
||||
>I have been loaded by explicit path.
|
||||
|
||||
(
|
||||
if whence spec; then print spec already loaded >&2; exit 1; fi
|
||||
autoload -Uz $PWD/extra/spec
|
||||
autoload spec
|
||||
spec
|
||||
)
|
||||
0:autoload with absolute path not cancelled by bare autoload
|
||||
>I have been loaded by explicit path.
|
||||
|
||||
%clean
|
||||
|
||||
rm -f file.in file.out
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
%prep
|
||||
|
||||
setopt localtraps
|
||||
|
||||
%test
|
||||
|
||||
unsetopt DEBUG_BEFORE_CMD
|
||||
debug-trap-bug1() {
|
||||
setopt localtraps
|
||||
print "print bug file here" >bug-file
|
||||
print "print this is line one
|
||||
print this is line two
|
||||
print this is line three
|
||||
print and this is line fifty-nine." >bug-file2
|
||||
function debug_trap_handler {
|
||||
print $functrace[1]
|
||||
do_bug
|
||||
}
|
||||
function do_bug {
|
||||
. ./bug-file
|
||||
}
|
||||
trap 'echo EXIT hit' EXIT
|
||||
trap 'debug_trap_handler' DEBUG
|
||||
. ./bug-file2
|
||||
}
|
||||
debug-trap-bug1
|
||||
0: Relationship between traps and sources
|
||||
>debug-trap-bug1:15
|
||||
>bug file here
|
||||
>this is line one
|
||||
>./bug-file2:1
|
||||
>bug file here
|
||||
>this is line two
|
||||
>./bug-file2:2
|
||||
>bug file here
|
||||
>this is line three
|
||||
>./bug-file2:3
|
||||
>bug file here
|
||||
>and this is line fifty-nine.
|
||||
>./bug-file2:4
|
||||
>bug file here
|
||||
>debug-trap-bug1:16
|
||||
>bug file here
|
||||
>EXIT hit
|
||||
|
||||
cat >zsh-trapreturn-bug2 <<-'HERE'
|
||||
cmd='./fdasfsdafd'
|
||||
[[ -x $cmd ]] && rm $cmd
|
||||
set -o DEBUG_BEFORE_CMD
|
||||
trap '[[ $? -ne 0 ]] && exit 0' DEBUG
|
||||
$cmd # invalid command
|
||||
# Failure
|
||||
exit 10
|
||||
HERE
|
||||
$ZTST_testdir/../Src/zsh -f ./zsh-trapreturn-bug2 2>erroutput.dif
|
||||
mystat=$?
|
||||
(
|
||||
setopt extendedglob
|
||||
print ${"$(< erroutput.dif)"%%:[^:]#: ./fdasfsdafd}
|
||||
)
|
||||
(( mystat == 0 ))
|
||||
0: trapreturn handling bug is properly fixed
|
||||
>./zsh-trapreturn-bug2:5
|
||||
|
||||
fn() {
|
||||
setopt localtraps localoptions debugbeforecmd
|
||||
trap '(( LINENO == 4 )) && setopt errexit' DEBUG
|
||||
print $LINENO three
|
||||
print $LINENO four
|
||||
print $LINENO five
|
||||
[[ -o errexit ]] && print "Hey, ERREXIT is set!"
|
||||
}
|
||||
fn
|
||||
1:Skip line from DEBUG trap
|
||||
>3 three
|
||||
>5 five
|
||||
|
||||
# Assignments are a special case, since they use a simpler
|
||||
# wordcode type, so we need to test skipping them separately.
|
||||
fn() {
|
||||
setopt localtraps localoptions debugbeforecmd
|
||||
trap '(( LINENO == 4 )) && setopt errexit' DEBUG
|
||||
x=three
|
||||
x=four
|
||||
print $LINENO $x
|
||||
[[ -o errexit ]] && print "Hey, ERREXIT is set!"
|
||||
}
|
||||
fn
|
||||
1:Skip assignment from DEBUG trap
|
||||
>5 three
|
||||
|
||||
fn() {
|
||||
setopt localtraps localoptions debugbeforecmd
|
||||
trap 'print $LINENO' DEBUG
|
||||
[[ a = a ]] && print a is ok
|
||||
}
|
||||
fn
|
||||
0:line numbers of complex sublists
|
||||
>3
|
||||
>a is ok
|
||||
|
||||
fn() {
|
||||
setopt localtraps localoptions debugbeforecmd
|
||||
trap 'print $LINENO' DEBUG
|
||||
print before
|
||||
x=' first
|
||||
second
|
||||
third'
|
||||
print $x
|
||||
}
|
||||
fn
|
||||
0:line numbers of multiline assignments
|
||||
>3
|
||||
>before
|
||||
>4
|
||||
>7
|
||||
> first
|
||||
> second
|
||||
> third
|
||||
|
||||
fn() {
|
||||
emulate -L zsh; setopt debugbeforecmd
|
||||
trap 'print "$LINENO: '\''$ZSH_DEBUG_CMD'\''"' DEBUG
|
||||
print foo &&
|
||||
print bar ||
|
||||
print rod
|
||||
x=y
|
||||
print $x
|
||||
fn2() { echo wow }
|
||||
fn2
|
||||
}
|
||||
fn
|
||||
0:ZSH_DEBUG_CMD in debug traps
|
||||
>3: 'print foo && print bar || print rod'
|
||||
>foo
|
||||
>bar
|
||||
>6: 'x=y '
|
||||
>7: 'print $x'
|
||||
>y
|
||||
>8: 'fn2 () {
|
||||
> echo wow
|
||||
>}'
|
||||
>9: 'fn2'
|
||||
>0: 'echo wow'
|
||||
>wow
|
||||
|
||||
foo() {
|
||||
emulate -L zsh; setopt debugbeforecmd
|
||||
trap '[[ $ZSH_DEBUG_CMD == *bar* ]] && return 2' DEBUG
|
||||
echo foo
|
||||
echo bar
|
||||
}
|
||||
foo
|
||||
2:Status of forced return from eval-style DEBUG trap
|
||||
>foo
|
||||
|
||||
%clean
|
||||
|
||||
rm -f bug-file bug-file2 erroutput.dif zsh-trapreturn-bug2
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
%prep
|
||||
|
||||
mkdir prompt.tmp
|
||||
cd prompt.tmp
|
||||
mydir=$PWD
|
||||
SHLVL=2
|
||||
setopt extendedglob
|
||||
|
||||
%test
|
||||
|
||||
hash -d mydir=$mydir
|
||||
print -P ' %%%): %)
|
||||
%%~: %~
|
||||
%%d: %d
|
||||
%%1/: %1/
|
||||
%%h: %h
|
||||
%%L: %L
|
||||
%%M: %M
|
||||
%%m: %m
|
||||
%%n: %n
|
||||
%%N: %N
|
||||
%%i: %i
|
||||
a%%{...%%}b: a%{%}b
|
||||
'
|
||||
0q:Basic prompt escapes as shown.
|
||||
> %): )
|
||||
> %~: ~mydir
|
||||
> %d: $mydir
|
||||
> %1/: ${mydir:t}
|
||||
> %h: 0
|
||||
> %L: 2
|
||||
> %M: $HOST
|
||||
> %m: ${HOST%%.*}
|
||||
> %n: $USERNAME
|
||||
> %N: (eval)
|
||||
> %i: 2
|
||||
> a%{...%}b: ab
|
||||
>
|
||||
|
||||
true
|
||||
print -P '%?'
|
||||
false
|
||||
print -P '%?'
|
||||
0:`%?' prompt escape
|
||||
>0
|
||||
>1
|
||||
|
||||
PS4="%_> "
|
||||
setopt xtrace
|
||||
if true; then true; else false; fi
|
||||
unsetopt xtrace
|
||||
0:`%_' prompt escape
|
||||
?if> true
|
||||
?then> true
|
||||
?> unsetopt xtrace
|
||||
|
||||
diff =(print -P '%#') =(print -P '%(!.#.%%)')
|
||||
0:`%#' prompt escape and its equivalent
|
||||
|
||||
psvar=(caesar adsum jam forte)
|
||||
print -P '%v' '%4v'
|
||||
0:`%v' prompt escape
|
||||
>caesar forte
|
||||
|
||||
true
|
||||
print -P '%(?.true.false)'
|
||||
false
|
||||
print -P '%(?.true.false)'
|
||||
0:ternary prompt escapes
|
||||
>true
|
||||
>false
|
||||
|
||||
print -P 'start %10<...<truncated at 10%<< Not truncated%3< ...<Not shown'
|
||||
print -P 'start %10>...>truncated at 10%>> Not truncated%3> ...>Not shown'
|
||||
0:prompt truncation
|
||||
>start ...d at 10 Not truncated ...
|
||||
>start truncat... Not truncated ...
|
||||
|
||||
# It's hard to check the time and date as they are moving targets.
|
||||
# We therefore just check that various forms of the date are consistent.
|
||||
# In fact, if you perform this at midnight it can still fail.
|
||||
# We could test for that, but we can't be bothered.
|
||||
# I hope LC_ALL is enough to make the format what's expected.
|
||||
|
||||
LC_ALL=C
|
||||
date1=$(print -P %w)
|
||||
date2=$(print -P %W)
|
||||
date3=$(print -P %D)
|
||||
if [[ $date1 != [A-Z][a-z][a-z][[:blank:]]##[0-9]## ]]; then
|
||||
print "Date \`$date1' is not in the form \`Day DD' (e.g. \`Mon 1'"
|
||||
fi
|
||||
if [[ $date2 != [0-9][0-9]/[0-9][0-9]/[0-9][0-9] ]]; then
|
||||
print "Date \`$date2' is not in the form \`DD/MM/YYYY'"
|
||||
fi
|
||||
if [[ $date3 != [0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
|
||||
print "Date \`$date3' is not in the form \`YY-MM-DD'"
|
||||
fi
|
||||
if (( $date1[5,-1] != $date2[4,5] )) || (( $date2[4,5] != $date3[7,8] ))
|
||||
then
|
||||
print "Days of month do not agree in $date1, $date2, $date3"
|
||||
fi
|
||||
if (( $date2[1,2] != $date3[4,5] )); then
|
||||
print "Months do not agree in $date2, $date3"
|
||||
fi
|
||||
if (( $date2[7,8] != $date3[1,2] )); then
|
||||
print "Years do not agree in $date2, $date3"
|
||||
fi
|
||||
0:Dates produced by prompt escapes
|
||||
|
||||
mkdir foo
|
||||
mkdir foo/bar
|
||||
mkdir foo/bar/rod
|
||||
(zsh_directory_name() {
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
local -a match mbegin mend
|
||||
if [[ $1 = d ]]; then
|
||||
if [[ $2 = (#b)(*bar)/rod ]]; then
|
||||
reply=(barmy ${#match[1]})
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if [[ $2 = barmy ]]; then
|
||||
reply=($mydir/foo/bar)
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
# success
|
||||
print ~[barmy]/anything
|
||||
cd foo/bar/rod
|
||||
print -P %~
|
||||
# failure
|
||||
setopt nonomatch
|
||||
print ~[scuzzy]/rubbish
|
||||
cd ../..
|
||||
print -P %~
|
||||
# catastrophic failure
|
||||
unsetopt nonomatch
|
||||
print ~[scuzzy]/rubbish
|
||||
)
|
||||
1q:Dynamic named directories
|
||||
>$mydir/foo/bar/anything
|
||||
>~[barmy]/rod
|
||||
>~[scuzzy]/rubbish
|
||||
>~mydir/foo
|
||||
?(eval):33: no directory expansion: ~[scuzzy]
|
||||
|
||||
(
|
||||
zsh_directory_name() {
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
local -a match mbegin mend
|
||||
if [[ $1 = n ]]; then
|
||||
if [[ $2 = *:l ]]; then
|
||||
reply=(${2%%:l}/very_long_directory_name)
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if [[ $2 = (#b)(*)/very_long_directory_name ]]; then
|
||||
reply=(${match[1]}:l ${#2})
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
parent=$PWD
|
||||
dir=$parent/very_long_directory_name
|
||||
mkdir $dir
|
||||
cd $dir
|
||||
fn() {
|
||||
PS4='+%N:%i> '
|
||||
setopt localoptions xtrace
|
||||
# The following is the key to the test.
|
||||
# It invokes zsh_directory_name which does PS4 output stuff
|
||||
# while we're doing prompt handling for the parameter
|
||||
# substitution. This checks recursion works OK.
|
||||
local d=${(%):-%~}
|
||||
print ${d//$parent/\<parent\>}
|
||||
}
|
||||
fn 2>stderr
|
||||
# post process error to remove variable contents
|
||||
while read line; do
|
||||
# tricky: reply is set to include directory length which is variable
|
||||
[[ $line = *reply* ]] && continue
|
||||
print ${line//$parent/\<parent\>}
|
||||
done <stderr >&2
|
||||
)
|
||||
0:Recursive use of prompts
|
||||
>~[<parent>:l]
|
||||
?+zsh_directory_name:1> emulate -L zsh
|
||||
?+zsh_directory_name:2> setopt extendedglob
|
||||
?+zsh_directory_name:3> local -a match mbegin mend
|
||||
?+zsh_directory_name:4> [[ d = n ]]
|
||||
?+zsh_directory_name:12> [[ <parent>/very_long_directory_name = (#b)(*)/very_long_directory_name ]]
|
||||
?+zsh_directory_name:14> return 0
|
||||
?+fn:7> local d='~[<parent>:l]'
|
||||
?+fn:8> print '~[<parent>:l]'
|
||||
|
|
@ -1,688 +0,0 @@
|
|||
# Tests for globbing
|
||||
|
||||
%prep
|
||||
mkdir glob.tmp
|
||||
mkdir glob.tmp/dir{1,2,3,4}
|
||||
mkdir glob.tmp/dir3/subdir
|
||||
: >glob.tmp/{,{dir1,dir2}/}{a,b,c}
|
||||
|
||||
globtest () {
|
||||
$ZTST_testdir/../Src/zsh -f $ZTST_srcdir/../Misc/$1
|
||||
}
|
||||
|
||||
regress_absolute_path_and_core_dump() {
|
||||
local absolute_dir=$(cd glob.tmp && pwd -P)
|
||||
[[ -n $absolute_dir ]] || return 1
|
||||
setopt localoptions extendedglob nullglob
|
||||
print $absolute_dir/**/*~/*
|
||||
setopt nonullglob nomatch
|
||||
print glob.tmp/**/*~(.)#
|
||||
}
|
||||
|
||||
%test
|
||||
|
||||
globtest globtests
|
||||
0:zsh globbing
|
||||
>0: [[ foo~ = foo~ ]]
|
||||
>0: [[ foo~ = (foo~) ]]
|
||||
>0: [[ foo~ = (foo~|) ]]
|
||||
>0: [[ foo.c = *.c~boo* ]]
|
||||
>1: [[ foo.c = *.c~boo*~foo* ]]
|
||||
>0: [[ fofo = (fo#)# ]]
|
||||
>0: [[ ffo = (fo#)# ]]
|
||||
>0: [[ foooofo = (fo#)# ]]
|
||||
>0: [[ foooofof = (fo#)# ]]
|
||||
>0: [[ fooofoofofooo = (fo#)# ]]
|
||||
>1: [[ foooofof = (fo##)# ]]
|
||||
>1: [[ xfoooofof = (fo#)# ]]
|
||||
>1: [[ foooofofx = (fo#)# ]]
|
||||
>0: [[ ofxoofxo = ((ofo#x)#o)# ]]
|
||||
>1: [[ ofooofoofofooo = (fo#)# ]]
|
||||
>0: [[ foooxfooxfoxfooox = (fo#x)# ]]
|
||||
>1: [[ foooxfooxofoxfooox = (fo#x)# ]]
|
||||
>0: [[ foooxfooxfxfooox = (fo#x)# ]]
|
||||
>0: [[ ofxoofxo = ((ofo#x)#o)# ]]
|
||||
>0: [[ ofoooxoofxo = ((ofo#x)#o)# ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxo = ((ofo#x)#o)# ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxoo = ((ofo#x)#o)# ]]
|
||||
>1: [[ ofoooxoofxoofoooxoofxofo = ((ofo#x)#o)# ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxooofxofxo = ((ofo#x)#o)# ]]
|
||||
>0: [[ aac = ((a))#a(c) ]]
|
||||
>0: [[ ac = ((a))#a(c) ]]
|
||||
>1: [[ c = ((a))#a(c) ]]
|
||||
>0: [[ aaac = ((a))#a(c) ]]
|
||||
>1: [[ baaac = ((a))#a(c) ]]
|
||||
>0: [[ abcd = ?(a|b)c#d ]]
|
||||
>0: [[ abcd = (ab|ab#)c#d ]]
|
||||
>0: [[ acd = (ab|ab#)c#d ]]
|
||||
>0: [[ abbcd = (ab|ab#)c#d ]]
|
||||
>0: [[ effgz = (bc##d|ef#g?|(h|)i(j|k)) ]]
|
||||
>0: [[ efgz = (bc##d|ef#g?|(h|)i(j|k)) ]]
|
||||
>0: [[ egz = (bc##d|ef#g?|(h|)i(j|k)) ]]
|
||||
>0: [[ egzefffgzbcdij = (bc##d|ef#g?|(h|)i(j|k))# ]]
|
||||
>1: [[ egz = (bc##d|ef##g?|(h|)i(j|k)) ]]
|
||||
>0: [[ ofoofo = (ofo##)# ]]
|
||||
>0: [[ oxfoxoxfox = (oxf(ox)##)# ]]
|
||||
>1: [[ oxfoxfox = (oxf(ox)##)# ]]
|
||||
>0: [[ ofoofo = (ofo##|f)# ]]
|
||||
>0: [[ foofoofo = (foo|f|fo)(f|ofo##)# ]]
|
||||
>0: [[ oofooofo = (of|oofo##)# ]]
|
||||
>0: [[ fffooofoooooffoofffooofff = (f#o#)# ]]
|
||||
>1: [[ fffooofoooooffoofffooofffx = (f#o#)# ]]
|
||||
>0: [[ fofoofoofofoo = (fo|foo)# ]]
|
||||
>0: [[ foo = ((^x)) ]]
|
||||
>0: [[ foo = ((^x)*) ]]
|
||||
>1: [[ foo = ((^foo)) ]]
|
||||
>0: [[ foo = ((^foo)*) ]]
|
||||
>0: [[ foobar = ((^foo)) ]]
|
||||
>0: [[ foobar = ((^foo)*) ]]
|
||||
>1: [[ foot = z*~*x ]]
|
||||
>0: [[ zoot = z*~*x ]]
|
||||
>1: [[ foox = z*~*x ]]
|
||||
>1: [[ zoox = z*~*x ]]
|
||||
>0: [[ moo.cow = (*~*.*).(*~*.*) ]]
|
||||
>1: [[ mad.moo.cow = (*~*.*).(*~*.*) ]]
|
||||
>0: [[ moo.cow = (^*.*).(^*.*) ]]
|
||||
>1: [[ sane.moo.cow = (^*.*).(^*.*) ]]
|
||||
>1: [[ mucca.pazza = mu(^c#)?.pa(^z#)? ]]
|
||||
>1: [[ _foo~ = _(|*[^~]) ]]
|
||||
>0: [[ fff = ((^f)) ]]
|
||||
>0: [[ fff = ((^f)#) ]]
|
||||
>0: [[ fff = ((^f)##) ]]
|
||||
>0: [[ ooo = ((^f)) ]]
|
||||
>0: [[ ooo = ((^f)#) ]]
|
||||
>0: [[ ooo = ((^f)##) ]]
|
||||
>0: [[ foo = ((^f)) ]]
|
||||
>0: [[ foo = ((^f)#) ]]
|
||||
>0: [[ foo = ((^f)##) ]]
|
||||
>1: [[ f = ((^f)) ]]
|
||||
>1: [[ f = ((^f)#) ]]
|
||||
>1: [[ f = ((^f)##) ]]
|
||||
>0: [[ foot = (^z*|*x) ]]
|
||||
>1: [[ zoot = (^z*|*x) ]]
|
||||
>0: [[ foox = (^z*|*x) ]]
|
||||
>0: [[ zoox = (^z*|*x) ]]
|
||||
>0: [[ foo = (^foo)# ]]
|
||||
>1: [[ foob = (^foo)b* ]]
|
||||
>0: [[ foobb = (^foo)b* ]]
|
||||
>1: [[ foob = (*~foo)b* ]]
|
||||
>0: [[ foobb = (*~foo)b* ]]
|
||||
>1: [[ zsh = ^z* ]]
|
||||
>0: [[ a%1X = [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] ]]
|
||||
>1: [[ a%1 = [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] ]]
|
||||
>0: [[ [: = [[:]# ]]
|
||||
>0: [[ :] = []:]# ]]
|
||||
>0: [[ :] = [:]]# ]]
|
||||
>0: [[ [ = [[] ]]
|
||||
>0: [[ ] = []] ]]
|
||||
>0: [[ [] = [^]]] ]]
|
||||
>0: [[ fooxx = (#i)FOOXX ]]
|
||||
>1: [[ fooxx = (#l)FOOXX ]]
|
||||
>0: [[ FOOXX = (#l)fooxx ]]
|
||||
>1: [[ fooxx = (#i)FOO(#I)X(#i)X ]]
|
||||
>0: [[ fooXx = (#i)FOO(#I)X(#i)X ]]
|
||||
>0: [[ fooxx = ((#i)FOOX)x ]]
|
||||
>1: [[ fooxx = ((#i)FOOX)X ]]
|
||||
>1: [[ BAR = (bar|(#i)foo) ]]
|
||||
>0: [[ FOO = (bar|(#i)foo) ]]
|
||||
>0: [[ Modules = (#i)*m* ]]
|
||||
>0: [[ fooGRUD = (#i)(bar|(#I)foo|(#i)rod)grud ]]
|
||||
>1: [[ FOOGRUD = (#i)(bar|(#I)foo|(#i)rod)grud ]]
|
||||
>0: [[ readme = (#i)readme~README|readme ]]
|
||||
>0: [[ readme = (#i)readme~README|readme~README ]]
|
||||
>0: [[ 633 = <1-1000>33 ]]
|
||||
>0: [[ 633 = <-1000>33 ]]
|
||||
>0: [[ 633 = <1->33 ]]
|
||||
>0: [[ 633 = <->33 ]]
|
||||
>0: [[ 12345678901234567890123456789012345678901234567890123456789012345678901234567890foo = <42->foo ]]
|
||||
>0: [[ READ.ME = (#ia1)readme ]]
|
||||
>1: [[ READ..ME = (#ia1)readme ]]
|
||||
>0: [[ README = (#ia1)readm ]]
|
||||
>0: [[ READM = (#ia1)readme ]]
|
||||
>0: [[ README = (#ia1)eadme ]]
|
||||
>0: [[ EADME = (#ia1)readme ]]
|
||||
>0: [[ READEM = (#ia1)readme ]]
|
||||
>1: [[ ADME = (#ia1)readme ]]
|
||||
>1: [[ README = (#ia1)read ]]
|
||||
>0: [[ bob = (#a1)[b][b] ]]
|
||||
>1: [[ bob = (#a1)[b][b]a ]]
|
||||
>0: [[ bob = (#a1)[b]o[b]a ]]
|
||||
>1: [[ bob = (#a1)[c]o[b] ]]
|
||||
>0: [[ abcd = (#a2)XbcX ]]
|
||||
>0: [[ abcd = (#a2)ad ]]
|
||||
>0: [[ ad = (#a2)abcd ]]
|
||||
>0: [[ abcd = (#a2)bd ]]
|
||||
>0: [[ bd = (#a2)abcd ]]
|
||||
>0: [[ badc = (#a2)abcd ]]
|
||||
>0: [[ adbc = (#a2)abcd ]]
|
||||
>1: [[ dcba = (#a2)abcd ]]
|
||||
>0: [[ dcba = (#a3)abcd ]]
|
||||
>0: [[ aabaXaaabY = (#a1)(a#b)#Y ]]
|
||||
>0: [[ aabaXaaabY = (#a1)(a#b)(a#b)Y ]]
|
||||
>0: [[ aaXaaaaabY = (#a1)(a#b)(a#b)Y ]]
|
||||
>0: [[ aaaXaaabY = (#a1)(a##b)##Y ]]
|
||||
>0: [[ aaaXbaabY = (#a1)(a##b)##Y ]]
|
||||
>1: [[ read.me = (#ia1)README~READ.ME ]]
|
||||
>0: [[ read.me = (#ia1)README~READ_ME ]]
|
||||
>1: [[ read.me = (#ia1)README~(#a1)READ_ME ]]
|
||||
>0: [[ test = *((#s)|/)test((#e)|/)* ]]
|
||||
>0: [[ test/path = *((#s)|/)test((#e)|/)* ]]
|
||||
>0: [[ path/test = *((#s)|/)test((#e)|/)* ]]
|
||||
>0: [[ path/test/ohyes = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ atest = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ testy = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ testy/path = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ path/atest = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ atest/path = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ path/testy = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ path/testy/ohyes = *((#s)|/)test((#e)|/)* ]]
|
||||
>1: [[ path/atest/ohyes = *((#s)|/)test((#e)|/)* ]]
|
||||
>0: [[ XabcdabcY = X(ab|c|d)(#c5)Y ]]
|
||||
>0: [[ XabcdabcY = X(ab|c|d)(#c1,5)Y ]]
|
||||
>0: [[ XabcdabcY = X(ab|c|d)(#c5,8)Y ]]
|
||||
>0: [[ XabcdabcY = X(ab|c|d)(#c4,)Y ]]
|
||||
>1: [[ XabcdabcY = X(ab|c|d)(#c6,)Y ]]
|
||||
>1: [[ XabcdabcY = X(ab|c|d)(#c1,4)Y ]]
|
||||
>0: [[ ZX = Z(|)(#c1)X ]]
|
||||
>0: [[ froofroo = (fro(#c2))(#c2) ]]
|
||||
>1: [[ froofroofroo = (fro(#c2))(#c2) ]]
|
||||
>1: [[ froofro = (fro(#c2))(#c2) ]]
|
||||
>0: [[ ax = ?(#c1,2)x ]]
|
||||
>0: [[ ax = ?(#c1,)x ]]
|
||||
>0: [[ ax = ?(#c0,1)x ]]
|
||||
>1: [[ ax = ?(#c0,0)x ]]
|
||||
>1: [[ ax = ?(#c2,)x ]]
|
||||
>0: [[ aa = a(#c1,2)a ]]
|
||||
>0: [[ aa = a(#c1,)a ]]
|
||||
>0: [[ aa = a(#c0,1)a ]]
|
||||
>1: [[ aa = a(#c0,0)a ]]
|
||||
>1: [[ aa = a(#c2,)a ]]
|
||||
>0: [[ test.zsh = *.?(#c1)sh ]]
|
||||
>0: [[ test.bash = *.?(#c2)sh ]]
|
||||
>0: [[ test.bash = *.?(#c1,2)sh ]]
|
||||
>0: [[ test.bash = *.?(#c1,)sh ]]
|
||||
>0: [[ test.zsh = *.?(#c1,)sh ]]
|
||||
>0 tests failed.
|
||||
|
||||
globtest globtests.ksh
|
||||
0:ksh compatibility
|
||||
>0: [[ fofo = *(f*(o)) ]]
|
||||
>0: [[ ffo = *(f*(o)) ]]
|
||||
>0: [[ foooofo = *(f*(o)) ]]
|
||||
>0: [[ foooofof = *(f*(o)) ]]
|
||||
>0: [[ fooofoofofooo = *(f*(o)) ]]
|
||||
>1: [[ foooofof = *(f+(o)) ]]
|
||||
>1: [[ xfoooofof = *(f*(o)) ]]
|
||||
>1: [[ foooofofx = *(f*(o)) ]]
|
||||
>0: [[ ofxoofxo = *(*(of*(o)x)o) ]]
|
||||
>1: [[ ofooofoofofooo = *(f*(o)) ]]
|
||||
>0: [[ foooxfooxfoxfooox = *(f*(o)x) ]]
|
||||
>1: [[ foooxfooxofoxfooox = *(f*(o)x) ]]
|
||||
>0: [[ foooxfooxfxfooox = *(f*(o)x) ]]
|
||||
>0: [[ ofxoofxo = *(*(of*(o)x)o) ]]
|
||||
>0: [[ ofoooxoofxo = *(*(of*(o)x)o) ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxo = *(*(of*(o)x)o) ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxoo = *(*(of*(o)x)o) ]]
|
||||
>1: [[ ofoooxoofxoofoooxoofxofo = *(*(of*(o)x)o) ]]
|
||||
>0: [[ ofoooxoofxoofoooxoofxooofxofxo = *(*(of*(o)x)o) ]]
|
||||
>0: [[ aac = *(@(a))a@(c) ]]
|
||||
>0: [[ ac = *(@(a))a@(c) ]]
|
||||
>1: [[ c = *(@(a))a@(c) ]]
|
||||
>0: [[ aaac = *(@(a))a@(c) ]]
|
||||
>1: [[ baaac = *(@(a))a@(c) ]]
|
||||
>0: [[ abcd = ?@(a|b)*@(c)d ]]
|
||||
>0: [[ abcd = @(ab|a*@(b))*(c)d ]]
|
||||
>0: [[ acd = @(ab|a*(b))*(c)d ]]
|
||||
>0: [[ abbcd = @(ab|a*(b))*(c)d ]]
|
||||
>0: [[ effgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
|
||||
>0: [[ efgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
|
||||
>0: [[ egz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
|
||||
>0: [[ egzefffgzbcdij = *(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
|
||||
>1: [[ egz = @(b+(c)d|e+(f)g?|?(h)i@(j|k)) ]]
|
||||
>0: [[ ofoofo = *(of+(o)) ]]
|
||||
>0: [[ oxfoxoxfox = *(oxf+(ox)) ]]
|
||||
>1: [[ oxfoxfox = *(oxf+(ox)) ]]
|
||||
>0: [[ ofoofo = *(of+(o)|f) ]]
|
||||
>0: [[ foofoofo = @(foo|f|fo)*(f|of+(o)) ]]
|
||||
>0: [[ oofooofo = *(of|oof+(o)) ]]
|
||||
>0: [[ fffooofoooooffoofffooofff = *(*(f)*(o)) ]]
|
||||
>1: [[ fffooofoooooffoofffooofffx = *(*(f)*(o)) ]]
|
||||
>0: [[ fofoofoofofoo = *(fo|foo) ]]
|
||||
>0: [[ foo = !(x) ]]
|
||||
>0: [[ foo = !(x)* ]]
|
||||
>1: [[ foo = !(foo) ]]
|
||||
>0: [[ foo = !(foo)* ]]
|
||||
>0: [[ foobar = !(foo) ]]
|
||||
>0: [[ foobar = !(foo)* ]]
|
||||
>0: [[ moo.cow = !(*.*).!(*.*) ]]
|
||||
>1: [[ mad.moo.cow = !(*.*).!(*.*) ]]
|
||||
>1: [[ mucca.pazza = mu!(*(c))?.pa!(*(z))? ]]
|
||||
>1: [[ _foo~ = _?(*[^~]) ]]
|
||||
>0: [[ fff = !(f) ]]
|
||||
>0: [[ fff = *(!(f)) ]]
|
||||
>0: [[ fff = +(!(f)) ]]
|
||||
>0: [[ ooo = !(f) ]]
|
||||
>0: [[ ooo = *(!(f)) ]]
|
||||
>0: [[ ooo = +(!(f)) ]]
|
||||
>0: [[ foo = !(f) ]]
|
||||
>0: [[ foo = *(!(f)) ]]
|
||||
>0: [[ foo = +(!(f)) ]]
|
||||
>1: [[ f = !(f) ]]
|
||||
>1: [[ f = *(!(f)) ]]
|
||||
>1: [[ f = +(!(f)) ]]
|
||||
>0: [[ foot = @(!(z*)|*x) ]]
|
||||
>1: [[ zoot = @(!(z*)|*x) ]]
|
||||
>0: [[ foox = @(!(z*)|*x) ]]
|
||||
>0: [[ zoox = @(!(z*)|*x) ]]
|
||||
>0: [[ foo = *(!(foo)) ]]
|
||||
>1: [[ foob = !(foo)b* ]]
|
||||
>0: [[ foobb = !(foo)b* ]]
|
||||
>0: [[ fooxx = (#i)FOOXX ]]
|
||||
>1: [[ fooxx = (#l)FOOXX ]]
|
||||
>0: [[ FOOXX = (#l)fooxx ]]
|
||||
>1: [[ fooxx = (#i)FOO@(#I)X@(#i)X ]]
|
||||
>0: [[ fooXx = (#i)FOO@(#I)X@(#i)X ]]
|
||||
>0: [[ fooxx = @((#i)FOOX)x ]]
|
||||
>1: [[ fooxx = @((#i)FOOX)X ]]
|
||||
>1: [[ BAR = @(bar|(#i)foo) ]]
|
||||
>0: [[ FOO = @(bar|(#i)foo) ]]
|
||||
>0: [[ Modules = (#i)*m* ]]
|
||||
>0 tests failed.
|
||||
|
||||
(unsetopt multibyte
|
||||
[[ björn = *[åäöÅÄÖ]* ]])
|
||||
0:single byte match with top bit set
|
||||
|
||||
( regress_absolute_path_and_core_dump )
|
||||
0:exclusions regression test
|
||||
>
|
||||
>glob.tmp/a glob.tmp/b glob.tmp/c glob.tmp/dir1 glob.tmp/dir1/a glob.tmp/dir1/b glob.tmp/dir1/c glob.tmp/dir2 glob.tmp/dir2/a glob.tmp/dir2/b glob.tmp/dir2/c glob.tmp/dir3 glob.tmp/dir3/subdir glob.tmp/dir4
|
||||
|
||||
print glob.tmp/*(/)
|
||||
0:Just directories
|
||||
>glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir3 glob.tmp/dir4
|
||||
|
||||
print glob.tmp/*(.)
|
||||
0:Just files
|
||||
>glob.tmp/a glob.tmp/b glob.tmp/c
|
||||
|
||||
print glob.tmp/*(.e^'reply=( glob.tmp/*/${REPLY:t} )'^:t)
|
||||
0:Globbing used recursively (inside e glob qualifier)
|
||||
>a a b b c c
|
||||
|
||||
print glob.tmp/*/*(e:'reply=( glob.tmp/**/*([1]) )'::t)
|
||||
0:Recursive globbing used recursively (inside e glob qualifier)
|
||||
>a a a a a a a
|
||||
|
||||
print glob.tmp/**/(:h)
|
||||
0:Head modifier
|
||||
>. glob.tmp glob.tmp glob.tmp glob.tmp glob.tmp/dir3
|
||||
|
||||
print glob.tmp(:r)
|
||||
0:Remove extension modifier
|
||||
>glob
|
||||
|
||||
print glob.tmp/*(:s/./_/)
|
||||
0:Substitute modifier
|
||||
>glob_tmp/a glob_tmp/b glob_tmp/c glob_tmp/dir1 glob_tmp/dir2 glob_tmp/dir3 glob_tmp/dir4
|
||||
|
||||
print glob.tmp/*(F)
|
||||
0:Just full dirs
|
||||
>glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir3
|
||||
|
||||
print glob.tmp/*(^F)
|
||||
0:Omit full dirs
|
||||
>glob.tmp/a glob.tmp/b glob.tmp/c glob.tmp/dir4
|
||||
|
||||
print glob.tmp/*(/^F)
|
||||
0:Just empty dirs
|
||||
>glob.tmp/dir4
|
||||
|
||||
setopt extendedglob
|
||||
print glob.tmp/**/*~*/dir3(/*|(#e))(/)
|
||||
0:Exclusions with complicated path specifications
|
||||
>glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir4
|
||||
|
||||
print -l -- glob.tmp/*(P:-f:)
|
||||
0:Prepending words to each argument
|
||||
>-f
|
||||
>glob.tmp/a
|
||||
>-f
|
||||
>glob.tmp/b
|
||||
>-f
|
||||
>glob.tmp/c
|
||||
>-f
|
||||
>glob.tmp/dir1
|
||||
>-f
|
||||
>glob.tmp/dir2
|
||||
>-f
|
||||
>glob.tmp/dir3
|
||||
>-f
|
||||
>glob.tmp/dir4
|
||||
|
||||
print -l -- glob.tmp/*(P:one word:P:another word:)
|
||||
0:Prepending two words to each argument
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/a
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/b
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/c
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/dir1
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/dir2
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/dir3
|
||||
>one word
|
||||
>another word
|
||||
>glob.tmp/dir4
|
||||
|
||||
[[ "" = "" ]] && echo OK
|
||||
0:Empty strings
|
||||
>OK
|
||||
|
||||
foo="this string has a : colon in it"
|
||||
print ${foo%% #:*}
|
||||
0:Must-match arguments in complex patterns
|
||||
>this string has a
|
||||
|
||||
mkdir glob.tmp/ra=1.0_et=3.5
|
||||
touch glob.tmp/ra=1.0_et=3.5/foo
|
||||
print glob.tmp/ra=1.0_et=3.5/???
|
||||
0:Bug with intermediate paths with plain strings but tokenized characters
|
||||
>glob.tmp/ra=1.0_et=3.5/foo
|
||||
|
||||
doesmatch() {
|
||||
setopt localoptions extendedglob
|
||||
print -n $1 $2\
|
||||
if [[ $1 = $~2 ]]; then print yes; else print no; fi;
|
||||
}
|
||||
doesmatch MY_IDENTIFIER '[[:IDENT:]]##'
|
||||
doesmatch YOUR:IDENTIFIER '[[:IDENT:]]##'
|
||||
IFS=$'\n' doesmatch $'\n' '[[:IFS:]]'
|
||||
IFS=' ' doesmatch $'\n' '[[:IFS:]]'
|
||||
IFS=':' doesmatch : '[[:IFSSPACE:]]'
|
||||
IFS=' ' doesmatch ' ' '[[:IFSSPACE:]]'
|
||||
WORDCHARS="" doesmatch / '[[:WORD:]]'
|
||||
WORDCHARS="/" doesmatch / '[[:WORD:]]'
|
||||
0:Named character sets handled internally
|
||||
>MY_IDENTIFIER [[:IDENT:]]## yes
|
||||
>YOUR:IDENTIFIER [[:IDENT:]]## no
|
||||
>
|
||||
> [[:IFS:]] yes
|
||||
>
|
||||
> [[:IFS:]] no
|
||||
>: [[:IFSSPACE:]] no
|
||||
> [[:IFSSPACE:]] yes
|
||||
>/ [[:WORD:]] no
|
||||
>/ [[:WORD:]] yes
|
||||
|
||||
[[ foo = (#c0)foo ]]
|
||||
2:Misplaced (#c...) flag
|
||||
?(eval):1: bad pattern: (#c0)foo
|
||||
|
||||
mkdir glob.tmp/dir5
|
||||
touch glob.tmp/dir5/N123
|
||||
print glob.tmp/dir5/N<->(N)
|
||||
rm -rf glob.tmp/dir5
|
||||
0:Numeric glob is not usurped by process substitution.
|
||||
>glob.tmp/dir5/N123
|
||||
|
||||
tpd() {
|
||||
[[ $1 = $~2 ]]
|
||||
print -r "$1, $2: $?"
|
||||
}
|
||||
test_pattern_disables() {
|
||||
emulate -L zsh
|
||||
tpd 'forthcoming' 'f*g'
|
||||
disable -p '*'
|
||||
tpd 'forthcoming' 'f*g'
|
||||
tpd 'f*g' 'f*g'
|
||||
tpd '[frog]' '[frog]'
|
||||
tpd '[frog]' '\[[f]rog\]'
|
||||
disable -p '['
|
||||
tpd '[frog]' '[frog]'
|
||||
tpd '[frog]' '\[[f]rog\]'
|
||||
setopt extendedglob
|
||||
tpd 'foo' '^bar'
|
||||
disable -p '^'
|
||||
tpd 'foo' '^bar'
|
||||
tpd '^bar' '^bar'
|
||||
tpd 'rumble' '(rumble|bluster)'
|
||||
tpd '(thunder)' '(thunder)'
|
||||
disable -p '('
|
||||
tpd 'rumble' '(rumble|bluster)'
|
||||
tpd '(thunder)' '(thunder)'
|
||||
setopt kshglob
|
||||
tpd 'scramble' '@(panic|frenzy|scramble)'
|
||||
tpd '@(scrimf)' '@(scrimf)'
|
||||
disable -p '@('
|
||||
tpd 'scramble' '@(panic|frenzy|scramble)'
|
||||
tpd '@(scrimf)' '@(scrimf)'
|
||||
disable -p
|
||||
}
|
||||
test_pattern_disables
|
||||
print Nothing should be disabled.
|
||||
disable -p
|
||||
0:disable -p
|
||||
>forthcoming, f*g: 0
|
||||
>forthcoming, f*g: 1
|
||||
>f*g, f*g: 0
|
||||
>[frog], [frog]: 1
|
||||
>[frog], \[[f]rog\]: 0
|
||||
>[frog], [frog]: 0
|
||||
>[frog], \[[f]rog\]: 1
|
||||
>foo, ^bar: 0
|
||||
>foo, ^bar: 1
|
||||
>^bar, ^bar: 0
|
||||
>rumble, (rumble|bluster): 0
|
||||
>(thunder), (thunder): 1
|
||||
>rumble, (rumble|bluster): 1
|
||||
>(thunder), (thunder): 0
|
||||
>scramble, @(panic|frenzy|scramble): 0
|
||||
>@(scrimf), @(scrimf): 1
|
||||
>scramble, @(panic|frenzy|scramble): 1
|
||||
>@(scrimf), @(scrimf): 0
|
||||
>'(' '*' '[' '^' '@('
|
||||
>Nothing should be disabled.
|
||||
|
||||
(
|
||||
setopt nomatch
|
||||
x=( '' )
|
||||
print $^x(N)
|
||||
)
|
||||
0:No error with empty null glob with (N).
|
||||
>
|
||||
|
||||
(setopt kshglob
|
||||
test_array=(
|
||||
'+fours' '+*'
|
||||
'@titude' '@*'
|
||||
'!bang' '!*'
|
||||
# and check they work in the real kshglob cases too...
|
||||
'+bus+bus' '+(+bus|-car)'
|
||||
'@sinhats' '@(@sinhats|wrensinfens)'
|
||||
'!kerror' '!(!somethingelse)'
|
||||
# and these don't match, to be sure
|
||||
'+more' '+(+less)'
|
||||
'@all@all' '@(@all)'
|
||||
'!goesitall' '!(!goesitall)'
|
||||
)
|
||||
for str pat in $test_array; do
|
||||
eval "[[ $str = $pat ]]" && print "$str matches $pat"
|
||||
done
|
||||
true
|
||||
)
|
||||
0:kshglob option does not break +, @, ! without following open parenthesis
|
||||
>+fours matches +*
|
||||
>@titude matches @*
|
||||
>!bang matches !*
|
||||
>+bus+bus matches +(+bus|-car)
|
||||
>@sinhats matches @(@sinhats|wrensinfens)
|
||||
>!kerror matches !(!somethingelse)
|
||||
|
||||
(
|
||||
setopt extendedglob
|
||||
cd glob.tmp
|
||||
[[ -n a*(#qN) ]] && print File beginning with a
|
||||
[[ -z z*(#qN) ]] && print No file beginning with z
|
||||
setopt nonomatch
|
||||
[[ -n z*(#q) ]] && print Normal string if nullglob not set
|
||||
)
|
||||
0:Force glob expansion in conditions using (#q)
|
||||
>File beginning with a
|
||||
>No file beginning with z
|
||||
>Normal string if nullglob not set
|
||||
|
||||
(){ print $#@ } glob.tmp/dir*(Y1)
|
||||
(){ print $#@ } glob.tmp/file*(NY1)
|
||||
(){ [[ "$*" == */dir?\ */dir? ]] && print Returns matching filenames } glob.tmp/dir*(Y2)
|
||||
(){ print "Limit is upper bound:" ${(o)@:t} } glob.tmp/dir*(Y5)
|
||||
(){ print "Negated:" $@:t } glob.tmp/dir*(Y1^Y)
|
||||
(){ print "Sorting:" $@:t } glob.tmp/dir*(Y4On)
|
||||
(){ [[ $#@ -eq 1 ]] && print Globs before last path component } glob.tmp/dir?/subdir(NY1)
|
||||
(){ [[ $1 == glob.tmp/a ]] } glob.tmp/**/a(Y1) && print Breadth first
|
||||
(){ [[ $#@ -eq 0 ]] && print Respects qualifiers } glob.tmp/dir*(NY1.)
|
||||
(print -- *(Y)) 2>/dev/null || print "Argument required"
|
||||
0:short-circuit modifier
|
||||
>1
|
||||
>0
|
||||
>Returns matching filenames
|
||||
>Limit is upper bound: dir1 dir2 dir3 dir4
|
||||
>Negated: dir1 dir2 dir3 dir4
|
||||
>Sorting: dir4 dir3 dir2 dir1
|
||||
>Globs before last path component
|
||||
>Breadth first
|
||||
>Respects qualifiers
|
||||
>Argument required
|
||||
|
||||
[[ "ce fichier n'existe pas" = (#b)ce\ (f[^ ]#)\ *s(#q./) ]]
|
||||
print $match[1]
|
||||
0:(#q) is ignored completely in conditional pattern matching
|
||||
>fichier
|
||||
|
||||
# The following should not cause excessive slowdown.
|
||||
print glob.tmp/*.*
|
||||
print glob.tmp/**************************.*************************
|
||||
0:Optimisation to squeeze multiple *'s used as ordinary glob wildcards.
|
||||
>glob.tmp/ra=1.0_et=3.5
|
||||
>glob.tmp/ra=1.0_et=3.5
|
||||
|
||||
[[ 1_2_ = (*_)(#c1) ]] && print 1 OK # because * matches 1_2
|
||||
[[ 1_2_ = (*_)(#c2) ]] && print 2 OK
|
||||
[[ 1_2_ = (*_)(#c3) ]] || print 3 OK
|
||||
0:Some more complicated backtracking with match counts.
|
||||
>1 OK
|
||||
>2 OK
|
||||
>3 OK
|
||||
|
||||
[[ foo = 'f'\o"o" ]]
|
||||
0:Stripping of quotes from patterns (1)
|
||||
|
||||
[[ foo = 'f'('o'|'a')('o'|'b') ]]
|
||||
0:Stripping of quotes from patterns (2)
|
||||
|
||||
[[ fob = 'f'('o'|'a')('o'|'b') ]]
|
||||
0:Stripping of quotes from patterns (3)
|
||||
|
||||
[[ fab = 'f'('o'|'a')('o'|'b') ]]
|
||||
0:Stripping of quotes from patterns (4)
|
||||
|
||||
[[ fib != 'f'('o'|'a')('o'|'b') ]]
|
||||
0:Stripping of quotes from patterns (4)
|
||||
|
||||
[[ - != [a-z] ]]
|
||||
0:- is a special character in ranges
|
||||
|
||||
[[ - = ['a-z'] ]]
|
||||
0:- is not a special character in ranges if quoted
|
||||
|
||||
[[ b-1 = [a-z]-[0-9] ]]
|
||||
0:- untokenized following a bracketed subexpression
|
||||
|
||||
[[ b-1 = []a-z]-[]0-9] ]]
|
||||
0:- "]" after "[" is normal range character and - still works
|
||||
|
||||
headremove="bcdef"
|
||||
print ${headremove#[a-z]}
|
||||
0:active - works in pattern in parameter
|
||||
>cdef
|
||||
|
||||
headremove="bcdef"
|
||||
print ${headremove#['a-z']}
|
||||
headremove="-cdef"
|
||||
print ${headremove#['a-z']}
|
||||
0:quoted - works in pattern in parameter
|
||||
>bcdef
|
||||
>cdef
|
||||
|
||||
[[ a != [^a] ]]
|
||||
0:^ active in character class if not quoted
|
||||
|
||||
[[ a = ['^a'] ]]
|
||||
0:^ not active in character class if quoted
|
||||
|
||||
[[ a != [!a] ]]
|
||||
0:! active in character class if not quoted
|
||||
|
||||
[[ a = ['!a'] ]]
|
||||
0:! not active in character class if quoted
|
||||
|
||||
# Actually, we don't need the quoting here,
|
||||
# c.f. the next test. This just makes it look
|
||||
# more standard.
|
||||
cset="^a-z"
|
||||
[[ "^" = ["$cset"] ]] || print Fail 1
|
||||
[[ "a" = ["$cset"] ]] || print Fail 2
|
||||
[[ "-" = ["$cset"] ]] || print Fail 3
|
||||
[[ "z" = ["$cset"] ]] || print Fail 4
|
||||
[[ "1" != ["$cset"] ]] || print Fail 5
|
||||
[[ "b" != ["$cset"] ]] || print Fail 6
|
||||
0:character set specified as quoted variable
|
||||
|
||||
cset="^a-z"
|
||||
[[ "^" = [$~cset] ]] || print Fail 1
|
||||
[[ "a" != [$~cset] ]] || print Fail 2
|
||||
[[ "-" = [$~cset] ]] || print Fail 3
|
||||
[[ "z" != [$~cset] ]] || print Fail 4
|
||||
[[ "1" = [$~cset] ]] || print Fail 5
|
||||
[[ "b" != [$~cset] ]] || print Fail 6
|
||||
0:character set specified as active variable
|
||||
|
||||
() { print -l -- $@:a } / /..{,/} /1 /nonexistent/..{,/} /deeper/nonexistent/..{,/}
|
||||
0:modifier ':a' doesn't require existence
|
||||
>/
|
||||
>/
|
||||
>/
|
||||
>/1
|
||||
>/
|
||||
>/
|
||||
>/deeper
|
||||
>/deeper
|
||||
|
||||
() { set -- ${PWD}/$^@; print -l -- $@:A } glob.tmp/nonexistent/foo/bar/baz
|
||||
0:modifier ':A' doesn't require existence
|
||||
*>*/glob.tmp/nonexistent/foo/bar/baz
|
||||
|
||||
ln -s dir3/subdir glob.tmp/link
|
||||
() {
|
||||
print ${1:A} | grep glob.tmp
|
||||
} glob.tmp/link/../../hello
|
||||
rm glob.tmp/link
|
||||
0:modifier ':A' resolves '..' components before symlinks
|
||||
# There should be no output
|
||||
|
||||
ln -s dir3/subdir glob.tmp/link
|
||||
() {
|
||||
print ${1:P}
|
||||
} glob.tmp/link/../../hello/world
|
||||
rm glob.tmp/link
|
||||
0:modifier ':P' resolves symlinks before '..' components
|
||||
*>*glob.tmp/hello/world
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
# Tests for process substitution: <(...), >(...) and =(...).
|
||||
|
||||
%prep
|
||||
if grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h > /dev/null 2>&1 ||
|
||||
grep '#define HAVE_FIFOS' $ZTST_testdir/../config.h > /dev/null 2>&1; then
|
||||
mkdir procsubst.tmp
|
||||
cd procsubst.tmp
|
||||
print 'First\tSecond\tThird\tFourth' >FILE1
|
||||
print 'Erste\tZweite\tDritte\tVierte' >FILE2
|
||||
else
|
||||
ZTST_unimplemented="process substitution is not supported"
|
||||
true
|
||||
fi
|
||||
|
||||
function copycat { cat "$@" }
|
||||
|
||||
%test
|
||||
paste <(cut -f1 FILE1) <(cut -f3 FILE2)
|
||||
0:<(...) substitution
|
||||
>First Dritte
|
||||
|
||||
# slightly desperate hack to force >(...) to be synchronous
|
||||
{ paste <(cut -f2 FILE1) <(cut -f4 FILE2) } > >(sed 's/e/E/g' >OUTFILE)
|
||||
cat OUTFILE
|
||||
0:>(...) substitution
|
||||
>SEcond ViErtE
|
||||
|
||||
diff =(cat FILE1) =(cat FILE2)
|
||||
1:=(...) substituion
|
||||
>1c1
|
||||
>< First Second Third Fourth
|
||||
>---
|
||||
>> Erste Zweite Dritte Vierte
|
||||
|
||||
copycat <(print First) <(print Zweite)
|
||||
0:FDs remain open for external commands called from functions
|
||||
>First
|
||||
>Zweite
|
||||
|
||||
catfield2() {
|
||||
local -a args
|
||||
args=(${(s.,.)1})
|
||||
print $args[1]
|
||||
cat $args[2]
|
||||
print $args[3]
|
||||
}
|
||||
catfield2 up,<(print $'\x64'own),sideways
|
||||
0:<(...) when embedded within an argument
|
||||
>up
|
||||
>down
|
||||
>sideways
|
||||
|
||||
outputfield2() {
|
||||
local -a args
|
||||
args=(${(s.,.)1})
|
||||
print $args[1]
|
||||
echo 'How sweet the moonlight sits upon the bank' >$args[2]
|
||||
print $args[3]
|
||||
}
|
||||
outputfield2 muddy,>(sed -e s/s/th/g >outputfield2.txt),vesture
|
||||
# yuk
|
||||
while [[ ! -e outputfield2.txt || ! -s outputfield2.txt ]]; do :; done
|
||||
cat outputfield2.txt
|
||||
0:>(...) when embedded within an argument
|
||||
>muddy
|
||||
>vesture
|
||||
>How thweet the moonlight thitth upon the bank
|
||||
|
||||
catfield1() {
|
||||
local -a args
|
||||
args=(${(s.,.)1})
|
||||
cat $args[1]
|
||||
print $args[2]
|
||||
}
|
||||
catfield1 =(echo s$'\x69't),jessica
|
||||
0:=(...) followed by something else without a break
|
||||
>sit
|
||||
>jessica
|
||||
|
||||
(
|
||||
setopt nonomatch
|
||||
# er... why is this treated as a glob?
|
||||
print everything,=(here is left),alone
|
||||
)
|
||||
0:=(...) preceded by other stuff has no special effect
|
||||
>everything,=(here is left),alone
|
||||
|
||||
print something=${:-=(echo 'C,D),(F,G)'}
|
||||
1: Graceful handling of bad substitution in enclosed context
|
||||
?(eval):1: unterminated `=(...)'
|
||||
# '`
|
||||
|
||||
() {
|
||||
print -n "first: "
|
||||
cat $1
|
||||
print -n "second: "
|
||||
cat $2
|
||||
} =(echo This becomes argument one) =(echo and this argument two)
|
||||
function {
|
||||
print -n "third: "
|
||||
cat $1
|
||||
print -n "fourth: "
|
||||
cat $2
|
||||
} =(echo This becomes argument three) =(echo and this argument four)
|
||||
0:Process environment of anonymous functions
|
||||
>first: This becomes argument one
|
||||
>second: and this argument two
|
||||
>third: This becomes argument three
|
||||
>fourth: and this argument four
|
||||
|
||||
() {
|
||||
# Make sure we don't close the file descriptor too early
|
||||
eval 'print "Execute a complicated command first" | sed s/command/order/'
|
||||
cat $1
|
||||
} <(echo This line was brought to you by the letters F and D)
|
||||
0:Process substitution as anonymous function argument
|
||||
>Execute a complicated order first
|
||||
>This line was brought to you by the letters F and D
|
||||
|
||||
alias foo='cat <('
|
||||
eval 'foo echo this is bound to work)'
|
||||
0:backtacking within command string parsing with alias still pending
|
||||
>this is bound to work
|
||||
|
||||
alias foo='cat <( print'
|
||||
eval 'foo here is some output)'
|
||||
0:full alias expanded when substitution starts in alias
|
||||
>here is some output
|
||||
|
||||
if ! (mkfifo test_pipe >/dev/null 2>&1); then
|
||||
ZTST_skip="mkfifo not available"
|
||||
else
|
||||
echo 1 | tee >(cat > test_pipe) | (){
|
||||
local pipein
|
||||
read pipein <test_pipe
|
||||
print $pipein
|
||||
read pipein
|
||||
print $pipein
|
||||
}
|
||||
fi
|
||||
0:proc subst fd in forked subshell closed in parent
|
||||
>1
|
||||
>1
|
||||
|
||||
if [[ ! -e test_pipe ]]; then
|
||||
ZTST_skip="mkfifo not available"
|
||||
else
|
||||
echo 1 | tee >(cat > test_pipe) | paste - test_pipe
|
||||
fi
|
||||
0:proc subst fd in forked subshell closed in parent (external command)
|
||||
>1 1
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,112 +0,0 @@
|
|||
# Tests for array indexing
|
||||
|
||||
%prep
|
||||
|
||||
foo=(a b c d e f g)
|
||||
arr=(foo bar baz)
|
||||
mkdir array.tmp
|
||||
touch array.tmp/{1..9}
|
||||
|
||||
%test
|
||||
|
||||
echo .$foo[1].
|
||||
0:The first element
|
||||
>.a.
|
||||
|
||||
echo .$foo[1,4].
|
||||
0:Normal multi-item indexing
|
||||
>.a b c d.
|
||||
|
||||
echo .$foo[1,0].
|
||||
0:This should be empty
|
||||
>..
|
||||
|
||||
echo .$foo[4,1].
|
||||
0:Another empty slice
|
||||
>..
|
||||
|
||||
echo .$foo[1,-8].
|
||||
0:An empty slice with a negative end
|
||||
>..
|
||||
|
||||
echo .$foo[0].
|
||||
0:Treat 0 as empty
|
||||
>..
|
||||
|
||||
echo .$foo[0,0].
|
||||
0:Treat 0,0 as empty
|
||||
>..
|
||||
|
||||
echo .$foo[0,1].
|
||||
0:Another weird way to access the first element
|
||||
>.a.
|
||||
|
||||
echo .$foo[3].
|
||||
0:An inner element
|
||||
>.c.
|
||||
|
||||
echo .$foo[2,2].
|
||||
0:Another inner element
|
||||
>.b.
|
||||
|
||||
echo .$foo[2,-4].
|
||||
0:A slice with a negative end
|
||||
>.b c d.
|
||||
|
||||
echo .$foo[-4,5].
|
||||
0:A slice with a negative start
|
||||
>.d e.
|
||||
|
||||
echo .$foo[-6,-2].
|
||||
0:A slice with a negative start and end
|
||||
>.b c d e f.
|
||||
|
||||
echo .${${arr[2]}[1]}.
|
||||
echo .${${arr[-2]}[1]}.
|
||||
echo .${${arr[2,2]}[1]}.
|
||||
echo .${${arr[-2,-2]}[1]}.
|
||||
echo .${${arr[2,-2]}[1]}.
|
||||
echo .${${arr[-2,2]}[1]}.
|
||||
0:Slices should return an array, elements a scalar
|
||||
>.b.
|
||||
>.b.
|
||||
>.bar.
|
||||
>.bar.
|
||||
>.bar.
|
||||
>.bar.
|
||||
|
||||
setopt ksh_arrays
|
||||
echo .${foo[1,2]}.
|
||||
unsetopt ksh_arrays
|
||||
0:Ksh array indexing
|
||||
>.b c.
|
||||
|
||||
setopt ksh_arrays
|
||||
echo .${foo[0,1]}.
|
||||
unsetopt ksh_arrays
|
||||
0:Ksh array indexing (ii)
|
||||
>.a b.
|
||||
|
||||
setopt ksh_arrays
|
||||
echo .${foo[1,-1]}.
|
||||
unsetopt ksh_arrays
|
||||
0:Ksh array indexing (iii)
|
||||
>.b c d e f g.
|
||||
|
||||
cd array.tmp
|
||||
echo . ?([3,5]) .
|
||||
cd ..
|
||||
0:Glob array indexing
|
||||
>. 3 4 5 .
|
||||
|
||||
cd array.tmp
|
||||
echo . ?([2,-2]) .
|
||||
cd ..
|
||||
0:Glob array indexing (ii)
|
||||
>. 2 3 4 5 6 7 8 .
|
||||
|
||||
cd array.tmp
|
||||
echo . ?([-6,-4]) .
|
||||
cd ..
|
||||
0:Glob array indexing (iii)
|
||||
>. 4 5 6 .
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
# Test parameter subscripting.
|
||||
|
||||
%prep
|
||||
|
||||
s='Twinkle, twinkle, little *, [how] I [wonder] what? You are!'
|
||||
a=('1' ']' '?' '\2' '\]' '\?' '\\3' '\\]' '\\?' '\\\4' '\\\]' '\\\?')
|
||||
typeset -g -A A
|
||||
A=($a)
|
||||
|
||||
%test
|
||||
|
||||
x=','
|
||||
print $s[(i)winkle] $s[(I)winkle]
|
||||
print ${s[(i)You are]} $#s
|
||||
print ${s[(r)$x,(R)$x]}
|
||||
0:Scalar pattern subscripts without wildcards
|
||||
>2 11
|
||||
>53 60
|
||||
>, twinkle, little *,
|
||||
|
||||
x='*'
|
||||
print $s[(i)*] $s[(i)\*] $s[(i)$x*] $s[(i)${(q)x}*] $s[(I)$x\*]
|
||||
print $s[(r)?,(R)\?] $s[(r)\?,(R)?]
|
||||
print $s[(r)\*,(R)*]
|
||||
print $s[(r)\],(R)\[]
|
||||
0:Scalar pattern subscripts with wildcards
|
||||
>1 26 1 26 26
|
||||
>Twinkle, twinkle, little *, [how] I [wonder] what? ? You are!
|
||||
>*, [how] I [wonder] what? You are!
|
||||
>] I [
|
||||
|
||||
print $s[(i)x] : $s[(I)x]
|
||||
print $s[(r)x] : $s[(R)x]
|
||||
0:Scalar pattern subscripts that do not match
|
||||
>61 : 0
|
||||
>:
|
||||
|
||||
print -R $s[$s[(i)\[]] $s[(i)$s[(r)\*]] $s[(i)${(q)s[(r)\]]}]
|
||||
0:Scalar subscripting using a pattern subscript to get the index
|
||||
>[ 1 33
|
||||
|
||||
print -R $a[(r)?] $a[(R)?]
|
||||
print $a[(n:2:i)?] $a[(n:2:I)?]
|
||||
print $a[(i)\?] $a[(I)\?]
|
||||
print $a[(i)*] $a[(i)\*]
|
||||
0:Array pattern subscripts
|
||||
>1 ?
|
||||
>2 2
|
||||
>3 3
|
||||
>1 13
|
||||
|
||||
# It'd be nice to do some of the following with (r), but we run into
|
||||
# limitations of the ztst script parsing of backslashes in the output.
|
||||
print -R $a[(i)\\\\?] $a[(i)\\\\\?]
|
||||
print -R $a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]
|
||||
print -R ${a[(i)\\\\\\\\?]} ${a[(i)\\\\\\\\\?]}
|
||||
print -R "$a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]"
|
||||
print -R $a[(i)\]] $a[(i)\\\\\]] $a[(i)\\\\\\\\\]] $a[(i)\\\\\\\\\\\\\]]
|
||||
print -R $a[(i)${(q)a[5]}] $a[(i)${(q)a[8]}] $a[(i)${(q)a[11]}]
|
||||
print -R $a[(i)${a[3]}] $a[(i)${a[6]}] $a[(i)${a[9]}] $a[(i)${a[12]}]
|
||||
0:Array pattern subscripts with multiple backslashes
|
||||
>4 6
|
||||
>7 9
|
||||
>7 9
|
||||
>7 9
|
||||
>2 5 8 11
|
||||
>5 8 11
|
||||
>1 3 4 6
|
||||
|
||||
print -R $A[1] $A[?] $A[\\\\3] $A[\\\]]
|
||||
print -R $A[$a[11]]
|
||||
print -R $A[${(q)a[5]}]
|
||||
0:Associative array lookup (direct subscripting)
|
||||
>] \2 \\] \?
|
||||
>\\\?
|
||||
>\\\?
|
||||
|
||||
# The (o) is necessary here for predictable output ordering
|
||||
print -R $A[(I)\?] ${(o)A[(I)?]}
|
||||
print -R $A[(i)\\\\\\\\3]
|
||||
print -R $A[(I)\\\\\\\\\?] ${(o)A[(I)\\\\\\\\?]}
|
||||
0:Associative array lookup (pattern subscripting)
|
||||
>? 1 ?
|
||||
>\\3
|
||||
>\\? \\3 \\?
|
||||
|
||||
print -R $A[(R)\?] : ${(o)A[(R)?]}
|
||||
print -R $A[(R)\\\\\?] ${(o)A[(R)\\\\?]} ${(o)A[(R)\\\\\?]}
|
||||
print -R ${(o)A[(R)\\\\\\\\\]]}
|
||||
0:Associative array lookup (reverse subscripting)
|
||||
>: ]
|
||||
>\? \2 \? \?
|
||||
>\\]
|
||||
|
||||
eval 'A[*]=star'
|
||||
1:Illegal associative array assignment
|
||||
?(eval):1: A: attempt to set slice of associative array
|
||||
|
||||
x='*'
|
||||
A[$x]=xstar
|
||||
A[${(q)x}]=qxstar
|
||||
print -R ${(k)A[(r)xstar]} $A[$x]
|
||||
print -R ${(k)A[(r)qxstar]} $A[${(q)x}]
|
||||
A[(e)*]=star
|
||||
A[\*]=backstar
|
||||
print -R ${(k)A[(r)star]} $A[(e)*]
|
||||
print -R ${(k)A[(r)backstar]} $A[\*]
|
||||
0:Associative array assignment
|
||||
>* xstar
|
||||
>\* qxstar
|
||||
>* star
|
||||
>\* backstar
|
||||
|
||||
o='['
|
||||
c=']'
|
||||
A[\]]=cbrack
|
||||
A[\[]=obrack
|
||||
A[\\\[]=backobrack
|
||||
A[\\\]]=backcbrack
|
||||
print -R $A[$o] $A[$c] $A[\[] $A[\]] $A[\\\[] $A[\\\]]
|
||||
print -R $A[(i)\[] $A[(i)\]] $A[(i)\\\\\[] $A[(i)\\\\\]]
|
||||
0:Associative array keys with open and close brackets
|
||||
>obrack cbrack obrack cbrack backobrack backcbrack
|
||||
>[ ] \[ \]
|
||||
|
||||
print -R $A[$o] $A[$s[(r)\[]]
|
||||
print -R $A[(r)$c] $A[(r)$s[(r)\]]]
|
||||
print -R $A[$A[(i)\\\\\]]]
|
||||
0:Associative array lookup using a pattern subscript to get the key
|
||||
>obrack obrack
|
||||
>] ]
|
||||
>backcbrack
|
||||
|
||||
print -R ${A[${A[(r)\\\\\\\\\]]}]::=zounds}
|
||||
print -R ${A[${A[(r)\\\\\\\\\]]}]}
|
||||
print -R $A[\\\\\]]
|
||||
0:Associative array substitution-assignment with reverse pattern subscript key
|
||||
>zounds
|
||||
>zounds
|
||||
>zounds
|
||||
|
||||
print -R ${(o)A[(K)\]]}
|
||||
print -R ${(o)A[(K)\\\]]}
|
||||
0:Associative array keys interpreted as patterns
|
||||
>\2 backcbrack cbrack star
|
||||
>\\\4 \\\? star zounds
|
||||
|
||||
# It doesn't matter which element we get, since we never guarantee
|
||||
# ordering of an associative array. So just test the number of matches.
|
||||
array=(${(o)A[(k)\]]})
|
||||
print ${#array}
|
||||
array=(${(o)A[(k)\\\]]})
|
||||
print ${#array}
|
||||
0:Associative array keys interpreted as patterns, single match
|
||||
>1
|
||||
>1
|
||||
|
||||
typeset -g "A[one\"two\"three\"quotes]"=QQQ
|
||||
typeset -g 'A[one\"two\"three\"quotes]'=qqq
|
||||
print -R "$A[one\"two\"three\"quotes]"
|
||||
print -R $A[one\"two\"three\"quotes]
|
||||
A[one"two"three"four"quotes]=QqQq
|
||||
print -R $A[one"two"three"four"quotes]
|
||||
print -R $A[$A[(i)one\"two\"three\"quotes]]
|
||||
print -R "$A[$A[(i)one\"two\"three\"quotes]]"
|
||||
0:Associative array keys with double quotes
|
||||
>QQQ
|
||||
>qqq
|
||||
>QqQq
|
||||
>qqq
|
||||
>QQQ
|
||||
|
||||
print ${x::=$A[$A[(i)one\"two\"three\"quotes]]}
|
||||
print $x
|
||||
print ${x::="$A[$A[(i)one\"two\"three\"quotes]]"}
|
||||
print $x
|
||||
0:More keys with double quotes, used in assignment-expansion
|
||||
>qqq
|
||||
>qqq
|
||||
>QQQ
|
||||
>QQQ
|
||||
|
||||
qqq=lower
|
||||
QQQ=upper
|
||||
print ${(P)A[one\"two\"three\"quotes]}
|
||||
print "${(P)A[$A[(i)one\"two\"three\"quotes]]}"
|
||||
0:Keys with double quotes and the (P) expansion flag
|
||||
>lower
|
||||
>upper
|
||||
|
||||
typeset -ga empty
|
||||
echo X${${empty##*}[-1]}X
|
||||
0:Negative index applied to substition result from empty array
|
||||
>XX
|
||||
|
||||
print $empty[(i)] $empty[(I)]
|
||||
0:(i) returns 1 for empty array, (I) returns 0.
|
||||
>1 0
|
||||
|
||||
array=(one two three four)
|
||||
print X$array[0]X
|
||||
0:Element zero is empty if KSH_ZERO_SUBSCRIPT is off.
|
||||
>XX
|
||||
|
||||
array[0]=fumble
|
||||
1:Can't set element zero if KSH_ZERO_SUBSCRIPT is off.
|
||||
?(eval):1: array: assignment to invalid subscript range
|
||||
|
||||
print X$array[(R)notfound]X
|
||||
0:(R) returns empty if not found if KSH_ZERO_SUBSCRIPT is off.
|
||||
>XX
|
||||
|
||||
setopt KSH_ZERO_SUBSCRIPT
|
||||
print X$array[0]X
|
||||
0:Element zero is element one if KSH_ZERO_SUBSCRIPT is on.
|
||||
>XoneX
|
||||
|
||||
array[0]=fimble
|
||||
print $array
|
||||
0:Can set element zero if KSH_ZERO_SUBSCRIPT is on.
|
||||
>fimble two three four
|
||||
|
||||
print X$array[(R)notfound]X
|
||||
0:(R) yuckily returns the first element on failure withe KSH_ZERO_SUBSCRIPT
|
||||
>XfimbleX
|
||||
|
||||
unsetopt KSH_ZERO_SUBSCRIPT
|
||||
array[(R)notfound,(r)notfound]=(help help here come the seventies retreads)
|
||||
print $array
|
||||
0:[(R)notfound,(r)notfound] replaces the whole array
|
||||
>help help here come the seventies retreads
|
||||
|
||||
string="Why, if it isn't Officer Dibble"
|
||||
print "[${string[0]}][${string[1]}][${string[0,3]}]"
|
||||
0:String subscripts with KSH_ZERO_SUBSCRIPT unset
|
||||
>[][W][Why]
|
||||
|
||||
setopt KSH_ZERO_SUBSCRIPT
|
||||
print "[${string[0]}][${string[1]}][${string[0,3]}]"
|
||||
0:String subscripts with KSH_ZERO_SUBSCRIPT set
|
||||
>[W][W][Why]
|
||||
|
||||
unsetopt KSH_ZERO_SUBSCRIPT
|
||||
string[0,3]="Goodness"
|
||||
print $string
|
||||
0:Assignment to chunk of string ignores element 0
|
||||
>Goodness, if it isn't Officer Dibble
|
||||
|
||||
string[0]=!
|
||||
1:Can't set only element zero of string
|
||||
?(eval):1: string: assignment to invalid subscript range
|
||||
|
||||
typeset -A assoc=(leader topcat officer dibble sidekick choochoo)
|
||||
alias myind='echo leader' myletter='echo 1' myletter2='echo 4'
|
||||
print ${assoc[$(myind)]}
|
||||
print $assoc[$(myind)]
|
||||
print ${assoc[$(myind)][$(myletter)]}${assoc[$(myind)][$(myletter2)]}
|
||||
assoc[$(myind)]='of the gang'
|
||||
print ${assoc[$(myind)]}
|
||||
print $assoc[$(myind)]
|
||||
print $assoc[leader]
|
||||
0: Parsing subscript with non-trivial tokenisation
|
||||
>topcat
|
||||
>topcat
|
||||
>tc
|
||||
>of the gang
|
||||
>of the gang
|
||||
>of the gang
|
||||
|
|
@ -1,587 +0,0 @@
|
|||
%prep
|
||||
|
||||
# Find a UTF-8 locale.
|
||||
setopt multibyte
|
||||
# Don't let LC_* override our choice of locale.
|
||||
unset -m LC_\*
|
||||
mb_ok=
|
||||
langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8
|
||||
$(locale -a 2>/dev/null | egrep 'utf8|UTF-8'))
|
||||
for LANG in $langs; do
|
||||
if [[ é = ? ]]; then
|
||||
mb_ok=1
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if [[ -z $mb_ok ]]; then
|
||||
ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented"
|
||||
else
|
||||
print -u $ZTST_fd Testing multibyte with locale $LANG
|
||||
mkdir multibyte.tmp && cd multibyte.tmp
|
||||
fi
|
||||
|
||||
%test
|
||||
|
||||
a=ténébreux
|
||||
for i in {1..9}; do
|
||||
print ${a[i]}
|
||||
for j in {$i..9}; do
|
||||
print $i $j ${a[i,j]} ${a[-j,-i]}
|
||||
done
|
||||
done
|
||||
0:Basic indexing with multibyte characters
|
||||
>t
|
||||
>1 1 t x
|
||||
>1 2 té ux
|
||||
>1 3 tén eux
|
||||
>1 4 téné reux
|
||||
>1 5 ténéb breux
|
||||
>1 6 ténébr ébreux
|
||||
>1 7 ténébre nébreux
|
||||
>1 8 ténébreu énébreux
|
||||
>1 9 ténébreux ténébreux
|
||||
>é
|
||||
>2 2 é u
|
||||
>2 3 én eu
|
||||
>2 4 éné reu
|
||||
>2 5 énéb breu
|
||||
>2 6 énébr ébreu
|
||||
>2 7 énébre nébreu
|
||||
>2 8 énébreu énébreu
|
||||
>2 9 énébreux ténébreu
|
||||
>n
|
||||
>3 3 n e
|
||||
>3 4 né re
|
||||
>3 5 néb bre
|
||||
>3 6 nébr ébre
|
||||
>3 7 nébre nébre
|
||||
>3 8 nébreu énébre
|
||||
>3 9 nébreux ténébre
|
||||
>é
|
||||
>4 4 é r
|
||||
>4 5 éb br
|
||||
>4 6 ébr ébr
|
||||
>4 7 ébre nébr
|
||||
>4 8 ébreu énébr
|
||||
>4 9 ébreux ténébr
|
||||
>b
|
||||
>5 5 b b
|
||||
>5 6 br éb
|
||||
>5 7 bre néb
|
||||
>5 8 breu énéb
|
||||
>5 9 breux ténéb
|
||||
>r
|
||||
>6 6 r é
|
||||
>6 7 re né
|
||||
>6 8 reu éné
|
||||
>6 9 reux téné
|
||||
>e
|
||||
>7 7 e n
|
||||
>7 8 eu én
|
||||
>7 9 eux tén
|
||||
>u
|
||||
>8 8 u é
|
||||
>8 9 ux té
|
||||
>x
|
||||
>9 9 x t
|
||||
|
||||
s=é
|
||||
print A${s[-2]}A B${s[-1]}B C${s[0]}C D${s[1]}D E${s[2]}E
|
||||
0:Out of range subscripts with multibyte characters
|
||||
>AA BéB CC DéD EE
|
||||
|
||||
print ${a[(i)é]} ${a[(I)é]} ${a[${a[(i)é]},${a[(I)é]}]}
|
||||
0:Reverse indexing with multibyte characters
|
||||
>2 4 éné
|
||||
|
||||
print ${a[(r)én,(r)éb]}
|
||||
0:Subscript searching with multibyte characters
|
||||
>énéb
|
||||
|
||||
print ${a[(rb:1:)é,-1]}
|
||||
print ${a[(rb:2:)é,-1]}
|
||||
print ${a[(rb:3:)é,-1]}
|
||||
print ${a[(rb:4:)é,-1]}
|
||||
print ${a[(rb:5:)é,-1]}
|
||||
0:Subscript searching with initial offset
|
||||
>énébreux
|
||||
>énébreux
|
||||
>ébreux
|
||||
>ébreux
|
||||
>
|
||||
|
||||
print ${a[(rn:1:)é,-1]}
|
||||
print ${a[(rn:2:)é,-1]}
|
||||
print ${a[(rn:3:)é,-1]}
|
||||
0:Subscript searching with count
|
||||
>énébreux
|
||||
>ébreux
|
||||
>
|
||||
|
||||
print ${a[(R)én,(R)éb]}
|
||||
0:Backward subscript searching with multibyte characters
|
||||
>énéb
|
||||
|
||||
# Starting offsets with (R) seem to be so strange as to be hardly
|
||||
# worth testing.
|
||||
|
||||
setopt extendedglob
|
||||
[[ $a = (#b)t(én)(éb)reux ]] || print "Failed to match." >&2
|
||||
for i in {1..${#match}}; do
|
||||
print $match[i] $mbegin[i] $mend[i] ${a[$mbegin[i],$mend[i]]}
|
||||
done
|
||||
0:Multibyte offsets in pattern tests
|
||||
>én 2 3 én
|
||||
>éb 4 5 éb
|
||||
|
||||
b=${(U)a}
|
||||
print $b
|
||||
print ${(L)b}
|
||||
desdichado="Je suis le $a, le veuf, l'inconsolé"
|
||||
print ${(C)desdichado}
|
||||
lxiv="l'état c'est moi"
|
||||
print ${(C)lxiv}
|
||||
0:Case modification of multibyte strings
|
||||
>TÉNÉBREUX
|
||||
>ténébreux
|
||||
>Je Suis Le Ténébreux, Le Veuf, L'Inconsolé
|
||||
>L'État C'Est Moi
|
||||
|
||||
array=(ølaf ødd øpened án encyclopædia)
|
||||
barray=(${(U)array})
|
||||
print $barray
|
||||
print ${(L)barray}
|
||||
print ${(C)array}
|
||||
print ${(C)barray}
|
||||
0:Case modification of arrays with multibyte strings
|
||||
>ØLAF ØDD ØPENED ÁN ENCYCLOPÆDIA
|
||||
>ølaf ødd øpened án encyclopædia
|
||||
>Ølaf Ødd Øpened Án Encyclopædia
|
||||
>Ølaf Ødd Øpened Án Encyclopædia
|
||||
|
||||
print $(( ##¥ ))
|
||||
pound=£
|
||||
print $(( #pound ))
|
||||
alpha=α
|
||||
print $(( ##α )) $(( #alpha ))
|
||||
0:Conversion to Unicode in mathematical expressions
|
||||
>165
|
||||
>163
|
||||
>945 945
|
||||
|
||||
unsetopt posix_identifiers
|
||||
expr='hähä=3 || exit 1; print $hähä'
|
||||
eval $expr
|
||||
setopt posix_identifiers
|
||||
(eval $expr)
|
||||
1:POSIX_IDENTIFIERS option
|
||||
>3
|
||||
?(eval):1: command not found: hähä=3
|
||||
|
||||
foo="Ølaf«Ødd«øpénëd«ån«àpple"
|
||||
print -l ${(s.«.)foo}
|
||||
ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος."
|
||||
print -l ${=ioh}
|
||||
print ${(w)#ioh}
|
||||
0:Splitting with multibyte characters
|
||||
>Ølaf
|
||||
>Ødd
|
||||
>øpénëd
|
||||
>ån
|
||||
>àpple
|
||||
>Ἐν
|
||||
>ἀρχῇ
|
||||
>ἦν
|
||||
>ὁ
|
||||
>λόγος,
|
||||
>καὶ
|
||||
>ὁ
|
||||
>λόγος
|
||||
>ἦν
|
||||
>πρὸς
|
||||
>τὸν
|
||||
>θεόν,
|
||||
>καὶ
|
||||
>θεὸς
|
||||
>ἦν
|
||||
>ὁ
|
||||
>λόγος.
|
||||
>17
|
||||
|
||||
read -d £ one
|
||||
read -d £ two
|
||||
print $one
|
||||
print $two
|
||||
0:read with multibyte delimiter
|
||||
<first£second£
|
||||
>first
|
||||
>second
|
||||
|
||||
(IFS=«
|
||||
read -d » -A array
|
||||
print -l $array)
|
||||
0:read -A with multibyte IFS
|
||||
<dominus«illuminatio«mea»ignored
|
||||
>dominus
|
||||
>illuminatio
|
||||
>mea
|
||||
|
||||
read -k2 -u0 twochars
|
||||
print $twochars
|
||||
0:read multibyte characters
|
||||
<«»ignored
|
||||
>«»
|
||||
|
||||
read -q -u0 mb
|
||||
print $?
|
||||
0:multibyte character makes read -q return false
|
||||
<«
|
||||
>1
|
||||
|
||||
# See if the system grokks first-century Greek...
|
||||
ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος."
|
||||
for (( i = 1; i <= ${#ioh}; i++ )); do
|
||||
# FC3 doesn't recognise ῇ (U+1FC7: Greek small letter eta with
|
||||
# perispomeni and ypogegrammeni, of course) as a lower case character.
|
||||
if [[ $ioh[i] != [[:lower:]] && $i != 7 ]]; then
|
||||
for tp in upper space punct invalid; do
|
||||
if [[ $tp = invalid || $ioh[i] = [[:${tp}:]] ]]; then
|
||||
print "$i: $tp"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
0:isw* functions on non-ASCII wide characters
|
||||
>1: upper
|
||||
>3: space
|
||||
>8: space
|
||||
>11: space
|
||||
>13: space
|
||||
>19: punct
|
||||
>20: space
|
||||
>24: space
|
||||
>26: space
|
||||
>32: space
|
||||
>35: space
|
||||
>40: space
|
||||
>44: space
|
||||
>49: punct
|
||||
>50: space
|
||||
>54: space
|
||||
>59: space
|
||||
>62: space
|
||||
>64: space
|
||||
>70: punct
|
||||
|
||||
ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος"
|
||||
print ${ioh#[[:alpha:]]##}
|
||||
print ${ioh##[[:alpha:]]##}
|
||||
print ${ioh%[[:alpha:]]##}
|
||||
print ${ioh%%[[:alpha:]]##}
|
||||
print ${(S)ioh#λ*ς}
|
||||
print ${(S)ioh##λ*ς}
|
||||
print ${(S)ioh%θ*ς}
|
||||
print ${(S)ioh%%θ*ς}
|
||||
0:Parameter #, ##, %, %% with multibyte characters
|
||||
>ν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
|
||||
> ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
|
||||
>Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγο
|
||||
>Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ
|
||||
>Ἐν ἀρχῇ ἦν ὁ , καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
|
||||
>Ἐν ἀρχῇ ἦν ὁ
|
||||
>Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ ἦν ὁ λόγος
|
||||
>Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ
|
||||
|
||||
a="1ë34ë6"
|
||||
print ${(BEN)a#*4}
|
||||
print ${(BEN)a##*ë}
|
||||
print ${(BEN)a%4*}
|
||||
print ${(BEN)a%%ë*}
|
||||
print ${(SBEN)a#ë3}
|
||||
print ${(SBEN)a%4ë}
|
||||
0:Flags B, E, N and S in ${...#...} and ${...%...}
|
||||
>1 5 4
|
||||
>1 6 5
|
||||
>4 7 3
|
||||
>2 7 5
|
||||
>2 4 2
|
||||
>4 6 2
|
||||
|
||||
foo=(κατέβην χθὲς εἰς Πειραιᾶ)
|
||||
print ${(l.3..¥.r.3..£.)foo}
|
||||
print ${(l.4..¥.r.2..£.)foo}
|
||||
print ${(l.5..¥.r.1..£.)foo}
|
||||
print ${(l.4..¥..«.r.4..£..».)foo}
|
||||
print ${(l.4..¥..Σωκράτης.r.4..£..Γλαύκωνος.)foo}
|
||||
0:simultaneous left and right padding
|
||||
>κατέβη ¥χθὲς£ ¥¥εἰς£ Πειραι
|
||||
>¥κατέβ ¥¥χθὲς ¥¥¥εἰς ¥Πειρα
|
||||
>¥¥κατέ ¥¥¥χθὲ ¥¥¥¥εἰ ¥¥Πειρ
|
||||
>«κατέβην ¥«χθὲς»£ ¥¥«εἰς»£ «Πειραιᾶ
|
||||
>ςκατέβην ηςχθὲςΓλ τηςεἰςΓλ ςΠειραιᾶ
|
||||
# er... yeah, that looks right...
|
||||
|
||||
foo=picobarn
|
||||
print ${foo:s£bar£rod£:s¥rod¥stick¥}
|
||||
0:Delimiters in modifiers
|
||||
>picostickn
|
||||
|
||||
# TODO: if we get paired multibyte bracket delimiters to work
|
||||
# (as Emacs does, the smug so-and-so), the following should change.
|
||||
foo=bar
|
||||
print ${(r£5££X£)foo}
|
||||
print ${(l«10««Y««HI«)foo}
|
||||
0:Delimiters in parameter flags
|
||||
>barXX
|
||||
>YYYYYHIbar
|
||||
|
||||
printf "%4.3s\n" főobar
|
||||
0:Multibyte characters in printf widths
|
||||
> főo
|
||||
|
||||
# We ask for case-insensitive sorting here (and supply upper case
|
||||
# characters) so that we exercise the logic in the shell that lowers the
|
||||
# case of the string for case-insensitive sorting.
|
||||
print -oi HÛH HÔH HÎH HÊH HÂH
|
||||
(LC_ALL=C; print -oi HAH HUH HEH HÉH HÈH)
|
||||
0:Multibyte characters in print sorting
|
||||
>HÂH HÊH HÎH HÔH HÛH
|
||||
>HAH HEH HUH HÈH HÉH
|
||||
|
||||
# These are control characters in Unicode, so don't show up.
|
||||
# We just want to check they're not being treated as tokens.
|
||||
for x in {128..150}; do
|
||||
print ${(#)x}
|
||||
done | while read line; do
|
||||
print ${#line} $(( #line ))
|
||||
done
|
||||
0:evaluated character number with multibyte characters
|
||||
>1 128
|
||||
>1 129
|
||||
>1 130
|
||||
>1 131
|
||||
>1 132
|
||||
>1 133
|
||||
>1 134
|
||||
>1 135
|
||||
>1 136
|
||||
>1 137
|
||||
>1 138
|
||||
>1 139
|
||||
>1 140
|
||||
>1 141
|
||||
>1 142
|
||||
>1 143
|
||||
>1 144
|
||||
>1 145
|
||||
>1 146
|
||||
>1 147
|
||||
>1 148
|
||||
>1 149
|
||||
>1 150
|
||||
|
||||
touch ngs1txt ngs2txt ngs10txt ngs20txt ngs100txt ngs200txt
|
||||
setopt numericglobsort
|
||||
print -l ngs*
|
||||
0:NUMERIC_GLOB_SORT option in UTF-8 locale
|
||||
>ngs1txt
|
||||
>ngs2txt
|
||||
>ngs10txt
|
||||
>ngs20txt
|
||||
>ngs100txt
|
||||
>ngs200txt
|
||||
|
||||
# Not strictly multibyte, but gives us a well-defined locale for testing.
|
||||
foo=$'X\xc0Y\x07Z\x7fT'
|
||||
print -r ${(q)foo}
|
||||
0:Backslash-quoting of unprintable/invalid characters uses $'...'
|
||||
>X$'\300'Y$'\a'Z$'\177'T
|
||||
|
||||
# This also isn't strictly multibyte and is here to reduce the
|
||||
# likelihood of a "cannot do character set conversion" error.
|
||||
(print $'\u00e9') 2>&1 | read
|
||||
if [[ $REPLY != é ]]; then
|
||||
print "warning: your system can't do simple Unicode conversion." >&$ZTST_fd
|
||||
print "Check you have a correctly installed iconv library." >&$ZTST_fd
|
||||
# cheat
|
||||
repeat 4 print OK
|
||||
else
|
||||
testfn() { (LC_ALL=C; print $'\u00e9') }
|
||||
repeat 4 testfn 2>&1 | while read line; do
|
||||
if [[ $line = *"character not in range"* ]]; then
|
||||
print OK
|
||||
elif [[ $line = "?" ]]; then
|
||||
print OK
|
||||
else
|
||||
print Failed: no error message and no question mark
|
||||
fi
|
||||
done
|
||||
fi
|
||||
true
|
||||
0:error handling in Unicode quoting
|
||||
>OK
|
||||
>OK
|
||||
>OK
|
||||
>OK
|
||||
|
||||
tmp1='glob/\(\)Ą/*'
|
||||
[[ glob/'()Ą'/foo == $~tmp1 ]] && print "Matched against $tmp1"
|
||||
tmp1='glob/\(\)Ā/*'
|
||||
[[ glob/'()Ā'/bar == $~tmp1 ]] && print "Matched against $tmp1"
|
||||
0:Backslashes and metafied characters in patterns
|
||||
>Matched against glob/()Ą/*
|
||||
>Matched against glob/()Ā/*
|
||||
|
||||
mkdir 梶浦由記 'Пётр Ильич Чайковский'
|
||||
(cd 梶浦由記; print ${${(%):-%~}:t})
|
||||
(cd 'Пётр Ильич Чайковский'; print ${${(%):-%~}:t})
|
||||
0:Metafied characters in prompt expansion
|
||||
>梶浦由記
|
||||
>Пётр Ильич Чайковский
|
||||
|
||||
(
|
||||
setopt nonomatch
|
||||
tmp1=Ą
|
||||
tmpA=(Ą 'Пётр Ильич Чайковский' 梶浦由記)
|
||||
print ${tmp1} ${(%)tmp1} ${(%%)tmp1}
|
||||
print ${#tmp1} ${#${(%)tmp1}} ${#${(%%)tmp1}}
|
||||
print ${tmpA}
|
||||
print ${(%)tmpA}
|
||||
print ${(%%)tmpA}
|
||||
)
|
||||
0:More metafied characters in prompt expansion
|
||||
>Ą Ą Ą
|
||||
>1 1 1
|
||||
>Ą Пётр Ильич Чайковский 梶浦由記
|
||||
>Ą Пётр Ильич Чайковский 梶浦由記
|
||||
>Ą Пётр Ильич Чайковский 梶浦由記
|
||||
|
||||
setopt cbases
|
||||
print $'\xc5' | read
|
||||
print $(( [#16] #REPLY ))
|
||||
0:read passes through invalid multibyte characters
|
||||
>0xC5
|
||||
|
||||
word=abcま
|
||||
word[-1]=
|
||||
print $word
|
||||
word=abcま
|
||||
word[-2]=
|
||||
print $word
|
||||
word=abcま
|
||||
word[4]=d
|
||||
print $word
|
||||
word=abcま
|
||||
word[3]=not_c
|
||||
print $word
|
||||
0:assignment with negative indices
|
||||
>abc
|
||||
>abま
|
||||
>abcd
|
||||
>abnot_cま
|
||||
|
||||
# The following doesn't necessarily need UTF-8, but this gives
|
||||
# us the full effect --- if we parse this wrongly the \xe9
|
||||
# in combination with the tokenized input afterwards looks like a
|
||||
# valid UTF-8 character. But it isn't.
|
||||
print $'$\xe9#``' >test_bad_param
|
||||
(setopt nonomatch
|
||||
. ./test_bad_param)
|
||||
127:Invalid parameter name with following tokenized input
|
||||
?./test_bad_param:1: command not found: $\M-i#
|
||||
|
||||
lines=$'one\tZSH\tthree\nfour\tfive\tsix'
|
||||
print -X8 -r -- $lines
|
||||
0:Tab expansion with extra-wide characters
|
||||
>one ZSH three
|
||||
>four five six
|
||||
# This doesn't look aligned in my editor because actually the characters
|
||||
# aren't quite double width, but the arithmetic is correct.
|
||||
# It appears just to be an effect of the font.
|
||||
|
||||
() {
|
||||
emulate -L zsh
|
||||
setopt errreturn
|
||||
local cdpath=(.)
|
||||
mkdir ホ
|
||||
cd ホ
|
||||
cd ..
|
||||
cd ./ホ
|
||||
cd ..
|
||||
}
|
||||
0:cd with special characters
|
||||
|
||||
test_array=(
|
||||
'[[ \xcc = \xcc ]]'
|
||||
'[[ \xcc != \xcd ]]'
|
||||
'[[ \xcc != \ucc ]]'
|
||||
'[[ \ucc = \ucc ]]'
|
||||
'[[ \ucc = [\ucc] ]]'
|
||||
'[[ \xcc != [\ucc] ]]'
|
||||
# Not clear how useful the following is...
|
||||
'[[ \xcc = [\xcc] ]]'
|
||||
)
|
||||
for test in $test_array; do
|
||||
if ! eval ${(g::)test} ; then
|
||||
print -rl "Test $test failed" >&2
|
||||
fi
|
||||
done
|
||||
0:Invalid characters in pattern matching
|
||||
|
||||
[[ $'\xe3' == [[:INCOMPLETE:]] ]] || print fail 1
|
||||
[[ $'\xe3\x83' == [[:INCOMPLETE:]][[:INVALID:]] ]] || print fail 2
|
||||
[[ $'\xe3\x83\x9b' != [[:INCOMPLETE:][:INVALID:]] ]] || print fail 3
|
||||
[[ $'\xe3\x83\x9b' = ? ]] || print fail 4
|
||||
0:Testing incomplete and invalid multibyte character components
|
||||
|
||||
print -r -- ${(q+):-ホ}
|
||||
foo='She said "ホ". I said "You can'\''t '\''ホ'\'' me!'
|
||||
print -r -- ${(q+)foo}
|
||||
0:${(q+)...} with printable multibyte characters
|
||||
>ホ
|
||||
>'She said "ホ". I said "You can'\''t '\''ホ'\'' me!'
|
||||
|
||||
# This will silently succeed if zsh/parameter isn't available
|
||||
(zmodload zsh/parameter >/dev/null 2>&1
|
||||
f() {
|
||||
: $(:)
|
||||
"↓"
|
||||
}
|
||||
: $functions)
|
||||
0:Multibyte handling of functions parameter
|
||||
|
||||
# c1=U+0104 (Ą) and c2=U+0120 (Ġ) are chosen so that
|
||||
# u1 = utf8(c1) = c4 84 < u2 = utf8(c2) = c4 a0
|
||||
# metafy(u1) = c4 83 a4 > metafy(u2) = c4 83 80
|
||||
# in both UTF-8 and ASCII collations (the latter is used in macOS
|
||||
# and some versions of BSDs).
|
||||
local -a names=( $'\u0104' $'\u0120' )
|
||||
print -o $names
|
||||
mkdir -p colltest
|
||||
cd colltest
|
||||
touch $names
|
||||
print ?
|
||||
0:Sorting of metafied characters
|
||||
>Ą Ġ
|
||||
>Ą Ġ
|
||||
|
||||
printf '%q%q\n' 你你
|
||||
0:printf %q and quotestring and general metafy / token madness
|
||||
>你你
|
||||
|
||||
# This test is kept last as it introduces an additional
|
||||
# dependency on the system regex library.
|
||||
if zmodload zsh/regex 2>/dev/null; then
|
||||
[[ $'\ua0' =~ '^.$' ]] && print OK
|
||||
[[ $'\ua0' =~ $'^\ua0$' ]] && print OK
|
||||
[[ $'\ua0'X =~ '^X$' ]] || print OK
|
||||
else
|
||||
ZTST_skip="regexp library not found."
|
||||
fi
|
||||
0:Ensure no confusion on metafied input to regex module
|
||||
>OK
|
||||
>OK
|
||||
>OK
|
||||
F:A failure here may indicate the system regex library does not
|
||||
F:support character sets outside the portable 7-bit range.
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
# Tests for command substitution.
|
||||
|
||||
%prep
|
||||
mkdir cmdsubst.tmp
|
||||
touch cmdsubst.tmp/file{1,2}.txt
|
||||
|
||||
%test
|
||||
foo="two words"
|
||||
print -l `echo $foo bar`
|
||||
0:Basic `...` substitution
|
||||
>two
|
||||
>words
|
||||
>bar
|
||||
|
||||
foo="two words"
|
||||
print -l $(echo $foo bar)
|
||||
0:Basic $(...) substitution
|
||||
>two
|
||||
>words
|
||||
>bar
|
||||
|
||||
foo='intricate buffoonery'
|
||||
print -l "`echo $foo and licentiousness`"
|
||||
0:Quoted `...` substitution
|
||||
>intricate buffoonery and licentiousness
|
||||
|
||||
foo="more words"
|
||||
print -l "$(echo $foo here)"
|
||||
0:Quoted $(...) substitution
|
||||
>more words here
|
||||
|
||||
# we used never to get this one right, but I think it is now...
|
||||
print -r "`print -r \\\\\\\\`"
|
||||
0:Stripping of backslasshes in quoted `...`
|
||||
>\\
|
||||
|
||||
print -r "$(print -r \\\\\\\\)"
|
||||
0:Stripping of backslashes in quoted $(...)
|
||||
>\\\\
|
||||
|
||||
fnify() { print \"$*\"; }
|
||||
print `fnify \`fnify understatement\``
|
||||
0:Nested `...`
|
||||
>""understatement""
|
||||
|
||||
print $(fnify $(fnify overboard))
|
||||
0:Nested $(...)
|
||||
>""overboard""
|
||||
|
||||
fructify() { print \'$*\'; }
|
||||
print "`fructify \`fructify indolence\``"
|
||||
0:Nested quoted `...`
|
||||
>''indolence''
|
||||
|
||||
print "$(fructify $(fructify obtuseness))"
|
||||
0:Nested quoted $(...)
|
||||
>''obtuseness''
|
||||
|
||||
gesticulate() { print \!$*\!; }
|
||||
print $((gesticulate wildly); gesticulate calmly)
|
||||
0:$(( ... ) ... ) is not arithmetic
|
||||
>!wildly! !calmly!
|
||||
|
||||
commencify() { print +$*+; }
|
||||
print "$((commencify output); commencify input)"
|
||||
0:quoted $(( ... ) .. ) is not arithmetic
|
||||
>+output+
|
||||
>+input+
|
||||
|
||||
(
|
||||
cd cmdsubst.tmp
|
||||
print first: ${$(print \*)}
|
||||
print second: ${~$(print \*)}
|
||||
print third: ${$(print *)}
|
||||
print fourth: "${~$(print \*)}"
|
||||
print fifth: ${~"$(print \*)"}
|
||||
)
|
||||
0:mixing $(...) with parameter substitution and globbing
|
||||
>first: *
|
||||
>second: file1.txt file2.txt
|
||||
>third: file1.txt file2.txt
|
||||
>fourth: *
|
||||
>fifth: file1.txt file2.txt
|
||||
|
||||
$(exit 0) $(exit 3) || print $?
|
||||
0:empty command uses exit value of last substitution
|
||||
>3
|
||||
|
||||
X=$(exit 2) $(exit 0) || print $?
|
||||
0:variable assignments processed after other substitutions
|
||||
>2
|
||||
|
||||
false
|
||||
``
|
||||
0:Empty command substitution resets status
|
||||
|
||||
false
|
||||
echo `echo $?`
|
||||
0:Non-empty command substitution inherits status
|
||||
>1
|
||||
|
||||
echo $(( ##\" ))
|
||||
echo $(echo \")
|
||||
echo $((echo \"); echo OK)
|
||||
0:Handling of backslash double quote in parenthesised substitutions
|
||||
>34
|
||||
>"
|
||||
>" OK
|
||||
|
||||
echo $(case foo in
|
||||
foo)
|
||||
echo This test worked.
|
||||
;;
|
||||
bar)
|
||||
echo This test failed in a rather bizarre way.
|
||||
;;
|
||||
*)
|
||||
echo This test failed.
|
||||
;;
|
||||
esac)
|
||||
0:Parsing of command substitution with unmatched parentheses: case, basic
|
||||
>This test worked.
|
||||
|
||||
echo "$(case bar in
|
||||
foo)
|
||||
echo This test spoobed.
|
||||
;;
|
||||
bar)
|
||||
echo This test plurbled.
|
||||
;;
|
||||
*)
|
||||
echo This test bzonked.
|
||||
;;
|
||||
esac)"
|
||||
0:Parsing of command substitution with unmatched parentheses: case with quotes
|
||||
>This test plurbled.
|
||||
|
||||
echo before $(
|
||||
echo start; echo unpretentious |
|
||||
while read line; do
|
||||
case $line in
|
||||
u*)
|
||||
print Word began with u
|
||||
print and ended with a crunch
|
||||
;;
|
||||
esac
|
||||
done | sed -e 's/Word/Universe/'; echo end
|
||||
) after
|
||||
0:Parsing of command substitution with ummatched parentheses: with frills
|
||||
>before start Universe began with u and ended with a crunch end after
|
||||
|
||||
alias foo='echo $('
|
||||
eval 'foo echo this just works, OK\?)'
|
||||
0:backtracking within command string parsing with alias still pending
|
||||
>this just works, OK?
|
||||
|
||||
(
|
||||
set errexit
|
||||
show_nargs() { print $#; }
|
||||
print a $() b
|
||||
print c "$()" d
|
||||
)
|
||||
0:Empty $() is a valid empty substitution.
|
||||
>a b
|
||||
>c d
|
||||
|
||||
empty=$() && print "'$empty'"
|
||||
0:Empty $() is a valid assignment
|
||||
>''
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
# Tests for brace expansion
|
||||
|
||||
%prep
|
||||
|
||||
foo=(a b c)
|
||||
arr=(foo bar baz)
|
||||
|
||||
%test
|
||||
|
||||
print X{1,2,{3..6},7,8}Y
|
||||
0:Basic brace expansion
|
||||
>X1Y X2Y X3Y X4Y X5Y X6Y X7Y X8Y
|
||||
|
||||
print ${foo}{one,two,three}$arr
|
||||
0:Brace expansion with arrays, no RC_EXPAND_PARAM
|
||||
>a b conefoo ctwofoo cthreefoo bar baz
|
||||
|
||||
print ${^foo}{one,two,three}$arr
|
||||
0:Brace expansion with arrays, with RC_EXPAND_PARAM (1)
|
||||
>aonefoo atwofoo athreefoo bonefoo btwofoo bthreefoo conefoo ctwofoo cthreefoo bar baz
|
||||
|
||||
print ${foo}{one,two,three}$^arr
|
||||
0:Brace expansion with arrays, with RC_EXPAND_PARAM (2)
|
||||
>a b conefoo ctwofoo cthreefoo conebar ctwobar cthreebar conebaz ctwobaz cthreebaz
|
||||
|
||||
print ${^foo}{one,two,three}$^arr
|
||||
0:Brace expansion with arrays, with RC_EXPAND_PARAM (3)
|
||||
>aonefoo atwofoo athreefoo aonebar atwobar athreebar aonebaz atwobaz athreebaz bonefoo btwofoo bthreefoo bonebar btwobar bthreebar bonebaz btwobaz bthreebaz conefoo ctwofoo cthreefoo conebar ctwobar cthreebar conebaz ctwobaz cthreebaz
|
||||
|
||||
print X{01..4}Y
|
||||
0:Numeric range expansion, padding (1)
|
||||
>X01Y X02Y X03Y X04Y
|
||||
|
||||
print X{1..04}Y
|
||||
0:Numeric range expansion, padding (2)
|
||||
>X01Y X02Y X03Y X04Y
|
||||
|
||||
print X{7..12}Y
|
||||
0:Numeric range expansion, padding (or not) (3)
|
||||
>X7Y X8Y X9Y X10Y X11Y X12Y
|
||||
|
||||
print X{07..12}Y
|
||||
0:Numeric range expansion, padding (4)
|
||||
>X07Y X08Y X09Y X10Y X11Y X12Y
|
||||
|
||||
print X{7..012}Y
|
||||
0:Numeric range expansion, padding (5)
|
||||
>X007Y X008Y X009Y X010Y X011Y X012Y
|
||||
|
||||
print X{4..1}Y
|
||||
0:Numeric range expansion, decreasing
|
||||
>X4Y X3Y X2Y X1Y
|
||||
|
||||
print X{1..4}{1..4}Y
|
||||
0:Numeric range expansion, combined braces
|
||||
>X11Y X12Y X13Y X14Y X21Y X22Y X23Y X24Y X31Y X32Y X33Y X34Y X41Y X42Y X43Y X44Y
|
||||
|
||||
print X{-4..4}Y
|
||||
0:Numeric range expansion, negative numbers (1)
|
||||
>X-4Y X-3Y X-2Y X-1Y X0Y X1Y X2Y X3Y X4Y
|
||||
|
||||
print X{4..-4}Y
|
||||
0:Numeric range expansion, negative numbers (2)
|
||||
>X4Y X3Y X2Y X1Y X0Y X-1Y X-2Y X-3Y X-4Y
|
||||
|
||||
print X{004..-4..2}Y
|
||||
0:Numeric range expansion, stepping and padding (1)
|
||||
>X004Y X002Y X000Y X-02Y X-04Y
|
||||
|
||||
print X{4..-4..02}Y
|
||||
0:Numeric range expansion, stepping and padding (1)
|
||||
>X04Y X02Y X00Y X-2Y X-4Y
|
||||
|
||||
print X{1..32..3}Y
|
||||
0:Numeric range expansion, step alignment (1)
|
||||
>X1Y X4Y X7Y X10Y X13Y X16Y X19Y X22Y X25Y X28Y X31Y
|
||||
|
||||
print X{1..32..-3}Y
|
||||
0:Numeric range expansion, step alignment (2)
|
||||
>X31Y X28Y X25Y X22Y X19Y X16Y X13Y X10Y X7Y X4Y X1Y
|
||||
|
||||
print X{32..1..3}Y
|
||||
0:Numeric range expansion, step alignment (3)
|
||||
>X32Y X29Y X26Y X23Y X20Y X17Y X14Y X11Y X8Y X5Y X2Y
|
||||
|
||||
print X{32..1..-3}Y
|
||||
0:Numeric range expansion, step alignment (4)
|
||||
>X2Y X5Y X8Y X11Y X14Y X17Y X20Y X23Y X26Y X29Y X32Y
|
||||
|
||||
setopt brace_ccl
|
||||
print X{za-q521}Y
|
||||
unsetopt brace_ccl
|
||||
0:BRACE_CCL on
|
||||
>X1Y X2Y X5Y XaY XbY XcY XdY XeY XfY XgY XhY XiY XjY XkY XlY XmY XnY XoY XpY XqY XzY
|
||||
|
||||
print X{za-q521}Y
|
||||
0:BRACE_CCL off
|
||||
>X{za-q521}Y
|
||||
|
||||
print -r hey{a..j}there
|
||||
0:{char..char} ranges, simple case
|
||||
>heyathere heybthere heycthere heydthere heyethere heyfthere heygthere heyhthere heyithere heyjthere
|
||||
|
||||
print -r gosh{1,{Z..a},2}cripes
|
||||
0:{char..char} ranges, ASCII ordering
|
||||
>gosh1cripes goshZcripes gosh[cripes gosh\cripes gosh]cripes gosh^cripes gosh_cripes gosh`cripes goshacripes gosh2cripes
|
||||
|
||||
print -r crumbs{y..p}ooh
|
||||
0:{char..char} ranges, reverse
|
||||
>crumbsyooh crumbsxooh crumbswooh crumbsvooh crumbsuooh crumbstooh crumbssooh crumbsrooh crumbsqooh crumbspooh
|
||||
|
||||
print -r left{[..]}right
|
||||
0:{char..char} ranges with tokenized characters
|
||||
>left[right left\right left]right
|
||||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue