INIT
This commit is contained in:
commit
9dd7ce43ba
|
|
@ -0,0 +1,11 @@
|
|||
.idea/
|
||||
.vscode/
|
||||
node_modules/
|
||||
dist/
|
||||
tmp/
|
||||
temp/
|
||||
logs/
|
||||
*.log
|
||||
**/dump.rdb
|
||||
**/.DS_Store
|
||||
auth.json
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# OMZ
|
||||
|
||||
fork自 oh my zsh,更纯净 更快速
|
||||
|
||||
## USAGE
|
||||
|
||||
```shell
|
||||
|
||||
# 进入你的zsh配置目录 例如 ~/.config/zsh
|
||||
cd ~/.config/zsh
|
||||
git submodule add https://github.com/yaocccc/omz
|
||||
|
||||
# 在你的zsh配置里 source ~/.config/zsh/omz/omz.zsh (举例)
|
||||
echo "source $ZSH/omz/omz.zsh" >> $ZSH/init.zsh
|
||||
```
|
||||
|
||||
## UPDATE
|
||||
|
||||
```plaintext
|
||||
git submodule update
|
||||
或者
|
||||
cd $OMZ && git pull
|
||||
```
|
||||
|
||||
## REQUIRES
|
||||
|
||||
- zsh
|
||||
- fzf
|
||||
- fd
|
||||
- bat (可选 更好的文本预览效果)
|
||||
- exa (可选 更好的ls预览效果)
|
||||
|
||||
```plaintext
|
||||
请自行安装fd
|
||||
On macOS: brew install fd
|
||||
On Arch Linux: pacman -S fd
|
||||
On Ubuntu: apt install fd-find && ln -s $(which fdfind)
|
||||
On Debian: sudo apt-get install fd-find && ln -s $(which fdfind) ~/.local/bin/fd
|
||||
|
||||
请自行安装fzf
|
||||
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
|
||||
~/.fzf/install
|
||||
```
|
||||
|
||||
## PLUGINS
|
||||
|
||||
1. z
|
||||
> `z keyword`
|
||||
> 按使用频率跳转到keyword关联目录
|
||||
> 例如 `z zsh` 可快速跳转到 `~/.config/zsh` 目录
|
||||
|
||||
2. extract
|
||||
> `extract xxx`
|
||||
> extract一个压缩文件
|
||||
> 可根据不同压缩文件类型进行解压 无需记忆长解压指令
|
||||
|
||||
3. zsh-autosuggestions
|
||||
> 输入命令时从history中找到最符合的命令
|
||||
> \<right> 使用该 suggestion
|
||||
|
||||
4. zsh-syntax-highlighting
|
||||
> 高亮输入命令
|
||||
|
||||
5. fzf-tab
|
||||
> tab时使用fzf进行候选选择
|
||||
|
||||
## 配置目录结构
|
||||
|
||||
```plaintext
|
||||
omz
|
||||
├── cache/ -- 部分需要缓存的配置
|
||||
├── lib/ -- 部分依赖文件
|
||||
│ ├── omz.sh -- omz.sh
|
||||
│ └── file_preview.sh -- 文件预览脚本 for fzf
|
||||
├── config/
|
||||
│ ├── fzf.zsh -- fzf 及 fzf-tab配置
|
||||
│ ├── git.zsh -- git相关配置
|
||||
│ ├── hook.zsh -- 命令或启动钩子配置
|
||||
│ └── omz.zsh -- omz基础配置
|
||||
├── plugins/ -- 插件
|
||||
├── themes/ -- 主题
|
||||
├── omz.zsh -- 配置入口
|
||||
└── README.md -- README
|
||||
```
|
||||
|
||||

|
||||
|
|
@ -0,0 +1,20 @@
|
|||
alias fzf='fzf --preview "bat -p --color=always {} | head -100" --height 40%'
|
||||
|
||||
export FZF_DEFAULT_OPTS="--height 50% --layout=reverse --history=$OMZ/cache/fzfhistory"
|
||||
export FZF_DEFAULT_COMMAND="fd --exclude={.git,.idea,.vscode,.sass-cache,node_modules,build,dist,vendor} --type f"
|
||||
export FZF_PREVIEW_COMMAND='$OMZ/lib/file_preview.sh {}'
|
||||
|
||||
zstyle ':completion:complete:*:options' sort false
|
||||
zstyle ':fzf-tab:complete:_zlua:*' query-string input
|
||||
zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w"
|
||||
zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-preview 'ps --pid=$word -o cmd --no-headers -w -w'
|
||||
zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-flags --preview-window=down:3:wrap
|
||||
zstyle ':fzf-tab:complete:systemctl-*:*' fzf-preview 'SYSTEMD_COLORS=1 systemctl status $word'
|
||||
zstyle ':fzf-tab:complete:(\\|)run-help:*' fzf-preview 'run-help $word'
|
||||
zstyle ':fzf-tab:complete:(\\|*/|)man:*' fzf-preview 'man $word'
|
||||
zstyle ':fzf-tab:complete:git-(add|diff|restore):*' fzf-preview 'git diff --color=always $word'
|
||||
zstyle ':fzf-tab:complete:git-log:*' fzf-preview 'git log --color=always $word'
|
||||
zstyle ':fzf-tab:complete:git-show:*' fzf-preview 'git show --color=always $word'
|
||||
zstyle ':fzf-tab:complete:git-checkout:*' fzf-preview '[ -f "$realpath" ] && git diff --color=always $word || git log --color=always $word'
|
||||
zstyle ':fzf-tab:complete:*:*' fzf-preview 'less ${(Q)realpath}'
|
||||
export LESSOPEN='| bash $OMZ/lib/file_preview.sh %s'
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
export GIT_TERMINAL_PROMPT=1
|
||||
|
||||
alias git='git --no-pager'
|
||||
alias gco='git checkout'
|
||||
alias gpo='git push origin $(git symbolic-ref --short -q HEAD)'
|
||||
alias gpl='git pull origin $(git symbolic-ref --short -q HEAD) --ff-only'
|
||||
alias gd='git diff'
|
||||
alias gs='git status'
|
||||
alias gss='git status -s'
|
||||
alias gpt='git push origin --tags'
|
||||
alias glt='git tag -n --sort=taggerdate | tail -n ${1-10}'
|
||||
gat() { git tag -a $1 -m "$2" }
|
||||
gam() { git add --all && git commit -m "$*" }
|
||||
gitlog() {
|
||||
git --no-pager log --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:$1 --graph -n ${2-10} \
|
||||
}
|
||||
gll() { gitlog "%h %s" $1 }
|
||||
glll() { gitlog "%h %cd %cn: %s" $1 }
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# auto update the terminal name
|
||||
preexec_hook() { _cmd=($(echo $2)); print -n "\e]2;${(q)_cmd[1]}\a"; }
|
||||
add-zsh-hook -Uz preexec preexec_hook
|
||||
|
||||
# auto to last pwd
|
||||
chpwd_hook() { echo $PWD > $ZSH/cache/currentdir }
|
||||
add-zsh-hook -Uz chpwd chpwd_hook
|
||||
currentdir=$(cat $ZSH/cache/currentdir 2>/dev/null)
|
||||
[ -d "$currentdir" ] && cd $currentdir
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
source $OMZ/lib/omz.sh
|
||||
source $OMZ/plugins/z/z.plugin.zsh
|
||||
source $OMZ/plugins/extract/extract.plugin.zsh
|
||||
source $OMZ/plugins/fzf-tab/fzf-tab.zsh
|
||||
source $OMZ/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
|
||||
source $OMZ/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#! /usr/bin/env sh
|
||||
mime=$(file -bL --mime-type "$1")
|
||||
category=${mime%%/*}
|
||||
if [ -d "$1" ]; then
|
||||
exa -l --no-user --no-time --icons 2>/dev/null || ls --color=tty "$1" || ls -G "$1"
|
||||
elif [ "$category" = text ]; then
|
||||
(bat -p --color=always "$1" || cat "$1") 2>/dev/null | head -100
|
||||
elif [ "$category" = image ]; then
|
||||
img2txt "$1"
|
||||
else
|
||||
echo $1 is a $category file
|
||||
fi
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
ZSH_CACHE_DIR="$OMZ/cache"
|
||||
SHORT_HOST=${HOST/.*/}
|
||||
autoload -Uz add-zsh-hook
|
||||
zmodload -i zsh/complist
|
||||
unsetopt correct
|
||||
autoload -U compaudit compinit
|
||||
autoload -U compinit && compinit
|
||||
setopt auto_pushd
|
||||
setopt pushd_ignore_dups
|
||||
setopt pushdminus
|
||||
alias -g ...='../..'
|
||||
alias -g ....='../../..'
|
||||
alias -g .....='../../../..'
|
||||
alias -g ......='../../../../..'
|
||||
alias -- -='cd -'
|
||||
alias 1='cd -'
|
||||
alias 2='cd -2'
|
||||
alias 3='cd -3'
|
||||
alias 4='cd -4'
|
||||
alias 5='cd -5'
|
||||
alias 6='cd -6'
|
||||
alias 7='cd -7'
|
||||
alias 8='cd -8'
|
||||
alias 9='cd -9'
|
||||
alias md='mkdir -p'
|
||||
alias rd=rmdir
|
||||
|
||||
function d () {
|
||||
if [[ -n $1 ]]; then
|
||||
dirs "$@"
|
||||
else
|
||||
dirs -v | head -10
|
||||
fi
|
||||
}
|
||||
compdef _dirs d
|
||||
ls --color=tty . &>/dev/null && alias ls='ls --color=tty' || alias ls='ls -G'
|
||||
alias lsa='ls -lah'
|
||||
alias l='ls -lah'
|
||||
alias ll='ls -lh'
|
||||
alias la='ls -lAh'
|
||||
|
||||
grep-flag-available() {
|
||||
echo | grep $1 "" >/dev/null 2>&1
|
||||
}
|
||||
GREP_OPTIONS=""
|
||||
if grep-flag-available --color=auto; then
|
||||
GREP_OPTIONS+=" --color=auto"
|
||||
fi
|
||||
VCS_FOLDERS="{.bzr,CVS,.git,.hg,.svn}"
|
||||
|
||||
if grep-flag-available --exclude-dir=.cvs; then
|
||||
GREP_OPTIONS+=" --exclude-dir=$VCS_FOLDERS"
|
||||
elif grep-flag-available --exclude=.cvs; then
|
||||
GREP_OPTIONS+=" --exclude=$VCS_FOLDERS"
|
||||
fi
|
||||
alias grep="grep $GREP_OPTIONS"
|
||||
unset GREP_OPTIONS
|
||||
unset VCS_FOLDERS
|
||||
unfunction grep-flag-available
|
||||
function omz_history {
|
||||
local clear list
|
||||
zparseopts -E c=clear l=list
|
||||
|
||||
if [[ -n "$clear" ]]; then
|
||||
# if -c provided, clobber the history file
|
||||
echo -n >| "$HISTFILE"
|
||||
echo >&2 History file deleted. Reload the session to see its effects.
|
||||
elif [[ -n "$list" ]]; then
|
||||
# if -l provided, run as if calling `fc' directly
|
||||
builtin fc "$@"
|
||||
else
|
||||
[[ ${@[-1]-} = *[0-9]* ]] && builtin fc -l "$@" || builtin fc -l "$@" 1
|
||||
fi
|
||||
}
|
||||
|
||||
case ${HIST_STAMPS-} in
|
||||
"mm/dd/yyyy") alias history='omz_history -f' ;;
|
||||
"dd.mm.yyyy") alias history='omz_history -E' ;;
|
||||
"yyyy-mm-dd") alias history='omz_history -i' ;;
|
||||
"") alias history='omz_history' ;;
|
||||
*) alias history="omz_history -t '$HIST_STAMPS'" ;;
|
||||
esac
|
||||
|
||||
HISTFILE="$OMZ/cache/zshhistory"
|
||||
HISTSIZE=50000
|
||||
SAVEHIST=10000
|
||||
|
||||
setopt extended_history
|
||||
setopt hist_expire_dups_first
|
||||
setopt hist_ignore_dups
|
||||
setopt hist_ignore_space
|
||||
setopt hist_verify
|
||||
setopt inc_append_history
|
||||
setopt share_history
|
||||
|
||||
if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
|
||||
function zle-line-init() {
|
||||
echoti smkx
|
||||
}
|
||||
function zle-line-finish() {
|
||||
echoti rmkx
|
||||
}
|
||||
zle -N zle-line-init
|
||||
zle -N zle-line-finish
|
||||
fi
|
||||
bindkey -e # Use emacs key bindings
|
||||
bindkey '\ew' kill-region # [Esc-w] - Kill from the cursor to the mark
|
||||
bindkey -s '\el' 'ls\n' # [Esc-l] - run command: ls
|
||||
bindkey '^r' history-incremental-search-backward # [Ctrl-r] - Search backward incrementally for a specified string. The string may begin with ^ to anchor the search to the beginning of the line.
|
||||
if [[ "${terminfo[kpp]}" != "" ]]; then
|
||||
bindkey "${terminfo[kpp]}" up-line-or-history # [PageUp] - Up a line of history
|
||||
fi
|
||||
if [[ "${terminfo[knp]}" != "" ]]; then
|
||||
bindkey "${terminfo[knp]}" down-line-or-history # [PageDown] - Down a line of history
|
||||
fi
|
||||
if [[ "${terminfo[kcuu1]}" != "" ]]; then
|
||||
autoload -U up-line-or-beginning-search
|
||||
zle -N up-line-or-beginning-search
|
||||
bindkey "${terminfo[kcuu1]}" up-line-or-beginning-search
|
||||
fi
|
||||
if [[ "${terminfo[kcud1]}" != "" ]]; then
|
||||
autoload -U down-line-or-beginning-search
|
||||
zle -N down-line-or-beginning-search
|
||||
bindkey "${terminfo[kcud1]}" down-line-or-beginning-search
|
||||
fi
|
||||
if [[ "${terminfo[khome]}" != "" ]]; then
|
||||
bindkey "${terminfo[khome]}" beginning-of-line # [Home] - Go to beginning of line
|
||||
fi
|
||||
if [[ "${terminfo[kend]}" != "" ]]; then
|
||||
bindkey "${terminfo[kend]}" end-of-line # [End] - Go to end of line
|
||||
fi
|
||||
bindkey ' ' magic-space # [Space] - do history expansion
|
||||
bindkey '^[[1;5C' forward-word # [Ctrl-RightArrow] - move forward one word
|
||||
bindkey '^[[1;5D' backward-word # [Ctrl-LeftArrow] - move backward one word
|
||||
if [[ "${terminfo[kcbt]}" != "" ]]; then
|
||||
bindkey "${terminfo[kcbt]}" reverse-menu-complete # [Shift-Tab] - move through the completion menu backwards
|
||||
fi
|
||||
bindkey '^?' backward-delete-char # [Backspace] - delete backward
|
||||
if [[ "${terminfo[kdch1]}" != "" ]]; then
|
||||
bindkey "${terminfo[kdch1]}" delete-char # [Delete] - delete forward
|
||||
else
|
||||
bindkey "^[[3~" delete-char
|
||||
bindkey "^[3;5~" delete-char
|
||||
bindkey "\e[3~" delete-char
|
||||
fi
|
||||
autoload -U edit-command-line
|
||||
zle -N edit-command-line
|
||||
bindkey '\C-x\C-e' edit-command-line
|
||||
bindkey "^[m" copy-prev-shell-word
|
||||
bindkey '^H' backward-kill-word
|
||||
|
||||
autoload -U colors && colors
|
||||
setopt auto_cd
|
||||
setopt multios
|
||||
setopt prompt_subst
|
||||
|
||||
function git_prompt_info() {
|
||||
local ref
|
||||
if [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then
|
||||
ref=$(command git symbolic-ref HEAD 2> /dev/null) || \
|
||||
ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0
|
||||
echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX"
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_git_dirty() {
|
||||
local STATUS
|
||||
local -a FLAGS
|
||||
FLAGS=('--porcelain')
|
||||
FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}"
|
||||
STATUS=$(command git status ${FLAGS} 2> /dev/null | tail -n1)
|
||||
if [[ -n $STATUS ]]; then
|
||||
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
|
||||
else
|
||||
echo "$ZSH_THEME_GIT_PROMPT_CLEAN"
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export OMZ=$(cd $(dirname $0);pwd)
|
||||
source $OMZ/config/git.zsh
|
||||
source $OMZ/config/omz.zsh
|
||||
source $OMZ/config/fzf.zsh
|
||||
source $OMZ/config/hook.zsh
|
||||
source $OMZ/themes/simple.zsh-theme
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#compdef extract
|
||||
#autoload
|
||||
|
||||
_arguments \
|
||||
'(-r --remove)'{-r,--remove}'[Remove archive.]' \
|
||||
"*::archive file:_files -g '(#i)*.(7z|Z|apk|aar|bz2|deb|gz|ipsw|jar|lrz|lz4|lzma|rar|rpm|sublime-package|tar|tar.bz2|tar.gz|tar.lrz|tar.lz|tar.lz4|tar.xz|tar.zma|tar.zst|tbz|tbz2|tgz|tlz|txz|tzst|war|whl|xpi|xz|zip|zst)(-.)'" \
|
||||
&& return 0
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
alias x=extract
|
||||
|
||||
extract() {
|
||||
local remove_archive
|
||||
local success
|
||||
local extract_dir
|
||||
|
||||
if (( $# == 0 )); then
|
||||
cat <<-'EOF' >&2
|
||||
Usage: extract [-option] [file ...]
|
||||
|
||||
Options:
|
||||
-r, --remove Remove archive after unpacking.
|
||||
EOF
|
||||
fi
|
||||
|
||||
remove_archive=1
|
||||
if [[ "$1" == "-r" ]] || [[ "$1" == "--remove" ]]; then
|
||||
remove_archive=0
|
||||
shift
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
if [[ ! -f "$1" ]]; then
|
||||
echo "extract: '$1' is not a valid file" >&2
|
||||
shift
|
||||
continue
|
||||
fi
|
||||
|
||||
success=0
|
||||
extract_dir="${1:t:r}"
|
||||
case "${1:l}" in
|
||||
(*.tar.gz|*.tgz) (( $+commands[pigz] )) && { pigz -dc "$1" | tar xv } || tar zxvf "$1" ;;
|
||||
(*.tar.bz2|*.tbz|*.tbz2) tar xvjf "$1" ;;
|
||||
(*.tar.xz|*.txz)
|
||||
tar --xz --help &> /dev/null \
|
||||
&& tar --xz -xvf "$1" \
|
||||
|| xzcat "$1" | tar xvf - ;;
|
||||
(*.tar.zma|*.tlz)
|
||||
tar --lzma --help &> /dev/null \
|
||||
&& tar --lzma -xvf "$1" \
|
||||
|| lzcat "$1" | tar xvf - ;;
|
||||
(*.tar.zst|*.tzst)
|
||||
tar --zstd --help &> /dev/null \
|
||||
&& tar --zstd -xvf "$1" \
|
||||
|| zstdcat "$1" | tar xvf - ;;
|
||||
(*.tar) tar xvf "$1" ;;
|
||||
(*.tar.lz) (( $+commands[lzip] )) && tar xvf "$1" ;;
|
||||
(*.tar.lz4) lz4 -c -d "$1" | tar xvf - ;;
|
||||
(*.tar.lrz) (( $+commands[lrzuntar] )) && lrzuntar "$1" ;;
|
||||
(*.gz) (( $+commands[pigz] )) && pigz -dk "$1" || gunzip -k "$1" ;;
|
||||
(*.bz2) bunzip2 "$1" ;;
|
||||
(*.xz) unxz "$1" ;;
|
||||
(*.lrz) (( $+commands[lrunzip] )) && lrunzip "$1" ;;
|
||||
(*.lz4) lz4 -d "$1" ;;
|
||||
(*.lzma) unlzma "$1" ;;
|
||||
(*.z) uncompress "$1" ;;
|
||||
(*.zip|*.war|*.jar|*.sublime-package|*.ipsw|*.xpi|*.apk|*.aar|*.whl) unzip "$1" -d $extract_dir ;;
|
||||
(*.rar) unrar x -ad "$1" ;;
|
||||
(*.rpm) mkdir "$extract_dir" && cd "$extract_dir" && rpm2cpio "../$1" | cpio --quiet -id && cd .. ;;
|
||||
(*.7z) 7za x "$1" ;;
|
||||
(*.deb)
|
||||
mkdir -p "$extract_dir/control"
|
||||
mkdir -p "$extract_dir/data"
|
||||
cd "$extract_dir"; ar vx "../${1}" > /dev/null
|
||||
cd control; tar xzvf ../control.tar.gz
|
||||
cd ../data; extract ../data.tar.*
|
||||
cd ..; rm *.tar.* debian-binary
|
||||
cd ..
|
||||
;;
|
||||
(*.zst) unzstd "$1" ;;
|
||||
(*)
|
||||
echo "extract: '$1' cannot be extracted" >&2
|
||||
success=1
|
||||
;;
|
||||
esac
|
||||
|
||||
(( success = $success > 0 ? $success : $? ))
|
||||
(( $success == 0 )) && (( $remove_archive == 0 )) && rm "$1"
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
modules/** linguist-vendored
|
||||
modules/Src/aloxaf/*.c -linguist-vendored
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
I can make sure:
|
||||
- [ ] I am using the latest version of fzf-tab
|
||||
- [ ] this is the minimal zshrc which can reproduce this bug
|
||||
- [ ] fzf-tab is loaded after `compinit`
|
||||
- [ ] fzf-tab is loaded after plugins which will wrap <kbd>Tab</kbd>, like [junegunn/fzf/completion.zsh](https://github.com/junegunn/fzf/blob/master/shell/completion.zsh)
|
||||
- [ ] fzf-tab is loaded before zsh-autosuggestions, zsh-syntax-highlighting and fast-syntax-highlighting.
|
||||
|
||||
#### To Reproduce
|
||||
Steps to reproduce the behavior:
|
||||
1. Type '...'
|
||||
2. Press <kbd>Tab</kbd>
|
||||
4. See error
|
||||
|
||||
#### Expected behavior
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
#### Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
#### Environment:
|
||||
- OS: [e.g. Arch Linux]
|
||||
- zsh version: [e.g. 5.8.1]
|
||||
|
||||
#### Minimal zshrc
|
||||
If applicable, add a minimal zshrc to help us analyze.
|
||||
|
||||
#### Log
|
||||
If applicable, use `C-x .` to trigger completion and provide the log.
|
||||
|
||||
If there are only three lines in your log, please make sure your fzf-tab is loaded with the correct order (see the checklist above).
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FR]"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
name: Question
|
||||
about: Ask a question about fzf-tab
|
||||
title: "[Q]"
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe your question**
|
||||
A clear and concise description of your question.
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: run test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: install zsh (ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: sudo apt-get install zsh
|
||||
|
||||
- name: test completion (ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: cd test && zsh -f runtests.zsh fzftab.ztst
|
||||
|
||||
- name: build binary module
|
||||
run: zsh -fc 'source ./fzf-tab.zsh && build-fzf-tab-module'
|
||||
|
||||
- name: test binary module (ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: cd test && zsh -f runtests.zsh fzftab.ztst
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
*.zwc
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019-2021 Aloxaf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
# fzf-tab
|
||||
|
||||
[](https://github.com/Aloxaf/fzf-tab/actions?query=workflow%3Aci)
|
||||
[](https://github.com/Aloxaf/fzf-tab/blob/master/LICENSE)
|
||||
|
||||
Replace zsh's default completion selection menu with fzf!
|
||||
|
||||
[](https://asciinema.org/a/293849)
|
||||
|
||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
||||
**Table of Contents**
|
||||
|
||||
- [fzf-tab](#fzf-tab)
|
||||
- [Install](#install)
|
||||
- [Manual](#manual)
|
||||
- [Antigen](#antigen)
|
||||
- [Zinit](#zinit)
|
||||
- [Oh-My-Zsh](#oh-my-zsh)
|
||||
- [Prezto](#prezto)
|
||||
- [Usage](#usage)
|
||||
- [Configure](#configure)
|
||||
- [Binary module](#binary-module)
|
||||
- [Difference from other plugins](#difference-from-other-plugins)
|
||||
- [Compatibility with other plugins](#compatibility-with-other-plugins)
|
||||
- [Related projects](#related-projects)
|
||||
|
||||
<!-- markdown-toc end -->
|
||||
|
||||
# Install
|
||||
|
||||
**NOTE: fzf-tab needs to be loaded after `compinit`, but before plugins which will wrap widgets, such as [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) or [fast-syntax-highlighting](https://github.com/zdharma-continuum/fast-syntax-highlighting)!!**
|
||||
|
||||
**NOTE 2: fzf-tab ALSO needs [fzf](https://github.com/junegunn/fzf) installed, otherwise it cannot work!**
|
||||
|
||||
### Manual
|
||||
|
||||
First, clone this repository.
|
||||
|
||||
```zsh
|
||||
git clone https://github.com/Aloxaf/fzf-tab ~/somewhere
|
||||
```
|
||||
|
||||
Then add the following line to your `~/.zshrc`.
|
||||
|
||||
```zsh
|
||||
source ~/somewhere/fzf-tab.plugin.zsh
|
||||
```
|
||||
|
||||
### Antigen
|
||||
|
||||
```zsh
|
||||
antigen bundle Aloxaf/fzf-tab
|
||||
```
|
||||
|
||||
### Zinit
|
||||
|
||||
```zsh
|
||||
zinit light Aloxaf/fzf-tab
|
||||
```
|
||||
|
||||
### Oh-My-Zsh
|
||||
|
||||
Clone this repository to your custom directory and then add `fzf-tab` to your plugin list.
|
||||
|
||||
```zsh
|
||||
git clone https://github.com/Aloxaf/fzf-tab ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/fzf-tab
|
||||
```
|
||||
|
||||
### Prezto
|
||||
|
||||
Clone this repository to your contrib directory and then add `fzf-tab` to your module list in `.zpreztorc`.
|
||||
|
||||
```zsh
|
||||
git clone https://github.com/Aloxaf/fzf-tab $ZPREZTODIR/contrib/fzf-tab
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
Just press <kbd>Tab</kbd> as usual~
|
||||
|
||||
Available keybindings:
|
||||
|
||||
- <kbd>Ctrl</kdb>+<kdb>Space</kbd>: select multiple results, can be configured by `fzf-bindings` tag
|
||||
|
||||
- <kbd>F1</kbd>/<kbd>F2</kbd>: switch between groups, can be configured by `switch-group` tag
|
||||
|
||||
- <kbd>/</kbd>: trigger continuous completion (useful when completing a deep path), can be configured by `continuous-trigger` tag
|
||||
|
||||
Available commands:
|
||||
|
||||
- `disable-fzf-tab`: disable fzf-tab and fallback to compsys
|
||||
|
||||
- `enable-fzf-tab`: enable fzf-tab
|
||||
|
||||
- `toggle-fzf-tab`: toggle the state of fzf-tab. This is also a zle widget.
|
||||
|
||||
## Configure
|
||||
|
||||
A common configuration is:
|
||||
|
||||
```zsh
|
||||
# disable sort when completing `git checkout`
|
||||
zstyle ':completion:*:git-checkout:*' sort false
|
||||
# set descriptions format to enable group support
|
||||
zstyle ':completion:*:descriptions' format '[%d]'
|
||||
# set list-colors to enable filename colorizing
|
||||
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
|
||||
# preview directory's content with exa when completing cd
|
||||
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'exa -1 --color=always $realpath'
|
||||
# switch group using `,` and `.`
|
||||
zstyle ':fzf-tab:*' switch-group ',' '.'
|
||||
```
|
||||
|
||||
For more information, please see [Wiki#Configuration](https://github.com/Aloxaf/fzf-tab/wiki/Configuration).
|
||||
|
||||
## Binary module
|
||||
|
||||
By default, fzf-tab uses [zsh-ls-colors](https://github.com/xPMo/zsh-ls-colors) to parse and apply ZLS_COLORS if you have set the `list-colors` tag.
|
||||
|
||||
However, it is a pure zsh script and is slow if you have too many files to colorize.
|
||||
fzf-tab is shipped with a binary module to speed up this process. You can build it with `build-fzf-tab-module`, then it will be enabled automatically.
|
||||
|
||||
# Difference from other plugins
|
||||
|
||||
fzf-tab doesn't do "complete", it just shows you the results of the default completion system.
|
||||
|
||||
So it works EVERYWHERE (variables, function names, directory stack, in-word completion, etc.).
|
||||
And most of your configuration for default completion system is still valid.
|
||||
|
||||
# Compatibility with other plugins
|
||||
|
||||
Some plugins may also bind "^I" to their custom widget, like [fzf/shell/completion.zsh](https://github.com/junegunn/fzf/blob/master/shell/completion.zsh) or [ohmyzsh/lib/completion.zsh](https://github.com/ohmyzsh/ohmyzsh/blob/master/lib/completion.zsh#L61-L73).
|
||||
|
||||
By default, fzf-tab will call the widget previously bound to "^I" to get the completion list. So there is no problem in most cases, unless fzf-tab is initialized before a plugin which doesn't handle the previous binding properly.
|
||||
|
||||
So if you find your fzf-tab doesn't work properly, **please make sure it is the last plugin to bind "^I"** (If you don't know what I mean, just put it to the end of your plugin list).
|
||||
|
||||
# Related projects
|
||||
|
||||
- https://github.com/lincheney/fzf-tab-completion (fzf tab completion for zsh, bash and GNU readline apps)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
source "${0:A:h}/fzf-tab.zsh"
|
||||
|
|
@ -0,0 +1,412 @@
|
|||
# temporarily change options
|
||||
'builtin' 'local' '-a' '_ftb_opts'
|
||||
[[ ! -o 'aliases' ]] || _ftb_opts+=('aliases')
|
||||
[[ ! -o 'sh_glob' ]] || _ftb_opts+=('sh_glob')
|
||||
[[ ! -o 'no_brace_expand' ]] || _ftb_opts+=('no_brace_expand')
|
||||
'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand'
|
||||
|
||||
# thanks Valodim/zsh-capture-completion
|
||||
-ftb-compadd() {
|
||||
# parse all options
|
||||
local -A apre hpre dscrs _oad
|
||||
local -a isfile _opts __ expl
|
||||
zparseopts -E -a _opts P:=apre p:=hpre d:=dscrs X+:=expl O:=_oad A:=_oad D:=_oad f=isfile \
|
||||
i: S: s: I: x: r: R: W: F: M+: E: q e Q n U C \
|
||||
J:=__ V:=__ a=__ l=__ k=__ o=__ 1=__ 2=__
|
||||
|
||||
# store $curcontext for further usage
|
||||
_ftb_curcontext=${curcontext#:}
|
||||
|
||||
# just delegate and leave if any of -O, -A or -D are given or fzf-tab is not enabled
|
||||
# or fzf-tab is disabled in the current context
|
||||
if (( $#_oad != 0 || ! IN_FZF_TAB )) \
|
||||
|| { -ftb-zstyle -m disabled-on "any" } \
|
||||
|| ({ -ftb-zstyle -m disabled-on "files" } && [[ -n $isfile ]]); then
|
||||
builtin compadd "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
# store matches in $__hits and descriptions in $__dscr
|
||||
local -a __hits __dscr
|
||||
if (( $#dscrs == 1 )); then
|
||||
__dscr=( "${(@P)${(v)dscrs}}" )
|
||||
fi
|
||||
builtin compadd -A __hits -D __dscr "$@"
|
||||
local ret=$?
|
||||
if (( $#__hits == 0 )); then
|
||||
return $ret
|
||||
fi
|
||||
|
||||
# only store the fist `-X`
|
||||
expl=$expl[2]
|
||||
|
||||
# keep order of group description
|
||||
[[ -n $expl ]] && _ftb_groups+=$expl
|
||||
|
||||
# store these values in _ftb_compcap
|
||||
local -a keys=(apre hpre PREFIX SUFFIX IPREFIX ISUFFIX)
|
||||
local key expanded __tmp_value=$'<\0>' # placeholder
|
||||
for key in $keys; do
|
||||
expanded=${(P)key}
|
||||
if [[ -n $expanded ]]; then
|
||||
__tmp_value+=$'\0'$key$'\0'$expanded
|
||||
fi
|
||||
done
|
||||
if [[ -n $expl ]]; then
|
||||
# store group index
|
||||
__tmp_value+=$'\0group\0'$_ftb_groups[(ie)$expl]
|
||||
fi
|
||||
if [[ -n $isfile ]]; then
|
||||
# NOTE: need a extra ${} here or ~ expansion won't work
|
||||
__tmp_value+=$'\0realdir\0'${${(Qe)~${:-$IPREFIX$hpre}}}
|
||||
fi
|
||||
_opts+=("${(@kv)apre}" "${(@kv)hpre}" $isfile)
|
||||
__tmp_value+=$'\0args\0'${(pj:\1:)_opts}
|
||||
|
||||
if (( $+builtins[fzf-tab-compcap-generate] )); then
|
||||
fzf-tab-compcap-generate __hits __dscr __tmp_value
|
||||
else
|
||||
# dscr - the string to show to users
|
||||
# word - the string to be inserted
|
||||
local dscr word i
|
||||
for i in {1..$#__hits}; do
|
||||
word=$__hits[i] dscr=$__dscr[i]
|
||||
if [[ -n $dscr ]]; then
|
||||
dscr=${dscr//$'\n'}
|
||||
elif [[ -n $word ]]; then
|
||||
dscr=$word
|
||||
fi
|
||||
_ftb_compcap+=$dscr$'\2'$__tmp_value$'\0word\0'$word
|
||||
done
|
||||
fi
|
||||
|
||||
# tell zsh that the match is successful
|
||||
builtin compadd -U -qS '' -R -ftb-remove-space ''
|
||||
}
|
||||
|
||||
# when insert multi results, a whitespace will be added to each result
|
||||
# remove left space of our fake result because I can't remove right space
|
||||
# FIXME: what if the left char is not whitespace: `echo $widgets[\t`
|
||||
-ftb-remove-space() {
|
||||
[[ $LBUFFER[-1] == ' ' ]] && LBUFFER[-1]=''
|
||||
}
|
||||
|
||||
-ftb-zstyle() {
|
||||
zstyle $1 ":fzf-tab:$_ftb_curcontext" ${@:2}
|
||||
}
|
||||
|
||||
-ftb-complete() {
|
||||
local -a _ftb_compcap
|
||||
local -Ua _ftb_groups
|
||||
local choice choices _ftb_curcontext continuous_trigger print_query accept_line bs=$'\2' nul=$'\0'
|
||||
local ret=0
|
||||
|
||||
# must run with user options; don't move `emulate -L zsh` above this line
|
||||
(( $+builtins[fzf-tab-compcap-generate] )) && fzf-tab-compcap-generate -i
|
||||
COLUMNS=500 _ftb__main_complete "$@" || ret=$?
|
||||
(( $+builtins[fzf-tab-compcap-generate] )) && fzf-tab-compcap-generate -o
|
||||
|
||||
emulate -L zsh -o extended_glob
|
||||
|
||||
local _ftb_query _ftb_complist=() _ftb_headers=() command opts
|
||||
-ftb-generate-complist # sets `_ftb_complist`
|
||||
|
||||
-ftb-zstyle -s continuous-trigger continuous_trigger || {
|
||||
[[ $OSTYPE == msys ]] && continuous_trigger=// || continuous_trigger=/
|
||||
}
|
||||
|
||||
case $#_ftb_complist in
|
||||
0) return 1;;
|
||||
1)
|
||||
choices=("EXPECT_KEY" "${_ftb_compcap[1]%$bs*}")
|
||||
if (( _ftb_continue_last )); then
|
||||
choices[1]=$continuous_trigger
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
-ftb-generate-query # sets `_ftb_query`
|
||||
-ftb-generate-header # sets `_ftb_headers`
|
||||
-ftb-zstyle -s print-query print_query || print_query=alt-enter
|
||||
-ftb-zstyle -s accept-line accept_line
|
||||
|
||||
choices=("${(@f)"$(builtin print -rl -- $_ftb_headers $_ftb_complist | -ftb-fzf)"}")
|
||||
ret=$?
|
||||
# choices=(query_string expect_key returned_word)
|
||||
|
||||
# insert query string directly
|
||||
if [[ $choices[2] == $print_query ]] || [[ -n $choices[1] && $#choices == 1 ]] ; then
|
||||
local -A v=("${(@0)${_ftb_compcap[1]}}")
|
||||
local -a args=("${(@ps:\1:)v[args]}")
|
||||
[[ -z $args[1] ]] && args=() # don't pass an empty string
|
||||
IPREFIX=$v[IPREFIX] PREFIX=$v[PREFIX] SUFFIX=$v[SUFFIX] ISUFFIX=$v[ISUFFIX]
|
||||
# NOTE: should I use `-U` here?, ../f\tabcd -> ../abcd
|
||||
builtin compadd "${args[@]:--Q}" -Q -- $choices[1]
|
||||
|
||||
compstate[list]=
|
||||
compstate[insert]=
|
||||
if (( $#choices[1] > 0 )); then
|
||||
compstate[insert]='2'
|
||||
[[ $RBUFFER == ' '* ]] || compstate[insert]+=' '
|
||||
fi
|
||||
return $ret
|
||||
fi
|
||||
choices[1]=()
|
||||
|
||||
choices=("${(@)${(@)choices%$nul*}#*$nul}")
|
||||
|
||||
unset CTXT
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -n $choices[1] && $choices[1] == $continuous_trigger ]]; then
|
||||
typeset -gi _ftb_continue=1
|
||||
typeset -gi _ftb_continue_last=1
|
||||
fi
|
||||
|
||||
if [[ -n $choices[1] && $choices[1] == $accept_line ]]; then
|
||||
typeset -gi _ftb_accept=1
|
||||
fi
|
||||
choices[1]=()
|
||||
|
||||
for choice in "$choices[@]"; do
|
||||
local -A v=("${(@0)${_ftb_compcap[(r)${(b)choice}$bs*]#*$bs}}")
|
||||
local -a args=("${(@ps:\1:)v[args]}")
|
||||
[[ -z $args[1] ]] && args=() # don't pass an empty string
|
||||
IPREFIX=$v[IPREFIX] PREFIX=$v[PREFIX] SUFFIX=$v[SUFFIX] ISUFFIX=$v[ISUFFIX]
|
||||
builtin compadd "${args[@]:--Q}" -Q -- "$v[word]"
|
||||
done
|
||||
|
||||
compstate[list]=
|
||||
compstate[insert]=
|
||||
if (( $#choices == 1 )); then
|
||||
compstate[insert]='2'
|
||||
[[ $RBUFFER == ' '* ]] || compstate[insert]+=' '
|
||||
elif (( $#choices > 1 )); then
|
||||
compstate[insert]='all'
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
fzf-tab-debug() {
|
||||
(( $+_ftb_debug_cnt )) || typeset -gi _ftb_debug_cnt
|
||||
local tmp=${TMPPREFIX:-/tmp/zsh}-$$-fzf-tab-$(( ++_ftb_debug_cnt )).log
|
||||
local -i debug_fd=-1 IN_FZF_TAB=1
|
||||
{
|
||||
exec {debug_fd}>&2 2>| $tmp
|
||||
local -a debug_indent; debug_indent=( '%'{3..20}'(e. .)' )
|
||||
local PROMPT4 PS4="${(j::)debug_indent}+%N:%i> "
|
||||
setopt xtrace
|
||||
: $ZSH_NAME $ZSH_VERSION
|
||||
zle .fzf-tab-orig-$_ftb_orig_widget
|
||||
unsetopt xtrace
|
||||
if (( debug_fd != -1 )); then
|
||||
zle -M "fzf-tab-debug: Trace output left in $tmp"
|
||||
fi
|
||||
} always {
|
||||
(( debug_fd != -1 )) && exec 2>&$debug_fd {debug_fd}>&-
|
||||
}
|
||||
}
|
||||
|
||||
fzf-tab-complete() {
|
||||
# this name must be ugly to avoid clashes
|
||||
local -i _ftb_continue=1 _ftb_continue_last=0 _ftb_accept=0 ret=0
|
||||
# hide the cursor until finishing completion, so that users won't see cursor up and down
|
||||
# NOTE: MacOS Terminal doesn't support civis & cnorm
|
||||
echoti civis >/dev/tty 2>/dev/null
|
||||
while (( _ftb_continue )); do
|
||||
_ftb_continue=0
|
||||
local IN_FZF_TAB=1
|
||||
{
|
||||
zle .fzf-tab-orig-$_ftb_orig_widget
|
||||
ret=$?
|
||||
} always {
|
||||
IN_FZF_TAB=0
|
||||
}
|
||||
if (( _ftb_continue )); then
|
||||
zle .split-undo
|
||||
zle .reset-prompt
|
||||
zle -R
|
||||
zle fzf-tab-dummy
|
||||
fi
|
||||
done
|
||||
echoti cnorm >/dev/tty 2>/dev/null
|
||||
zle .redisplay
|
||||
(( _ftb_accept )) && zle .accept-line
|
||||
return $ret
|
||||
}
|
||||
|
||||
# this function does nothing, it is used to be wrapped by other plugins like f-sy-h.
|
||||
# this make it possible to call the wrapper function without causing any other side effects.
|
||||
fzf-tab-dummy() { }
|
||||
|
||||
zle -N fzf-tab-debug
|
||||
zle -N fzf-tab-complete
|
||||
zle -N fzf-tab-dummy
|
||||
|
||||
disable-fzf-tab() {
|
||||
emulate -L zsh -o extended_glob
|
||||
(( $+_ftb_orig_widget )) || return 0
|
||||
|
||||
bindkey '^I' $_ftb_orig_widget
|
||||
case $_ftb_orig_list_grouped in
|
||||
0) zstyle ':completion:*' list-grouped false ;;
|
||||
1) zstyle ':completion:*' list-grouped true ;;
|
||||
2) zstyle -d ':completion:*' list-grouped ;;
|
||||
esac
|
||||
unset _ftb_orig_widget _ftb_orig_list_groupded
|
||||
|
||||
# unhook compadd so that _approximate can work properply
|
||||
unfunction compadd 2>/dev/null
|
||||
|
||||
functions[_main_complete]=$functions[_ftb__main_complete]
|
||||
functions[_approximate]=$functions[_ftb__approximate]
|
||||
|
||||
# Don't remove .fzf-tab-orig-$_ftb_orig_widget as we won't be able to reliably
|
||||
# create it if enable-fzf-tab is called again.
|
||||
}
|
||||
|
||||
enable-fzf-tab() {
|
||||
emulate -L zsh -o extended_glob
|
||||
(( ! $+_ftb_orig_widget )) || disable-fzf-tab
|
||||
|
||||
typeset -g _ftb_orig_widget="${${$(builtin bindkey '^I')##* }:-expand-or-complete}"
|
||||
if (( ! $+widgets[.fzf-tab-orig-$_ftb_orig_widget] )); then
|
||||
# Widgets that get replaced by compinit.
|
||||
local compinit_widgets=(
|
||||
complete-word
|
||||
delete-char-or-list
|
||||
expand-or-complete
|
||||
expand-or-complete-prefix
|
||||
list-choices
|
||||
menu-complete
|
||||
menu-expand-or-complete
|
||||
reverse-menu-complete
|
||||
)
|
||||
# Note: We prefix the name of the widget with '.' so that it doesn't get wrapped.
|
||||
if [[ $widgets[$_ftb_orig_widget] == builtin &&
|
||||
$compinit_widgets[(Ie)$_ftb_orig_widget] != 0 ]]; then
|
||||
# We are initializing before compinit and being asked to fall back to a completion
|
||||
# widget that isn't defined yet. Create our own copy of the widget ahead of time.
|
||||
zle -C .fzf-tab-orig-$_ftb_orig_widget .$_ftb_orig_widget _main_complete
|
||||
else
|
||||
# Copy the widget before it's wrapped by zsh-autosuggestions and zsh-syntax-highlighting.
|
||||
zle -A $_ftb_orig_widget .fzf-tab-orig-$_ftb_orig_widget
|
||||
fi
|
||||
fi
|
||||
|
||||
zstyle -t ':completion:*' list-grouped false
|
||||
typeset -g _ftb_orig_list_grouped=$?
|
||||
|
||||
zstyle ':completion:*' list-grouped false
|
||||
bindkey -M emacs '^I' fzf-tab-complete
|
||||
bindkey -M viins '^I' fzf-tab-complete
|
||||
bindkey -M emacs '^X.' fzf-tab-debug
|
||||
bindkey -M viins '^X.' fzf-tab-debug
|
||||
|
||||
# make sure we can copy them
|
||||
autoload +X -Uz _main_complete _approximate
|
||||
|
||||
# hook compadd
|
||||
functions[compadd]=$functions[-ftb-compadd]
|
||||
|
||||
# hook _main_complete to trigger fzf-tab
|
||||
functions[_ftb__main_complete]=$functions[_main_complete]
|
||||
function _main_complete() { -ftb-complete "$@" }
|
||||
|
||||
# TODO: This is not a full support, see #47
|
||||
# _approximate will also hook compadd
|
||||
# let it call -ftb-compadd instead of builtin compadd so that fzf-tab can capture result
|
||||
# make sure _approximate has been loaded.
|
||||
functions[_ftb__approximate]=$functions[_approximate]
|
||||
function _approximate() {
|
||||
# if not called by fzf-tab, don't do anything with compadd
|
||||
(( ! IN_FZF_TAB )) || unfunction compadd
|
||||
_ftb__approximate
|
||||
(( ! IN_FZF_TAB )) || functions[compadd]=$functions[-ftb-compadd]
|
||||
}
|
||||
}
|
||||
|
||||
toggle-fzf-tab() {
|
||||
emulate -L zsh -o extended_glob
|
||||
if (( $+_ftb_orig_widget )); then
|
||||
disable-fzf-tab
|
||||
else
|
||||
enable-fzf-tab
|
||||
fi
|
||||
}
|
||||
|
||||
build-fzf-tab-module() {
|
||||
local MACOS
|
||||
local NPROC
|
||||
if [[ ${OSTYPE} == darwin* ]]; then
|
||||
MACOS=true
|
||||
NPROC=$(sysctl -n hw.logicalcpu)
|
||||
else
|
||||
NPROC=$(nproc)
|
||||
fi
|
||||
pushd $FZF_TAB_HOME/modules
|
||||
CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O2" LDFLAGS=-L/usr/local/lib ./configure --disable-gdbm --without-tcsetpgrp ${MACOS:+DL_EXT=bundle}
|
||||
make -j${NPROC}
|
||||
local ret=$?
|
||||
popd
|
||||
if (( ${ret} != 0 )); then
|
||||
print -P "%F{red}%BThe module building has failed. See the output above for details.%f%b" >&2
|
||||
else
|
||||
print -P "%F{green}%BThe module has been built successfully.%f%b"
|
||||
fi
|
||||
}
|
||||
|
||||
zmodload zsh/zutil
|
||||
zmodload zsh/mapfile
|
||||
zmodload -F zsh/stat b:zstat
|
||||
|
||||
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
FZF_TAB_HOME="${0:A:h}"
|
||||
|
||||
source "$FZF_TAB_HOME"/lib/zsh-ls-colors/ls-colors.zsh fzf-tab-lscolors
|
||||
|
||||
typeset -ga _ftb_group_colors=(
|
||||
$'\x1b[94m' $'\x1b[32m' $'\x1b[33m' $'\x1b[35m' $'\x1b[31m' $'\x1b[38;5;27m' $'\x1b[36m'
|
||||
$'\x1b[38;5;100m' $'\x1b[38;5;98m' $'\x1b[91m' $'\x1b[38;5;80m' $'\x1b[92m'
|
||||
$'\x1b[38;5;214m' $'\x1b[38;5;165m' $'\x1b[38;5;124m' $'\x1b[38;5;120m'
|
||||
)
|
||||
|
||||
# init
|
||||
() {
|
||||
emulate -L zsh -o extended_glob
|
||||
|
||||
fpath+=($FZF_TAB_HOME/lib)
|
||||
|
||||
autoload -Uz -- $FZF_TAB_HOME/lib/-#ftb*(:t)
|
||||
|
||||
if (( $+FZF_TAB_COMMAND || $+FZF_TAB_OPTS || $+FZF_TAB_QUERY || $+FZF_TAB_SINGLE_GROUP || $+fzf_tab_preview_init )) \
|
||||
|| zstyle -m ":fzf-tab:*" command '*' \
|
||||
|| zstyle -m ":fzf-tab:*" extra-opts '*'; then
|
||||
print -P "%F{red}%B[fzf-tab] Sorry, your configuration is not supported anymore\n" \
|
||||
"See https://github.com/Aloxaf/fzf-tab/pull/132 for more information%f%b"
|
||||
fi
|
||||
|
||||
if [[ -n $FZF_TAB_HOME/modules/Src/aloxaf/fzftab.(so|bundle)(#qN) ]]; then
|
||||
module_path+=("$FZF_TAB_HOME/modules/Src")
|
||||
zmodload aloxaf/fzftab
|
||||
|
||||
if [[ $FZF_TAB_MODULE_VERSION != "0.2.2" ]]; then
|
||||
zmodload -u aloxaf/fzftab
|
||||
local rebuild
|
||||
print -Pn "%F{yellow}fzftab module needs to be rebuild, rebuild now?[Y/n]:%f"
|
||||
read -q rebuild
|
||||
if [[ $rebuild == y ]]; then
|
||||
build-fzf-tab-module
|
||||
zmodload aloxaf/fzftab
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
enable-fzf-tab
|
||||
zle -N toggle-fzf-tab
|
||||
|
||||
# restore options
|
||||
(( ${#_ftb_opts} )) && setopt ${_ftb_opts[@]}
|
||||
'builtin' 'unset' '_ftb_opts'
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/hint/zsh
|
||||
emulate -L zsh -o cbases -o octalzeroes
|
||||
|
||||
local REPLY
|
||||
local -a reply stat lstat
|
||||
|
||||
# fzf-tab-lscolors::match-by $1 lstat follow
|
||||
zstat -A lstat -L -- $1
|
||||
# follow symlink
|
||||
(( lstat[3] & 0170000 )) && zstat -A stat -- $1 2>/dev/null
|
||||
|
||||
fzf-tab-lscolors::from-mode "$1" "$lstat[3]" $stat[3]
|
||||
# fall back to name
|
||||
[[ -z $REPLY ]] && fzf-tab-lscolors::from-name $1
|
||||
|
||||
# If this is a symlink
|
||||
if [[ -n $lstat[14] ]]; then
|
||||
local sym_color=$REPLY
|
||||
local rsv_color=$REPLY
|
||||
local rsv=$lstat[14]
|
||||
# If this is not a broken symlink
|
||||
if [[ -e $rsv ]]; then
|
||||
# fzf-tab-lscolors::match-by $rsv stat
|
||||
zstat -A stat -- $rsv
|
||||
fzf-tab-lscolors::from-mode $rsv $stat[3]
|
||||
# fall back to name
|
||||
[[ -z $REPLY ]] && fzf-tab-lscolors::from-name $rsv
|
||||
rsv_color=$REPLY
|
||||
fi
|
||||
dpre=$'\033[0m\033['$sym_color'm'
|
||||
dsuf+=$'\033[0m -> \033['$rsv_color'm'$rsv
|
||||
else
|
||||
dpre=$'\033[0m\033['$REPLY'm'
|
||||
fi
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
#!/hint/zsh
|
||||
|
||||
# import math functions
|
||||
autoload -Uz zmathfunc
|
||||
zmathfunc
|
||||
|
||||
local tmp_dir=${TMPPREFIX:-/tmp/zsh}-fzf-tab-$USER
|
||||
[[ -d $tmp_dir ]] || command mkdir $tmp_dir
|
||||
|
||||
local ftb_preview_init="
|
||||
zmodload zsh/mapfile
|
||||
local -a _ftb_compcap=(\"\${(@f)mapfile[$tmp_dir/compcap.$$]}\")
|
||||
local -a _ftb_groups=(\"\${(@f)mapfile[$tmp_dir/groups.$$]}\")
|
||||
local bs=\$'\2'
|
||||
# get description
|
||||
export desc=\${\${\"\$(<{f})\"%\$'\0'*}#*\$'\0'}
|
||||
# get ctxt for current completion
|
||||
local -A ctxt=(\"\${(@0)\${_ftb_compcap[(r)\${(b)desc}\$bs*]#*\$bs}}\")
|
||||
# get group
|
||||
if (( \$+ctxt[group] )); then
|
||||
export group=\$_ftb_groups[\$ctxt[group]]
|
||||
fi
|
||||
# get original word
|
||||
export word=\${(Q)ctxt[word]}
|
||||
# get real path if it is file
|
||||
if (( \$+ctxt[realdir] )); then
|
||||
export realpath=\${ctxt[realdir]}\$word
|
||||
fi
|
||||
$(typeset -p words)
|
||||
"
|
||||
local binds=tab:down,btab:up,change:top,ctrl-space:toggle
|
||||
local fzf_command fzf_flags fzf_preview debug_command tmp switch_group fzf_pad fzf_min_height
|
||||
local ret=0
|
||||
|
||||
-ftb-zstyle -s fzf-command fzf_command || fzf_command=fzf
|
||||
-ftb-zstyle -a fzf-bindings tmp && binds+=,${(j:,:)tmp}
|
||||
-ftb-zstyle -a fzf-flags fzf_flags
|
||||
-ftb-zstyle -s fzf-preview fzf_preview
|
||||
-ftb-zstyle -a switch-group switch_group || switch_group=(F1 F2)
|
||||
-ftb-zstyle -s fzf-pad fzf_pad || fzf_pad=2
|
||||
-ftb-zstyle -s fzf-min-height fzf_min_height || fzf_min_height=0
|
||||
|
||||
-ftb-zstyle -a debug-command debug_command && {
|
||||
${(eX)debug_command} $fzf_flags
|
||||
return
|
||||
}
|
||||
|
||||
print -rl -- $_ftb_compcap > $tmp_dir/compcap.$$
|
||||
print -rl -- $_ftb_groups > $tmp_dir/groups.$$
|
||||
print -r -- ${ftb_preview_init/{f}/\$1} > $tmp_dir/ftb_preview_init.$$
|
||||
|
||||
binds=${binds//{_FTB_INIT_}/. $tmp_dir/ftb_preview_init.$$ {f} $'\n'}
|
||||
|
||||
local -i header_lines=$#_ftb_headers
|
||||
local -i lines=$(( $#_ftb_compcap + fzf_pad + header_lines ))
|
||||
local reload_command="$commands[zsh] -f $FZF_TAB_HOME/lib/ftb-switch-group $$ $header_lines $tmp_dir"
|
||||
|
||||
# detect if we will use tmux popup
|
||||
local use_tmux_popup=0
|
||||
if [[ $fzf_command == "ftb-tmux-popup" ]]; then
|
||||
use_tmux_popup=1
|
||||
fi
|
||||
|
||||
if (( ! use_tmux_popup )); then
|
||||
# fzf will cause the current line to refresh, so move the cursor down.
|
||||
echoti cud1 >/dev/tty
|
||||
# reset cursor before call fzf
|
||||
echoti cnorm >/dev/tty 2>/dev/null
|
||||
fi
|
||||
|
||||
cat > $tmp_dir/completions.$$
|
||||
|
||||
local dd='gdd'
|
||||
if (( ${+commands[$dd]} == 0 )) ; then
|
||||
dd='dd'
|
||||
fi
|
||||
if (( ${+commands[$dd]} == 0 )) ; then
|
||||
dd='true' # nop if dd is not installed
|
||||
fi
|
||||
|
||||
_ftb_query="${_ftb_query}$(command "$dd" bs=1G count=1 status=none iflag=nonblock < /dev/tty 2>/dev/null)" || true
|
||||
|
||||
$fzf_command \
|
||||
--ansi \
|
||||
--bind=$binds \
|
||||
--bind="${switch_group[1]}:reload($reload_command -1),${switch_group[2]}:reload($reload_command 1)" \
|
||||
--color=hl:$(( header_lines == 0 ? 188 : 255 )) \
|
||||
--cycle \
|
||||
--delimiter='\x00' \
|
||||
--expect=$continuous_trigger,$print_query,$accept_line \
|
||||
--header-lines=$header_lines \
|
||||
--height=${FZF_TMUX_HEIGHT:=$(( min(max(lines, fzf_min_height), LINES / 3 * 2) ))} \
|
||||
--layout=reverse \
|
||||
--multi \
|
||||
--nth=2,3 \
|
||||
--print-query \
|
||||
--query=$_ftb_query \
|
||||
--tiebreak=begin \
|
||||
${fzf_preview:+--preview=${ftb_preview_init/{f}/'{f}'}$fzf_preview} \
|
||||
$fzf_flags < $tmp_dir/completions.$$ || ret=$?
|
||||
|
||||
if (( ! use_tmux_popup )); then
|
||||
echoti civis >/dev/tty 2>/dev/null
|
||||
echoti cuu1 >/dev/tty
|
||||
fi
|
||||
|
||||
command rm $tmp_dir/*.$$ 2>/dev/null
|
||||
return $ret
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
#!/hint/zsh
|
||||
|
||||
local dsuf dpre k _v filepath first_word show_group default_color prefix bs=$'\b'
|
||||
local -a list_colors group_colors tcandidates reply match mbegin mend
|
||||
local -i same_word=1 colorful=0
|
||||
local -Ua duplicate_groups=()
|
||||
local -A word_map=()
|
||||
|
||||
(( $#_ftb_compcap == 0 )) && return
|
||||
|
||||
-ftb-zstyle -s show-group show_group || show_group=full
|
||||
-ftb-zstyle -s default-color default_color || default_color=$'\x1b[37m'
|
||||
-ftb-zstyle -s prefix prefix || {
|
||||
zstyle -m ':completion:*:descriptions' format '*' && prefix='·'
|
||||
}
|
||||
-ftb-zstyle -a group-colors group_colors || group_colors=($_ftb_group_colors)
|
||||
zstyle -a ":completion:$_ftb_curcontext" list-colors list_colors
|
||||
|
||||
# init colorize
|
||||
if (( $+builtins[fzf-tab-candidates-generate] )); then
|
||||
fzf-tab-candidates-generate -i list_colors
|
||||
else
|
||||
local -A namecolors=(${(@s:=:)${(@s.:.)list_colors}:#[[:alpha:]][[:alpha:]]=*})
|
||||
local -A modecolors=(${(@Ms:=:)${(@s.:.)list_colors}:#[[:alpha:]][[:alpha:]]=*})
|
||||
(( $#namecolors == 0 && $#modecolors == 0 )) && list_colors=()
|
||||
fi
|
||||
|
||||
if (( $#_ftb_groups == 1 )); then
|
||||
-ftb-zstyle -m single-group prefix || prefix=''
|
||||
-ftb-zstyle -m single-group color || group_colors=("$default_color")
|
||||
fi
|
||||
|
||||
if (( $+builtins[fzf-tab-candidates-generate] )); then
|
||||
fzf-tab-candidates-generate
|
||||
else
|
||||
for k _v in "${(@ps:\2:)_ftb_compcap}"; do
|
||||
local -A v=("${(@0)_v}")
|
||||
[[ $v[word] == ${first_word:=$v[word]} ]] || same_word=0
|
||||
|
||||
# add character and color to describe the type of the files
|
||||
dsuf='' dpre=''
|
||||
if (( $+v[realdir] )); then
|
||||
filepath=$v[realdir]${(Q)v[word]}
|
||||
if [[ -d $filepath ]]; then
|
||||
dsuf=/
|
||||
fi
|
||||
# add color and resolve symlink if have list-colors
|
||||
# detail: http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcomplist-Module
|
||||
if (( $#list_colors )) && [[ -a $filepath || -L $filepath ]]; then
|
||||
-ftb-colorize $filepath
|
||||
colorful=1
|
||||
elif [[ -L $filepath ]]; then
|
||||
dsuf=@
|
||||
fi
|
||||
if [[ $options[list_types] == off ]]; then
|
||||
dsuf=''
|
||||
fi
|
||||
fi
|
||||
|
||||
# add color to description if they have group index
|
||||
if (( $+v[group] )); then
|
||||
local color=$group_colors[$v[group]]
|
||||
# add a hidden group index at start of string to keep group order when sorting
|
||||
# first group index is for builtin sort, sencond is for GNU sort
|
||||
tcandidates+=$v[group]$'\b'$color$prefix$dpre$'\0'$v[group]$'\b'$k$'\0'$dsuf
|
||||
else
|
||||
tcandidates+=$default_color$dpre$'\0'$k$'\0'$dsuf
|
||||
fi
|
||||
|
||||
# check group with duplicate member
|
||||
if [[ $show_group == brief ]]; then
|
||||
if (( $+word_map[$v[word]] && $+v[group] )); then
|
||||
duplicate_groups+=$v[group] # add this group
|
||||
duplicate_groups+=$word_map[$v[word]] # add previous group
|
||||
fi
|
||||
word_map[$v[word]]=$v[group]
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
(( same_word )) && tcandidates[2,-1]=()
|
||||
|
||||
# sort and remove sort group or other index
|
||||
zstyle -T ":completion:$_ftb_curcontext" sort
|
||||
if (( $? != 1 )); then
|
||||
if (( colorful )); then
|
||||
# if enable list_colors, we should skip the first field
|
||||
if [[ ${commands[sort]:A:t} != (|busybox*) ]]; then
|
||||
# this is faster but doesn't work if `find` is from busybox
|
||||
tcandidates=(${(f)"$(command sort -u -t '\0' -k 2 <<< ${(pj:\n:)tcandidates})"})
|
||||
else
|
||||
# slower but portable
|
||||
tcandidates=(${(@o)${(@)tcandidates:/(#b)([^$'\0']#)$'\0'(*)/$match[2]$'\0'$match[1]}})
|
||||
tcandidates=(${(@)tcandidates/(#b)(*)$'\0'([^$'\0']#)/$match[2]$'\0'$match[1]})
|
||||
fi
|
||||
else
|
||||
tcandidates=("${(@o)tcandidates}")
|
||||
fi
|
||||
fi
|
||||
typeset -gUa _ftb_complist=("${(@)tcandidates//[0-9]#$bs}")
|
||||
|
||||
# hide needless group
|
||||
if (( $#_ftb_groups )); then
|
||||
local i to_hide indexs=({1..$#_ftb_groups})
|
||||
case $show_group in
|
||||
brief) to_hide=(${indexs:|duplicate_groups}) ;;
|
||||
none) to_hide=($indexs) ;;
|
||||
esac
|
||||
for i in $to_hide; do
|
||||
# NOTE: _ftb_groups is unique array
|
||||
_ftb_groups[i]="__hide__$i"
|
||||
done
|
||||
fi
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/hint/zsh
|
||||
|
||||
typeset -ga _ftb_headers=()
|
||||
local i tmp group_colors
|
||||
local -i mlen=0 len=0
|
||||
|
||||
if (( $#_ftb_groups == 1 )) && { ! -ftb-zstyle -m single-group "header" }; then
|
||||
return
|
||||
fi
|
||||
|
||||
# calculate the max column width
|
||||
for i in $_ftb_groups; do
|
||||
(( $#i > mlen )) && mlen=$#i
|
||||
done
|
||||
mlen+=1
|
||||
|
||||
-ftb-zstyle -a group-colors group_colors || group_colors=($_ftb_group_colors)
|
||||
|
||||
for (( i=1; i<=$#_ftb_groups; i++ )); do
|
||||
[[ $_ftb_groups[i] == "__hide__"* ]] && continue
|
||||
|
||||
if (( len + $#_ftb_groups[i] > COLUMNS - 5 )); then
|
||||
_ftb_headers+=$tmp
|
||||
tmp='' && len=0
|
||||
fi
|
||||
if (( len + mlen > COLUMNS - 5 )); then
|
||||
# the last column doesn't need padding
|
||||
_ftb_headers+=$tmp$group_colors[i]$_ftb_groups[i]$'\033[00m'
|
||||
tmp='' && len=0
|
||||
else
|
||||
tmp+=$group_colors[i]${(r:$mlen:)_ftb_groups[i]}$'\033[00m'
|
||||
len+=$mlen
|
||||
fi
|
||||
done
|
||||
(( $#tmp )) && _ftb_headers+=$tmp
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/hint/zsh
|
||||
|
||||
if zmodload -s zsh/pcre; then
|
||||
setopt localoptions rematch_pcre
|
||||
fi
|
||||
|
||||
local key qtype tmp query_string
|
||||
typeset -g _ftb_query=
|
||||
-ftb-zstyle -a query-string query_string || query_string=(prefix input first)
|
||||
for qtype in $query_string; do
|
||||
if [[ $qtype == prefix ]]; then
|
||||
# find the longest common prefix among descriptions
|
||||
local -a keys=(${_ftb_compcap%$'\2'*})
|
||||
tmp=$keys[1]
|
||||
local MATCH match mbegin mend prefix=(${(s::)tmp})
|
||||
for key in ${keys:1}; do
|
||||
(( $#tmp )) || break
|
||||
[[ $key == $tmp* ]] && continue
|
||||
# interpose characters from the current common prefix and $key and see how
|
||||
# many pairs of equal characters we get at the start of the resulting string
|
||||
[[ ${(j::)${${(s::)key[1,$#tmp]}:^prefix}} =~ '^(((.)\3)*)' ]]
|
||||
# truncate common prefix and maintain loop invariant: ${(s::)tmp} == $prefix
|
||||
tmp[$#MATCH/2+1,-1]=""
|
||||
prefix[$#MATCH/2+1,-1]=()
|
||||
done
|
||||
elif [[ $qtype == input ]]; then
|
||||
local fv=${_ftb_compcap[1]#*$'\2'}
|
||||
local -A v=("${(@0)fv}")
|
||||
tmp=$v[PREFIX]
|
||||
if (( $RBUFFER[(i)$v[SUFFIX]] != 1 )); then
|
||||
tmp=${tmp/%$v[SUFFIX]}
|
||||
fi
|
||||
tmp=${${tmp#$v[hpre]}#$v[apre]}
|
||||
fi
|
||||
if (( $query_string[(I)longest] )); then
|
||||
(( $#tmp > $#_ftb_query )) && _ftb_query=$tmp
|
||||
elif [[ -n $tmp ]]; then
|
||||
_ftb_query=$tmp && break
|
||||
fi
|
||||
done
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/hint/zsh
|
||||
emulate -L zsh -o extended_glob
|
||||
|
||||
zmodload zsh/mapfile
|
||||
|
||||
# receive arguments
|
||||
local pid=$1 header_lines=$2 tmp_dir=$3 offset=$@[-1]
|
||||
|
||||
# read completion list
|
||||
local -a list=(${(f)mapfile[$tmp_dir/completions.$pid]})
|
||||
|
||||
# get total group count
|
||||
if (( $#list > 10000 )); then
|
||||
local -Ua total=(${(f)"$(print -l ${list:$header_lines} | grep -a -oP '^\x1b\[[0-9;]*m')"})
|
||||
else
|
||||
local -Ua total=(${(M)${list:$header_lines}#$'\x1b['[0-9;]#*m})
|
||||
fi
|
||||
|
||||
# get current group index, start from 2
|
||||
local current=2
|
||||
if [[ -f $tmp_dir/current-group.$pid ]]; then
|
||||
current=$(( $(<$tmp_dir/current-group.$pid) + offset ))
|
||||
fi
|
||||
(( current > $#total )) && current=1
|
||||
(( current == 0 )) && current=$#total
|
||||
echo $current > $tmp_dir/current-group.$pid
|
||||
|
||||
# print headers
|
||||
if (( header_lines != 0 )); then
|
||||
print -l ${list[1,header_lines]/${total[current]}/$'\x1b[1m'}
|
||||
fi
|
||||
|
||||
# print current group
|
||||
if (( $#list > 10000 )); then
|
||||
print -l ${list:$header_lines} | grep -a -F "${total[current]}"
|
||||
else
|
||||
print -l ${(M)${list:$header_lines}:#${total[current]}*}
|
||||
fi
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/hint/zsh
|
||||
# Show results with tmux popup
|
||||
# Example usage:
|
||||
# zstyle ':fzf-tab:*' fzf-command ftb-tmux-popup
|
||||
# zstyle ':fzf-tab:*' popup-pad 0 0
|
||||
# It can also be used as a standalone tool, like:
|
||||
# ls | ftb-tmux-popup
|
||||
emulate -L zsh -o extended_glob
|
||||
|
||||
# import min
|
||||
autoload -Uz zmathfunc
|
||||
zmathfunc
|
||||
|
||||
: ${tmp_dir:=${TMPPREFIX:-/tmp/zsh}-fzf-tab-$USER}
|
||||
|
||||
# fallback to fzf if it is not running in tmux
|
||||
if (( ! $+TMUX_PANE )); then
|
||||
fzf $@
|
||||
return
|
||||
fi
|
||||
|
||||
local ret=0
|
||||
|
||||
local -a fzf_opts=($@)
|
||||
fzf_opts=(${${fzf_opts/--height*}/--layout*})
|
||||
|
||||
# get position of cursor and size of window
|
||||
local -a tmp=($(command tmux display-message -p "#{pane_top} #{cursor_y} #{pane_left} #{cursor_x} #{window_height} #{window_width} #{status} #{status-position}"))
|
||||
local cursor_y=$((tmp[1] + tmp[2])) cursor_x=$((tmp[3] + tmp[4])) window_height=$tmp[5] window_width=$tmp[6] window_top=0
|
||||
|
||||
if [[ $tmp[8] == 'top' ]]; then
|
||||
window_top=$tmp[7]
|
||||
cursor_y=$((cursor_y + window_top))
|
||||
fi
|
||||
|
||||
# if not called by fzf-tab
|
||||
if (( ! $+IN_FZF_TAB )); then
|
||||
[[ -d $tmp_dir ]] || mkdir -p $tmp_dir
|
||||
cat > $tmp_dir/completions.$$
|
||||
fi
|
||||
|
||||
local text REPLY comp_lines comp_length length popup_pad popup_min_size
|
||||
|
||||
zstyle -a ":fzf-tab:$_ftb_curcontext" popup-pad popup_pad || popup_pad=(0 0)
|
||||
zstyle -a ":fzf-tab:$_ftb_curcontext" popup-min-size popup_min_size || popup_min_size=(0 0)
|
||||
|
||||
# get the size of content, note we should remove all ANSI color code
|
||||
comp_lines=$(( ${#${(f)mapfile[$tmp_dir/completions.$$]}} + $popup_pad[2] ))
|
||||
if (( comp_lines <= 500 )); then
|
||||
comp_length=0
|
||||
for line in ${(f)mapfile[$tmp_dir/completions.$$]}; do
|
||||
length=${(m)#${(S)line//$'\x1b['[0-9]#*m}}
|
||||
(( length >= comp_length )) && comp_length=$length
|
||||
done
|
||||
else
|
||||
# FIXME: can't get the correct width of CJK characters.
|
||||
comp_length=$( command perl -ne 's/\x1b\[[0-9;]*m//g;s/\x00//g; $m= length() if $m < length(); END { print $m }' < $tmp_dir/completions.$$ )
|
||||
fi
|
||||
comp_length=$(( comp_length + $popup_pad[1] ))
|
||||
|
||||
local popup_height popup_y popup_width popup_x adjust_height
|
||||
|
||||
# adjust the popup height if the fzf finder info style is not default
|
||||
if (( $fzf_opts[(I)--info=*(hidden|inline)*] > 0 )); then
|
||||
adjust_height=-1
|
||||
fi
|
||||
|
||||
# calculate the popup height and y position
|
||||
if (( cursor_y * 2 > window_height )); then
|
||||
# show above the cursor
|
||||
popup_height=$(( min(max(comp_lines + 4, popup_min_size[2]), cursor_y - window_top) + adjust_height ))
|
||||
popup_y=$cursor_y
|
||||
else
|
||||
# show below the cursor
|
||||
popup_height=$(( min(max(comp_lines + 4, popup_min_size[2]), window_height - cursor_y + window_top - 1) + adjust_height ))
|
||||
popup_y=$(( cursor_y + popup_height + 1 ))
|
||||
fzf_opts+=(--layout=reverse)
|
||||
fi
|
||||
|
||||
# calculate the popup width and x position
|
||||
popup_width=$(( min(max(comp_length + 5, popup_min_size[1]), window_width) ))
|
||||
popup_x=$(( cursor_x + popup_width > window_width ? window_width - popup_width : cursor_x ))
|
||||
|
||||
echo -E "$commands[fzf] ${(qq)fzf_opts[@]} < $tmp_dir/completions.$$ > $tmp_dir/result-$$" > $tmp_dir/fzf-$$
|
||||
{
|
||||
tmux popup -x $popup_x -y $popup_y \
|
||||
-w $popup_width -h $popup_height \
|
||||
-d $PWD -E ". $tmp_dir/fzf-$$" || ret=$?
|
||||
echo -E "$(<$tmp_dir/result-$$)"
|
||||
} always {
|
||||
command rm $tmp_dir/*-$$
|
||||
(( $+IN_FZF_TAB )) || command rm $tmp_dir/completions.$$
|
||||
}
|
||||
return $ret
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Gamma
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
# zsh-ls-colors
|
||||
|
||||

|
||||
|
||||
A zsh library to use `LS_COLORS` in scripts or other plugins.
|
||||
|
||||
For a simple demo, see the `demo` script in this repo.
|
||||
|
||||
For more advanced usage,
|
||||
instructions are located at top of the source files for `from-mode` and `from-name`.
|
||||
If a use case isn't adequately covered,
|
||||
please open an issue!
|
||||
|
||||
## Using zsh-ls-colors in a plugin
|
||||
|
||||
You can use this as a submodule or a subtree.
|
||||
|
||||
### submodule:
|
||||
|
||||
```sh
|
||||
# Add (only once)
|
||||
git submodule add git://github.com/xPMo/zsh-ls-colors.git ls-colors
|
||||
git commit -m 'Add ls-colors as submodule'
|
||||
|
||||
# Update
|
||||
cd ls-colors
|
||||
git fetch
|
||||
git checkout origin/master
|
||||
cd ..
|
||||
git commit ls-colors -m 'Update ls-colors to latest'
|
||||
```
|
||||
|
||||
### Subtree:
|
||||
|
||||
```sh
|
||||
# Initial add
|
||||
git subtree add --prefix=ls-colors/ --squash -m 'Add ls-colors as a subtree' \
|
||||
git://github.com/xPMo/zsh-ls-colors.git master
|
||||
|
||||
# Update
|
||||
git subtree pull --prefix=ls-colors/ --squash -m 'Update ls-colors to latest' \
|
||||
git://github.com/xPMo/zsh-ls-colors.git master
|
||||
|
||||
|
||||
# Or, after adding a remote:
|
||||
git remote add ls-colors git://github.com/xPMo/zsh-ls-colors.git
|
||||
|
||||
# Initial add
|
||||
git subtree add --prefix=ls-colors/ --squash -m 'Add ls-colors as a subtree' ls-colors master
|
||||
|
||||
# Update
|
||||
git subtree pull --prefix=ls-colors/ --squash -m 'Update ls-colors to latest' ls-colors master
|
||||
```
|
||||
|
||||
### Function namespacing
|
||||
|
||||
Since functions are a public namespace,
|
||||
this plugin allows you to customize the preifix for your plugin:
|
||||
|
||||
```zsh
|
||||
# load functions as my-lscolors::{init,match-by,from-name,from-mode}
|
||||
source ${0:h}/ls-colors/ls-colors.zsh my-lscolors
|
||||
```
|
||||
|
||||
### Parameter namespacing
|
||||
|
||||
While indirect parameter expansion exists with `${(P)var}`,
|
||||
it doesn't play nicely with array parameters.
|
||||
|
||||
There are multiple strategies to prevent unnecessary re-parsing:
|
||||
|
||||
```zsh
|
||||
# Call once when loading.
|
||||
# Pollutes global namespace but prevents re-parsing
|
||||
ls-color::init
|
||||
```
|
||||
|
||||
```zsh
|
||||
# Don't call init at all and only use ::match-by.
|
||||
# Doesn't pollute global namespace but reparses LS_COLORS on every call
|
||||
ls-color::match-by $file lstat
|
||||
```
|
||||
|
||||
```zsh
|
||||
# Initialize within a scope with local parameters.
|
||||
# Best for not polluting global namespace when multiple filenames need to be parsed.
|
||||
(){
|
||||
local -A namecolors modecolors
|
||||
ls-color::init
|
||||
|
||||
for arg; do
|
||||
...
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
```zsh
|
||||
# Serialize:
|
||||
typeset -g LS_COLORS_CACHE_FILE=$(mktemp)
|
||||
(){
|
||||
local -A namecolors modecolors
|
||||
ls-color::init
|
||||
typeset -p modecolors namecolors >| $LS_COLORS_CACHE_FILE
|
||||
zcompile $LS_COLORS_CACHE_FILE
|
||||
}
|
||||
|
||||
my-function(){
|
||||
local -A namecolors modecolors
|
||||
source $LS_COLORS_CACHE_FILE
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env zsh
|
||||
# set $0 (ref: zdharma.org/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html#zero-handling)
|
||||
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
|
||||
# load library functions
|
||||
source ls-colors.zsh ''
|
||||
|
||||
# to name the functions with a different namespace
|
||||
# call source with a different argument
|
||||
#source my-plugin::ls
|
||||
|
||||
# init (sets modecolors and namecolors)
|
||||
# You have options. Either you can pollute global namespace:
|
||||
ls-color::init
|
||||
# Or you can have ::match-by re-parse colors on every call
|
||||
: # (do nothing)
|
||||
# Or if you have multiple calls, you can parse colors once for a scope:
|
||||
(){
|
||||
local -A modecolors namecolors
|
||||
ls-color::init
|
||||
|
||||
for arg; do
|
||||
ls-color::match-by $arg lstat
|
||||
: do something else
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# colors can also be added for other globs after init as well:
|
||||
namecolors[*.md]='01' # bold markdown files
|
||||
|
||||
# EXTENDED_GLOB is enabled when matching, so things like this are possible:
|
||||
namecolors[(#i)(*/|)license(|.*)]='04' # underline LICENSE, or license.txt, or similar
|
||||
|
||||
local file reply
|
||||
# color each file in the argument list
|
||||
for file; do
|
||||
ls-color::match-by $file all
|
||||
# point to symlink resolution if it exists
|
||||
print '\e['$reply[1]'m'$file'\e[0m'${reply[2]:+' → \e['$reply[3]'m'$reply[2]'\e[0m'}
|
||||
done
|
||||
|
||||
# =======================
|
||||
# Alternate manual method:
|
||||
for file; do
|
||||
ls-color::match-by $file lstat follow
|
||||
if [[ $reply[2] ]]; then
|
||||
# This is a symlink
|
||||
symlink_color=$reply[1]
|
||||
# If broken, use link color for destination
|
||||
resolved_color=$reply[1]
|
||||
resolved=$reply[2]
|
||||
if [[ -e $file ]]; then
|
||||
# Not broken, update destination color
|
||||
ls-color::match-by $file stat
|
||||
resolved_color=$reply[1]
|
||||
fi
|
||||
print '\e['$symlink_color'm'$file'\e[0m → \e['$resolved_color'm'$resolved'\e[0m'
|
||||
else
|
||||
# This is not a symlink
|
||||
print '\e['$reply[1]'m'$file'\e[0m'
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
#!/usr/bin/env zsh
|
||||
|
||||
# set the prefix for all functions
|
||||
local pfx=${1:-'ls-color'}
|
||||
|
||||
# {{{ From mode
|
||||
# Usage:
|
||||
# $1: filename
|
||||
# $2: The value of struct stat st_mode
|
||||
# If empty, modecolors lookup will be skipped
|
||||
# $3: (If symlink) The value of struct stat st_mode
|
||||
# for the target of $1's symlink. If unset,
|
||||
# interpret as a broken link.
|
||||
# Sets REPLY to the console code
|
||||
${pfx}::from-mode () {
|
||||
|
||||
emulate -L zsh
|
||||
setopt cbases octalzeroes extendedglob
|
||||
|
||||
[[ -z $2 ]] && return 1
|
||||
|
||||
local -i reg=0
|
||||
local -a codes
|
||||
|
||||
local -i st_mode=$(($2))
|
||||
# See man 7 inode for more info
|
||||
# file type
|
||||
case $(( st_mode & 0170000 )) in
|
||||
$(( 0140000 )) ) codes=( $modecolors[so] ) ;;
|
||||
$(( 0120000 )) ) # symlink, special handling
|
||||
if ! (($+3)); then
|
||||
REPLY=$modecolors[or]
|
||||
elif [[ $modecolors[ln] = target ]]; then
|
||||
"$0" "$1" "${@:3}"
|
||||
else
|
||||
REPLY=$modecolors[ln]
|
||||
fi
|
||||
return
|
||||
;;
|
||||
$(( 0100000 )) ) codes=( ); reg=1 ;; # regular file
|
||||
$(( 0060000 )) ) codes=( $modecolors[bd] ) ;;
|
||||
$(( 0040000 )) ) codes=( $modecolors[di] ) ;;
|
||||
$(( 0020000 )) ) codes=( $modecolors[cd] ) ;;
|
||||
$(( 0010000 )) ) codes=( $modecolors[pi] ) ;;
|
||||
esac
|
||||
|
||||
# setuid/setgid/sticky/other-writable
|
||||
(( st_mode & 04000 )) && codes+=( $modecolors[su] )
|
||||
(( st_mode & 02000 )) && codes+=( $modecolors[sg] )
|
||||
(( ! reg )) && case $(( st_mode & 01002 )) in
|
||||
# sticky
|
||||
$(( 01000 )) ) codes+=( $modecolors[st] ) ;;
|
||||
# other-writable
|
||||
$(( 00002 )) ) codes+=( $modecolors[ow] ) ;;
|
||||
# other-writable and sticky
|
||||
$(( 01002 )) ) codes+=( $modecolors[tw] ) ;;
|
||||
esac
|
||||
|
||||
# executable
|
||||
if (( ! $#codes )); then
|
||||
(( st_mode & 0111 )) && codes+=( $modecolors[ex] )
|
||||
fi
|
||||
|
||||
# return nonzero if no matching code
|
||||
[[ ${REPLY::=${(j:;:)codes}} ]]
|
||||
} # }}}
|
||||
# {{{ From name
|
||||
# Usage:
|
||||
# $1: filename
|
||||
#
|
||||
# Sets REPLY to the console code
|
||||
${pfx}::from-name () {
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
# Return non-zero if no keys match
|
||||
[[ ${REPLY::=$namecolors[(k)$1]} ]]
|
||||
} # }}}
|
||||
# {{{ Init
|
||||
# WARNING: initializes namecolors and modecolors in global scope
|
||||
${pfx}::init () {
|
||||
emulate -L zsh
|
||||
|
||||
# Use $1 if provided, otherwise use LS_COLORS
|
||||
# Use LSCOLORS on BSD
|
||||
local LS_COLORS=${1:-${LS_COLORS:-$LSCOLORS}}
|
||||
|
||||
# read in LS_COLORS
|
||||
typeset -gA namecolors=(${(@s:=:)${(@s.:.)LS_COLORS}:#[[:alpha:]][[:alpha:]]=*})
|
||||
typeset -gA modecolors=(${(@Ms:=:)${(@s.:.)LS_COLORS}:#[[:alpha:]][[:alpha:]]=*})
|
||||
}
|
||||
# }}}
|
||||
# {{{ Match by
|
||||
# Usage:
|
||||
# $1: filename
|
||||
# Optional (must be $2): g[lobal]: Use existing stat | lstat in parent scope
|
||||
# ${@:2}: Append to reply:
|
||||
# - l[stat] : Look up using lstat (don't follow symlink), if empty match name
|
||||
# - s[tat] : Look up using stat (do follow symlink), if empty match name
|
||||
# - n[ame] : Only match name
|
||||
# - f[ollow]: Get resolution path of symlink
|
||||
# - L[stat] : Same as above but don't match name
|
||||
# - S[tat] : Same as above but don't match name
|
||||
# - a[ll] : If a broken symlink: lstat follow lstat
|
||||
# : If a symlink : lstat follow stat
|
||||
# : Otherwise : lstat
|
||||
# - A[ll] : If a broken symlink: Lstat follow Lstat
|
||||
# : If a symlink : Lstat follow Stat
|
||||
# : Otherwise : Lstat
|
||||
#
|
||||
# or returns non-zero
|
||||
${pfx}::match-by () {
|
||||
emulate -L zsh
|
||||
setopt extendedglob cbases octalzeroes
|
||||
|
||||
local arg REPLY name=$1 pfx=${0%::match-by}
|
||||
shift
|
||||
|
||||
# init in local scope if not using global params
|
||||
if ! [[ -v namecolors && -v modecolors ]]; then
|
||||
local -A namecolors modecolors
|
||||
${pfx}::init
|
||||
fi
|
||||
|
||||
if [[ ${1:l} = (g|global) ]]; then
|
||||
shift
|
||||
else
|
||||
local -a stat lstat
|
||||
declare -ga reply=()
|
||||
fi
|
||||
|
||||
zmodload -F zsh/stat b:zstat
|
||||
for arg; do
|
||||
case ${arg[1]:l} in
|
||||
n|name)
|
||||
${pfx}::from-name $name
|
||||
reply+=("$REPLY")
|
||||
;;
|
||||
l|lstat)
|
||||
(($#lstat)) || zstat -A lstat -L $name || return 1
|
||||
if ((lstat[3] & 0170000 )); then
|
||||
# follow symlink
|
||||
(($#stat)) || zstat -A stat $name 2>/dev/null
|
||||
fi
|
||||
${pfx}::from-mode "$name" "$lstat[3]" $stat[3]
|
||||
if [[ $REPLY || ${2[1]} = L ]]; then
|
||||
reply+=("$REPLY")
|
||||
else # fall back to name
|
||||
"$0" "$name" g n
|
||||
fi
|
||||
;;
|
||||
s|stat)
|
||||
(($#stat)) || zstat -A stat $name || return 1
|
||||
${pfx}::from-mode $name $stat[3]
|
||||
reply+=("$REPLY")
|
||||
if [[ $REPLY || ${arg[1]} = S ]]; then
|
||||
reply+=("$REPLY")
|
||||
else # fall back to name
|
||||
"$0" "$name" g n
|
||||
fi
|
||||
;;
|
||||
f|follow)
|
||||
(($#lstat)) || zstat -A lstat -L $name || return 1
|
||||
reply+=("$lstat[14]")
|
||||
;;
|
||||
a|all)
|
||||
# Match case
|
||||
"$0" "$name" g ${${${arg[1]%a}:+L}:-l}
|
||||
# won't append if empty
|
||||
reply+=($lstat[14])
|
||||
# $stat[14] will be empty if not a symlink
|
||||
if [[ $lstat[14] ]]; then
|
||||
if [[ -e $name ]]; then
|
||||
"$0" "$name" g ${${${arg[1]%a}:+S}:-s}
|
||||
else
|
||||
reply+=($reply[-2])
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*) return 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
# }}}
|
||||
# vim: set foldmethod=marker:
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
DISTFILES_SRC='
|
||||
META-FAQ
|
||||
configure config.h.in stamp-h.in
|
||||
'
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
autoconf
|
||||
autoheader
|
||||
echo > stamp-h.in
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
defs.mk
|
||||
*.swp
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
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])
|
||||
])
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#
|
||||
# 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:
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#!/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
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#!/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
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# 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'
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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.
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#
|
||||
# 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:
|
||||
|
|
@ -0,0 +1 @@
|
|||
1580588806
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
*.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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
set ai
|
||||
set sw=4
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
--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
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
#
|
||||
# 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)
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
set ai
|
||||
set sw=4
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
Makefile.in
|
||||
*.epro
|
||||
*.export
|
||||
*.mdh
|
||||
*.mdhi
|
||||
*.mdhs
|
||||
*.pro
|
||||
*.syms
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
#include "fzftab.mdh"
|
||||
#include "fzftab.pro"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* get_color(char* file, const struct stat* sb);
|
||||
const char* get_suffix(char* file, const struct stat* sb);
|
||||
const char* colorize_from_mode(char* file, const struct stat* sb);
|
||||
const char* colorize_from_name(char* file);
|
||||
char** fzf_tab_colorize(char* file);
|
||||
int compile_patterns(char* nam, char** list_colors);
|
||||
char* ftb_strcat(char* dst, int n, ...);
|
||||
|
||||
/* Indixes into the terminal string arrays. */
|
||||
#define COL_NO 0
|
||||
#define COL_FI 1
|
||||
#define COL_DI 2
|
||||
#define COL_LN 3
|
||||
#define COL_PI 4
|
||||
#define COL_SO 5
|
||||
#define COL_BD 6
|
||||
#define COL_CD 7
|
||||
#define COL_OR 8
|
||||
#define COL_MI 9
|
||||
#define COL_SU 10
|
||||
#define COL_SG 11
|
||||
#define COL_TW 12
|
||||
#define COL_OW 13
|
||||
#define COL_ST 14
|
||||
#define COL_EX 15
|
||||
#define COL_LC 16
|
||||
#define COL_RC 17
|
||||
#define COL_EC 18
|
||||
#define COL_TC 19
|
||||
#define COL_SP 20
|
||||
#define COL_MA 21
|
||||
#define COL_HI 22
|
||||
#define COL_DU 23
|
||||
#define COL_SA 24
|
||||
|
||||
#define NUM_COLS 25
|
||||
|
||||
/* Names of the terminal strings. */
|
||||
static char* colnames[] = { "no", "fi", "di", "ln", "pi", "so", "bd", "cd", "or", "mi", "su", "sg",
|
||||
"tw", "ow", "st", "ex", "lc", "rc", "ec", "tc", "sp", "ma", "hi", "du", "sa", NULL };
|
||||
|
||||
/* Default values. */
|
||||
static char* defcols[]
|
||||
= { "0", "0", "1;31", "1;36", "33", "1;35", "1;33", "1;33", NULL, NULL, "37;41", "30;43",
|
||||
"30;42", "34;42", "37;44", "1;32", "\033[", "m", NULL, "0", "0", "7", NULL, NULL, "0" };
|
||||
|
||||
static char* fzf_tab_module_version;
|
||||
|
||||
struct pattern {
|
||||
Patprog pat;
|
||||
char color[50];
|
||||
};
|
||||
|
||||
static int opt_list_type = OPT_INVALID;
|
||||
static int pat_cnt = 0;
|
||||
static struct pattern* name_color = NULL;
|
||||
static char mode_color[NUM_COLS][20];
|
||||
|
||||
// TODO: use ZLS_COLORS ?
|
||||
int compile_patterns(char* nam, char** list_colors)
|
||||
{
|
||||
// clean old name_color and set pat_cnt = 0
|
||||
if (pat_cnt != 0) {
|
||||
while (--pat_cnt) {
|
||||
freepatprog(name_color[pat_cnt].pat);
|
||||
}
|
||||
free(name_color);
|
||||
}
|
||||
// initialize mode_color with default value
|
||||
for (int i = 0; i < NUM_COLS; i++) {
|
||||
if (defcols[i]) {
|
||||
strcpy(mode_color[i], defcols[i]);
|
||||
}
|
||||
}
|
||||
// empty array, just return
|
||||
if (list_colors == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// how many pattens?
|
||||
while (list_colors[pat_cnt] != NULL) {
|
||||
pat_cnt++;
|
||||
}
|
||||
name_color = zshcalloc(pat_cnt * sizeof(struct pattern));
|
||||
|
||||
for (int i = 0; i < pat_cnt; i++) {
|
||||
char* pat = ztrdup(list_colors[i]);
|
||||
char* color = strrchr(pat, '=');
|
||||
if (color == NULL)
|
||||
continue;
|
||||
*color = '\0';
|
||||
tokenize(pat);
|
||||
remnulargs(pat);
|
||||
|
||||
// mode=color
|
||||
bool skip = false;
|
||||
for (int j = 0; j < NUM_COLS; j++) {
|
||||
if (strpfx(colnames[j], list_colors[i])) {
|
||||
strcpy(mode_color[j], color + 1);
|
||||
name_color[i].pat = NULL;
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// name=color
|
||||
if ((name_color[i].pat = patcompile(pat, PAT_ZDUP, NULL))) {
|
||||
strcpy(name_color[i].color, color + 1);
|
||||
}
|
||||
|
||||
free(pat);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: use zsh mod_export function `file_type` ?
|
||||
const char* get_suffix(char* file, const struct stat* sb)
|
||||
{
|
||||
struct stat sb2;
|
||||
mode_t filemode = sb->st_mode;
|
||||
|
||||
if (S_ISBLK(filemode))
|
||||
return "#";
|
||||
else if (S_ISCHR(filemode))
|
||||
return "%";
|
||||
else if (S_ISDIR(filemode))
|
||||
return "/";
|
||||
else if (S_ISFIFO(filemode))
|
||||
return "|";
|
||||
else if (S_ISLNK(filemode))
|
||||
if (strpfx(mode_color[COL_LN], "target")) {
|
||||
if (stat(file, &sb2) == -1) {
|
||||
return "@";
|
||||
}
|
||||
return get_suffix(file, &sb2);
|
||||
} else {
|
||||
return "@";
|
||||
}
|
||||
else if (S_ISREG(filemode))
|
||||
return (filemode & S_IXUGO) ? "*" : "";
|
||||
else if (S_ISSOCK(filemode))
|
||||
return "=";
|
||||
else
|
||||
return "?";
|
||||
}
|
||||
|
||||
const char* get_color(char* file, const struct stat* sb)
|
||||
{
|
||||
// no list-colors, return empty color
|
||||
if (pat_cnt == 0) {
|
||||
return "";
|
||||
}
|
||||
const char* ret;
|
||||
if ((ret = colorize_from_mode(file, sb)) || (ret = colorize_from_name(file))) {
|
||||
return ret;
|
||||
}
|
||||
return mode_color[COL_FI];
|
||||
}
|
||||
|
||||
const char* colorize_from_name(char* file)
|
||||
{
|
||||
for (int i = 0; i < pat_cnt; i++) {
|
||||
if (name_color && name_color[i].pat && pattry(name_color[i].pat, file)) {
|
||||
return name_color[i].color;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* colorize_from_mode(char* file, const struct stat* sb)
|
||||
{
|
||||
struct stat sb2;
|
||||
|
||||
switch (sb->st_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
return mode_color[COL_DI];
|
||||
case S_IFLNK: {
|
||||
if (strpfx(mode_color[COL_LN], "target")) {
|
||||
if (stat(file, &sb2) == -1) {
|
||||
return mode_color[COL_OR];
|
||||
}
|
||||
return get_color(file, &sb2);
|
||||
}
|
||||
}
|
||||
case S_IFIFO:
|
||||
return mode_color[COL_PI];
|
||||
case S_IFSOCK:
|
||||
return mode_color[COL_SO];
|
||||
case S_IFBLK:
|
||||
return mode_color[COL_BD];
|
||||
case S_IFCHR:
|
||||
return mode_color[COL_CD];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sb->st_mode & S_ISUID) {
|
||||
return mode_color[COL_SU];
|
||||
} else if (sb->st_mode & S_ISGID) {
|
||||
return mode_color[COL_SG];
|
||||
// tw ow st ??
|
||||
} else if (sb->st_mode & S_IXUSR) {
|
||||
return mode_color[COL_EX];
|
||||
}
|
||||
|
||||
/* Check for suffix alias */
|
||||
size_t len = strlen(file);
|
||||
/* shortest valid suffix format is a.b */
|
||||
if (len > 2) {
|
||||
const char* suf = file + len - 1;
|
||||
while (suf > file + 1) {
|
||||
if (suf[-1] == '.') {
|
||||
if (sufaliastab->getnode(sufaliastab, suf)) {
|
||||
return mode_color[COL_SA];
|
||||
}
|
||||
break;
|
||||
}
|
||||
suf--;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct {
|
||||
char** array;
|
||||
size_t len;
|
||||
size_t size;
|
||||
} ftb_compcap;
|
||||
|
||||
// Usage:
|
||||
// initialize fzf-tab-generate-compcap -i
|
||||
// output to _ftb_compcap fzf-tab-generate-compcap -o
|
||||
// add a entry fzf-tab-generate-compcap word desc opts
|
||||
static int bin_fzf_tab_compcap_generate(char* nam, char** args, Options ops, UNUSED(int func))
|
||||
{
|
||||
if (OPT_ISSET(ops, 'o')) {
|
||||
// write final result to _ftb_compcap
|
||||
setaparam("_ftb_compcap", ftb_compcap.array);
|
||||
ftb_compcap.array = NULL;
|
||||
return 0;
|
||||
} else if (OPT_ISSET(ops, 'i')) {
|
||||
// init
|
||||
if (ftb_compcap.array)
|
||||
freearray(ftb_compcap.array);
|
||||
ftb_compcap.array = zshcalloc(1024 * sizeof(char*));
|
||||
ftb_compcap.len = 0, ftb_compcap.size = 1024;
|
||||
return 0;
|
||||
}
|
||||
if (ftb_compcap.array == NULL) {
|
||||
zwarnnam(nam, "please initialize it first");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get paramaters
|
||||
char **words = getaparam(args[0]), **dscrs = getaparam(args[1]), *opts = getsparam(args[2]);
|
||||
if (!words || !dscrs || !opts) {
|
||||
zwarnnam(nam, "wrong argument");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *bs = metafy("\2", 1, META_DUP), *nul = metafy("\0word\0", 6, META_DUP);
|
||||
size_t dscrs_cnt = arrlen(dscrs);
|
||||
|
||||
for (int i = 0; words[i]; i++) {
|
||||
// TODO: replace '\n'
|
||||
char* buffer = zshcalloc(256 * sizeof(char));
|
||||
char* dscr = i < dscrs_cnt ? dscrs[i] : words[i];
|
||||
|
||||
buffer = ftb_strcat(buffer, 5, dscr, bs, opts, nul, words[i]);
|
||||
ftb_compcap.array[ftb_compcap.len++] = buffer;
|
||||
|
||||
if (ftb_compcap.len == ftb_compcap.size) {
|
||||
ftb_compcap.array
|
||||
= zrealloc(ftb_compcap.array, (1024 + ftb_compcap.size) * sizeof(char*));
|
||||
ftb_compcap.size += 1024;
|
||||
memset(ftb_compcap.array + ftb_compcap.size - 1024, 0, 1024 * sizeof(char*));
|
||||
}
|
||||
}
|
||||
|
||||
zsfree(bs);
|
||||
zsfree(nul);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cat n string, return the pointer to the new string
|
||||
// `size` is the size of dst
|
||||
// dst will be reallocated if is not big enough
|
||||
char* ftb_strcat(char* dst, int n, ...)
|
||||
{
|
||||
va_list valist;
|
||||
va_start(valist, n);
|
||||
|
||||
char* final = zrealloc(dst, 128);
|
||||
size_t size = 128, max_len = 128 - 1;
|
||||
dst = final;
|
||||
|
||||
for (int i = 0, idx = 0; i < n; i++) {
|
||||
char* src = va_arg(valist, char*);
|
||||
for (; *src != '\0'; dst++, src++, idx++) {
|
||||
if (idx == max_len) {
|
||||
size += size / 2;
|
||||
final = zrealloc(final, size);
|
||||
max_len = size - 1;
|
||||
dst = &final[idx];
|
||||
}
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
*dst = '\0';
|
||||
va_end(valist);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
// accept an
|
||||
char** fzf_tab_colorize(char* file)
|
||||
{
|
||||
// TODO: can avoid so many zalloc here?
|
||||
file = unmeta(file);
|
||||
|
||||
struct stat sb;
|
||||
if (lstat(file, &sb) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* suffix = "";
|
||||
if (isset(opt_list_type)) {
|
||||
suffix = get_suffix(file, &sb);
|
||||
}
|
||||
const char* color = get_color(file, &sb);
|
||||
|
||||
char* symlink = "";
|
||||
const char* symcolor = "";
|
||||
if ((sb.st_mode & S_IFMT) == S_IFLNK) {
|
||||
symlink = zalloc(PATH_MAX);
|
||||
int end = readlink(file, symlink, PATH_MAX);
|
||||
symlink[end] = '\0';
|
||||
if (stat(file, &sb) == -1) {
|
||||
symcolor = mode_color[COL_OR];
|
||||
} else {
|
||||
char tmp[PATH_MAX];
|
||||
realpath(file, tmp);
|
||||
symcolor = get_color(file, &sb);
|
||||
}
|
||||
}
|
||||
|
||||
char** reply = zshcalloc((4 + 1) * sizeof(char*));
|
||||
|
||||
if (strlen(color) != 0) {
|
||||
reply[0] = zalloc(128);
|
||||
reply[1] = zalloc(128);
|
||||
sprintf(reply[0], "%s%s%s", mode_color[COL_LC], color, mode_color[COL_RC]);
|
||||
sprintf(reply[1], "%s%s%s", mode_color[COL_LC], "0", mode_color[COL_RC]);
|
||||
} else {
|
||||
reply[0] = ztrdup("");
|
||||
reply[1] = ztrdup("");
|
||||
}
|
||||
|
||||
reply[2] = ztrdup(suffix);
|
||||
|
||||
if (symlink[0] != '\0') {
|
||||
reply[3] = zalloc(PATH_MAX);
|
||||
sprintf(reply[3], "%s%s%s%s%s%s%s", mode_color[COL_LC], symcolor, mode_color[COL_RC],
|
||||
symlink, mode_color[COL_LC], "0", mode_color[COL_RC]);
|
||||
free(symlink);
|
||||
} else {
|
||||
reply[3] = ztrdup("");
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
reply[i] = metafy(reply[i], -1, META_REALLOC);
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
static int bin_fzf_tab_candidates_generate(char* nam, char** args, Options ops, UNUSED(int func))
|
||||
{
|
||||
if (OPT_ISSET(ops, 'i')) {
|
||||
// compile list_colors pattern
|
||||
if (*args == NULL) {
|
||||
zwarnnam(nam, "please specify an array");
|
||||
return 1;
|
||||
} else {
|
||||
char** array = getaparam(*args);
|
||||
return compile_patterns(nam, array);
|
||||
}
|
||||
}
|
||||
|
||||
char **ftb_compcap = getaparam("_ftb_compcap"), **group_colors = getaparam("group_colors"),
|
||||
*default_color = getsparam("default_color"), *prefix = getsparam("prefix");
|
||||
|
||||
size_t group_colors_len = arrlen(group_colors);
|
||||
size_t ftb_compcap_len = arrlen(ftb_compcap);
|
||||
|
||||
char *bs = metafy("\b", 1, META_DUP), *nul = metafy("\0", 1, META_DUP),
|
||||
*soh = metafy("\2", 1, META_DUP);
|
||||
|
||||
char **candidates = zshcalloc(sizeof(char*) * (ftb_compcap_len + 1)),
|
||||
*filepath = zshcalloc(PATH_MAX * sizeof(char)), *dpre = zshcalloc(128),
|
||||
*dsuf = zshcalloc(128);
|
||||
|
||||
char* first_word = zshcalloc(512 * sizeof(char));
|
||||
int same_word = 1;
|
||||
|
||||
for (int i = 0; i < ftb_compcap_len; i++) {
|
||||
char *word = "", *group = NULL, *realdir = NULL;
|
||||
strcpy(dpre, "");
|
||||
strcpy(dsuf, "");
|
||||
|
||||
// extract all the variables what we need
|
||||
char** compcap = sepsplit(ftb_compcap[i], soh, 1, 0);
|
||||
char* desc = compcap[0];
|
||||
char** info = sepsplit(compcap[1], nul, 1, 0);
|
||||
|
||||
for (int j = 0; info[j]; j += 2) {
|
||||
if (!strcmp(info[j], "word")) {
|
||||
word = info[j + 1];
|
||||
// unquote word
|
||||
parse_subst_string(word);
|
||||
remnulargs(word);
|
||||
untokenize(word);
|
||||
} else if (!strcmp(info[j], "group")) {
|
||||
group = info[j + 1];
|
||||
} else if (!strcmp(info[j], "realdir")) {
|
||||
realdir = info[j + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// check if all the words are the same
|
||||
if (i == 0) {
|
||||
first_word = ftb_strcat(first_word, 1, word);
|
||||
} else if (same_word && strcmp(word, first_word) != 0) {
|
||||
same_word = 0;
|
||||
}
|
||||
|
||||
// add character and color to describe the type of the files
|
||||
if (realdir) {
|
||||
filepath = ftb_strcat(filepath, 2, realdir, word);
|
||||
char** reply = fzf_tab_colorize(filepath);
|
||||
if (reply != NULL) {
|
||||
dpre = ftb_strcat(dpre, 2, reply[1], reply[0]);
|
||||
if (reply[3][0] != '\0') {
|
||||
dsuf = ftb_strcat(dsuf, 4, reply[1], reply[2], " -> ", reply[3]);
|
||||
} else {
|
||||
dsuf = ftb_strcat(dsuf, 2, reply[1], reply[2]);
|
||||
}
|
||||
if (dpre[0] != '\0') {
|
||||
setiparam("colorful", 1);
|
||||
}
|
||||
freearray(reply);
|
||||
}
|
||||
}
|
||||
|
||||
char* result = zshcalloc(256 * sizeof(char));
|
||||
|
||||
// add color to description if they have group index
|
||||
if (group) {
|
||||
// use strtol ?
|
||||
int group_index = atoi(group);
|
||||
char* color = group_index >= group_colors_len ? "" : group_colors[group_index - 1];
|
||||
// add prefix
|
||||
result = ftb_strcat(
|
||||
result, 11, group, bs, color, prefix, dpre, nul, group, bs, desc, nul, dsuf);
|
||||
} else {
|
||||
result = ftb_strcat(result, 6, default_color, dpre, nul, desc, nul, dsuf);
|
||||
}
|
||||
// quotedzputs(result, stdout);
|
||||
// putchar('\n');
|
||||
candidates[i] = result;
|
||||
|
||||
freearray(info);
|
||||
freearray(compcap);
|
||||
}
|
||||
|
||||
setaparam("tcandidates", candidates);
|
||||
setiparam("same_word", same_word);
|
||||
zsfree(dpre);
|
||||
zsfree(dsuf);
|
||||
zsfree(filepath);
|
||||
zsfree(first_word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("fzf-tab-compcap-generate", 0, bin_fzf_tab_compcap_generate, 0, -1, 0, "io", NULL),
|
||||
BUILTIN("fzf-tab-candidates-generate", 0, bin_fzf_tab_candidates_generate, 0, -1, 0, "i", NULL),
|
||||
};
|
||||
|
||||
static struct paramdef patab[] = {
|
||||
STRPARAMDEF("FZF_TAB_MODULE_VERSION", &fzf_tab_module_version),
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static struct features module_features = {
|
||||
bintab, sizeof(bintab) / sizeof(*bintab),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
patab, sizeof(patab) / sizeof(*patab),
|
||||
0,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
int setup_(UNUSED(Module m)) { return 0; }
|
||||
|
||||
int features_(Module m, char*** features)
|
||||
{
|
||||
*features = featuresarray(m, &module_features);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enables_(Module m, int** enables) { return handlefeatures(m, &module_features, enables); }
|
||||
|
||||
int boot_(UNUSED(Module m))
|
||||
{
|
||||
fzf_tab_module_version = ztrdup("0.2.2");
|
||||
// different zsh version may have different value of list_type's index
|
||||
// so query it dynamically
|
||||
opt_list_type = optlookup("list_types");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cleanup_(UNUSED(Module m)) { return setfeatureenables(m, &module_features, NULL); }
|
||||
|
||||
int finish_(UNUSED(Module m))
|
||||
{
|
||||
printf("fzf-tab module unloaded.\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
name=aloxaf/fzftab
|
||||
link=dynamic
|
||||
load=no
|
||||
|
||||
autofeatures="b:fzf-tab-colorize p:FZF_TAB_MODULE_VERSION"
|
||||
|
||||
objects="fzftab.o"
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,742 @@
|
|||
/*
|
||||
* 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 */
|
||||
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
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,701 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
#
|
||||
# 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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,116 @@
|
|||
#! /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
|
||||
|
|
@ -0,0 +1,468 @@
|
|||
#!/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
|
|
@ -0,0 +1,955 @@
|
|||
/*
|
||||
* 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
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
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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));
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# 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)
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#
|
||||
# {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 "};"
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
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
|
|
@ -0,0 +1,147 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// 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"
|
||||
|
|
@ -0,0 +1,900 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Makefile
|
||||
*.tmp
|
||||
*.swp
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
DISTFILES_SRC='
|
||||
'
|
||||
|
|
@ -0,0 +1,790 @@
|
|||
#
|
||||
# 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
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# 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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue