diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.gitattributes b/dots/.config/zsh/config/plugins/fzf-tab/.gitattributes
deleted file mode 100644
index 0f952061..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-modules/** linguist-vendored
-modules/Src/aloxaf/*.c -linguist-vendored
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/bug_report.md b/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index e804a3af..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,42 +0,0 @@
----
-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 Tab, 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 Tab
-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).
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/feature_request.md b/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 524940e5..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-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.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/question.md b/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index 9d2f92cc..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-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.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.github/workflows/ci.yaml b/dots/.config/zsh/config/plugins/fzf-tab/.github/workflows/ci.yaml
deleted file mode 100644
index 893f8a45..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.github/workflows/ci.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-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
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/.gitignore b/dots/.config/zsh/config/plugins/fzf-tab/.gitignore
deleted file mode 100644
index 416cfaac..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.zwc
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/LICENSE b/dots/.config/zsh/config/plugins/fzf-tab/LICENSE
deleted file mode 100644
index a3c39ebb..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-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.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/README.md b/dots/.config/zsh/config/plugins/fzf-tab/README.md
deleted file mode 100644
index 63981219..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/README.md
+++ /dev/null
@@ -1,138 +0,0 @@
-# fzf-tab
-
-[![CI](https://github.com/Aloxaf/fzf-tab/workflows/ci/badge.svg)](https://github.com/Aloxaf/fzf-tab/actions?query=workflow%3Aci)
-[![GitHub license](https://img.shields.io/github/license/Aloxaf/fzf-tab)](https://github.com/Aloxaf/fzf-tab/blob/master/LICENSE)
-
-Replace zsh's default completion selection menu with fzf!
-
-[![asciicast](https://asciinema.org/a/293849.svg)](https://asciinema.org/a/293849)
-
-
-**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)
-
-
-
-# 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)!!**
-
-### 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 Tab as usual~
-
-Available keybindings:
-
-- Ctrl+Space: select multiple results, can be configured by `fzf-bindings` tag
-
-- F1/F2: switch between groups, can be configured by `switch-group` tag
-
-- /: 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)
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.plugin.zsh b/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.plugin.zsh
deleted file mode 100644
index f78964c2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.plugin.zsh
+++ /dev/null
@@ -1,3 +0,0 @@
-0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
-0="${${(M)0:#/*}:-$PWD/$0}"
-source "${0:A:h}/fzf-tab.zsh"
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.zsh b/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.zsh
deleted file mode 100644
index 24e04556..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/fzf-tab.zsh
+++ /dev/null
@@ -1,399 +0,0 @@
-# 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=__
-
- # just delegate and leave if any of -O, -A or -D are given or fzf-tab is not enabled
- if (( $#_oad != 0 || ! IN_FZF_TAB )); 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
-
- # store $curcontext for furthur usage
- _ftb_curcontext=${curcontext#:}
-
- # 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
- if [[ ${OSTYPE} == darwin* ]]; then
- MACOS=true
- 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)
- popd
-}
-
-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'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-colorize b/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-colorize
deleted file mode 100644
index 3b1909bd..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-colorize
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-fzf b/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-fzf
deleted file mode 100755
index 19adf046..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-fzf
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/hint/zsh
-
-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 descriptoin
-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
-"
-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
-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 -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:=$(( lines > LINES / 3 * 2 ? LINES / 3 * 2 : lines ))} \
- --layout=reverse \
- --multi \
- --nth=2,3 \
- --print-query \
- --query=$_ftb_query \
- --tiebreak=begin \
- ${fzf_preview:+--preview=$ftb_preview_init$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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-complist b/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-complist
deleted file mode 100644
index 42dd0339..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-complist
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-header b/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-header
deleted file mode 100644
index a54fee12..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-header
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-query b/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-query
deleted file mode 100644
index 4f546049..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/-ftb-generate-query
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-switch-group b/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-switch-group
deleted file mode 100644
index 8d069567..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-switch-group
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-tmux-popup b/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-tmux-popup
deleted file mode 100755
index 68d1e296..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/ftb-tmux-popup
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/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
-
-zstyle -a ":fzf-tab:$_ftb_curcontext" popup-pad popup_pad || popup_pad=(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
-
-# calculate the popup height and y position
-if (( cursor_y * 2 > window_height )); then
- # show above the cursor
- popup_height=$(( min(comp_lines + 4, cursor_y - window_top) ))
- popup_y=$cursor_y
-else
- # show below the cursor
- popup_height=$(( min(comp_lines + 4, window_height - cursor_y + window_top - 1) ))
- popup_y=$(( cursor_y + popup_height + 1 ))
- fzf_opts+=(--layout=reverse)
-fi
-
-# calculate the popup width and x position
-popup_width=$(( min(comp_length + 5, 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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/LICENSE b/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/LICENSE
deleted file mode 100644
index 940b4c2b..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-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.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/README.md b/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/README.md
deleted file mode 100644
index 7736ce66..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/README.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# zsh-ls-colors
-
-![Demo screenshot](https://raw.githubusercontent.com/xPMo/zsh-ls-colors/image/demo.png)
-
-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
-
- ...
-}
-```
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/demo b/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/demo
deleted file mode 100755
index a5e468d2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/demo
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/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
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/ls-colors.zsh b/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/ls-colors.zsh
deleted file mode 100644
index 276a7bb7..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/lib/zsh-ls-colors/ls-colors.zsh
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/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:
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/.cvsignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/.cvsignore
deleted file mode 100644
index 95cdc587..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/.cvsignore
+++ /dev/null
@@ -1,16 +0,0 @@
-Makefile
-META-FAQ
-config.cache
-config.h
-config.h.in
-config.log
-config.modules
-config.modules.sh
-config.status
-configure
-cscope.out
-stamp-h
-stamp-h.in
-autom4te.cache
-*.swp
-.git
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/.distfiles b/dots/.config/zsh/config/plugins/fzf-tab/modules/.distfiles
deleted file mode 100644
index d618a779..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/.distfiles
+++ /dev/null
@@ -1,4 +0,0 @@
-DISTFILES_SRC='
- META-FAQ
- configure config.h.in stamp-h.in
-'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/.editorconfig b/dots/.config/zsh/config/plugins/fzf-tab/modules/.editorconfig
deleted file mode 100644
index 808512ec..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/.editorconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-# Top-most editorconfig file
-
-root = true
-
-[*]
-end_of_line = lf
-tab_width = 8
-indent_size = 2
-indent_style = tab
-
-[ChangeLog]
-indent_size = 8
-
-[*.[ch]]
-indent_size = 4
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/.gitignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/.gitignore
deleted file mode 100644
index f4201365..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/.gitignore
+++ /dev/null
@@ -1,155 +0,0 @@
-Makefile
-tags
-TAGS
-*.o
-*.o.c
-*.orig
-*.a
-*.so
-*.dll
-*~
-.*.sw?
-\#*
-
-/META-FAQ
-/config.cache
-/config.h
-/config.log
-/config.modules
-/config.modules.sh
-/config.status
-/config.status.lineno
-/cscope.out
-/stamp-h
-/autom4te.cache
-
-Config/defs.mk
-
-CVS
-.#*
-
-Doc/help
-Doc/help.txt
-Doc/help/[_a-zA-Z0-9]*
-
-Doc/intro.pdf
-Doc/intro.ps
-Doc/intro.a4.pdf
-Doc/intro.a4.ps
-Doc/intro.us.pdf
-Doc/intro.us.ps
-Doc/version.yo
-Doc/texi2html.conf
-Doc/zsh*.1
-Doc/zsh.texi
-Doc/zsh.info*
-Doc/*.html
-Doc/zsh.aux
-Doc/zsh.toc
-Doc/zsh.cp
-Doc/zsh.cps
-Doc/zsh.fn
-Doc/zsh.fns
-Doc/zsh.ky
-Doc/zsh.kys
-Doc/zsh.pg
-Doc/zsh.pgs
-Doc/zsh.vr
-Doc/zsh.vrs
-Doc/zsh.log
-Doc/zsh.dvi
-Doc/zsh_a4.dvi
-Doc/zsh_us.dvi
-Doc/zsh.tp
-Doc/zsh.tps
-Doc/zsh.idx
-Doc/zsh_*.ps
-Doc/infodir
-Doc/zsh.pdf
-Doc/zsh_a4.pdf
-Doc/zsh_us.pdf
-
-Doc/Zsh/modlist.yo
-Doc/Zsh/modmenu.yo
-Doc/Zsh/manmodmenu.yo
-
-Etc/FAQ
-Etc/FAQ.html
-
-Src/*.epro
-Src/*.export
-Src/*.mdh
-Src/*.mdh.tmp
-Src/*.mdhi
-Src/*.mdhs
-Src/*.syms
-Src/Makemod.in
-Src/Makemod
-Src/[_a-zA-Z0-9]*.pro
-Src/ansi2knr
-Src/bltinmods.list
-Src/cscope.out
-Src/libzsh.so*
-Src/modules-bltin
-Src/modules.index
-Src/modules.index.tmp
-Src/modules.stamp
-Src/patchlevel.h
-Src/sigcount.h
-Src/signames.c
-Src/signames2.c
-Src/stamp-modobjs
-Src/stamp-modobjs.tmp
-Src/tags
-Src/TAGS
-Src/version.h
-Src/zsh
-Src/zsh.exe
-Src/zshcurses.h
-Src/zshpaths.h
-Src/zshterm.h
-Src/zshxmods.h
-
-Src/Builtins/Makefile.in
-Src/Builtins/*.export
-Src/Builtins/so_locations
-Src/Builtins/*.pro
-Src/Builtins/*.epro
-Src/Builtins/*.syms
-Src/Builtins/*.mdh
-Src/Builtins/*.mdhi
-Src/Builtins/*.mdhs
-Src/Builtins/*.mdh.tmp
-Src/Builtins/rlimits.h
-
-Src/Modules/Makefile.in
-Src/Modules/*.export
-Src/Modules/so_locations
-Src/Modules/*.pro
-Src/Modules/*.epro
-Src/Modules/*.syms
-Src/Modules/*.mdh
-Src/Modules/*.mdhi
-Src/Modules/*.mdhs
-Src/Modules/*.mdh.tmp
-Src/Modules/errnames.c
-Src/Modules/errcount.h
-Src/Modules/curses_keys.h
-
-Src/Zle/Makefile.in
-Src/Zle/*.export
-Src/Zle/so_locations
-Src/Zle/*.pro
-Src/Zle/*.epro
-Src/Zle/*.syms
-Src/Zle/*.mdh
-Src/Zle/*.mdhi
-Src/Zle/*.mdhs
-Src/Zle/*.mdh.tmp
-Src/Zle/thingies.list
-Src/Zle/widgets.list
-Src/Zle/zle_things.h
-Src/Zle/zle_widget.h
-
-Test/*.tmp
-/.project
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/.preconfig b/dots/.config/zsh/config/plugins/fzf-tab/modules/.preconfig
deleted file mode 100755
index f9729bd9..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/.preconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /bin/sh
-
-set -e
-
-autoconf
-autoheader
-echo > stamp-h.in
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.cvsignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.cvsignore
deleted file mode 100644
index dd265a71..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-defs.mk
-*.swp
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.distfiles b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.distfiles
deleted file mode 100644
index f03668b3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/.distfiles
+++ /dev/null
@@ -1,2 +0,0 @@
-DISTFILES_SRC='
-'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/aczshoot.m4 b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/aczshoot.m4
deleted file mode 100644
index 3b90c6c7..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/aczshoot.m4
+++ /dev/null
@@ -1,8 +0,0 @@
-AC_DEFUN([zsh_OOT],
-[
-AC_CHECK_HEADERS(stdarg.h varargs.h termios.h termio.h)
-
-AC_TYPE_SIGNAL
-
-AC_DEFINE([ZSH_OOT_MODULE], [], [Out-of-tree module])
-])
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/clean.mk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/clean.mk
deleted file mode 100644
index 918a84ff..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/clean.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Makefile fragment for cleanup
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-mostlyclean: mostlyclean-recursive mostlyclean-here
-clean: clean-recursive clean-here
-distclean: distclean-recursive distclean-here
-realclean: realclean-recursive realclean-here
-
-mostlyclean-here:
-clean-here: mostlyclean-here
-distclean-here: clean-here
-realclean-here: distclean-here
-
-mostlyclean-recursive clean-recursive distclean-recursive realclean-recursive:
- @subdirs='$(SUBDIRS)'; if test -n "$$subdirs"; then \
- target=`echo $@ | sed s/-recursive//`; \
- for subdir in $$subdirs; do \
- (cd $$subdir && $(MAKE) $(MAKEDEFS) $$target) || exit 1; \
- done; \
- fi
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/config.mk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/config.mk
deleted file mode 100644
index fd9abf6a..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/config.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Makefile fragment for building Makefiles
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-config: Makefile
- @subdirs='$(SUBDIRS)'; for subdir in $$subdirs; do \
- (cd $$subdir && $(MAKE) $(MAKEDEFS) $@) || exit 1; \
- done
-
-CONFIG_INCS = \
-$(dir_top)/Config/clean.mk $(dir_top)/Config/config.mk \
-$(dir_top)/Config/defs.mk $(dir_top)/Config/version.mk
-
-Makefile: Makefile.in $(dir_top)/config.status $(CONFIG_INCS)
- cd $(dir_top) && \
- $(SHELL) ./config.status `echo $(subdir)/$@ | sed 's%^./%%'`
-
-$(dir_top)/Config/defs.mk: $(sdir_top)/Config/defs.mk.in $(dir_top)/config.status
- cd $(dir_top) && \
- $(SHELL) ./config.status Config/defs.mk
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/defs.mk.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/defs.mk.in
deleted file mode 100644
index 2bc17482..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/defs.mk.in
+++ /dev/null
@@ -1,114 +0,0 @@
-#
-# Basic Makefile definitions
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-# fundamentals
-SHELL = /bin/sh
-@SET_MAKE@
-EXEEXT = @EXEEXT@
-
-# headers
-ZSH_CURSES_H = @ZSH_CURSES_H@
-ZSH_TERM_H = @ZSH_TERM_H@
-
-# install basename
-tzsh = @tzsh@
-
-# installation directories
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-libdir = @libdir@
-MODDIR = $(libdir)/$(tzsh)/$(VERSION)
-infodir = @infodir@
-mandir = @mandir@
-datarootdir = @datarootdir@
-datadir = @datadir@
-fndir = @fndir@
-fixed_sitefndir = @fixed_sitefndir@
-sitefndir = @sitefndir@
-scriptdir = @scriptdir@
-sitescriptdir = @sitescriptdir@
-htmldir = @htmldir@
-runhelpdir = @runhelpdir@
-runhelp = @runhelp@
-
-# compilation
-CC = @CC@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-DEFS = @DEFS@
-CFLAGS = @CFLAGS@
-LDFLAGS = @LDFLAGS@
-EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
-DLCFLAGS = @DLCFLAGS@
-DLLDFLAGS = @DLLDFLAGS@
-LIBLDFLAGS = @LIBLDFLAGS@
-EXELDFLAGS = @EXELDFLAGS@
-LIBS = @LIBS@
-DL_EXT = @DL_EXT@
-DLLD = @DLLD@
-EXPOPT = @EXPOPT@
-IMPOPT = @IMPOPT@
-
-# utilities
-AWK = @AWK@
-ANSI2KNR = @ANSI2KNR@
-YODL = @YODL@ @YODL_OPTIONS@
-YODL2TXT = @YODL@2txt
-YODL2HTML = @YODL@2html
-
-# install utility
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-
-# variables used in determining what to install
-FUNCTIONS_SUBDIRS = @FUNCTIONS_SUBDIRS@
-
-# Additional fpath entries (eg. for vendor specific directories).
-additionalfpath = @additionalfpath@
-
-# flags passed to recursive makes in subdirectories
-MAKEDEFS = \
-prefix='$(prefix)' exec_prefix='$(exec_prefix)' bindir='$(bindir)' \
-libdir='$(libdir)' MODDIR='$(MODDIR)' infodir='$(infodir)' mandir='$(mandir)' \
-datadir='$(datadir)' fndir='$(fndir)' htmldir='$(htmldir)' runhelpdir='$(runhelpdir)' \
-CC='$(CC)' CPPFLAGS='$(CPPFLAGS)' DEFS='$(DEFS)' CFLAGS='$(CFLAGS)' \
-LDFLAGS='$(LDFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \
-DLCFLAGS='$(DLCFLAGS)' DLLDFLAGS='$(DLLDFLAGS)' \
-LIBLDFLAGS='$(LIBLDFLAGS)' EXELDFLAGS='$(EXELDFLAGS)' \
-LIBS='$(LIBS)' DL_EXT='$(DL_EXT)' DLLD='$(DLLD)' \
-AWK='$(AWK)' ANSI2KNR='$(ANSI2KNR)' \
-YODL='$(YODL)' YODL2TXT='$(YODL2TXT)' YODL2HTML='$(YODL2HTML)' \
-FUNCTIONS_INSTALL='$(FUNCTIONS_INSTALL)' tzsh='$(tzsh)'
-
-# override built-in suffix list
-.SUFFIXES:
-
-# parallel build is not supported (pmake, gmake)
-.NOTPARALLEL:
-
-# parallel build is not supported (dmake)
-.NO_PARALLEL:
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/installfns.sh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/installfns.sh
deleted file mode 100755
index 149f359c..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/installfns.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/sh
-
-fndir=$DESTDIR$fndir
-scriptdir=$DESTDIR$scriptdir
-
-/bin/sh $sdir_top/mkinstalldirs $fndir || exit 1;
-
-allfuncs="`grep ' functions=.' ${dir_top}/config.modules |
- sed -e '/^#/d' -e '/ link=no/d' -e 's/^.* functions=//'`"
-
-allfuncs="`cd $sdir_top; echo ${allfuncs}`"
-
-test -d installfnsdir || mkdir installfnsdir
-
-# We now have a list of files, but we need to use `test -f' to check
-# (1) the glob got expanded (2) we are not looking at directories.
-for file in $allfuncs; do
- if test -f $sdir_top/$file; then
- case "$file" in
- */CVS/*) continue;;
- esac
- if test x$FUNCTIONS_SUBDIRS != x && test x$FUNCTIONS_SUBDIRS != xno; then
- case "$file" in
- Completion/*/*)
- subdir="`echo $file | sed -e 's%/[^/]*/[^/]*$%%'`"
- instdir="$fndir/$subdir"
- ;;
- Completion/*)
- instdir="$fndir/Completion"
- ;;
- Scripts/*)
- instdir="$scriptdir"
- ;;
- *)
- subdir="`echo $file | sed -e 's%/[^/]*$%%' -e 's%^Functions/%%'`"
- instdir="$fndir/$subdir"
- ;;
- esac
- else
- case "$file" in
- Scripts/*)
- instdir="$scriptdir"
- ;;
- *)
- instdir="$fndir"
- ;;
- esac
- fi
- basename=`basename $file`
- ok=0
- if test -d $instdir || /bin/sh $sdir_top/mkinstalldirs $instdir; then
- if sed "s|@runhelpdir@|$runhelpdir|" <$sdir_top/$file \
- >installfnsdir/$basename; then
- if $INSTALL_DATA installfnsdir/$basename $instdir; then
- ok=1
- fi
- fi
- fi
- case $ok in
- 0)
- rm -rf installfnsdir
- exit 1
- ;;
- esac
- read line < $sdir_top/$file
- case "$line" in
- '#!'*)
- chmod +x $instdir/`echo $file | sed -e 's%^.*/%%'`
- ;;
- esac
- fi
-done
-
-rm -rf installfnsdir
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/uninstallfns.sh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/uninstallfns.sh
deleted file mode 100755
index 7c223889..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/uninstallfns.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-fndir=$DESTDIR$fndir
-scriptdir=$DESTDIR$scriptdir
-
-allfuncs="`grep ' functions=' ${dir_top}/config.modules |
- sed -e '/^#/d' -e '/ link=no/d' -e 's/^.* functions=//'`"
-
-allfuncs="`cd ${sdir_top}; echo ${allfuncs}`"
-
-case $fndir in
- *$VERSION*)
- # Version specific function directory, safe to remove completely.
- rm -rf $fndir
- ;;
- *) # The following will only apply with a custom install directory
- # with no version information. This is rather undesirable.
- # But let's try and do the best we can.
- # We now have a list of files, but we need to use `test -f' to check
- # (1) the glob got expanded (2) we are not looking at directories.
- for file in $allfuncs; do
- case $file in
- Scripts/*)
- ;;
- *)
- if test -f $sdir_top/$file; then
- if test x$FUNCTIONS_SUBDIRS != x -a x$FUNCTIONS_SUBDIRS != xno; then
- file=`echo $file | sed -e 's%%^(Functions|Completion)/%'`
- rm -f $fndir/$file
- else
- bfile="`echo $file | sed -e 's%^.*/%%'`"
- rm -f "$fndir/$bfile"
- fi
- fi
- ;;
- esac
- done
- ;;
-esac
-
-case $scriptdir in
- *$VERSION*)
- # $scriptdir might be the parent of fndir.
- rm -rf $scriptdir
- ;;
- *) for file in $allfuncs; do
- case $file in
- Scripts/*)
- if test -f $sdir_top/$file; then
- bfile="`echo $file | sed -e 's%^.*/%%'`"
- rm -f "$scriptdir/$bfile"
- fi
- ;;
- esac
- done
- ;;
-esac
-
-exit 0
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/version.mk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/version.mk
deleted file mode 100644
index 0ebed5e7..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Config/version.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Makefile fragment for version numbers
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-# This must also serve as a shell script, so do not add spaces around the
-# `=' signs.
-
-VERSION=5.3.1-dev-0
-VERSION_DATE='December 22, 2016'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/LICENCE b/dots/.config/zsh/config/plugins/fzf-tab/modules/LICENCE
deleted file mode 100644
index 08fcf88f..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/LICENCE
+++ /dev/null
@@ -1,37 +0,0 @@
-Unless otherwise noted in the header of specific files, files in this
-distribution have the licence shown below.
-
-However, note that certain shell functions are licensed under versions
-of the GNU General Public Licence. Anyone distributing the shell as a
-binary including those files needs to take account of this. Search
-shell functions for "Copyright" for specific copyright information.
-None of the core functions are affected by this, so those files may
-simply be omitted.
-
---
-
-The Z Shell is copyright (c) 1992-2017 Paul Falstad, Richard Coleman,
-Zoltán Hidvégi, Andrew Main, Peter Stephenson, Sven Wischnowsky, and
-others. All rights reserved. Individual authors, whether or not
-specifically named, retain copyright in all changes; in what follows, they
-are referred to as `the Zsh Development Group'. This is for convenience
-only and this body has no legal status. The Z shell is distributed under
-the following licence; any provisions made in individual files take
-precedence.
-
-Permission is hereby granted, without written agreement and without
-licence or royalty fees, to use, copy, modify, and distribute this
-software and to distribute modified versions of this software for any
-purpose, provided that the above copyright notice and the following
-two paragraphs appear in all copies of this software.
-
-In no event shall the Zsh Development Group be liable to any party for
-direct, indirect, special, incidental, or consequential damages arising out
-of the use of this software and its documentation, even if the Zsh
-Development Group have been advised of the possibility of such damage.
-
-The Zsh Development Group specifically disclaim any warranties, including,
-but not limited to, the implied warranties of merchantability and fitness
-for a particular purpose. The software provided hereunder is on an "as is"
-basis, and the Zsh Development Group have no obligation to provide
-maintenance, support, updates, enhancements, or modifications.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Makefile.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/Makefile.in
deleted file mode 100644
index 4f9aa1aa..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Makefile.in
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for top level of zsh distribution
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-subdir = .
-dir_top = .
-SUBDIRS = Src
-
-@VERSION_MK@
-
-# source/build directories
-VPATH = @srcdir@
-sdir = @srcdir@
-sdir_top = @top_srcdir@
-INSTALL = @INSTALL@
-
-@DEFS_MK@
-
-# ========== DEPENDENCIES FOR BUILDING ==========
-
-# default target
-all: config.h config.modules
- cd Src && $(MAKE) $(MAKEDEFS) $@
-
-# prepare module configuration
-prep:
- @cd Src && $(MAKE) $(MAKEDEFS) $@
-
-# ========== DEPENDENCIES FOR CLEANUP ==========
-
-@CLEAN_MK@
-
-distclean-here:
- rm -f Makefile config.h config.status config.log config.cache config.modules config.modules.sh stamp-h Config/defs.mk
- rm -rf autom4te.cache
-
-realclean-here:
- cd $(sdir) && rm -f config.h.in stamp-h.in configure
-
-# ========== DEPENDENCIES FOR MAINTENANCE ==========
-
-@CONFIG_MK@
-
-config: config.h
-
-config.status: $(sdir)/configure
- $(SHELL) ./config.status --recheck
-
-$(sdir)/configure: $(sdir)/aclocal.m4 $(sdir)/aczsh.m4 $(sdir)/configure.ac
- cd $(sdir) && autoconf
-
-config.h: stamp-h
-stamp-h: $(sdir)/config.h.in config.status
- cd $(dir_top) && $(SHELL) ./config.status config.h $@
-
-config.modules: $(sdir)/config.h.in config.status config.modules.sh
- cd $(dir_top) && $(SHELL) ./config.status $@ && \
- $(SHELL) ./config.modules.sh
-
-$(sdir)/config.h.in: $(sdir)/stamp-h.in
-$(sdir)/stamp-h.in: $(sdir)/configure
- cd $(sdir) && autoheader
- echo > $(sdir)/stamp-h.in
-
-FORCE:
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/RECOMPILE_REQUEST b/dots/.config/zsh/config/plugins/fzf-tab/modules/RECOMPILE_REQUEST
deleted file mode 100644
index cbf32b01..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/RECOMPILE_REQUEST
+++ /dev/null
@@ -1 +0,0 @@
-1580588806
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.cvsignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.cvsignore
deleted file mode 100644
index 47b31911..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.cvsignore
+++ /dev/null
@@ -1,35 +0,0 @@
-*.dll
-*.epro
-*.export
-*.mdh
-*.mdh.tmp
-*.mdhi
-*.mdhs
-*.o
-*.o.c
-*.so
-*.swp
-*.syms
-Makefile
-Makemod.in Makemod
-[_a-zA-Z0-9]*.pro
-ansi2knr
-bltinmods.list
-cscope.out
-libzsh.so*
-modules-bltin
-modules.index
-modules.index.tmp
-modules.stamp
-patchlevel.h
-sigcount.h
-signames.c signames2.c
-stamp-modobjs
-stamp-modobjs.tmp
-tags TAGS
-version.h
-zsh
-zshcurses.h
-zshpaths.h
-zshterm.h
-zshxmods.h
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.distfiles b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.distfiles
deleted file mode 100644
index f03668b3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.distfiles
+++ /dev/null
@@ -1,2 +0,0 @@
-DISTFILES_SRC='
-'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.exrc b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.exrc
deleted file mode 100644
index 91d0b39e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.exrc
+++ /dev/null
@@ -1,2 +0,0 @@
-set ai
-set sw=4
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.indent.pro b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.indent.pro
deleted file mode 100644
index 1b41514f..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/.indent.pro
+++ /dev/null
@@ -1,27 +0,0 @@
---dont-format-comments
---procnames-start-lines
---no-parameter-indentation
---indent-level4
---line-comments-indentation4
---cuddle-else
---brace-indent0
---dont-star-comments
---blank-lines-after-declarations
---blank-lines-after-procedures
---no-blank-lines-after-commas
---comment-indentation33
---declaration-comment-column33
---no-comment-delimiters-on-blank-lines
---continuation-indentation4
---case-indentation0
---else-endif-column33
---no-space-after-casts
---no-blank-before-sizeof
---declaration-indentation0
---continue-at-parentheses
---no-space-after-function-call-names
---swallow-optional-blank-lines
---dont-space-special-semicolon
---tab-size8
---line-length132
---braces-on-if-line
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makefile.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makefile.in
deleted file mode 100644
index 2987b649..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makefile.in
+++ /dev/null
@@ -1,164 +0,0 @@
-#
-# Makefile for Src subdirectory
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-subdir = Src
-dir_top = ..
-SUBDIRS =
-
-@VERSION_MK@
-
-# source/build directories
-VPATH = @srcdir@
-sdir = @srcdir@
-sdir_top = @top_srcdir@
-INSTALL = @INSTALL@
-LN = @LN@
-
-@DEFS_MK@
-
-sdir_src = $(sdir)
-dir_src = .
-
-# ========= DEPENDENCIES FOR BUILDING ==========
-
-LINK = $(CC) $(LDFLAGS) $(EXELDFLAGS) $(EXTRA_LDFLAGS) -o $@
-DLLINK = $(DLLD) $(LDFLAGS) $(LIBLDFLAGS) $(DLLDFLAGS) -o $@
-
-all: zsh.export modules
-.PHONY: all
-
-modules: headers
-.PHONY: modules
-
-L = @L@
-
-LSTMP =
-LLIST =
-NSTMP = stamp-modobjs
-NLIST = `cat stamp-modobjs`
-
-LIBZSH = libzsh-$(VERSION).$(DL_EXT)
-NIBZSH =
-INSTLIB = @INSTLIB@
-UNINSTLIB = @UNINSTLIB@
-
-ZSH_EXPORT = $(EXPOPT)zsh.export
-ZSH_NXPORT =
-ENTRYOBJ = modentry..o
-NNTRYOBJ =
-
-LDRUNPATH = LD_RUN_PATH=$(libdir)/$(tzsh)
-NDRUNPATH =
-
-EXTRAZSHOBJS = @EXTRAZSHOBJS@
-
-stamp-modobjs: modobjs
- @if cmp -s stamp-modobjs.tmp stamp-modobjs; then \
- rm -f stamp-modobjs.tmp; \
- echo "\`stamp-modobjs' is up to date."; \
- else \
- mv -f stamp-modobjs.tmp stamp-modobjs; \
- echo "Updated \`stamp-modobjs'."; \
- fi
-
-modobjs: headers rm-modobjs-tmp
-.PHONY: modobjs
-
-rm-modobjs-tmp:
- rm -f stamp-modobjs.tmp
-.PHONY: rm-modobjs-tmp
-
-@CONFIG_MK@
-
-Makemod: $(CONFIG_INCS) $(dir_top)/config.modules
- @case $(sdir_top) in \
- /*) top_srcdir=$(sdir_top) ;; \
- *) top_srcdir=$(subdir)/$(sdir_top) ;; \
- esac; \
- export top_srcdir; \
- echo 'cd $(dir_top) && $(SHELL)' \
- '$$top_srcdir/$(subdir)/mkmakemod.sh $(subdir) Makemod'; \
- cd $(dir_top) && \
- $(SHELL) $$top_srcdir/$(subdir)/mkmakemod.sh $(subdir) Makemod
-prep: Makemod
- @$(MAKE) -f Makemod $(MAKEDEFS) prep || rm -f Makemod
-.PHONY: prep
-
-FORCE:
-.PHONY: FORCE
-
-# ========== LINKING IN MODULES ==========
-
-mymods.conf:
- @echo Linking with the standard modules.
-
-modules: $(@E@NTRYOBJ)
-
-$(ENTRYOBJ): FORCE
- @$(MAKE) -f Makemod $(MAKEDEFS) $@
-
-# ========== DEPENDENCIES FOR CLEANUP ==========
-
-# Since module cleanup rules depend on Makemod, they come first. This
-# forces module stuff to get cleaned before Makemod itself gets
-# deleted.
-
-mostlyclean-here:
- rm -f stamp-modobjs stamp-modobjs.tmp
-.PHONY: mostlyclean-here
-
-clean-here:
- rm -f modules.stamp zsh$(EXEEXT)
- rm -f libzsh-*.$(DL_EXT)
-.PHONY: clean-here
-
-distclean-here:
- rm -f TAGS tags
- rm -f Makefile
-.PHONY: distclean-here
-
-mostlyclean: mostlyclean-modules
-clean: clean-modules
-distclean: distclean-modules
-realclean: realclean-modules
-.PHONY: mostlyclean clean distclean realclean
-
-# Don't remake Makemod just to delete things, even if it doesn't exist.
-mostlyclean-modules clean-modules distclean-modules realclean-modules:
- if test -f Makemod; then \
- $(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \
- fi; \
- exit 0
-.PHONY: mostlyclean-modules clean-modules distclean-modules \
- realclean-modules
-
-@CLEAN_MK@
-
-# ========== RECURSIVE MAKES ==========
-
-modobjs modules headers proto zsh.export: Makemod
- @$(MAKE) -f Makemod $(MAKEDEFS) $@
-.PHONY: headers proto
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makemod.in.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makemod.in.in
deleted file mode 100644
index ea0cdc3a..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/Makemod.in.in
+++ /dev/null
@@ -1,192 +0,0 @@
-#
-# Makemod.in.in
-#
-# Copyright (c) 1995-1997 Richard Coleman
-# All rights reserved.
-#
-# Permission is hereby granted, without written agreement and without
-# license or royalty fees, to use, copy, modify, and distribute this
-# software and to distribute modified versions of this software for any
-# purpose, provided that the above copyright notice and the following
-# two paragraphs appear in all copies of this software.
-#
-# In no event shall Richard Coleman or the Zsh Development Group be liable
-# to any party for direct, indirect, special, incidental, or consequential
-# damages arising out of the use of this software and its documentation,
-# even if Richard Coleman and the Zsh Development Group have been advised of
-# the possibility of such damage.
-#
-# Richard Coleman and the Zsh Development Group specifically disclaim any
-# warranties, including, but not limited to, the implied warranties of
-# merchantability and fitness for a particular purpose. The software
-# provided hereunder is on an "as is" basis, and Richard Coleman and the
-# Zsh Development Group have no obligation to provide maintenance,
-# support, updates, enhancements, or modifications.
-#
-
-# ========== OVERRIDABLE VARIABLES ==========
-
-# subdir is done by mkmakemod.sh
-# dir_top is done by mkmakemod.sh
-# SUBDIRS is done by mkmakemod.sh
-
-@VERSION_MK@
-
-# source/build directories
-VPATH = @srcdir@
-sdir = @srcdir@
-sdir_top = @top_srcdir@
-INSTALL = @INSTALL@
-
-@DEFS_MK@
-
-sdir_src = $(sdir_top)/Src
-dir_src = $(dir_top)/Src
-
-# ========== COMPILATION RULES ==========
-
-DNCFLAGS =
-
-COMPILE = $(CC) -c -I. -I$(dir_top)/Src -I$(sdir_top)/Src -I$(sdir_top)/Src/Zle -I$(sdir) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(D@L@CFLAGS)
-DLCOMPILE = $(CC) -c -I. -I$(dir_top)/Src -I$(sdir_top)/Src -I$(sdir_top)/Src/Zle -I$(sdir) $(CPPFLAGS) $(DEFS) -DMODULE $(CFLAGS) $(DLCFLAGS)
-LINK = $(CC) $(LDFLAGS) $(EXELDFLAGS) $(EXTRA_LDFLAGS) -o $@
-DLLINK = $(DLLD) $(LDFLAGS) $(LIBLDFLAGS) $(DLLDFLAGS) -o $@
-
-KNR_OBJ=.o
-KNROBJ=._foo_
-
-ANSIOBJ=.o
-ANSI_OBJ=._foo_
-
-.SUFFIXES: .c .$(DL_EXT) ..o .._foo_ .o ._foo_ .syms .pro .epro
-
-.c$(ANSI@U@OBJ):
- $(COMPILE) -o $@ $<
- @rm -f $(dir_src)/stamp-modobjs
-
-.c$(KNR@U@OBJ):
- @ANSI2KNR@ $< > $@.c
- $(COMPILE) -o $@ $@.c
- rm -f $@.c
- @rm -f $(dir_src)/stamp-modobjs
-
-.c.$(ANSI@U@OBJ):
- $(DLCOMPILE) -o $@ $<
-
-.c.$(KNR@U@OBJ):
- @ANSI2KNR@ $< > $@.c
- $(DLCOMPILE) -o $@ $@.c
- rm -f $@.c
-
-.c.syms:
- $(AWK) -f $(sdir_src)/makepro.awk $< $(subdir) > $@
-
-.syms.epro:
- (echo '/* Generated automatically */'; sed -n '/^E/{s/^E//;p;}' < $<) \
- > $@
- (echo '/* Generated automatically */'; sed -n '/^L/{s/^L//;p;}' < $<) \
- > `echo $@ | sed 's/\.epro$$/.pro/'`
-
-PROTODEPS = $(sdir_src)/makepro.awk
-
-# ========== DEPENDENCIES FOR BUILDING ==========
-
-all: modobjs modules
-.PHONY: all
-
-modobjs: $(MODOBJS)
-modules: $(MODULES)
-headers: $(MDHS)
-proto: $(PROTOS)
-.PHONY: modobjs modules headers proto
-
-prep:
- @case $(sdir_top) in \
- /*) top_srcdir=$(sdir_top) ;; \
- *) top_srcdir=$(subdir)/$(sdir_top) ;; \
- esac; \
- export top_srcdir; \
- cd $(dir_top) || exit 1; \
- subdirs='$(SUBDIRS)'; \
- for subdir in $$subdirs; do \
- dir=$(subdir)/$$subdir; \
- test -d $$dir || mkdir $$dir; \
- $(SHELL) $$top_srcdir/Src/mkmakemod.sh $$dir Makefile || exit 1; \
- ( cd $$dir && $(MAKE) $(MAKEDEFS) $@ ) || exit 1; \
- done
-.PHONY: prep
-
-headers: $(dir_src)/modules.stamp
-$(dir_src)/modules.stamp: $(MDDS)
- $(MAKE) -f $(makefile) $(MAKEDEFS) prep
- echo 'timestamp for *.mdd files' > $@
-.PHONY: headers
-
-FORCE:
-.PHONY: FORCE
-
-# ========== DEPENDENCIES FOR INSTALLING ==========
-
-install: install.bin install.modules
-uninstall: uninstall.bin uninstall.modules
-.PHONY: install uninstall
-
-install.bin: install.bin-here
-uninstall.bin: uninstall.bin-here
-install.modules: install.modules-here
-uninstall.modules: uninstall.modules-here
-.PHONY: install.bin uninstall.bin install.modules uninstall.modules
-
-install.bin-here uninstall.bin-here:
-install.modules-here uninstall.modules-here:
-.PHONY: install.bin-here install.modules-here
-
-# ========== DEPENDENCIES FOR CLEANUP ==========
-
-@CLEAN_MK@
-
-mostlyclean-here:
- rm -f *.o *.export *.$(DL_EXT)
-.PHONY: mostlyclean-here
-
-clean-here:
- rm -f *.o.c *.syms *.pro *.epro *.mdh *.mdhi *.mdhs *.mdh.tmp
-.PHONY: clean-here
-
-distclean-here:
- rm -f $(makefile) $(makefile).in
-.PHONY: distclean-here
-
-# ========== RECURSIVE MAKES ==========
-
-install.bin uninstall.bin install.modules uninstall.modules \
-modobjs modules headers proto:
- @subdirs='$(SUBDIRS)'; for subdir in $$subdirs; do \
- ( cd $$subdir && $(MAKE) $(MAKEDEFS) $@ ) || exit 1; \
- done
-
-# ========== DEPENDENCIES FOR MAINTENANCE ==========
-
-$(makefile): $(makefile).in $(dir_top)/config.status
- @case $(sdir_top) in \
- /*) top_srcdir=$(sdir_top) ;; \
- *) top_srcdir=$(subdir)/$(sdir_top) ;; \
- esac; \
- export top_srcdir; \
- echo 'cd $(dir_top) && $(SHELL)' \
- '$$top_srcdir/Src/mkmakemod.sh -m $(subdir) $(makefile)'; \
- cd $(dir_top) && \
- $(SHELL) $$top_srcdir/Src/mkmakemod.sh -m $(subdir) $(makefile)
-
-$(makefile).in: $(sdir_src)/mkmakemod.sh $(sdir_src)/Makemod.in.in $(MDDS) \
- $(dir_top)/config.modules
- @case $(sdir_top) in \
- /*) top_srcdir=$(sdir_top) ;; \
- *) top_srcdir=$(subdir)/$(sdir_top) ;; \
- esac; \
- export top_srcdir; \
- echo 'cd $(dir_top) && $(SHELL)' \
- '$$top_srcdir/Src/mkmakemod.sh -i $(subdir) $(makefile)'; \
- cd $(dir_top) && \
- $(SHELL) $$top_srcdir/Src/mkmakemod.sh -i $(subdir) $(makefile)
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.cvsignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.cvsignore
deleted file mode 100644
index f72db844..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.cvsignore
+++ /dev/null
@@ -1,18 +0,0 @@
-Makefile
-Makefile.in
-*.export
-so_locations
-*.pro
-*.epro
-*.syms
-*.o
-*.o.c
-*.so
-*.mdh
-*.mdhi
-*.mdhs
-*.mdh.tmp
-*.swp
-errnames.c errcount.h
-*.dll
-curses_keys.h
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.distfiles b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.distfiles
deleted file mode 100644
index f03668b3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.distfiles
+++ /dev/null
@@ -1,2 +0,0 @@
-DISTFILES_SRC='
-'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.exrc b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.exrc
deleted file mode 100644
index 91d0b39e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.exrc
+++ /dev/null
@@ -1,2 +0,0 @@
-set ai
-set sw=4
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.gitignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.gitignore
deleted file mode 100644
index 92f708e2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-Makefile.in
-*.epro
-*.export
-*.mdh
-*.mdhi
-*.mdhs
-*.pro
-*.syms
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.c
deleted file mode 100644
index d945f863..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.c
+++ /dev/null
@@ -1,543 +0,0 @@
-#include "fzftab.mdh"
-#include "fzftab.pro"
-#include
-#include
-#include
-#include
-
-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))) {
- zwarnnam(nam, "bad pattern: %s", list_colors[i]);
- return 1;
- }
-
- 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;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.mdd b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.mdd
deleted file mode 100644
index 371bb951..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/aloxaf/fzftab.mdd
+++ /dev/null
@@ -1,7 +0,0 @@
-name=aloxaf/fzftab
-link=dynamic
-load=no
-
-autofeatures="b:fzf-tab-colorize p:FZF_TAB_MODULE_VERSION"
-
-objects="fzftab.o"
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/builtin.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/builtin.c
deleted file mode 100644
index 93fa9112..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/builtin.c
+++ /dev/null
@@ -1,7236 +0,0 @@
-/*
- * builtin.c - builtin commands
- *
- * 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 is defined so we get the prototype for open_memstream */
-#define _GNU_SOURCE 1
-
-#include "zsh.mdh"
-#include "builtin.pro"
-
-/* Builtins in the main executable */
-
-static struct builtin builtins[] =
-{
- BIN_PREFIX("-", BINF_DASH),
- BIN_PREFIX("builtin", BINF_BUILTIN),
- BIN_PREFIX("command", BINF_COMMAND),
- BIN_PREFIX("exec", BINF_EXEC),
- BIN_PREFIX("noglob", BINF_NOGLOB),
- BUILTIN("[", BINF_HANDLES_OPTS, bin_test, 0, -1, BIN_BRACKET, NULL, NULL),
- BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
- BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
- BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmrs", NULL),
- BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "dmktrRTUwWXz", "u"),
- BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
- BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
- BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
- BUILTIN("cd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
- BUILTIN("chdir", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
- BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
- BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmp:%rtuxz", NULL),
- BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
- BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL),
- BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
- BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
- BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "lLR", NULL),
- BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL),
- BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
- BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
- BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%TUZ:%afhi:%lp:%rtu", "xg"),
- BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
- /*
- * We used to behave as if the argument to -e was optional.
- * But that's actually not useful, so it's more consistent to
- * cause an error.
- */
- BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "aAdDe:EfiIlLmnpPrRt:W", NULL),
- BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
- BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlp:%rtux", "E"),
- BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmMstTuUWx:z", NULL),
- BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"),
- BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL),
- BUILTIN("hash", BINF_MAGICEQUALS, bin_hash, 0, -1, 0, "Ldfmrv", NULL),
-
-#ifdef ZSH_HASH_DEBUG
- BUILTIN("hashinfo", 0, bin_hashinfo, 0, 0, 0, NULL, NULL),
-#endif
-
- BUILTIN("history", 0, bin_fc, 0, -1, BIN_FC, "adDEfiLmnpPrt:", "l"),
- BUILTIN("integer", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "HL:%R:%Z:%ghi:%lp:%rtux", "i"),
- BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
- BUILTIN("kill", BINF_HANDLES_OPTS, bin_kill, 0, -1, 0, NULL, NULL),
- BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
- BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL),
- BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL),
- BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL),
-
-#if defined(ZSH_MEM) & defined(ZSH_MEM_DEBUG)
- BUILTIN("mem", 0, bin_mem, 0, 0, 0, "v", NULL),
-#endif
-
-#if defined(ZSH_PAT_DEBUG)
- BUILTIN("patdebug", 0, bin_patdebug, 1, -1, 0, "p", NULL),
-#endif
-
- BUILTIN("popd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 1, BIN_POPD, "q", NULL),
- BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "abcC:Df:ilmnNoOpPrRsSu:v:x:X:z-", NULL),
- BUILTIN("printf", BINF_SKIPINVALID | BINF_SKIPDASH, bin_print, 1, -1, BIN_PRINTF, "v:", NULL),
- BUILTIN("pushd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_PUSHD, "qsPL", NULL),
- BUILTIN("pushln", 0, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
- BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
- BUILTIN("r", 0, bin_fc, 0, -1, BIN_R, "IlLnr", NULL),
- BUILTIN("read", 0, bin_read, 0, -1, 0, "cd:ek:%lnpqrst:%zu:AE", NULL),
- BUILTIN("readonly", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, BIN_READONLY, "AE:%F:%HL:%R:%TUZ:%afghi:%lptux", "r"),
- BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "df", "r"),
- BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL),
- BUILTIN("set", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_set, 0, -1, 0, NULL, NULL),
- BUILTIN("setopt", 0, bin_setopt, 0, -1, BIN_SETOPT, NULL, NULL),
- BUILTIN("shift", BINF_PSPECIAL, bin_shift, 0, -1, 0, "p", NULL),
- BUILTIN("source", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
- BUILTIN("suspend", 0, bin_suspend, 0, 0, 0, "f", NULL),
- BUILTIN("test", BINF_HANDLES_OPTS, bin_test, 0, -1, BIN_TEST, NULL, NULL),
- BUILTIN("ttyctl", 0, bin_ttyctl, 0, 0, 0, "fu", NULL),
- BUILTIN("times", BINF_PSPECIAL, bin_times, 0, 0, 0, NULL, NULL),
- BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL),
- BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
- BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"),
- BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klp:%rtuxmz", NULL),
- BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
- BUILTIN("unalias", 0, bin_unhash, 0, -1, BIN_UNALIAS, "ams", NULL),
- BUILTIN("unfunction", 0, bin_unhash, 1, -1, BIN_UNFUNCTION, "m", "f"),
- BUILTIN("unhash", 0, bin_unhash, 1, -1, BIN_UNHASH, "adfms", NULL),
- BUILTIN("unset", BINF_PSPECIAL, bin_unset, 1, -1, BIN_UNSET, "fmv", NULL),
- BUILTIN("unsetopt", 0, bin_setopt, 0, -1, BIN_UNSETOPT, NULL, NULL),
- BUILTIN("wait", 0, bin_fg, 0, -1, BIN_WAIT, NULL, NULL),
- BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsSwx:", NULL),
- BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsSwx:", "ca"),
- BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsSwx:", "c"),
- BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "AFRILP:abcfdilmpsue", NULL),
- BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUMRcmzka", NULL),
-};
-
-/****************************************/
-/* Builtin Command Hash Table Functions */
-/****************************************/
-
-/* hash table containing builtin commands */
-
-/**/
-mod_export HashTable builtintab;
-
-/**/
-void
-createbuiltintable(void)
-{
- builtintab = newhashtable(85, "builtintab", NULL);
-
- builtintab->hash = hasher;
- builtintab->emptytable = NULL;
- builtintab->filltable = NULL;
- builtintab->cmpnodes = strcmp;
- builtintab->addnode = addhashnode;
- builtintab->getnode = gethashnode;
- builtintab->getnode2 = gethashnode2;
- builtintab->removenode = removehashnode;
- builtintab->disablenode = disablehashnode;
- builtintab->enablenode = enablehashnode;
- builtintab->freenode = freebuiltinnode;
- builtintab->printnode = printbuiltinnode;
-
- (void)addbuiltins("zsh", builtins, sizeof(builtins)/sizeof(*builtins));
-}
-
-/* Print a builtin */
-
-/**/
-static void
-printbuiltinnode(HashNode hn, int printflags)
-{
- Builtin bn = (Builtin) hn;
-
- if (printflags & PRINT_WHENCE_WORD) {
- printf("%s: builtin\n", bn->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_CSH) {
- printf("%s: shell built-in command\n", bn->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- printf("%s is a shell builtin\n", bn->node.nam);
- return;
- }
-
- /* default is name only */
- printf("%s\n", bn->node.nam);
-}
-
-/**/
-static void
-freebuiltinnode(HashNode hn)
-{
- Builtin bn = (Builtin) hn;
-
- if(!(bn->node.flags & BINF_ADDED)) {
- zsfree(bn->node.nam);
- zsfree(bn->optstr);
- zfree(bn, sizeof(struct builtin));
- }
-}
-
-/**/
-void
-init_builtins(void)
-{
- if (!EMULATION(EMULATE_ZSH)) {
- HashNode hn = reswdtab->getnode2(reswdtab, "repeat");
- if (hn)
- reswdtab->disablenode(hn, 0);
- }
-}
-
-/* Make sure we have space for a new option and increment. */
-
-#define OPT_ALLOC_CHUNK 16
-
-/**/
-static int
-new_optarg(Options ops)
-{
- /* Argument index must be a non-zero 6-bit number. */
- if (ops->argscount == 63)
- return 1;
- if (ops->argsalloc == ops->argscount) {
- char **newptr =
- (char **)zhalloc((ops->argsalloc + OPT_ALLOC_CHUNK) *
- sizeof(char *));
- if (ops->argsalloc)
- memcpy(newptr, ops->args, ops->argsalloc * sizeof(char *));
- ops->args = newptr;
- ops->argsalloc += OPT_ALLOC_CHUNK;
- }
- ops->argscount++;
- return 0;
-}
-
-
-/* execute a builtin handler function after parsing the arguments */
-
-/**/
-int
-execbuiltin(LinkList args, LinkList assigns, Builtin bn)
-{
- char *pp, *name, *optstr;
- int flags, argc, execop, xtr = isset(XTRACE);
- struct options ops;
-
- /* initialise options structure */
- memset(ops.ind, 0, MAX_OPS*sizeof(unsigned char));
- ops.args = NULL;
- ops.argscount = ops.argsalloc = 0;
-
- /* initialize some local variables */
- name = (char *) ugetnode(args);
-
- if (!bn->handlerfunc) {
- DPUTS(1, "Missing builtin detected too late");
- deletebuiltin(bn->node.nam);
- return 1;
- }
- /* get some information about the command */
- flags = bn->node.flags;
- optstr = bn->optstr;
-
- /* Set up the argument list. */
- /* count the arguments */
- argc = countlinknodes(args);
-
- {
- /*
- * Keep all arguments, including options, in an array.
- * We don't actually need the option part of the argument
- * after option processing, but it makes XTRACE output
- * much simpler.
- */
- VARARR(char *, argarr, argc + 1);
- char **argv;
-
- /*
- * Get the actual arguments, into argv. Remember argarr
- * may be an array declaration, depending on the compiler.
- */
- argv = argarr;
- while ((*argv++ = (char *)ugetnode(args)));
- argv = argarr;
-
- /* Sort out the options. */
- if (optstr) {
- char *arg = *argv;
- int sense; /* 1 for -x, 0 for +x */
- /* while arguments look like options ... */
- while (arg &&
- /* Must begin with - or maybe + */
- ((sense = (*arg == '-')) ||
- ((flags & BINF_PLUSOPTS) && *arg == '+'))) {
- /* Digits aren't arguments unless the command says they are. */
- if (!(flags & BINF_KEEPNUM) && idigit(arg[1]))
- break;
- /* For cd and friends, a single dash is not an option. */
- if ((flags & BINF_SKIPDASH) && !arg[1])
- break;
- if ((flags & BINF_DASHDASHVALID) && !strcmp(arg, "--")) {
- /*
- * Need to skip this before checking whether this is
- * really an option.
- */
- argv++;
- break;
- }
- /*
- * Unrecognised options to echo etc. are not really
- * options.
- *
- * Note this flag is not smart enough to handle option
- * arguments. In fact, ideally it shouldn't be added
- * to any new builtins, to preserve standard option
- * handling as much as possible.
- */
- if (flags & BINF_SKIPINVALID) {
- char *p = arg;
- while (*++p && strchr(optstr, (int) *p));
- if (*p)
- break;
- }
- /* handle -- or - (ops.ind['-']), and +
- * (ops.ind['-'] and ops.ind['+']) */
- if (arg[1] == '-')
- arg++;
- if (!arg[1]) {
- ops.ind['-'] = 1;
- if (!sense)
- ops.ind['+'] = 1;
- }
- /* save options in ops, as long as they are in bn->optstr */
- while (*++arg) {
- char *optptr;
- if ((optptr = strchr(optstr, execop = (int)*arg))) {
- ops.ind[(int)*arg] = (sense) ? 1 : 2;
- if (optptr[1] == ':') {
- char *argptr = NULL;
- if (optptr[2] == ':') {
- if (arg[1])
- argptr = arg+1;
- /* Optional argument in same word*/
- } else if (optptr[2] == '%') {
- /* Optional numeric argument in same
- * or next word. */
- if (arg[1] && idigit(arg[1]))
- argptr = arg+1;
- else if (argv[1] && idigit(*argv[1]))
- argptr = arg = *++argv;
- } else {
- /* Mandatory argument */
- if (arg[1])
- argptr = arg+1;
- else if ((arg = *++argv))
- argptr = arg;
- else {
- zwarnnam(name, "argument expected: -%c",
- execop);
- return 1;
- }
- }
- if (argptr) {
- if (new_optarg(&ops)) {
- zwarnnam(name,
- "too many option arguments");
- return 1;
- }
- ops.ind[execop] |= ops.argscount << 2;
- ops.args[ops.argscount-1] = argptr;
- while (arg[1])
- arg++;
- }
- }
- } else
- break;
- }
- /* The above loop may have exited on an invalid option. (We *
- * assume that any option requiring metafication is invalid.) */
- if (*arg) {
- if(*arg == Meta)
- *++arg ^= 32;
- zwarnnam(name, "bad option: %c%c", "+-"[sense], *arg);
- return 1;
- }
- arg = *++argv;
- /* for the "print" builtin, the options after -R are treated as
- options to "echo" */
- if ((flags & BINF_PRINTOPTS) && ops.ind['R'] &&
- !ops.ind['f']) {
- optstr = "ne";
- flags |= BINF_SKIPINVALID;
- }
- /* the option -- indicates the end of the options */
- if (ops.ind['-'])
- break;
- }
- } else if (!(flags & BINF_HANDLES_OPTS) && *argv &&
- !strcmp(*argv, "--")) {
- ops.ind['-'] = 1;
- argv++;
- }
-
- /* handle built-in options, for overloaded handler functions */
- if ((pp = bn->defopts)) {
- while (*pp) {
- /* only if not already set */
- if (!ops.ind[(int)*pp])
- ops.ind[(int)*pp] = 1;
- pp++;
- }
- }
-
- /* Fix the argument count by subtracting option arguments */
- argc -= argv - argarr;
-
- if (errflag) {
- errflag &= ~ERRFLAG_ERROR;
- return 1;
- }
-
- /* check that the argument count lies within the specified bounds */
- if (argc < bn->minargs || (argc > bn->maxargs && bn->maxargs != -1)) {
- zwarnnam(name, (argc < bn->minargs)
- ? "not enough arguments" : "too many arguments");
- return 1;
- }
-
- /* display execution trace information, if required */
- if (xtr) {
- /* Use full argument list including options for trace output */
- char **fullargv = argarr;
- printprompt4();
- fprintf(xtrerr, "%s", name);
- while (*fullargv) {
- fputc(' ', xtrerr);
- quotedzputs(*fullargv++, xtrerr);
- }
- if (assigns) {
- LinkNode node;
- for (node = firstnode(assigns); node; incnode(node)) {
- Asgment asg = (Asgment)node;
- fputc(' ', xtrerr);
- quotedzputs(asg->name, xtrerr);
- if (asg->flags & ASG_ARRAY) {
- fprintf(xtrerr, "=(");
- if (asg->value.array) {
- if (asg->flags & ASG_KEY_VALUE) {
- LinkNode keynode, valnode;
- keynode = firstnode(asg->value.array);
- for (;;) {
- if (!keynode)
- break;
- valnode = nextnode(keynode);
- if (!valnode)
- break;
- fputc('[', xtrerr);
- quotedzputs((char *)getdata(keynode),
- xtrerr);
- fprintf(stderr, "]=");
- quotedzputs((char *)getdata(valnode),
- xtrerr);
- keynode = nextnode(valnode);
- }
- } else {
- LinkNode arrnode;
- for (arrnode = firstnode(asg->value.array);
- arrnode;
- incnode(arrnode)) {
- fputc(' ', xtrerr);
- quotedzputs((char *)getdata(arrnode),
- xtrerr);
- }
- }
- }
- fprintf(xtrerr, " )");
- } else if (asg->value.scalar) {
- fputc('=', xtrerr);
- quotedzputs(asg->value.scalar, xtrerr);
- }
- }
- }
- fputc('\n', xtrerr);
- fflush(xtrerr);
- }
- /* call the handler function, and return its return value */
- if (flags & BINF_ASSIGN)
- {
- /*
- * Takes two sets of arguments.
- */
- HandlerFuncAssign assignfunc = (HandlerFuncAssign)bn->handlerfunc;
- return (*(assignfunc)) (name, argv, assigns, &ops, bn->funcid);
- }
- else
- {
- return (*(bn->handlerfunc)) (name, argv, &ops, bn->funcid);
- }
- }
-}
-
-/* Enable/disable an element in one of the internal hash tables. *
- * With no arguments, it lists all the currently enabled/disabled *
- * elements in that particular hash table. */
-
-/**/
-int
-bin_enable(char *name, char **argv, Options ops, int func)
-{
- HashTable ht;
- HashNode hn;
- ScanFunc scanfunc;
- Patprog pprog;
- int flags1 = 0, flags2 = 0;
- int match = 0, returnval = 0;
-
- /* Find out which hash table we are working with. */
- if (OPT_ISSET(ops,'p')) {
- return pat_enables(name, argv, func == BIN_ENABLE);
- } else if (OPT_ISSET(ops,'f'))
- ht = shfunctab;
- else if (OPT_ISSET(ops,'r'))
- ht = reswdtab;
- else if (OPT_ISSET(ops,'s'))
- ht = sufaliastab;
- else if (OPT_ISSET(ops,'a'))
- ht = aliastab;
- else
- ht = builtintab;
-
- /* Do we want to enable or disable? */
- if (func == BIN_ENABLE) {
- flags2 = DISABLED;
- scanfunc = ht->enablenode;
- } else {
- flags1 = DISABLED;
- scanfunc = ht->disablenode;
- }
-
- /* Given no arguments, print the names of the enabled/disabled elements *
- * in this hash table. If func == BIN_ENABLE, then scanhashtable will *
- * print nodes NOT containing the DISABLED flag, else scanhashtable will *
- * print nodes containing the DISABLED flag. */
- if (!*argv) {
- queue_signals();
- scanhashtable(ht, 1, flags1, flags2, ht->printnode, 0);
- unqueue_signals();
- return 0;
- }
-
- /* With -m option, treat arguments as glob patterns. */
- if (OPT_ISSET(ops,'m')) {
- for (; *argv; argv++) {
- queue_signals();
-
- /* parse pattern */
- tokenize(*argv);
- if ((pprog = patcompile(*argv, PAT_STATIC, 0)))
- match += scanmatchtable(ht, pprog, 0, 0, 0, scanfunc, 0);
- else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- unqueue_signals();
- }
- /* If we didn't match anything, we return 1. */
- if (!match)
- returnval = 1;
- return returnval;
- }
-
- /* Take arguments literally -- do not glob */
- queue_signals();
- for (; *argv; argv++) {
- if ((hn = ht->getnode2(ht, *argv))) {
- scanfunc(hn, 0);
- } else {
- zwarnnam(name, "no such hash table element: %s", *argv);
- returnval = 1;
- }
- }
- unqueue_signals();
- return returnval;
-}
-
-/* set: either set the shell options, or set the shell arguments, *
- * or declare an array, or show various things */
-
-/**/
-int
-bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
-{
- int action, optno, array = 0, hadopt = 0,
- hadplus = 0, hadend = 0, sort = 0;
- char **x, *arrayname = NULL;
-
- /* Obsolescent sh compatibility: set - is the same as set +xv *
- * and set - args is the same as set +xv -- args */
- if (!EMULATION(EMULATE_ZSH) && *args && **args == '-' && !args[0][1]) {
- dosetopt(VERBOSE, 0, 0, opts);
- dosetopt(XTRACE, 0, 0, opts);
- if (!args[1])
- return 0;
- }
-
- /* loop through command line options (begins with "-" or "+") */
- while (*args && (**args == '-' || **args == '+')) {
- action = (**args == '-');
- hadplus |= !action;
- if(!args[0][1])
- *args = "--";
- while (*++*args) {
- if(**args == Meta)
- *++*args ^= 32;
- if(**args != '-' || action)
- hadopt = 1;
- /* The pseudo-option `--' signifies the end of options. */
- if (**args == '-') {
- hadend = 1;
- args++;
- goto doneoptions;
- } else if (**args == 'o') {
- if (!*++*args)
- args++;
- if (!*args) {
- printoptionstates(hadplus);
- inittyptab();
- return 0;
- }
- if(!(optno = optlookup(*args)))
- zerrnam(nam, "no such option: %s", *args);
- else if(dosetopt(optno, action, 0, opts))
- zerrnam(nam, "can't change option: %s", *args);
- break;
- } else if(**args == 'A') {
- if(!*++*args)
- args++;
- array = action ? 1 : -1;
- arrayname = *args;
- if (!arrayname)
- goto doneoptions;
- else if (!isset(KSHARRAYS))
- {
- args++;
- goto doneoptions;
- }
- break;
- } else if (**args == 's')
- sort = action ? 1 : -1;
- else {
- if (!(optno = optlookupc(**args)))
- zerrnam(nam, "bad option: -%c", **args);
- else if(dosetopt(optno, action, 0, opts))
- zerrnam(nam, "can't change option: -%c", **args);
- }
- }
- args++;
- }
- if (errflag)
- return 1;
- doneoptions:
- inittyptab();
-
- /* Show the parameters, possibly with values */
- queue_signals();
- if (!arrayname)
- {
- if (!hadopt && !*args)
- scanhashtable(paramtab, 1, 0, 0, paramtab->printnode,
- hadplus ? PRINT_NAMEONLY : 0);
-
- if (array) {
- /* display arrays */
- scanhashtable(paramtab, 1, PM_ARRAY, 0, paramtab->printnode,
- hadplus ? PRINT_NAMEONLY : 0);
- }
- if (!*args && !hadend) {
- unqueue_signals();
- return 0;
- }
- }
- if (sort)
- strmetasort(args, sort < 0 ? SORTIT_BACKWARDS : 0, NULL);
- if (array) {
- /* create an array with the specified elements */
- char **a = NULL, **y;
- int len = arrlen(args);
-
- if (array < 0 && (a = getaparam(arrayname)) && arrlen_gt(a, len)) {
- a += len;
- len += arrlen(a);
- }
- for (x = y = zalloc((len + 1) * sizeof(char *)); len--;) {
- if (!*args)
- args = a;
- *y++ = ztrdup(*args++);
- }
- *y++ = NULL;
- setaparam(arrayname, x);
- } else {
- /* set shell arguments */
- freearray(pparams);
- pparams = zarrdup(args);
- }
- unqueue_signals();
- return 0;
-}
-
-/**** directory-handling builtins ****/
-
-/**/
-int doprintdir = 0; /* set in exec.c (for autocd) */
-
-/* pwd: display the name of the current directory */
-
-/**/
-int
-bin_pwd(UNUSED(char *name), UNUSED(char **argv), Options ops, UNUSED(int func))
-{
- if (OPT_ISSET(ops,'r') || OPT_ISSET(ops,'P') ||
- (isset(CHASELINKS) && !OPT_ISSET(ops,'L')))
- printf("%s\n", zgetcwd());
- else {
- zputs(pwd, stdout);
- putchar('\n');
- }
- return 0;
-}
-
-/* the directory stack */
-
-/**/
-mod_export LinkList dirstack;
-
-/* dirs: list the directory stack, or replace it with a provided list */
-
-/**/
-int
-bin_dirs(UNUSED(char *name), char **argv, Options ops, UNUSED(int func))
-{
- LinkList l;
-
- queue_signals();
- /* with -v, -p or no arguments display the directory stack */
- if (!(*argv || OPT_ISSET(ops,'c')) || OPT_ISSET(ops,'v') ||
- OPT_ISSET(ops,'p')) {
- LinkNode node;
- char *fmt;
- int pos = 1;
-
- /* with the -v option, display a numbered list, starting at zero */
- if (OPT_ISSET(ops,'v')) {
- printf("0\t");
- fmt = "\n%d\t";
- /* with the -p option, display entries one per line */
- } else if (OPT_ISSET(ops,'p'))
- fmt = "\n";
- else
- fmt = " ";
- if (OPT_ISSET(ops,'l'))
- zputs(pwd, stdout);
- else
- fprintdir(pwd, stdout);
- for (node = firstnode(dirstack); node; incnode(node)) {
- printf(fmt, pos++);
- if (OPT_ISSET(ops,'l'))
- zputs(getdata(node), stdout);
- else
- fprintdir(getdata(node), stdout);
-
- }
- unqueue_signals();
- putchar('\n');
- return 0;
- }
- /* replace the stack with the specified directories */
- l = znewlinklist();
- while (*argv)
- zaddlinknode(l, ztrdup(*argv++));
- freelinklist(dirstack, freestr);
- dirstack = l;
- unqueue_signals();
- return 0;
-}
-
-/* cd, chdir, pushd, popd */
-
-/**/
-void
-set_pwd_env(void)
-{
- Param pm;
-
- /* update the PWD and OLDPWD shell parameters */
-
- pm = (Param) paramtab->getnode(paramtab, "PWD");
- if (pm && PM_TYPE(pm->node.flags) != PM_SCALAR) {
- pm->node.flags &= ~PM_READONLY;
- unsetparam_pm(pm, 0, 1);
- }
-
- pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
- if (pm && PM_TYPE(pm->node.flags) != PM_SCALAR) {
- pm->node.flags &= ~PM_READONLY;
- unsetparam_pm(pm, 0, 1);
- }
-
- assignsparam("PWD", ztrdup(pwd), 0);
- assignsparam("OLDPWD", ztrdup(oldpwd), 0);
-
- pm = (Param) paramtab->getnode(paramtab, "PWD");
- if (!(pm->node.flags & PM_EXPORTED))
- addenv(pm, pwd);
- pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
- if (!(pm->node.flags & PM_EXPORTED))
- addenv(pm, oldpwd);
-}
-
-/* set if we are resolving links to their true paths */
-static int chasinglinks;
-
-/* The main pwd changing function. The real work is done by other *
- * functions. cd_get_dest() does the initial argument processing; *
- * cd_do_chdir() actually changes directory, if possible; cd_new_pwd() *
- * does the ancillary processing associated with actually changing *
- * directory. */
-
-/**/
-int
-bin_cd(char *nam, char **argv, Options ops, int func)
-{
- LinkNode dir;
- struct stat st1, st2;
-
- if (isset(RESTRICTED)) {
- zwarnnam(nam, "restricted");
- return 1;
- }
- doprintdir = (doprintdir == -1);
-
- chasinglinks = OPT_ISSET(ops,'P') ||
- (isset(CHASELINKS) && !OPT_ISSET(ops,'L'));
- queue_signals();
- zpushnode(dirstack, ztrdup(pwd));
- if (!(dir = cd_get_dest(nam, argv, OPT_ISSET(ops,'s'), func))) {
- zsfree(getlinknode(dirstack));
- unqueue_signals();
- return 1;
- }
- cd_new_pwd(func, dir, OPT_ISSET(ops, 'q'));
-
- if (stat(unmeta(pwd), &st1) < 0) {
- setjobpwd();
- zsfree(pwd);
- pwd = NULL;
- pwd = metafy(zgetcwd(), -1, META_DUP);
- } else if (stat(".", &st2) < 0) {
- if (chdir(unmeta(pwd)) < 0)
- zwarn("unable to chdir(%s): %e", pwd, errno);
- } else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
- if (chasinglinks) {
- setjobpwd();
- zsfree(pwd);
- pwd = NULL;
- pwd = metafy(zgetcwd(), -1, META_DUP);
- } else if (chdir(unmeta(pwd)) < 0)
- zwarn("unable to chdir(%s): %e", pwd, errno);
- }
- unqueue_signals();
- return 0;
-}
-
-/* Get directory to chdir to */
-
-/**/
-static LinkNode
-cd_get_dest(char *nam, char **argv, int hard, int func)
-{
- LinkNode dir = NULL;
- LinkNode target;
- char *dest;
-
- if (!argv[0]) {
- if (func == BIN_POPD && !nextnode(firstnode(dirstack))) {
- zwarnnam(nam, "directory stack empty");
- return NULL;
- }
- if (func == BIN_PUSHD && unset(PUSHDTOHOME))
- dir = nextnode(firstnode(dirstack));
- if (dir)
- zinsertlinknode(dirstack, dir, getlinknode(dirstack));
- else if (func != BIN_POPD) {
- if (!home) {
- zwarnnam(nam, "HOME not set");
- return NULL;
- }
- zpushnode(dirstack, ztrdup(home));
- }
- } else if (!argv[1]) {
- int dd;
- char *end;
-
- doprintdir++;
- if (argv[0][1] && (argv[0][0] == '+' || argv[0][0] == '-')
- && strspn(argv[0]+1, "0123456789") == strlen(argv[0]+1)) {
- dd = zstrtol(argv[0] + 1, &end, 10);
- if (*end == '\0') {
- if ((argv[0][0] == '+') ^ isset(PUSHDMINUS))
- for (dir = firstnode(dirstack); dir && dd; dd--, incnode(dir));
- else
- for (dir = lastnode(dirstack); dir != (LinkNode) dirstack && dd;
- dd--, dir = prevnode(dir));
- if (!dir || dir == (LinkNode) dirstack) {
- zwarnnam(nam, "no such entry in dir stack");
- return NULL;
- }
- }
- }
- if (!dir)
- zpushnode(dirstack, ztrdup(strcmp(argv[0], "-")
- ? (doprintdir--, argv[0]) : oldpwd));
- } else {
- char *u, *d;
- int len1, len2, len3;
-
- if (!(u = strstr(pwd, argv[0]))) {
- zwarnnam(nam, "string not in pwd: %s", argv[0]);
- return NULL;
- }
- len1 = strlen(argv[0]);
- len2 = strlen(argv[1]);
- len3 = u - pwd;
- d = (char *)zalloc(len3 + len2 + strlen(u + len1) + 1);
- strncpy(d, pwd, len3);
- strcpy(d + len3, argv[1]);
- strcat(d, u + len1);
- zpushnode(dirstack, d);
- doprintdir++;
- }
-
- target = dir;
- if (func == BIN_POPD) {
- if (!dir) {
- target = dir = firstnode(dirstack);
- } else if (dir != firstnode(dirstack)) {
- return dir;
- }
- dir = nextnode(dir);
- }
- if (!dir) {
- dir = firstnode(dirstack);
- }
- if (!dir || !getdata(dir)) {
- DPUTS(1, "Directory not set, not detected early enough");
- return NULL;
- }
- if (!(dest = cd_do_chdir(nam, getdata(dir), hard))) {
- if (!target)
- zsfree(getlinknode(dirstack));
- if (func == BIN_POPD)
- zsfree(remnode(dirstack, dir));
- return NULL;
- }
- if (dest != (char *)getdata(dir)) {
- zsfree(getdata(dir));
- setdata(dir, dest);
- }
- return target ? target : dir;
-}
-
-/* Change to given directory, if possible. This function works out *
- * exactly how the directory should be interpreted, including cdpath *
- * and CDABLEVARS. For each possible interpretation of the given *
- * path, this calls cd_try_chdir(), which attempts to chdir to that *
- * particular path. */
-
-/**/
-static char *
-cd_do_chdir(char *cnam, char *dest, int hard)
-{
- char **pp, *ret;
- int hasdot = 0, eno = ENOENT;
- /*
- * nocdpath indicates that cdpath should not be used.
- * This is the case iff dest is a relative path
- * whose first segment is . or .., but if the path is
- * absolute then cdpath won't be used anyway.
- */
- int nocdpath;
-#ifdef __CYGWIN__
- /*
- * Normalize path under Cygwin to avoid messing with
- * DOS style names with drives in them
- */
- static char buf[PATH_MAX+1];
-#ifdef HAVE_CYGWIN_CONV_PATH
- cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, dest, buf,
- PATH_MAX);
-#else
-#ifndef _SYS_CYGWIN_H
- void cygwin_conv_to_posix_path(const char *, char *);
-#endif
-
- cygwin_conv_to_posix_path(dest, buf);
-#endif
- dest = buf;
-#endif
- nocdpath = dest[0] == '.' &&
- (dest[1] == '/' || !dest[1] || (dest[1] == '.' &&
- (dest[2] == '/' || !dest[2])));
-
- /*
- * If we have an absolute path, use it as-is only
- */
- if (*dest == '/') {
- if ((ret = cd_try_chdir(NULL, dest, hard)))
- return ret;
- zwarnnam(cnam, "%e: %s", errno, dest);
- return NULL;
- }
-
- /*
- * If cdpath is being used, check it for ".".
- * Don't bother doing this if POSIXCD is set, we don't
- * need to know (though it doesn't actually matter).
- */
- if (!nocdpath && !isset(POSIXCD))
- for (pp = cdpath; *pp; pp++)
- if (!(*pp)[0] || ((*pp)[0] == '.' && (*pp)[1] == '\0'))
- hasdot = 1;
- /*
- * If
- * (- there is no . in cdpath
- * - or cdpath is not being used)
- * - and the POSIXCD option is not set
- * try the directory as-is (i.e. from .)
- */
- if (!hasdot && !isset(POSIXCD)) {
- if ((ret = cd_try_chdir(NULL, dest, hard)))
- return ret;
- if (errno != ENOENT)
- eno = errno;
- }
- /* if cdpath is being used, try given directory relative to each element in
- cdpath in turn */
- if (!nocdpath)
- for (pp = cdpath; *pp; pp++) {
- if ((ret = cd_try_chdir(*pp, dest, hard))) {
- if (isset(POSIXCD)) {
- /*
- * For POSIX we need to print the directory
- * any time CDPATH was used, except in the
- * special case of an empty segment being
- * treated as a ".".
- */
- if (**pp)
- doprintdir++;
- } else {
- if (strcmp(*pp, ".")) {
- doprintdir++;
- }
- }
- return ret;
- }
- if (errno != ENOENT)
- eno = errno;
- }
- /*
- * POSIX requires us to check "." after CDPATH rather than before.
- */
- if (isset(POSIXCD)) {
- if ((ret = cd_try_chdir(NULL, dest, hard)))
- return ret;
- if (errno != ENOENT)
- eno = errno;
- }
-
- /* handle the CDABLEVARS option */
- if ((ret = cd_able_vars(dest))) {
- if ((ret = cd_try_chdir(NULL, ret,hard))) {
- doprintdir++;
- return ret;
- }
- if (errno != ENOENT)
- eno = errno;
- }
-
- /* If we got here, it means that we couldn't chdir to any of the
- multitudinous possible paths allowed by zsh. We've run out of options!
- Add more here! */
- zwarnnam(cnam, "%e: %s", eno, dest);
- return NULL;
-}
-
-/* If the CDABLEVARS option is set, return the new *
- * interpretation of the given path. */
-
-/**/
-char *
-cd_able_vars(char *s)
-{
- char *rest, save;
-
- if (isset(CDABLEVARS)) {
- for (rest = s; *rest && *rest != '/'; rest++);
- save = *rest;
- *rest = 0;
- s = getnameddir(s);
- *rest = save;
-
- if (s && *rest)
- s = dyncat(s, rest);
-
- return s;
- }
- return NULL;
-}
-
-/* Attempt to change to a single given directory. The directory, *
- * for the convenience of the calling function, may be provided in *
- * two parts, which must be concatenated before attempting to chdir. *
- * Returns NULL if the chdir fails. If the directory change is *
- * possible, it is performed, and a pointer to the new full pathname *
- * is returned. */
-
-/**/
-static char *
-cd_try_chdir(char *pfix, char *dest, int hard)
-{
- char *buf;
- int dlen, dochaselinks = 0;
-
- /* handle directory prefix */
- if (pfix && *pfix) {
- if (*pfix == '/') {
-#ifdef __CYGWIN__
-/* NB: Don't turn "/"+"bin" into "//"+"bin" by mistake! "//bin" may *
- * not be what user really wants (probably wants "/bin"), but *
- * "//bin" could be valid too (see fixdir())! This is primarily for *
- * handling CDPATH correctly. Likewise for "//"+"bin" not becoming *
- * "///bin" (aka "/bin"). */
- int root = pfix[1] == '\0' || (pfix[1] == '/' && pfix[2] == '\0');
- buf = tricat(pfix, ( root ? "" : "/" ), dest);
-#else
- buf = tricat(pfix, "/", dest);
-#endif
- } else {
- int pfl = strlen(pfix);
- dlen = strlen(pwd);
- if (dlen == 1 && *pwd == '/')
- dlen = 0;
- buf = zalloc(dlen + pfl + strlen(dest) + 3);
- if (dlen)
- strcpy(buf, pwd);
- buf[dlen] = '/';
- strcpy(buf + dlen + 1, pfix);
- buf[dlen + 1 + pfl] = '/';
- strcpy(buf + dlen + pfl + 2, dest);
- }
- } else if (*dest == '/')
- buf = ztrdup(dest);
- else {
- dlen = strlen(pwd);
- if (pwd[dlen-1] == '/')
- --dlen;
- buf = zalloc(dlen + strlen(dest) + 2);
- strcpy(buf, pwd);
- buf[dlen] = '/';
- strcpy(buf + dlen + 1, dest);
- }
-
- /* Normalise path. See the definition of fixdir() for what this means.
- * We do not do this if we are chasing links.
- */
- if (!chasinglinks)
- dochaselinks = fixdir(buf);
- else
- unmetafy(buf, &dlen);
-
- /* We try the full path first. If that fails, try the
- * argument to cd relatively. This is useful if the cwd
- * or a parent directory is renamed in the interim.
- */
- if (lchdir(buf, NULL, hard) &&
- (pfix || *dest == '/' || lchdir(unmeta(dest), NULL, hard))) {
- free(buf);
- return NULL;
- }
- /* the chdir succeeded, so decide if we should force links to be chased */
- if (dochaselinks)
- chasinglinks = 1;
- return metafy(buf, -1, META_NOALLOC);
-}
-
-/* do the extra processing associated with changing directory */
-
-/**/
-static void
-cd_new_pwd(int func, LinkNode dir, int quiet)
-{
- char *new_pwd, *s;
- int dirstacksize;
-
- if (func == BIN_PUSHD)
- rolllist(dirstack, dir);
- new_pwd = remnode(dirstack, dir);
-
- if (func == BIN_POPD && firstnode(dirstack)) {
- zsfree(new_pwd);
- new_pwd = getlinknode(dirstack);
- } else if (func == BIN_CD && unset(AUTOPUSHD))
- zsfree(getlinknode(dirstack));
-
- if (chasinglinks) {
- s = findpwd(new_pwd);
- if (s) {
- zsfree(new_pwd);
- new_pwd = s;
- }
- }
- if (isset(PUSHDIGNOREDUPS)) {
- LinkNode n;
- for (n = firstnode(dirstack); n; incnode(n)) {
- if (!strcmp(new_pwd, getdata(n))) {
- zsfree(remnode(dirstack, n));
- break;
- }
- }
- }
-
- /* shift around the pwd variables, to make oldpwd and pwd relate to the
- current (i.e. new) pwd */
- zsfree(oldpwd);
- oldpwd = pwd;
- setjobpwd();
- pwd = new_pwd;
- set_pwd_env();
-
- if (isset(INTERACTIVE) || isset(POSIXCD)) {
- if (func != BIN_CD && isset(INTERACTIVE)) {
- if (unset(PUSHDSILENT) && !quiet)
- printdirstack();
- } else if (doprintdir) {
- fprintdir(pwd, stdout);
- putchar('\n');
- }
- }
-
- /* execute the chpwd function */
- fflush(stdout);
- fflush(stderr);
- if (!quiet)
- callhookfunc("chpwd", NULL, 1, NULL);
-
- dirstacksize = getiparam("DIRSTACKSIZE");
- /* handle directory stack sizes out of range */
- if (dirstacksize > 0) {
- int remove = countlinknodes(dirstack) -
- (dirstacksize < 2 ? 2 : dirstacksize);
- while (remove-- >= 0)
- zsfree(remnode(dirstack, lastnode(dirstack)));
- }
-}
-
-/* Print the directory stack */
-
-/**/
-static void
-printdirstack(void)
-{
- LinkNode node;
-
- fprintdir(pwd, stdout);
- for (node = firstnode(dirstack); node; incnode(node)) {
- putchar(' ');
- fprintdir(getdata(node), stdout);
- }
- putchar('\n');
-}
-
-/* Normalise a path. Segments consisting of ., and foo/.. *
- * combinations, are removed and the path is unmetafied.
- * Returns 1 if we found a ../ path which should force links to
- * be chased, 0 otherwise.
- */
-
-/**/
-int
-fixdir(char *src)
-{
- char *dest = src, *d0 = dest;
-#ifdef __CYGWIN__
- char *s0 = src;
-#endif
- /* This function is always called with n path containing at
- * least one slash, either because one was input by the user or
- * because the caller has prepended either pwd or a cdpath dir.
- * If asked to make a relative change and pwd is set to ".",
- * the current directory has been removed out from under us,
- * so force links to be chased.
- *
- * Ordinarily we can't get here with "../" as the first component
- * but handle the silly special case of ".." in cdpath.
- *
- * Order of comparisons here looks funny, but it short-circuits
- * most rapidly in the event of a false condition. Set to 2
- * here so we still obey the (lack of) CHASEDOTS option after
- * the first "../" is preserved (test chasedots > 1 below).
- */
- int chasedots = (src[0] == '.' && pwd[0] == '.' && pwd[1] == '\0' &&
- (src[1] == '/' || (src[1] == '.' && src[2] == '/'))) * 2;
-
-/*** if have RFS superroot directory ***/
-#ifdef HAVE_SUPERROOT
- /* allow /.. segments to remain */
- while (*src == '/' && src[1] == '.' && src[2] == '.' &&
- (!src[3] || src[3] == '/')) {
- *dest++ = '/';
- *dest++ = '.';
- *dest++ = '.';
- src += 3;
- }
-#endif
-
- for (;;) {
- /* compress multiple /es into single */
- if (*src == '/') {
-#ifdef __CYGWIN__
- /* allow leading // under cygwin, but /// still becomes / */
- if (src == s0 && src[1] == '/' && src[2] != '/')
- *dest++ = *src++;
-#endif
- *dest++ = *src++;
- while (*src == '/')
- src++;
- }
- /* if we are at the end of the input path, remove a trailing / (if it
- exists), and return ct */
- if (!*src) {
- while (dest > d0 + 1 && dest[-1] == '/')
- dest--;
- *dest = '\0';
- return chasedots;
- }
- if (src[0] == '.' && src[1] == '.' &&
- (src[2] == '\0' || src[2] == '/')) {
- if (isset(CHASEDOTS) || chasedots > 1) {
- chasedots = 1;
- /* and treat as normal path segment */
- } else {
- if (dest > d0 + 1) {
- /*
- * remove a foo/.. combination:
- * first check foo exists, else return.
- */
- struct stat st;
- *dest = '\0';
- if (stat(d0, &st) < 0 || !S_ISDIR(st.st_mode)) {
- char *ptrd, *ptrs;
- if (dest == src)
- *dest = '.';
- for (ptrs = src, ptrd = dest; *ptrs; ptrs++, ptrd++)
- *ptrd = (*ptrs == Meta) ? (*++ptrs ^ 32) : *ptrs;
- *ptrd = '\0';
- return 1;
- }
- for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--);
- if (dest[-1] != '/')
- dest--;
- }
- src++;
- while (*++src == '/');
- continue;
- }
- }
- if (src[0] == '.' && (src[1] == '/' || src[1] == '\0')) {
- /* skip a . section */
- while (*++src == '/');
- } else {
- /* copy a normal segment into the output */
- while (*src != '/' && *src != '\0')
- if ((*dest++ = *src++) == Meta)
- dest[-1] = *src++ ^ 32;
- }
- }
- /* unreached */
-}
-
-/**/
-mod_export void
-printqt(char *str)
-{
- /* Print str, but turn any single quote into '\'' or ''. */
- for (; *str; str++)
- if (*str == '\'')
- printf(isset(RCQUOTES) ? "''" : "'\\''");
- else
- putchar(*str);
-}
-
-/**/
-mod_export void
-printif(char *str, int c)
-{
- /* If flag c has an argument, print that */
- if (str) {
- printf(" -%c ", c);
- quotedzputs(str, stdout);
- }
-}
-
-/**** history list functions ****/
-
-/* fc, history, r */
-
-/**/
-int
-bin_fc(char *nam, char **argv, Options ops, int func)
-{
- zlong first = -1, last = -1;
- int retval;
- char *s;
- struct asgment *asgf = NULL, *asgl = NULL;
- Patprog pprog = NULL;
-
- /* fc is only permitted in interactive shells */
-#ifdef FACIST_INTERACTIVE
- if (!interact) {
- zwarnnam(nam, "not interactive shell");
- return 1;
- }
-#endif
- if (OPT_ISSET(ops,'p')) {
- char *hf = "";
- zlong hs = DEFAULT_HISTSIZE;
- zlong shs = 0;
- int level = OPT_ISSET(ops,'a') ? locallevel : -1;
- if (*argv) {
- hf = *argv++;
- if (*argv) {
- char *check;
- hs = zstrtol(*argv++, &check, 10);
- if (*check) {
- zwarnnam("fc", "HISTSIZE must be an integer");
- return 1;
- }
- if (*argv) {
- shs = zstrtol(*argv++, &check, 10);
- if (*check) {
- zwarnnam("fc", "SAVEHIST must be an integer");
- return 1;
- }
- } else
- shs = hs;
- if (*argv) {
- zwarnnam("fc", "too many arguments");
- return 1;
- }
- } else {
- hs = histsiz;
- shs = savehistsiz;
- }
- }
- if (!pushhiststack(hf, hs, shs, level))
- return 1;
- if (*hf) {
- struct stat st;
- if (stat(hf, &st) >= 0 || errno != ENOENT)
- readhistfile(hf, 1, HFILE_USE_OPTIONS);
- }
- return 0;
- }
- if (OPT_ISSET(ops,'P')) {
- if (*argv) {
- zwarnnam("fc", "too many arguments");
- return 1;
- }
- return !saveandpophiststack(-1, HFILE_USE_OPTIONS);
- }
- /* with the -m option, the first argument is taken *
- * as a pattern that history lines have to match */
- if (*argv && OPT_ISSET(ops,'m')) {
- tokenize(*argv);
- if (!(pprog = patcompile(*argv++, 0, NULL))) {
- zwarnnam(nam, "invalid match pattern");
- return 1;
- }
- }
- queue_signals();
- if (OPT_ISSET(ops,'R')) {
- /* read history from a file */
- readhistfile(*argv, 1, OPT_ISSET(ops,'I') ? HFILE_SKIPOLD : 0);
- unqueue_signals();
- return 0;
- }
- if (OPT_ISSET(ops,'W')) {
- /* write history to a file */
- savehistfile(*argv, 1, OPT_ISSET(ops,'I') ? HFILE_SKIPOLD : 0);
- unqueue_signals();
- return 0;
- }
- if (OPT_ISSET(ops,'A')) {
- /* append history to a file */
- savehistfile(*argv, 1, HFILE_APPEND |
- (OPT_ISSET(ops,'I') ? HFILE_SKIPOLD : 0));
- unqueue_signals();
- return 0;
- }
-
- if (zleactive) {
- unqueue_signals();
- zwarnnam(nam, "no interactive history within ZLE");
- return 1;
- }
-
- /* put foo=bar type arguments into the substitution list */
- while (*argv && equalsplit(*argv, &s)) {
- Asgment a = (Asgment) zhalloc(sizeof *a);
-
- if (!**argv) {
- zwarnnam(nam, "invalid replacement pattern: =%s", s);
- return 1;
- }
- if (!asgf)
- asgf = asgl = a;
- else {
- asgl->node.next = &a->node;
- asgl = a;
- }
- a->name = *argv;
- a->flags = 0;
- a->value.scalar = s;
- a->node.next = a->node.prev = NULL;
- argv++;
- }
- /* interpret and check first history line specifier */
- if (*argv) {
- first = fcgetcomm(*argv);
- if (first == -1) {
- unqueue_signals();
- return 1;
- }
- argv++;
- }
- /* interpret and check second history line specifier */
- if (*argv) {
- last = fcgetcomm(*argv);
- if (last == -1) {
- unqueue_signals();
- return 1;
- }
- argv++;
- }
- /* There is a maximum of two history specifiers. At least, there *
- * will be as long as the history list is one-dimensional. */
- if (*argv) {
- unqueue_signals();
- zwarnnam("fc", "too many arguments");
- return 1;
- }
- /* default values of first and last, and range checking */
- if (last == -1) {
- if (OPT_ISSET(ops,'l') && first < curhist) {
- /*
- * When listing base our calculations on curhist,
- * to show anything added since the edited history line.
- * Also, in that case curhist will have been modified
- * past the current history line; then we want to
- * show everything, because the user expects to
- * see the result of "print -s". Otherwise, we subtract
- * -1 from the line, because the user doesn't usually expect
- * to see the command line that caused history to be
- * listed.
- */
- last = (curline.histnum == curhist) ? addhistnum(curhist,-1,0)
- : curhist;
- if (last < firsthist())
- last = firsthist();
- }
- else
- last = first;
- }
- if (first == -1) {
- /*
- * When listing, we want to see everything that's been
- * added to the history, including by print -s, so use
- * curhist.
- * When reexecuting, we want to restrict to the last edited
- * command line to avoid giving the user a nasty turn
- * if some helpful soul ran "print -s 'rm -rf /'".
- */
- first = OPT_ISSET(ops,'l')? addhistnum(curhist,-16,0)
- : addhistnum(curline.histnum,-1,0);
- if (first < 1)
- first = 1;
- if (last < first)
- last = first;
- }
- if (OPT_ISSET(ops,'l')) {
- /* list the required part of the history */
- retval = fclist(stdout, ops, first, last, asgf, pprog, 0);
- unqueue_signals();
- }
- else {
- /* edit history file, and (if successful) use the result as a new command */
- int tempfd;
- FILE *out;
- char *fil;
-
- retval = 1;
- if ((tempfd = gettempfile(NULL, 1, &fil)) < 0
- || ((out = fdopen(tempfd, "w")) == NULL)) {
- unqueue_signals();
- zwarnnam("fc", "can't open temp file: %e", errno);
- } else {
- /*
- * Nasty behaviour results if we use the current history
- * line here. Treat it as if it doesn't exist, unless
- * that gives us an empty range.
- */
- if (last >= curhist) {
- last = curhist - 1;
- if (first > last) {
- unqueue_signals();
- zwarnnam("fc",
- "current history line would recurse endlessly, aborted");
- fclose(out);
- unlink(fil);
- return 1;
- }
- }
- ops->ind['n'] = 1; /* No line numbers here. */
- if (!fclist(out, ops, first, last, asgf, pprog, 1)) {
- char *editor;
-
- if (func == BIN_R)
- editor = "-";
- else if (OPT_HASARG(ops, 'e'))
- editor = OPT_ARG(ops, 'e');
- else
- editor = getsparam("FCEDIT");
- if (!editor)
- editor = getsparam("EDITOR");
- if (!editor)
- editor = DEFAULT_FCEDIT;
-
- unqueue_signals();
- if (fcedit(editor, fil)) {
- if (stuff(fil))
- zwarnnam("fc", "%e: %s", errno, fil);
- else {
- loop(0,1);
- retval = lastval;
- }
- }
- } else
- unqueue_signals();
- }
- unlink(fil);
- }
- return retval;
-}
-
-/* History handling functions: these are called by ZLE, as well as *
- * the actual builtins. fcgetcomm() gets a history line, specified *
- * either by number or leading string. fcsubs() performs a given *
- * set of simple old=new substitutions on a given command line. *
- * fclist() outputs a given range of history lines to a text file. */
-
-/* get the history event associated with s */
-
-/**/
-static zlong
-fcgetcomm(char *s)
-{
- zlong cmd;
-
- /* First try to match a history number. Negative *
- * numbers indicate reversed numbering. */
- if ((cmd = atoi(s)) != 0 || *s == '0') {
- if (cmd < 0)
- cmd = addhistnum(curline.histnum,cmd,HIST_FOREIGN);
- if (cmd < 0)
- cmd = 0;
- return cmd;
- }
- /* not a number, so search by string */
- cmd = hcomsearch(s);
- if (cmd == -1)
- zwarnnam("fc", "event not found: %s", s);
- return cmd;
-}
-
-/* Perform old=new substitutions. Uses the asgment structure from zsh.h, *
- * which is essentially a linked list of string,replacement pairs. */
-
-/**/
-static int
-fcsubs(char **sp, struct asgment *sub)
-{
- char *oldstr, *newstr, *oldpos, *newpos, *newmem, *s = *sp;
- int subbed = 0;
-
- /* loop through the linked list */
- while (sub) {
- oldstr = sub->name;
- newstr = sub->value.scalar;
- sub = (Asgment)sub->node.next;
- oldpos = s;
- /* loop over occurences of oldstr in s, replacing them with newstr */
- while ((newpos = (char *)strstr(oldpos, oldstr))) {
- newmem = (char *) zhalloc(1 + (newpos - s)
- + strlen(newstr) + strlen(newpos + strlen(oldstr)));
- ztrncpy(newmem, s, newpos - s);
- strcat(newmem, newstr);
- oldpos = newmem + strlen(newmem);
- strcat(newmem, newpos + strlen(oldstr));
- s = newmem;
- subbed = 1;
- }
- }
- *sp = s;
- return subbed;
-}
-
-/* Print a series of history events to a file. The file pointer is *
- * given by f, and the required range of events by first and last. *
- * subs is an optional list of foo=bar substitutions to perform on the *
- * history lines before output. com is an optional comp structure *
- * that the history lines are required to match. n, r, D and d are *
- * options: n indicates that each line should be numbered. r indicates *
- * that the lines should be output in reverse order (newest first). *
- * D indicates that the real time taken by each command should be *
- * output. d indicates that the time of execution of each command *
- * should be output; d>1 means that the date should be output too; d>3 *
- * means that mm/dd/yyyy form should be used for the dates, as opposed *
- * to dd.mm.yyyy form; d>7 means that yyyy-mm-dd form should be used. */
-
-/**/
-static int
-fclist(FILE *f, Options ops, zlong first, zlong last,
- struct asgment *subs, Patprog pprog, int is_command)
-{
- int fclistdone = 0, xflags = 0;
- zlong tmp;
- char *s, *tdfmt, *timebuf;
- Histent ent;
-
- /* reverse range if required */
- if (OPT_ISSET(ops,'r')) {
- tmp = last;
- last = first;
- first = tmp;
- }
- if (is_command && first > last) {
- zwarnnam("fc", "history events can't be executed backwards, aborted");
- if (f != stdout)
- fclose(f);
- return 1;
- }
-
- ent = gethistent(first, first < last? GETHIST_DOWNWARD : GETHIST_UPWARD);
- if (!ent || (first < last? ent->histnum > last : ent->histnum < last)) {
- if (first == last) {
- char buf[DIGBUFSIZE];
- convbase(buf, first, 10);
- zwarnnam("fc", "no such event: %s", buf);
- } else
- zwarnnam("fc", "no events in that range");
- if (f != stdout)
- fclose(f);
- return 1;
- }
-
- if (OPT_ISSET(ops,'d') || OPT_ISSET(ops,'f') ||
- OPT_ISSET(ops,'E') || OPT_ISSET(ops,'i') ||
- OPT_ISSET(ops,'t')) {
- if (OPT_ISSET(ops,'t')) {
- tdfmt = OPT_ARG(ops,'t');
- } else if (OPT_ISSET(ops,'i')) {
- tdfmt = "%Y-%m-%d %H:%M";
- } else if (OPT_ISSET(ops,'E')) {
- tdfmt = "%f.%-m.%Y %H:%M";
- } else if (OPT_ISSET(ops,'f')) {
- tdfmt = "%-m/%f/%Y %H:%M";
- } else {
- tdfmt = "%H:%M";
- }
- timebuf = zhalloc(256);
- } else {
- tdfmt = timebuf = NULL;
- }
-
- /* xflags exclude events */
- if (OPT_ISSET(ops,'L')) {
- xflags |= HIST_FOREIGN;
- }
- if (OPT_ISSET(ops,'I')) {
- xflags |= HIST_READ;
- }
-
- for (;;) {
- if (ent->node.flags & xflags)
- s = NULL;
- else
- s = dupstring(ent->node.nam);
- /* this if does the pattern matching, if required */
- if (s && (!pprog || pattry(pprog, s))) {
- /* perform substitution */
- fclistdone |= (subs ? fcsubs(&s, subs) : 1);
-
- /* do numbering */
- if (!OPT_ISSET(ops,'n')) {
- char buf[DIGBUFSIZE];
- convbase(buf, ent->histnum, 10);
- fprintf(f, "%5s%c ", buf,
- ent->node.flags & HIST_FOREIGN ? '*' : ' ');
- }
- /* output actual time (and possibly date) of execution of the
- command, if required */
- if (tdfmt != NULL) {
- struct tm *ltm;
- int len;
- ltm = localtime(&ent->stim);
- if ((len = ztrftime(timebuf, 256, tdfmt, ltm, 0L)) >= 0) {
- fwrite(timebuf, 1, len, f);
- fprintf(f, " ");
- }
- }
- /* display the time taken by the command, if required */
- if (OPT_ISSET(ops,'D')) {
- long diff;
- diff = (ent->ftim) ? ent->ftim - ent->stim : 0;
- fprintf(f, "%ld:%02ld ", diff / 60, diff % 60);
- }
-
- /* output the command */
- if (f == stdout) {
- nicezputs(s, f);
- putc('\n', f);
- } else {
- int len;
- unmetafy(s, &len);
- fwrite(s, 1, len, f);
- putc('\n', f);
- }
- }
- /* move on to the next history line, or quit the loop */
- if (first < last) {
- if (!(ent = down_histent(ent)) || ent->histnum > last)
- break;
- }
- else {
- if (!(ent = up_histent(ent)) || ent->histnum < last)
- break;
- }
- }
-
- /* final processing */
- if (f != stdout)
- fclose(f);
- if (!fclistdone) {
- if (subs)
- zwarnnam("fc", "no substitutions performed");
- else if (xflags || pprog)
- zwarnnam("fc", "no matching events found");
- return 1;
- }
- return 0;
-}
-
-/* edit a history file */
-
-/**/
-static int
-fcedit(char *ename, char *fn)
-{
- char *s;
-
- if (!strcmp(ename, "-"))
- return 1;
-
- s = tricat(ename, " ", fn);
- execstring(s, 1, 0, "fc");
- zsfree(s);
-
- return !lastval;
-}
-
-/**** parameter builtins ****/
-
-/* Separate an argument into name=value parts, returning them in an *
- * asgment structure. Because the asgment structure used is global, *
- * only one of these can be active at a time. The string s gets placed *
- * in this global structure, so it needs to be in permanent memory. */
-
-/**/
-static Asgment
-getasg(char ***argvp, LinkList assigns)
-{
- char *s = **argvp;
- static struct asgment asg;
-
- /* sanity check for valid argument */
- if (!s) {
- if (assigns) {
- Asgment asgp = (Asgment)firstnode(assigns);
- if (!asgp)
- return NULL;
- (void)uremnode(assigns, &asgp->node);
- return asgp;
- }
- return NULL;
- }
-
- /* check if name is empty */
- if (*s == '=') {
- zerr("bad assignment");
- return NULL;
- }
- asg.name = s;
- asg.flags = 0;
-
- /* search for `=' */
- for (; *s && *s != '='; s++);
-
- /* found `=', so return with a value */
- if (*s) {
- *s = '\0';
- asg.value.scalar = s + 1;
- } else {
- /* didn't find `=', so we only have a name */
- asg.value.scalar = NULL;
- }
- (*argvp)++;
- return &asg;
-}
-
-/* for new special parameters */
-enum {
- NS_NONE,
- NS_NORMAL,
- NS_SECONDS
-};
-
-static const struct gsu_scalar tiedarr_gsu =
-{ tiedarrgetfn, tiedarrsetfn, tiedarrunsetfn };
-
-/* Install a base if we are turning on a numeric option with an argument */
-
-static int
-typeset_setbase(const char *name, Param pm, Options ops, int on, int always)
-{
- char *arg = NULL;
-
- if ((on & PM_INTEGER) && OPT_HASARG(ops,'i'))
- arg = OPT_ARG(ops,'i');
- else if ((on & PM_EFLOAT) && OPT_HASARG(ops,'E'))
- arg = OPT_ARG(ops,'E');
- else if ((on & PM_FFLOAT) && OPT_HASARG(ops,'F'))
- arg = OPT_ARG(ops,'F');
-
- if (arg) {
- char *eptr;
- int base = (int)zstrtol(arg, &eptr, 10);
- if (*eptr) {
- if (on & PM_INTEGER)
- zwarnnam(name, "bad base value: %s", arg);
- else
- zwarnnam(name, "bad precision value: %s", arg);
- return 1;
- }
- if ((on & PM_INTEGER) && (base < 2 || base > 36)) {
- zwarnnam(name, "invalid base (must be 2 to 36 inclusive): %d",
- base);
- return 1;
- }
- pm->base = base;
- } else if (always)
- pm->base = 0;
-
- return 0;
-}
-
-/* Install a width if we are turning on a padding option with an argument */
-
-static int
-typeset_setwidth(const char * name, Param pm, Options ops, int on, int always)
-{
- char *arg = NULL;
-
- if ((on & PM_LEFT) && OPT_HASARG(ops,'L'))
- arg = OPT_ARG(ops,'L');
- else if ((on & PM_RIGHT_B) && OPT_HASARG(ops,'R'))
- arg = OPT_ARG(ops,'R');
- else if ((on & PM_RIGHT_Z) && OPT_HASARG(ops,'Z'))
- arg = OPT_ARG(ops,'Z');
-
- if (arg) {
- char *eptr;
- pm->width = (int)zstrtol(arg, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "bad width value: %s", arg);
- return 1;
- }
- } else if (always)
- pm->width = 0;
-
- return 0;
-}
-
-/* function to set a single parameter */
-
-/**/
-static Param
-typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
- int on, int off, int roff, Asgment asg, Param altpm,
- Options ops, int joinchar)
-{
- int usepm, tc, keeplocal = 0, newspecial = NS_NONE, readonly, dont_set = 0;
- char *subscript;
-
- /*
- * Do we use the existing pm? Note that this isn't the end of the
- * story, because if we try and create a new pm at the same
- * locallevel as an unset one we use the pm struct anyway: that's
- * handled in createparam(). Here we just avoid using it for the
- * present tests if it's unset.
- *
- * POSIXBUILTINS horror: we need to retain the 'readonly' or 'export'
- * flags of an unset parameter.
- */
- usepm = pm && (!(pm->node.flags & PM_UNSET) ||
- (isset(POSIXBUILTINS) &&
- (pm->node.flags & (PM_READONLY|PM_EXPORTED))));
-
- /*
- * We need to compare types with an existing pm if special,
- * even if that's unset
- */
- if (!usepm && pm && (pm->node.flags & PM_SPECIAL))
- usepm = 2; /* indicate that we preserve the PM_UNSET flag */
-
- /*
- * Don't use an existing param if
- * - the local level has changed, and
- * - we are really locallizing the parameter
- */
- if (usepm && locallevel != pm->level && (on & PM_LOCAL)) {
- /*
- * If the original parameter was special and we're creating
- * a new one, we need to keep it special.
- *
- * The -h (hide) flag prevents an existing special being made
- * local. It can be applied either to the special or in the
- * typeset/local statement for the local variable.
- */
- if ((pm->node.flags & PM_SPECIAL)
- && !(on & PM_HIDE) && !(pm->node.flags & PM_HIDE & ~off))
- newspecial = NS_NORMAL;
- usepm = 0;
- }
-
- /* attempting a type conversion, or making a tied colonarray? */
- tc = 0;
- if (ASG_ARRAYP(asg) && PM_TYPE(on) == PM_SCALAR &&
- !(usepm && (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))))
- on |= PM_ARRAY;
- if (usepm && ASG_ARRAYP(asg) && newspecial == NS_NONE &&
- PM_TYPE(pm->node.flags) != PM_ARRAY &&
- PM_TYPE(pm->node.flags) != PM_HASHED) {
- if (on & (PM_EFLOAT|PM_FFLOAT|PM_INTEGER)) {
- zerrnam(cname, "%s: can't assign array value to non-array", pname);
- return NULL;
- }
- if (pm->node.flags & PM_SPECIAL) {
- zerrnam(cname, "%s: can't assign array value to non-array special", pname);
- return NULL;
- }
- tc = 1;
- usepm = 0;
- }
- else if (usepm || newspecial != NS_NONE) {
- int chflags = ((off & pm->node.flags) | (on & ~pm->node.flags)) &
- (PM_INTEGER|PM_EFLOAT|PM_FFLOAT|PM_HASHED|
- PM_ARRAY|PM_TIED|PM_AUTOLOAD);
- /* keep the parameter if just switching between floating types */
- if ((tc = chflags && chflags != (PM_EFLOAT|PM_FFLOAT)))
- usepm = 0;
- }
-
- /*
- * Extra checks if converting the type of a parameter, or if
- * trying to remove readonlyness. It's dangerous doing either
- * with a special or a parameter which isn't loaded yet (which
- * may be special when it is loaded; we can't tell yet).
- */
- if ((readonly =
- ((usepm || newspecial != NS_NONE) &&
- (off & pm->node.flags & PM_READONLY))) ||
- tc) {
- if (pm->node.flags & PM_SPECIAL) {
- int err = 1;
- if (!readonly && !strcmp(pname, "SECONDS"))
- {
- /*
- * We allow SECONDS to change type between integer
- * and floating point. If we are creating a new
- * local copy we check the type here and allow
- * a new special to be created with that type.
- * We then need to make sure the correct type
- * for the special is restored at the end of the scope.
- * If we are changing the type of an existing
- * parameter, we do the whole thing here.
- */
- if (newspecial != NS_NONE)
- {
- /*
- * The first test allows `typeset' to copy the
- * existing type. This is the usual behaviour
- * for making special parameters local.
- */
- if (PM_TYPE(on) == 0 || PM_TYPE(on) == PM_INTEGER ||
- PM_TYPE(on) == PM_FFLOAT || PM_TYPE(on) == PM_EFLOAT)
- {
- newspecial = NS_SECONDS;
- err = 0; /* and continue */
- tc = 0; /* but don't do a normal conversion */
- }
- } else if (!setsecondstype(pm, on, off)) {
- if (asg->value.scalar &&
- !(pm = assignsparam(
- pname, ztrdup(asg->value.scalar), 0)))
- return NULL;
- usepm = 1;
- err = 0;
- }
- }
- if (err)
- {
- zerrnam(cname, "%s: can't change type of a special parameter",
- pname);
- return NULL;
- }
- } else if (pm->node.flags & PM_AUTOLOAD) {
- zerrnam(cname, "%s: can't change type of autoloaded parameter",
- pname);
- return NULL;
- }
- }
- else if (newspecial != NS_NONE && strcmp(pname, "SECONDS") == 0)
- newspecial = NS_SECONDS;
-
- if (isset(POSIXBUILTINS)) {
- /*
- * Stricter rules about retaining readonly attribute in this case.
- */
- if ((on & (PM_READONLY|PM_EXPORTED)) &&
- (!usepm || (pm->node.flags & PM_UNSET)) &&
- !ASG_VALUEP(asg))
- on |= PM_UNSET;
- else if (usepm && (pm->node.flags & PM_READONLY) &&
- !(on & PM_READONLY)) {
- zerr("read-only variable: %s", pm->node.nam);
- return NULL;
- }
- /* This is handled by createparam():
- if (usepm && (pm->node.flags & PM_EXPORTED) && !(off & PM_EXPORTED))
- on |= PM_EXPORTED;
- */
- }
-
- /*
- * A parameter will be local if
- * 1. we are re-using an existing local parameter
- * or
- * 2. we are not using an existing parameter, but
- * i. there is already a parameter, which will be hidden
- * or
- * ii. we are creating a new local parameter
- */
- if (usepm) {
- if ((asg->flags & ASG_ARRAY) ?
- !(PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) :
- (asg->value.scalar && (PM_TYPE(pm->node.flags &
- (PM_ARRAY|PM_HASHED))))) {
- zerrnam(cname, "%s: inconsistent type for assignment", pname);
- return NULL;
- }
- on &= ~PM_LOCAL;
- if (!on && !roff && !ASG_VALUEP(asg)) {
- if (OPT_ISSET(ops,'p'))
- paramtab->printnode(&pm->node, PRINT_TYPESET);
- else if (!OPT_ISSET(ops,'g') &&
- (unset(TYPESETSILENT) || OPT_ISSET(ops,'m')))
- paramtab->printnode(&pm->node, PRINT_INCLUDEVALUE);
- return pm;
- }
- if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerrnam(cname, "%s: restricted", pname);
- return pm;
- }
- if ((on & PM_UNIQUE) && !(pm->node.flags & PM_READONLY & ~off)) {
- Param apm;
- char **x;
- if (PM_TYPE(pm->node.flags) == PM_ARRAY) {
- x = (*pm->gsu.a->getfn)(pm);
- uniqarray(x);
- if (pm->node.flags & PM_SPECIAL) {
- if (zheapptr(x))
- x = zarrdup(x);
- (*pm->gsu.a->setfn)(pm, x);
- } else if (pm->ename && x)
- arrfixenv(pm->ename, x);
- } else if (PM_TYPE(pm->node.flags) == PM_SCALAR && pm->ename &&
- (apm =
- (Param) paramtab->getnode(paramtab, pm->ename))) {
- x = (*apm->gsu.a->getfn)(apm);
- uniqarray(x);
- if (x)
- arrfixenv(pm->node.nam, x);
- }
- }
- if (usepm == 2) /* do not change the PM_UNSET flag */
- pm->node.flags = (pm->node.flags | (on & ~PM_READONLY)) & ~off;
- else {
- /*
- * Keep unset if using readonly in POSIX mode.
- */
- if (!(on & PM_READONLY) || !isset(POSIXBUILTINS))
- off |= PM_UNSET;
- pm->node.flags = (pm->node.flags |
- (on & ~PM_READONLY)) & ~off;
- }
- if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
- if (typeset_setwidth(cname, pm, ops, on, 0))
- return NULL;
- }
- if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) {
- if (typeset_setbase(cname, pm, ops, on, 0))
- return NULL;
- }
- if (!(pm->node.flags & (PM_ARRAY|PM_HASHED))) {
- if (pm->node.flags & PM_EXPORTED) {
- if (!(pm->node.flags & PM_UNSET) && !pm->env && !ASG_VALUEP(asg))
- addenv(pm, getsparam(pname));
- } else if (pm->env && !(pm->node.flags & PM_HASHELEM))
- delenv(pm);
- DPUTS(ASG_ARRAYP(asg), "BUG: typeset got array value where scalar expected");
- if (asg->value.scalar &&
- !(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0)))
- return NULL;
- } else if (asg->flags & ASG_ARRAY) {
- int flags = (asg->flags & ASG_KEY_VALUE) ? ASSPM_KEY_VALUE : 0;
- if (!(pm = assignaparam(pname, asg->value.array ?
- zlinklist2array(asg->value.array) :
- mkarray(NULL), flags)))
- return NULL;
- }
- if (errflag)
- return NULL;
- pm->node.flags |= (on & PM_READONLY);
- if (OPT_ISSET(ops,'p'))
- paramtab->printnode(&pm->node, PRINT_TYPESET);
- return pm;
- }
-
- if ((asg->flags & ASG_ARRAY) ?
- !(on & (PM_ARRAY|PM_HASHED)) :
- (asg->value.scalar && (on & (PM_ARRAY|PM_HASHED)))) {
- zerrnam(cname, "%s: inconsistent type for assignment", pname);
- return NULL;
- }
-
- /*
- * We're here either because we're creating a new parameter,
- * or we're adding a parameter at a different local level,
- * or we're converting the type of a parameter. In the
- * last case only, we need to delete the old parameter.
- */
- if (tc) {
- /* Maintain existing readonly/exported status... */
- on |= ~off & (PM_READONLY|PM_EXPORTED) & pm->node.flags;
- /* ...but turn off existing readonly so we can delete it */
- pm->node.flags &= ~PM_READONLY;
- /*
- * If we're just changing the type, we should keep the
- * variable at the current level of localness.
- */
- keeplocal = pm->level;
- /*
- * Try to carry over a value, but not when changing from,
- * to, or between non-scalar types.
- *
- * (We can do better now, but it does have user-visible
- * implications.)
- */
- if (!ASG_VALUEP(asg) && !((pm->node.flags|on) & (PM_ARRAY|PM_HASHED))) {
- asg->value.scalar = dupstring(getsparam(pname));
- asg->flags = 0;
- }
- /* pname may point to pm->nam which is about to disappear */
- pname = dupstring(pname);
- unsetparam_pm(pm, 0, 1);
- }
-
- if (newspecial != NS_NONE) {
- Param tpm, pm2;
- if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerrnam(cname, "%s: restricted", pname);
- return pm;
- }
- if (pm->node.flags & PM_SINGLE) {
- zerrnam(cname, "%s: can only have a single instance", pname);
- return pm;
- }
- /*
- * For specials, we keep the same struct but zero everything.
- * Maybe it would be easier to create a new struct but copy
- * the get/set methods.
- */
- tpm = (Param) zshcalloc(sizeof *tpm);
-
- tpm->node.nam = pm->node.nam;
- if (pm->ename &&
- (pm2 = (Param) paramtab->getnode(paramtab, pm->ename)) &&
- pm2->level == locallevel) {
- /* This is getting silly, but anyway: if one of a path/PATH
- * pair has already been made local at the current level, we
- * have to make sure that the other one does not have its value
- * saved: since that comes from an internal variable it will
- * already reflect the local value, so restoring it on exit
- * would be wrong.
- *
- * This problem is also why we make sure we have a copy
- * of the environment entry in tpm->env, rather than relying
- * on the restored value to provide it.
- */
- tpm->node.flags = pm->node.flags | PM_NORESTORE;
- } else {
- copyparam(tpm, pm, 1);
- }
- tpm->old = pm->old;
- tpm->level = pm->level;
- tpm->base = pm->base;
- tpm->width = pm->width;
- if (pm->env)
- delenv(pm);
- tpm->env = NULL;
-
- pm->old = tpm;
- /*
- * The remaining on/off flags should be harmless to use,
- * because we've checked for unpleasant surprises above.
- */
- pm->node.flags = (PM_TYPE(pm->node.flags) | on | PM_SPECIAL) & ~off;
- /*
- * Readonlyness of special parameters must be preserved.
- */
- pm->node.flags |= tpm->node.flags & PM_READONLY;
- if (newspecial == NS_SECONDS) {
- /* We save off the raw internal value of the SECONDS var */
- tpm->u.dval = getrawseconds();
- setsecondstype(pm, on, off);
- }
-
- /*
- * Final tweak: if we've turned on one of the flags with
- * numbers, we should use the appropriate integer.
- */
- if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) {
- if (typeset_setwidth(cname, pm, ops, on, 1))
- return NULL;
- }
- if (on & (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) {
- if (typeset_setbase(cname, pm, ops, on, 1))
- return NULL;
- }
- } else if ((subscript = strchr(pname, '['))) {
- if (on & PM_READONLY) {
- zerrnam(cname,
- "%s: can't create readonly array elements", pname);
- return NULL;
- } else if ((on & PM_LOCAL) && locallevel) {
- *subscript = 0;
- pm = (Param) (paramtab == realparamtab ?
- /* getnode2() to avoid autoloading */
- paramtab->getnode2(paramtab, pname) :
- paramtab->getnode(paramtab, pname));
- *subscript = '[';
- if (!pm || pm->level != locallevel) {
- zerrnam(cname,
- "%s: can't create local array elements", pname);
- return NULL;
- }
- }
- if (PM_TYPE(on) == PM_SCALAR && !ASG_ARRAYP(asg)) {
- /*
- * This will either complain about bad identifiers, or will set
- * a hash element or array slice. This once worked by accident,
- * creating a stray parameter along the way via createparam(),
- * now called below in the isident() branch.
- */
- if (!(pm = assignsparam(
- pname,
- ztrdup(asg->value.scalar ? asg->value.scalar : ""), 0)))
- return NULL;
- dont_set = 1;
- asg->flags = 0;
- keeplocal = 0;
- on = pm->node.flags;
- } else if (PM_TYPE(on) == PM_ARRAY && ASG_ARRAYP(asg)) {
- int flags = (asg->flags & ASG_KEY_VALUE) ? ASSPM_KEY_VALUE : 0;
- if (!(pm = assignaparam(pname, asg->value.array ?
- zlinklist2array(asg->value.array) :
- mkarray(NULL), flags)))
- return NULL;
- dont_set = 1;
- keeplocal = 0;
- on = pm->node.flags;
- } else {
- zerrnam(cname,
- "%s: inconsistent array element or slice assignment", pname);
- return NULL;
- }
- }
- /*
- * As we can hide existing parameters, we allow a name if
- * it's not a normal identifier but is one of the special
- * set found in the parameter table. The second test is
- * because we can set individual positional parameters;
- * however "0" is not a positional parameter and is OK.
- *
- * It would be neater to extend isident() and be clearer
- * about where we allow various parameter types. It's
- * not entirely clear to me isident() should reject
- * specially named parameters given that it accepts digits.
- */
- else if ((isident(pname) || paramtab->getnode(paramtab, pname))
- && (!idigit(*pname) || !strcmp(pname, "0"))) {
- /*
- * Create a new node for a parameter with the flags in `on' minus the
- * readonly flag
- */
- pm = createparam(pname, on & ~PM_READONLY);
- if (!pm) {
- if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z |
- PM_INTEGER | PM_EFLOAT | PM_FFLOAT))
- zerrnam(cname, "can't change variable attribute: %s", pname);
- return NULL;
- }
- if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
- if (typeset_setwidth(cname, pm, ops, on, 0))
- return NULL;
- }
- if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) {
- if (typeset_setbase(cname, pm, ops, on, 0))
- return NULL;
- }
- } else {
- if (idigit(*pname))
- zerrnam(cname, "not an identifier: %s", pname);
- else
- zerrnam(cname, "not valid in this context: %s", pname);
- return NULL;
- }
-
- if (altpm && PM_TYPE(pm->node.flags) == PM_SCALAR) {
- /*
- * It seems safer to set this here than in createparam(),
- * to make sure we only ever use the colonarr functions
- * when u.data is correctly set.
- */
- struct tieddata *tdp = (struct tieddata *)
- zalloc(sizeof(struct tieddata));
- if (!tdp)
- return NULL;
- tdp->joinchar = joinchar;
- tdp->arrptr = &altpm->u.arr;
-
- pm->gsu.s = &tiedarr_gsu;
- pm->u.data = tdp;
- }
-
- if (keeplocal)
- pm->level = keeplocal;
- else if (on & PM_LOCAL)
- pm->level = locallevel;
- if (ASG_VALUEP(asg) && !dont_set) {
- Param ipm = pm;
- if (pm->node.flags & (PM_ARRAY|PM_HASHED)) {
- char **arrayval;
- int flags = (asg->flags & ASG_KEY_VALUE) ? ASSPM_KEY_VALUE : 0;
- if (!ASG_ARRAYP(asg)) {
- /*
- * Attempt to assign a scalar value to an array.
- * This can happen if the array is special.
- * We'll be lenient and guess what the user meant.
- * This is how normal assigment works.
- */
- if (*asg->value.scalar) {
- /* Array with one value */
- arrayval = mkarray(ztrdup(asg->value.scalar));
- } else {
- /* Empty array */
- arrayval = mkarray(NULL);
- }
- } else if (asg->value.array)
- arrayval = zlinklist2array(asg->value.array);
- else
- arrayval = mkarray(NULL);
- if (!(pm=assignaparam(pname, arrayval, flags)))
- return NULL;
- } else {
- DPUTS(ASG_ARRAYP(asg), "BUG: inconsistent array value for scalar");
- if (!(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0)))
- return NULL;
- }
- if (pm != ipm) {
- DPUTS(ipm->node.flags != pm->node.flags,
- "BUG: parameter recreated with wrong flags");
- unsetparam_pm(ipm, 0, 1);
- }
- } else if (newspecial != NS_NONE &&
- !(pm->old->node.flags & (PM_NORESTORE|PM_READONLY))) {
- /*
- * We need to use the special setting function to re-initialise
- * the special parameter to empty.
- */
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- pm->gsu.s->setfn(pm, ztrdup(""));
- break;
- case PM_INTEGER:
- /*
- * Restricted integers are dangerous to initialize to 0,
- * so don't do that.
- */
- if (!(pm->old->node.flags & PM_RESTRICTED))
- pm->gsu.i->setfn(pm, 0);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- pm->gsu.f->setfn(pm, 0.0);
- break;
- case PM_ARRAY:
- pm->gsu.a->setfn(pm, mkarray(NULL));
- break;
- case PM_HASHED:
- pm->gsu.h->setfn(pm, newparamtable(17, pm->node.nam));
- break;
- }
- }
- pm->node.flags |= (on & PM_READONLY);
-
- if (OPT_ISSET(ops,'p'))
- paramtab->printnode(&pm->node, PRINT_TYPESET);
-
- return pm;
-}
-
-/*
- * declare, export, float, integer, local, readonly, typeset
- *
- * Note the difference in interface from most builtins, covered by the
- * BINF_ASSIGN builtin flag. This is only made use of by builtins
- * called by reserved word, which only covers declare, local, readonly
- * and typeset. Otherwise assigns is NULL.
- */
-
-/**/
-int
-bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
-{
- Param pm;
- Asgment asg;
- Patprog pprog;
- char *optstr = TYPESET_OPTSTR;
- int on = 0, off = 0, roff, bit = PM_ARRAY;
- int i;
- int returnval = 0, printflags = 0;
- int hasargs;
-
- /* hash -f is really the builtin `functions' */
- if (OPT_ISSET(ops,'f'))
- return bin_functions(name, argv, ops, func);
-
- /* POSIX handles "readonly" specially */
- if (func == BIN_READONLY && isset(POSIXBUILTINS) && !OPT_PLUS(ops, 'g'))
- ops->ind['g'] = 1;
-
- /* Translate the options into PM_* flags. *
- * Unfortunately, this depends on the order *
- * these flags are defined in zsh.h */
- for (; *optstr; optstr++, bit <<= 1)
- {
- int optval = STOUC(*optstr);
- if (OPT_MINUS(ops,optval))
- on |= bit;
- else if (OPT_PLUS(ops,optval))
- off |= bit;
- }
- roff = off;
-
- /* Sanity checks on the options. Remove conflicting options. */
- if (on & PM_FFLOAT) {
- off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_EFLOAT;
- /* Allow `float -F' to work even though float sets -E by default */
- on &= ~PM_EFLOAT;
- }
- if (on & PM_EFLOAT)
- off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_FFLOAT;
- if (on & PM_INTEGER)
- off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_EFLOAT | PM_FFLOAT;
- /*
- * Allowing -Z with -L is a feature: left justify, suppressing
- * leading zeroes.
- */
- if (on & (PM_LEFT|PM_RIGHT_Z))
- off |= PM_RIGHT_B;
- if (on & PM_RIGHT_B)
- off |= PM_LEFT | PM_RIGHT_Z;
- if (on & PM_UPPER)
- off |= PM_LOWER;
- if (on & PM_LOWER)
- off |= PM_UPPER;
- if (on & PM_HASHED)
- off |= PM_ARRAY;
- if (on & PM_TIED)
- off |= PM_INTEGER | PM_EFLOAT | PM_FFLOAT | PM_ARRAY | PM_HASHED;
-
- on &= ~off;
-
- queue_signals();
-
- /* Given no arguments, list whatever the options specify. */
- if (OPT_ISSET(ops,'p')) {
- printflags |= PRINT_TYPESET;
- if (OPT_HASARG(ops,'p')) {
- char *eptr;
- int pflag = (int)zstrtol(OPT_ARG(ops,'p'), &eptr, 10);
- if (pflag == 1 && !*eptr)
- printflags |= PRINT_LINE;
- else if (pflag || *eptr) {
- zwarnnam(name, "bad argument to -p: %s", OPT_ARG(ops,'p'));
- unqueue_signals();
- return 1;
- }
- /* -p0 treated as -p for consistency */
- }
- }
- hasargs = *argv != NULL || (assigns && firstnode(assigns));
- if (!hasargs) {
- if (!OPT_ISSET(ops,'p')) {
- if (!(on|roff))
- printflags |= PRINT_TYPE;
- if (roff || OPT_ISSET(ops,'+'))
- printflags |= PRINT_NAMEONLY;
- }
- scanhashtable(paramtab, 1, on|roff, 0, paramtab->printnode, printflags);
- unqueue_signals();
- return 0;
- }
-
- if (!(OPT_ISSET(ops,'g') || OPT_ISSET(ops,'x') || OPT_ISSET(ops,'m')) ||
- OPT_PLUS(ops,'g') || *name == 'l' ||
- (!isset(GLOBALEXPORT) && !OPT_ISSET(ops,'g')))
- on |= PM_LOCAL;
-
- if (on & PM_TIED) {
- Param apm;
- struct asgment asg0, asg2;
- char *oldval = NULL, *joinstr;
- int joinchar, nargs;
-
- if (OPT_ISSET(ops,'m')) {
- zwarnnam(name, "incompatible options for -T");
- unqueue_signals();
- return 1;
- }
- on &= ~off;
- nargs = arrlen(argv) + (assigns ? countlinknodes(assigns) : 0);
- if (nargs < 2) {
- zwarnnam(name, "-T requires names of scalar and array");
- unqueue_signals();
- return 1;
- }
- if (nargs > 3) {
- zwarnnam(name, "too many arguments for -T");
- unqueue_signals();
- return 1;
- }
-
- if (!(asg = getasg(&argv, assigns))) {
- unqueue_signals();
- return 1;
- }
- asg0 = *asg;
- if (ASG_ARRAYP(&asg0)) {
- unqueue_signals();
- zwarnnam(name, "first argument of tie must be scalar: %s",
- asg0.name);
- return 1;
- }
-
- if (!(asg = getasg(&argv, assigns))) {
- unqueue_signals();
- return 1;
- }
- if (!ASG_ARRAYP(asg) && asg->value.scalar) {
- unqueue_signals();
- zwarnnam(name, "second argument of tie must be array: %s",
- asg->name);
- return 1;
- }
-
- if (!strcmp(asg0.name, asg->name)) {
- unqueue_signals();
- zerrnam(name, "can't tie a variable to itself: %s", asg0.name);
- return 1;
- }
- if (strchr(asg0.name, '[') || strchr(asg->name, '[')) {
- unqueue_signals();
- zerrnam(name, "can't tie array elements: %s", asg0.name);
- return 1;
- }
- if (ASG_VALUEP(asg) && ASG_VALUEP(&asg0)) {
- unqueue_signals();
- zerrnam(name, "only one tied parameter can have value: %s", asg0.name);
- return 1;
- }
-
- /*
- * Third argument, if given, is character used to join
- * the elements of the array in the scalar.
- */
- if (*argv)
- joinstr = *argv;
- else if (assigns && firstnode(assigns)) {
- Asgment nextasg = (Asgment)firstnode(assigns);
- if (ASG_ARRAYP(nextasg) || ASG_VALUEP(nextasg)) {
- zwarnnam(name, "third argument of tie must be join character");
- unqueue_signals();
- return 1;
- }
- joinstr = nextasg->name;
- } else
- joinstr = NULL;
- if (!joinstr)
- joinchar = ':';
- else if (!*joinstr)
- joinchar = 0;
- else if (*joinstr == Meta)
- joinchar = joinstr[1] ^ 32;
- else
- joinchar = *joinstr;
- /*
- * Keep the old value of the scalar. We need to do this
- * here as if it is already tied to the same array it
- * will be unset when we retie the array. This is all
- * so that typeset -T is idempotent.
- *
- * We also need to remember here whether the damn thing is
- * exported and pass that along. Isn't the world complicated?
- */
- if ((pm = (Param) paramtab->getnode(paramtab, asg0.name))
- && !(pm->node.flags & PM_UNSET)
- && (locallevel == pm->level || !(on & PM_LOCAL))) {
- if (pm->node.flags & PM_TIED) {
- unqueue_signals();
- if (PM_TYPE(pm->node.flags) != PM_SCALAR) {
- zwarnnam(name, "already tied as non-scalar: %s", asg0.name);
- } else if (!strcmp(asg->name, pm->ename)) {
- /*
- * Already tied in the fashion requested.
- */
- struct tieddata *tdp = (struct tieddata*)pm->u.data;
- int flags = (asg->flags & ASG_KEY_VALUE) ?
- ASSPM_KEY_VALUE : 0;
- /* Update join character */
- tdp->joinchar = joinchar;
- if (asg0.value.scalar)
- assignsparam(asg0.name, ztrdup(asg0.value.scalar), 0);
- else if (asg->value.array)
- assignaparam(
- asg->name, zlinklist2array(asg->value.array),flags);
- return 0;
- } else {
- zwarnnam(name, "can't tie already tied scalar: %s",
- asg0.name);
- }
- return 1;
- }
- if (!asg0.value.scalar && !asg->value.array &&
- !(PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)))
- oldval = ztrdup(getsparam(asg0.name));
- on |= (pm->node.flags & PM_EXPORTED);
- }
- /*
- * Create the tied array; this is normal except that
- * it has the PM_TIED flag set. Do it first because
- * we need the address.
- *
- * Don't attempt to set it yet, it's too early
- * to be exported properly.
- */
- asg2.name = asg->name;
- asg2.flags = 0;
- asg2.value.array = (LinkList)0;
- if (!(apm=typeset_single(name, asg->name,
- (Param)paramtab->getnode(paramtab,
- asg->name),
- func, (on | PM_ARRAY) & ~PM_EXPORTED,
- off, roff, &asg2, NULL, ops, 0))) {
- if (oldval)
- zsfree(oldval);
- unqueue_signals();
- return 1;
- }
- /*
- * Create the tied colonarray. We make it as a normal scalar
- * and fix up the oddities later.
- */
- if (!(pm=typeset_single(name, asg0.name,
- (Param)paramtab->getnode(paramtab,
- asg0.name),
- func, on, off, roff, &asg0, apm,
- ops, joinchar))) {
- if (oldval)
- zsfree(oldval);
- unsetparam_pm(apm, 1, 1);
- unqueue_signals();
- return 1;
- }
-
- /*
- * pm->ename is only deleted when the struct is, so
- * we need to free it here if it already exists.
- */
- if (pm->ename)
- zsfree(pm->ename);
- pm->ename = ztrdup(asg->name);
- if (apm->ename)
- zsfree(apm->ename);
- apm->ename = ztrdup(asg0.name);
- if (asg->value.array) {
- int flags = (asg->flags & ASG_KEY_VALUE) ? ASSPM_KEY_VALUE : 0;
- assignaparam(asg->name, zlinklist2array(asg->value.array), flags);
- } else if (oldval)
- assignsparam(asg0.name, oldval, 0);
- unqueue_signals();
-
- return 0;
- }
- if (off & PM_TIED) {
- unqueue_signals();
- zerrnam(name, "use unset to remove tied variables");
- return 1;
- }
-
- /* With the -m option, treat arguments as glob patterns */
- if (OPT_ISSET(ops,'m')) {
- if (!OPT_ISSET(ops,'p')) {
- if (!(on|roff))
- printflags |= PRINT_TYPE;
- if (!on)
- printflags |= PRINT_NAMEONLY;
- }
-
- while ((asg = getasg(&argv, assigns))) {
- LinkList pmlist = newlinklist();
- LinkNode pmnode;
-
- tokenize(asg->name); /* expand argument */
- if (!(pprog = patcompile(asg->name, 0, NULL))) {
- untokenize(asg->name);
- zwarnnam(name, "bad pattern : %s", asg->name);
- returnval = 1;
- continue;
- }
- if (OPT_PLUS(ops,'m') && !ASG_VALUEP(asg)) {
- scanmatchtable(paramtab, pprog, 1, on|roff, 0,
- paramtab->printnode, printflags);
- continue;
- }
- /*
- * Search through the parameter table and change all parameters
- * matching the glob pattern to have these flags and/or value.
- * Bad news: if the parameter gets altered, e.g. by
- * a type conversion, then paramtab can be shifted around,
- * so we need to store the parameters to alter on a separate
- * list for later use.
- */
- for (i = 0; i < paramtab->hsize; i++) {
- for (pm = (Param) paramtab->nodes[i]; pm;
- pm = (Param) pm->node.next) {
- if (((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) ||
- (pm->node.flags & PM_UNSET))
- continue;
- if (pattry(pprog, pm->node.nam))
- addlinknode(pmlist, pm);
- }
- }
- for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
- pm = (Param) getdata(pmnode);
- if (!typeset_single(name, pm->node.nam, pm, func, on, off, roff,
- asg, NULL, ops, 0))
- returnval = 1;
- }
- }
- unqueue_signals();
- return returnval;
- }
-
- /* Take arguments literally. Don't glob */
- while ((asg = getasg(&argv, assigns))) {
- HashNode hn = (paramtab == realparamtab ?
- /* getnode2() to avoid autoloading */
- paramtab->getnode2(paramtab, asg->name) :
- paramtab->getnode(paramtab, asg->name));
- if (OPT_ISSET(ops,'p')) {
- if (hn)
- paramtab->printnode(hn, printflags);
- else {
- zwarnnam(name, "no such variable: %s", asg->name);
- returnval = 1;
- }
- continue;
- }
- if (!typeset_single(name, asg->name, (Param)hn,
- func, on, off, roff, asg, NULL,
- ops, 0))
- returnval = 1;
- }
- unqueue_signals();
- return returnval;
-}
-
-/* Helper for bin_functions() when run as "autoload -X" */
-
-/**/
-int
-eval_autoload(Shfunc shf, char *name, Options ops, int func)
-{
- if (!(shf->node.flags & PM_UNDEFINED))
- return 1;
-
- if (shf->funcdef) {
- freeeprog(shf->funcdef);
- shf->funcdef = &dummy_eprog;
- }
- if (OPT_MINUS(ops,'X')) {
- char *fargv[3];
- fargv[0] = name;
- fargv[1] = "\"$@\"";
- fargv[2] = 0;
- shf->funcdef = mkautofn(shf);
- return bin_eval(name, fargv, ops, func);
- }
-
- return !loadautofn(shf, (OPT_ISSET(ops,'k') ? 2 :
- (OPT_ISSET(ops,'z') ? 0 : 1)), 1,
- OPT_ISSET(ops,'d'));
-}
-
-/* Helper for bin_functions() for -X and -r options */
-
-/**/
-static int
-check_autoload(Shfunc shf, char *name, Options ops, int func)
-{
- if (OPT_ISSET(ops,'X'))
- {
- return eval_autoload(shf, name, ops, func);
- }
- if ((OPT_ISSET(ops,'r') || OPT_ISSET(ops,'R')) &&
- (shf->node.flags & PM_UNDEFINED))
- {
- char *dir_path;
- if (shf->filename && (shf->node.flags & PM_LOADDIR)) {
- char *spec_path[2];
- spec_path[0] = shf->filename;
- spec_path[1] = NULL;
- if (getfpfunc(shf->node.nam, NULL, &dir_path, spec_path, 1)) {
- /* shf->filename is already correct. */
- return 0;
- }
- if (!OPT_ISSET(ops,'d')) {
- if (OPT_ISSET(ops,'R')) {
- zerr("%s: function definition file not found",
- shf->node.nam);
- return 1;
- }
- return 0;
- }
- }
- if (getfpfunc(shf->node.nam, NULL, &dir_path, NULL, 1)) {
- dircache_set(&shf->filename, NULL);
- if (*dir_path != '/') {
- dir_path = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP),
- "/", dir_path);
- dir_path = xsymlink(dir_path, 1);
- }
- dircache_set(&shf->filename, dir_path);
- shf->node.flags |= PM_LOADDIR;
- return 0;
- }
- if (OPT_ISSET(ops,'R')) {
- zerr("%s: function definition file not found",
- shf->node.nam);
- return 1;
- }
- /* with -r, we don't flag an error, just let it be found later. */
- }
- return 0;
-}
-
-/* List a user-defined math function. */
-static void
-listusermathfunc(MathFunc p)
-{
- int showargs;
-
- if (p->module)
- showargs = 3;
- else if (p->maxargs != (p->minargs ? p->minargs : -1))
- showargs = 2;
- else if (p->minargs)
- showargs = 1;
- else
- showargs = 0;
-
- printf("functions -M%s %s", (p->flags & MFF_STR) ? "s" : "", p->name);
- if (showargs) {
- printf(" %d", p->minargs);
- showargs--;
- }
- if (showargs) {
- printf(" %d", p->maxargs);
- showargs--;
- }
- if (showargs) {
- /*
- * function names are not required to consist of ident characters
- */
- putchar(' ');
- quotedzputs(p->module, stdout);
- showargs--;
- }
- putchar('\n');
-}
-
-
-static void
-add_autoload_function(Shfunc shf, char *funcname)
-{
- char *nam;
- if (*funcname == '/' && funcname[1] &&
- (nam = strrchr(funcname, '/')) && nam[1] &&
- (shf->node.flags & PM_UNDEFINED)) {
- char *dir;
- nam = strrchr(funcname, '/');
- if (nam == funcname) {
- dir = "/";
- } else {
- *nam++ = '\0';
- dir = funcname;
- }
- dircache_set(&shf->filename, NULL);
- dircache_set(&shf->filename, dir);
- shf->node.flags |= PM_LOADDIR;
- shf->node.flags |= PM_ABSPATH_USED;
- shfunctab->addnode(shfunctab, ztrdup(nam), shf);
- } else {
- Shfunc shf2;
- Funcstack fs;
- const char *calling_f = NULL;
- char buf[PATH_MAX+1];
-
- /* Find calling function */
- for (fs = funcstack; fs; fs = fs->prev) {
- if (fs->tp == FS_FUNC && fs->name && (!shf->node.nam || 0 != strcmp(fs->name,shf->node.nam))) {
- calling_f = fs->name;
- break;
- }
- }
-
- /* Get its directory */
- if (calling_f) {
- /* Should contain load directory, and be loaded via absolute path */
- if ((shf2 = (Shfunc) shfunctab->getnode2(shfunctab, calling_f))
- && (shf2->node.flags & PM_LOADDIR) && (shf2->node.flags & PM_ABSPATH_USED)
- && shf2->filename)
- {
- if (strlen(shf2->filename) + strlen(funcname) + 1 < PATH_MAX)
- {
- sprintf(buf, "%s/%s", shf2->filename, funcname);
- /* Set containing directory if the function file
- * exists (do normal FPATH processing otherwise) */
- if (!access(buf, R_OK)) {
- dircache_set(&shf->filename, NULL);
- dircache_set(&shf->filename, shf2->filename);
- shf->node.flags |= PM_LOADDIR;
- shf->node.flags |= PM_ABSPATH_USED;
- }
- }
- }
- }
-
- shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
- }
-}
-
-/* Display or change the attributes of shell functions. *
- * If called as autoload, it will define a new autoloaded *
- * (undefined) shell function. */
-
-/**/
-int
-bin_functions(char *name, char **argv, Options ops, int func)
-{
- Patprog pprog;
- Shfunc shf;
- int i, returnval = 0;
- int on = 0, off = 0, pflags = 0, roff, expand = 0;
-
- /* Do we have any flags defined? */
- if (OPT_PLUS(ops,'u'))
- off |= PM_UNDEFINED;
- else if (OPT_MINUS(ops,'u') || OPT_ISSET(ops,'X'))
- on |= PM_UNDEFINED;
- if (OPT_MINUS(ops,'U'))
- on |= PM_UNALIASED|PM_UNDEFINED;
- else if (OPT_PLUS(ops,'U'))
- off |= PM_UNALIASED;
- if (OPT_MINUS(ops,'t'))
- on |= PM_TAGGED;
- else if (OPT_PLUS(ops,'t'))
- off |= PM_TAGGED;
- if (OPT_MINUS(ops,'T'))
- on |= PM_TAGGED_LOCAL;
- else if (OPT_PLUS(ops,'T'))
- off |= PM_TAGGED_LOCAL;
- if (OPT_MINUS(ops,'W'))
- on |= PM_WARNNESTED;
- else if (OPT_PLUS(ops,'W'))
- off |= PM_WARNNESTED;
- roff = off;
- if (OPT_MINUS(ops,'z')) {
- on |= PM_ZSHSTORED;
- off |= PM_KSHSTORED;
- } else if (OPT_PLUS(ops,'z')) {
- off |= PM_ZSHSTORED;
- roff |= PM_ZSHSTORED;
- }
- if (OPT_MINUS(ops,'k')) {
- on |= PM_KSHSTORED;
- off |= PM_ZSHSTORED;
- } else if (OPT_PLUS(ops,'k')) {
- off |= PM_KSHSTORED;
- roff |= PM_KSHSTORED;
- }
- if (OPT_MINUS(ops,'d')) {
- on |= PM_CUR_FPATH;
- off |= PM_CUR_FPATH;
- } else if (OPT_PLUS(ops,'d')) {
- off |= PM_CUR_FPATH;
- roff |= PM_CUR_FPATH;
- }
-
- if ((off & PM_UNDEFINED) || (OPT_ISSET(ops,'k') && OPT_ISSET(ops,'z')) ||
- (OPT_ISSET(ops,'x') && !OPT_HASARG(ops,'x')) ||
- (OPT_MINUS(ops,'X') && (OPT_ISSET(ops,'m') || !scriptname))) {
- zwarnnam(name, "invalid option(s)");
- return 1;
- }
-
- if (OPT_ISSET(ops,'x')) {
- char *eptr;
- expand = (int)zstrtol(OPT_ARG(ops,'x'), &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expected after -x");
- return 1;
- }
- if (expand == 0) /* no indentation at all */
- expand = -1;
- }
-
- if (OPT_PLUS(ops,'f') || roff || OPT_ISSET(ops,'+'))
- pflags |= PRINT_NAMEONLY;
-
- if (OPT_MINUS(ops,'M') || OPT_PLUS(ops,'M')) {
- MathFunc p, q, prev;
- /*
- * Add/remove/list function as mathematical.
- */
- if (on || off || pflags || OPT_ISSET(ops,'X') || OPT_ISSET(ops,'u')
- || OPT_ISSET(ops,'U') || OPT_ISSET(ops,'w')) {
- zwarnnam(name, "invalid option(s)");
- return 1;
- }
- if (!*argv) {
- /* List functions. */
- queue_signals();
- for (p = mathfuncs; p; p = p->next)
- if (p->flags & MFF_USERFUNC)
- listusermathfunc(p);
- unqueue_signals();
- } else if (OPT_ISSET(ops,'m')) {
- /* List matching functions. */
- for (; *argv; argv++) {
- queue_signals();
- tokenize(*argv);
- if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
- for (p = mathfuncs, q = NULL; p; q = p) {
- MathFunc next;
- do {
- next = NULL;
- if ((p->flags & MFF_USERFUNC) &&
- pattry(pprog, p->name)) {
- if (OPT_PLUS(ops,'M')) {
- next = p->next;
- removemathfunc(q, p);
- p = next;
- } else
- listusermathfunc(p);
- }
- /* if we deleted one, retry with the new p */
- } while (next);
- if (p)
- p = p->next;
- }
- } else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- unqueue_signals();
- }
- } else if (OPT_PLUS(ops,'M')) {
- /* Delete functions. -m is allowed but is handled above. */
- for (; *argv; argv++) {
- queue_signals();
- for (p = mathfuncs, q = NULL; p; q = p, p = p->next) {
- if (!strcmp(p->name, *argv)) {
- if (!(p->flags & MFF_USERFUNC)) {
- zwarnnam(name, "+M %s: is a library function",
- *argv);
- returnval = 1;
- break;
- }
- removemathfunc(q, p);
- break;
- }
- }
- unqueue_signals();
- }
- } else {
- /* Add a function */
- int minargs, maxargs;
- char *funcname = *argv++;
- char *modname = NULL;
- char *ptr;
-
- if (OPT_ISSET(ops,'s')) {
- minargs = maxargs = 1;
- } else {
- minargs = 0;
- maxargs = -1;
- }
-
- ptr = itype_end(funcname, IIDENT, 0);
- if (idigit(*funcname) || funcname == ptr || *ptr) {
- zwarnnam(name, "-M %s: bad math function name", funcname);
- return 1;
- }
-
- if (*argv) {
- minargs = (int)zstrtol(*argv, &ptr, 0);
- if (minargs < 0 || *ptr) {
- zwarnnam(name, "-M: invalid min number of arguments: %s",
- *argv);
- return 1;
- }
- if (OPT_ISSET(ops,'s') && minargs != 1) {
- zwarnnam(name, "-Ms: must take a single string argument");
- return 1;
- }
- maxargs = minargs;
- argv++;
- }
- if (*argv) {
- maxargs = (int)zstrtol(*argv, &ptr, 0);
- if (maxargs < -1 ||
- (maxargs != -1 && maxargs < minargs) ||
- *ptr) {
- zwarnnam(name,
- "-M: invalid max number of arguments: %s",
- *argv);
- return 1;
- }
- if (OPT_ISSET(ops,'s') && maxargs != 1) {
- zwarnnam(name, "-Ms: must take a single string argument");
- return 1;
- }
- argv++;
- }
- if (*argv)
- modname = *argv++;
- if (*argv) {
- zwarnnam(name, "-M: too many arguments");
- return 1;
- }
-
- p = (MathFunc)zshcalloc(sizeof(struct mathfunc));
- p->name = ztrdup(funcname);
- p->flags = MFF_USERFUNC;
- if (OPT_ISSET(ops,'s'))
- p->flags |= MFF_STR;
- p->module = modname ? ztrdup(modname) : NULL;
- p->minargs = minargs;
- p->maxargs = maxargs;
-
- queue_signals();
- for (q = mathfuncs, prev = NULL; q; prev = q, q = q->next) {
- if (!strcmp(q->name, funcname)) {
- removemathfunc(prev, q);
- break;
- }
- }
-
- p->next = mathfuncs;
- mathfuncs = p;
- unqueue_signals();
- }
-
- return returnval;
- }
-
- if (OPT_MINUS(ops,'X')) {
- Funcstack fs;
- char *funcname = NULL;
- int ret;
- if (*argv && argv[1]) {
- zwarnnam(name, "-X: too many arguments");
- return 1;
- }
- queue_signals();
- for (fs = funcstack; fs; fs = fs->prev) {
- if (fs->tp == FS_FUNC) {
- /*
- * dupstring here is paranoia but unlikely to be
- * problematic
- */
- funcname = dupstring(fs->name);
- break;
- }
- }
- if (!funcname)
- {
- zerrnam(name, "bad autoload");
- ret = 1;
- } else {
- if ((shf = (Shfunc) shfunctab->getnode(shfunctab, funcname))) {
- DPUTS(!shf->funcdef,
- "BUG: Calling autoload from empty function");
- } else {
- shf = (Shfunc) zshcalloc(sizeof *shf);
- shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
- }
- if (*argv) {
- dircache_set(&shf->filename, NULL);
- dircache_set(&shf->filename, *argv);
- on |= PM_LOADDIR;
- }
- shf->node.flags = on;
- ret = eval_autoload(shf, funcname, ops, func);
- }
- unqueue_signals();
- return ret;
- } else if (!*argv) {
- /* If no arguments given, we will print functions. If flags *
- * are given, we will print only functions containing these *
- * flags, else we'll print them all. */
- int ret = 0;
-
- queue_signals();
- if (OPT_ISSET(ops,'U') && !OPT_ISSET(ops,'u'))
- on &= ~PM_UNDEFINED;
- scanshfunc(1, on|off, DISABLED, shfunctab->printnode,
- pflags, expand);
- unqueue_signals();
- return ret;
- }
-
- /* With the -m option, treat arguments as glob patterns */
- if (OPT_ISSET(ops,'m')) {
- on &= ~PM_UNDEFINED;
- for (; *argv; argv++) {
- queue_signals();
- /* expand argument */
- tokenize(*argv);
- if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
- /* with no options, just print all functions matching the glob pattern */
- if (!(on|off) && !OPT_ISSET(ops,'X')) {
- scanmatchshfunc(pprog, 1, 0, DISABLED,
- shfunctab->printnode, pflags, expand);
- } else {
- /* apply the options to all functions matching the glob pattern */
- for (i = 0; i < shfunctab->hsize; i++) {
- for (shf = (Shfunc) shfunctab->nodes[i]; shf;
- shf = (Shfunc) shf->node.next)
- if (pattry(pprog, shf->node.nam) &&
- !(shf->node.flags & DISABLED)) {
- shf->node.flags = (shf->node.flags |
- (on & ~PM_UNDEFINED)) & ~off;
- if (check_autoload(shf, shf->node.nam,
- ops, func)) {
- returnval = 1;
- }
- }
- }
- }
- } else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- unqueue_signals();
- }
- return returnval;
- }
-
- /* Take the arguments literally -- do not glob */
- queue_signals();
- for (; *argv; argv++) {
- if (OPT_ISSET(ops,'w'))
- returnval = dump_autoload(name, *argv, on, ops, func);
- else if ((shf = (Shfunc) shfunctab->getnode(shfunctab, *argv))) {
- /* if any flag was given */
- if (on|off) {
- /* turn on/off the given flags */
- shf->node.flags = (shf->node.flags | (on & ~PM_UNDEFINED)) & ~off;
- if (check_autoload(shf, shf->node.nam, ops, func))
- returnval = 1;
- } else
- /* no flags, so just print */
- printshfuncexpand(&shf->node, pflags, expand);
- } else if (on & PM_UNDEFINED) {
- int signum = -1, ok = 1;
-
- if (!strncmp(*argv, "TRAP", 4) &&
- (signum = getsignum(*argv + 4)) != -1) {
- /*
- * Because of the possibility of alternative names,
- * we must remove the trap explicitly.
- */
- removetrapnode(signum);
- }
-
- if (**argv == '/') {
- char *base = strrchr(*argv, '/') + 1;
- if (*base &&
- (shf = (Shfunc) shfunctab->getnode(shfunctab, base))) {
- char *dir;
- /* turn on/off the given flags */
- shf->node.flags =
- (shf->node.flags | (on & ~PM_UNDEFINED)) & ~off;
- if (shf->node.flags & PM_UNDEFINED) {
- /* update path if not yet loaded */
- if (base == *argv + 1)
- dir = "/";
- else {
- dir = *argv;
- base[-1] = '\0';
- }
- dircache_set(&shf->filename, NULL);
- dircache_set(&shf->filename, dir);
- }
- if (check_autoload(shf, shf->node.nam, ops, func))
- returnval = 1;
- continue;
- }
- }
-
- /* Add a new undefined (autoloaded) function to the *
- * hash table with the corresponding flags set. */
- shf = (Shfunc) zshcalloc(sizeof *shf);
- shf->node.flags = on;
- shf->funcdef = mkautofn(shf);
- shfunc_set_sticky(shf);
- add_autoload_function(shf, *argv);
-
- if (signum != -1) {
- if (settrap(signum, NULL, ZSIG_FUNC)) {
- shfunctab->removenode(shfunctab, *argv);
- shfunctab->freenode(&shf->node);
- returnval = 1;
- ok = 0;
- }
- }
-
- if (ok && check_autoload(shf, shf->node.nam, ops, func))
- returnval = 1;
- } else
- returnval = 1;
- }
- unqueue_signals();
- return returnval;
-}
-
-/**/
-Eprog
-mkautofn(Shfunc shf)
-{
- Eprog p;
-
- p = (Eprog) zalloc(sizeof(*p));
- p->len = 5 * sizeof(wordcode);
- p->prog = (Wordcode) zalloc(p->len);
- p->strs = NULL;
- p->shf = shf;
- p->npats = 0;
- p->nref = 1; /* allocated from permanent storage */
- p->pats = (Patprog *) p->prog;
- p->flags = EF_REAL;
- p->dump = NULL;
-
- p->prog[0] = WCB_LIST((Z_SYNC | Z_END), 0);
- p->prog[1] = WCB_SUBLIST(WC_SUBLIST_END, 0, 3);
- p->prog[2] = WCB_PIPE(WC_PIPE_END, 0);
- p->prog[3] = WCB_AUTOFN();
- p->prog[4] = WCB_END();
-
- return p;
-}
-
-/* unset: unset parameters */
-
-/**/
-int
-bin_unset(char *name, char **argv, Options ops, int func)
-{
- Param pm, next;
- Patprog pprog;
- char *s;
- int match = 0, returnval = 0;
- int i;
-
- /* unset -f is the same as unfunction */
- if (OPT_ISSET(ops,'f'))
- return bin_unhash(name, argv, ops, func);
-
- /* with -m option, treat arguments as glob patterns */
- if (OPT_ISSET(ops,'m')) {
- while ((s = *argv++)) {
- queue_signals();
- /* expand */
- tokenize(s);
- if ((pprog = patcompile(s, PAT_STATIC, NULL))) {
- /* Go through the parameter table, and unset any matches */
- for (i = 0; i < paramtab->hsize; i++) {
- for (pm = (Param) paramtab->nodes[i]; pm; pm = next) {
- /* record pointer to next, since we may free this one */
- next = (Param) pm->node.next;
- if ((!(pm->node.flags & PM_RESTRICTED) ||
- unset(RESTRICTED)) &&
- pattry(pprog, pm->node.nam)) {
- unsetparam_pm(pm, 0, 1);
- match++;
- }
- }
- }
- } else {
- untokenize(s);
- zwarnnam(name, "bad pattern : %s", s);
- returnval = 1;
- }
- unqueue_signals();
- }
- /* If we didn't match anything, we return 1. */
- if (!match)
- returnval = 1;
- return returnval;
- }
-
- /* do not glob -- unset the given parameter */
- queue_signals();
- while ((s = *argv++)) {
- char *ss = strchr(s, '['), *subscript = 0;
- if (ss) {
- char *sse;
- *ss = 0;
- if ((sse = parse_subscript(ss+1, 1, ']'))) {
- *sse = 0;
- subscript = dupstring(ss+1);
- *sse = ']';
- remnulargs(subscript);
- untokenize(subscript);
- }
- }
- if ((ss && !subscript) || !isident(s)) {
- if (ss)
- *ss = '[';
- zerrnam(name, "%s: invalid parameter name", s);
- returnval = 1;
- continue;
- }
- pm = (Param) (paramtab == realparamtab ?
- /* getnode2() to avoid autoloading */
- paramtab->getnode2(paramtab, s) :
- paramtab->getnode(paramtab, s));
- /*
- * Unsetting an unset variable is not an error.
- * This appears to be reasonably standard behaviour.
- */
- if (!pm)
- continue;
- else if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerrnam(name, "%s: restricted", pm->node.nam);
- returnval = 1;
- } else if (ss) {
- if (PM_TYPE(pm->node.flags) == PM_HASHED) {
- HashTable tht = paramtab;
- if ((paramtab = pm->gsu.h->getfn(pm)))
- unsetparam(subscript);
- paramtab = tht;
- } else if (PM_TYPE(pm->node.flags) == PM_SCALAR ||
- PM_TYPE(pm->node.flags) == PM_ARRAY) {
- struct value vbuf;
- vbuf.isarr = (PM_TYPE(pm->node.flags) == PM_ARRAY ?
- SCANPM_ARRONLY : 0);
- vbuf.pm = pm;
- vbuf.flags = 0;
- vbuf.start = 0;
- vbuf.end = -1;
- vbuf.arr = 0;
- *ss = '[';
- if (getindex(&ss, &vbuf, SCANPM_ASSIGNING) == 0 &&
- vbuf.pm && !(vbuf.pm->node.flags & PM_UNSET)) {
- if (PM_TYPE(pm->node.flags) == PM_SCALAR) {
- setstrvalue(&vbuf, ztrdup(""));
- } else {
- /* start is after the element for reverse index */
- int start = vbuf.start - !!(vbuf.flags & VALFLAG_INV);
- if (arrlen_gt(vbuf.pm->u.arr, start)) {
- char *arr[2];
- arr[0] = "";
- arr[1] = 0;
- setarrvalue(&vbuf, zarrdup(arr));
- }
- }
- }
- returnval = errflag;
- errflag &= ~ERRFLAG_ERROR;
- } else {
- zerrnam(name, "%s: invalid element for unset", s);
- returnval = 1;
- }
- } else {
- if (unsetparam_pm(pm, 0, 1))
- returnval = 1;
- }
- if (ss)
- *ss = '[';
- }
- unqueue_signals();
- return returnval;
-}
-
-/* type, whence, which, command */
-
-static LinkList matchednodes;
-
-static void
-fetchcmdnamnode(HashNode hn, UNUSED(int printflags))
-{
- Cmdnam cn = (Cmdnam) hn;
- addlinknode(matchednodes, cn->node.nam);
-}
-
-/**/
-int
-bin_whence(char *nam, char **argv, Options ops, int func)
-{
- HashNode hn;
- Patprog pprog;
- int returnval = 0;
- int printflags = 0;
- int aliasflags;
- int csh, all, v, wd;
- int informed = 0;
- int expand = 0;
- char *cnam, **allmatched = 0;
-
- /* Check some option information */
- csh = OPT_ISSET(ops,'c');
- v = OPT_ISSET(ops,'v');
- all = OPT_ISSET(ops,'a');
- wd = OPT_ISSET(ops,'w');
-
- if (OPT_ISSET(ops,'x')) {
- char *eptr;
- expand = (int)zstrtol(OPT_ARG(ops,'x'), &eptr, 10);
- if (*eptr) {
- zwarnnam(nam, "number expected after -x");
- return 1;
- }
- if (expand == 0) /* no indentation at all */
- expand = -1;
- }
-
- if (OPT_ISSET(ops,'w'))
- printflags |= PRINT_WHENCE_WORD;
- else if (OPT_ISSET(ops,'c'))
- printflags |= PRINT_WHENCE_CSH;
- else if (OPT_ISSET(ops,'v'))
- printflags |= PRINT_WHENCE_VERBOSE;
- else
- printflags |= PRINT_WHENCE_SIMPLE;
- if (OPT_ISSET(ops,'f'))
- printflags |= PRINT_WHENCE_FUNCDEF;
-
- if (func == BIN_COMMAND)
- if (OPT_ISSET(ops,'V')) {
- printflags = aliasflags = PRINT_WHENCE_VERBOSE;
- v = 1;
- } else {
- aliasflags = PRINT_LIST;
- printflags = PRINT_WHENCE_SIMPLE;
- v = 0;
- }
- else
- aliasflags = printflags;
-
- /* With -m option -- treat arguments as a glob patterns */
- if (OPT_ISSET(ops,'m')) {
- cmdnamtab->filltable(cmdnamtab);
- if (all) {
- pushheap();
- matchednodes = newlinklist();
- }
- queue_signals();
- for (; *argv; argv++) {
- /* parse the pattern */
- tokenize(*argv);
- if (!(pprog = patcompile(*argv, PAT_STATIC, NULL))) {
- untokenize(*argv);
- zwarnnam(nam, "bad pattern : %s", *argv);
- returnval = 1;
- continue;
- }
- if (!OPT_ISSET(ops,'p')) {
- /* -p option is for path search only. *
- * We're not using it, so search for ... */
-
- /* aliases ... */
- informed +=
- scanmatchtable(aliastab, pprog, 1, 0, DISABLED,
- aliastab->printnode, printflags);
-
- /* and reserved words ... */
- informed +=
- scanmatchtable(reswdtab, pprog, 1, 0, DISABLED,
- reswdtab->printnode, printflags);
-
- /* and shell functions... */
- informed +=
- scanmatchshfunc(pprog, 1, 0, DISABLED,
- shfunctab->printnode, printflags, expand);
-
- /* and builtins. */
- informed +=
- scanmatchtable(builtintab, pprog, 1, 0, DISABLED,
- builtintab->printnode, printflags);
- }
- /* Done search for `internal' commands, if the -p option *
- * was not used. Now search the path. */
- informed +=
- scanmatchtable(cmdnamtab, pprog, 1, 0, 0,
- (all ? fetchcmdnamnode : cmdnamtab->printnode),
- printflags);
- run_queued_signals();
- }
- unqueue_signals();
- if (all) {
- allmatched = argv = zlinklist2array(matchednodes);
- matchednodes = NULL;
- popheap();
- } else
- return returnval || !informed;
- }
-
- /* Take arguments literally -- do not glob */
- queue_signals();
- for (; *argv; argv++) {
- if (!OPT_ISSET(ops,'p') && !allmatched) {
- char *suf;
-
- /* Look for alias */
- if ((hn = aliastab->getnode(aliastab, *argv))) {
- aliastab->printnode(hn, aliasflags);
- informed = 1;
- if (!all)
- continue;
- }
- /* Look for suffix alias */
- if ((suf = strrchr(*argv, '.')) && suf[1] &&
- suf > *argv && suf[-1] != Meta &&
- (hn = sufaliastab->getnode(sufaliastab, suf+1))) {
- sufaliastab->printnode(hn, printflags);
- informed = 1;
- if (!all)
- continue;
- }
- /* Look for reserved word */
- if ((hn = reswdtab->getnode(reswdtab, *argv))) {
- reswdtab->printnode(hn, printflags);
- informed = 1;
- if (!all)
- continue;
- }
- /* Look for shell function */
- if ((hn = shfunctab->getnode(shfunctab, *argv))) {
- printshfuncexpand(hn, printflags, expand);
- informed = 1;
- if (!all)
- continue;
- }
- /* Look for builtin command */
- if ((hn = builtintab->getnode(builtintab, *argv))) {
- builtintab->printnode(hn, printflags);
- informed = 1;
- if (!all)
- continue;
- }
- /* Look for commands that have been added to the *
- * cmdnamtab with the builtin `hash foo=bar'. */
- if ((hn = cmdnamtab->getnode(cmdnamtab, *argv)) && (hn->flags & HASHED)) {
- cmdnamtab->printnode(hn, printflags);
- informed = 1;
- if (!all)
- continue;
- }
- }
-
- /* Option -a is to search the entire path, *
- * rather than just looking for one match. */
- if (all && **argv != '/') {
- char **pp, *buf;
-
- pushheap();
- for (pp = path; *pp; pp++) {
- if (**pp) {
- buf = zhtricat(*pp, "/", *argv);
- } else buf = dupstring(*argv);
-
- if (iscom(buf)) {
- if (wd) {
- printf("%s: command\n", *argv);
- } else {
- if (v && !csh) {
- zputs(*argv, stdout), fputs(" is ", stdout);
- quotedzputs(buf, stdout);
- } else
- zputs(buf, stdout);
- if (OPT_ISSET(ops,'s') || OPT_ISSET(ops, 'S'))
- print_if_link(buf, OPT_ISSET(ops, 'S'));
- fputc('\n', stdout);
- }
- informed = 1;
- }
- }
- if (!informed && (wd || v || csh)) {
- /* this is information and not an error so, as in csh, use stdout */
- zputs(*argv, stdout);
- puts(wd ? ": none" : " not found");
- returnval = 1;
- }
- popheap();
- } else if (func == BIN_COMMAND && OPT_ISSET(ops,'p') &&
- (hn = builtintab->getnode(builtintab, *argv))) {
- /*
- * Special case for "command -p[vV]" which needs to
- * show a builtin in preference to an external command.
- */
- builtintab->printnode(hn, printflags);
- informed = 1;
- } else if ((cnam = findcmd(*argv, 1,
- func == BIN_COMMAND &&
- OPT_ISSET(ops,'p')))) {
- /* Found external command. */
- if (wd) {
- printf("%s: command\n", *argv);
- } else {
- if (v && !csh) {
- zputs(*argv, stdout), fputs(" is ", stdout);
- quotedzputs(cnam, stdout);
- } else
- zputs(cnam, stdout);
- if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'S'))
- print_if_link(cnam, OPT_ISSET(ops,'S'));
- fputc('\n', stdout);
- }
- informed = 1;
- } else {
- /* Not found at all. That's not an error as such so this goes to stdout */
- if (v || csh || wd)
- zputs(*argv, stdout), puts(wd ? ": none" : " not found");
- returnval = 1;
- }
- }
- if (allmatched)
- freearray(allmatched);
-
- unqueue_signals();
- return returnval || !informed;
-}
-
-/**** command & named directory hash table builtins ****/
-
-/*****************************************************************
- * hash -- explicitly hash a command. *
- * 1) Given no arguments, list the hash table. *
- * 2) The -m option prints out commands in the hash table that *
- * match a given glob pattern. *
- * 3) The -f option causes the entire path to be added to the *
- * hash table (cannot be combined with any arguments). *
- * 4) The -r option causes the entire hash table to be discarded *
- * (cannot be combined with any arguments). *
- * 5) Given argument of the form foo=bar, add element to command *
- * hash table, so that when `foo' is entered, then `bar' is *
- * executed. *
- * 6) Given arguments not of the previous form, add it to the *
- * command hash table as if it were being executed. *
- * 7) The -d option causes analogous things to be done using *
- * the named directory hash table. *
- *****************************************************************/
-
-/**/
-int
-bin_hash(char *name, char **argv, Options ops, UNUSED(int func))
-{
- HashTable ht;
- Patprog pprog;
- Asgment asg;
- int returnval = 0;
- int printflags = 0;
-
- if (OPT_ISSET(ops,'d'))
- ht = nameddirtab;
- else
- ht = cmdnamtab;
-
- if (OPT_ISSET(ops,'r') || OPT_ISSET(ops,'f')) {
- /* -f and -r can't be used with any arguments */
- if (*argv) {
- zwarnnam("hash", "too many arguments");
- return 1;
- }
-
- /* empty the hash table */
- if (OPT_ISSET(ops,'r'))
- ht->emptytable(ht);
-
- /* fill the hash table in a standard way */
- if (OPT_ISSET(ops,'f'))
- ht->filltable(ht);
-
- return 0;
- }
-
- if (OPT_ISSET(ops,'L')) printflags |= PRINT_LIST;
-
- /* Given no arguments, display current hash table. */
- if (!*argv) {
- queue_signals();
- scanhashtable(ht, 1, 0, 0, ht->printnode, printflags);
- unqueue_signals();
- return 0;
- }
-
- queue_signals();
- while (*argv) {
- void *hn;
- if (OPT_ISSET(ops,'m')) {
- /* with the -m option, treat the argument as a glob pattern */
- tokenize(*argv); /* expand */
- if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
- /* display matching hash table elements */
- scanmatchtable(ht, pprog, 1, 0, 0, ht->printnode, printflags);
- } else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- argv++;
- continue;
- }
- if (!(asg = getasg(&argv, NULL))) {
- zwarnnam(name, "bad assignment");
- returnval = 1;
- break;
- } else if (ASG_VALUEP(asg)) {
- if(isset(RESTRICTED)) {
- zwarnnam(name, "restricted: %s", asg->value.scalar);
- returnval = 1;
- } else {
- /* The argument is of the form foo=bar, *
- * so define an entry for the table. */
- if(OPT_ISSET(ops,'d')) {
- /* shouldn't return NULL if asg->name is not NULL */
- if (*itype_end(asg->name, IUSER, 0)) {
- zwarnnam(name,
- "invalid character in directory name: %s",
- asg->name);
- returnval = 1;
- continue;
- } else {
- Nameddir nd = hn = zshcalloc(sizeof *nd);
- nd->node.flags = 0;
- nd->dir = ztrdup(asg->value.scalar);
- }
- } else {
- Cmdnam cn = hn = zshcalloc(sizeof *cn);
- cn->node.flags = HASHED;
- cn->u.cmd = ztrdup(asg->value.scalar);
- }
- ht->addnode(ht, ztrdup(asg->name), hn);
- if(OPT_ISSET(ops,'v'))
- ht->printnode(hn, 0);
- }
- } else if (!(hn = ht->getnode2(ht, asg->name))) {
- /* With no `=value' part to the argument, *
- * work out what it ought to be. */
- if(OPT_ISSET(ops,'d')) {
- if(!getnameddir(asg->name)) {
- zwarnnam(name, "no such directory name: %s", asg->name);
- returnval = 1;
- }
- } else {
- if (!hashcmd(asg->name, path)) {
- zwarnnam(name, "no such command: %s", asg->name);
- returnval = 1;
- }
- }
- if(OPT_ISSET(ops,'v') && (hn = ht->getnode2(ht, asg->name)))
- ht->printnode(hn, 0);
- } else if(OPT_ISSET(ops,'v'))
- ht->printnode(hn, 0);
- }
- unqueue_signals();
- return returnval;
-}
-
-/* unhash: remove specified elements from a hash table */
-
-/**/
-int
-bin_unhash(char *name, char **argv, Options ops, int func)
-{
- HashTable ht;
- HashNode hn, nhn;
- Patprog pprog;
- int match = 0, returnval = 0, all = 0;
- int i;
-
- /* Check which hash table we are working with. */
- if (func == BIN_UNALIAS) {
- if (OPT_ISSET(ops,'s'))
- ht = sufaliastab; /* suffix aliases */
- else
- ht = aliastab; /* aliases */
- if (OPT_ISSET(ops, 'a')) {
- if (*argv) {
- zwarnnam(name, "-a: too many arguments");
- return 1;
- }
- all = 1;
- } else if (!*argv) {
- zwarnnam(name, "not enough arguments");
- return 1;
- }
- } else if (OPT_ISSET(ops,'d'))
- ht = nameddirtab; /* named directories */
- else if (OPT_ISSET(ops,'f'))
- ht = shfunctab; /* shell functions */
- else if (OPT_ISSET(ops,'s'))
- ht = sufaliastab; /* suffix aliases, must precede aliases */
- else if (func == BIN_UNHASH && (OPT_ISSET(ops,'a')))
- ht = aliastab; /* aliases */
- else
- ht = cmdnamtab; /* external commands */
-
- if (all) {
- queue_signals();
- for (i = 0; i < ht->hsize; i++) {
- for (hn = ht->nodes[i]; hn; hn = nhn) {
- /* record pointer to next, since we may free this one */
- nhn = hn->next;
- ht->freenode(ht->removenode(ht, hn->nam));
- }
- }
- unqueue_signals();
- return 0;
- }
-
- /* With -m option, treat arguments as glob patterns. *
- * "unhash -m '*'" is legal, but not recommended. */
- if (OPT_ISSET(ops,'m')) {
- for (; *argv; argv++) {
- queue_signals();
- /* expand argument */
- tokenize(*argv);
- if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
- /* remove all nodes matching glob pattern */
- for (i = 0; i < ht->hsize; i++) {
- for (hn = ht->nodes[i]; hn; hn = nhn) {
- /* record pointer to next, since we may free this one */
- nhn = hn->next;
- if (pattry(pprog, hn->nam)) {
- ht->freenode(ht->removenode(ht, hn->nam));
- match++;
- }
- }
- }
- } else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- unqueue_signals();
- }
- /* If we didn't match anything, we return 1. */
- if (!match)
- returnval = 1;
- return returnval;
- }
-
- /* Take arguments literally -- do not glob */
- queue_signals();
- for (; *argv; argv++) {
- if ((hn = ht->removenode(ht, *argv))) {
- ht->freenode(hn);
- } else if (func == BIN_UNSET && isset(POSIXBUILTINS)) {
- /* POSIX: unset: "Unsetting a variable or function that was *
- * not previously set shall not be considered an error." */
- returnval = 0;
- } else {
- zwarnnam(name, "no such hash table element: %s", *argv);
- returnval = 1;
- }
- }
- unqueue_signals();
- return returnval;
-}
-
-/**** alias builtins ****/
-
-/* alias: display or create aliases. */
-
-/**/
-int
-bin_alias(char *name, char **argv, Options ops, UNUSED(int func))
-{
- Alias a;
- Patprog pprog;
- Asgment asg;
- int returnval = 0;
- int flags1 = 0, flags2 = DISABLED;
- int printflags = 0;
- int type_opts;
- HashTable ht = aliastab;
-
- /* Did we specify the type of alias? */
- type_opts = OPT_ISSET(ops, 'r') + OPT_ISSET(ops, 'g') +
- OPT_ISSET(ops, 's');
- if (type_opts) {
- if (type_opts > 1) {
- zwarnnam(name, "illegal combination of options");
- return 1;
- }
- if (OPT_ISSET(ops,'g'))
- flags1 |= ALIAS_GLOBAL;
- else
- flags2 |= ALIAS_GLOBAL;
- if (OPT_ISSET(ops, 's')) {
- /*
- * Although we keep suffix aliases in a different table,
- * it is useful to be able to distinguish Alias structures
- * without reference to the table, so we have a separate
- * flag, too.
- */
- flags1 |= ALIAS_SUFFIX;
- ht = sufaliastab;
- } else
- flags2 |= ALIAS_SUFFIX;
- }
-
- if (OPT_ISSET(ops,'L'))
- printflags |= PRINT_LIST;
- else if (OPT_PLUS(ops,'g') || OPT_PLUS(ops,'r') || OPT_PLUS(ops,'s') ||
- OPT_PLUS(ops,'m') || OPT_ISSET(ops,'+'))
- printflags |= PRINT_NAMEONLY;
-
- /* In the absence of arguments, list all aliases. If a command *
- * line flag is specified, list only those of that type. */
- if (!*argv) {
- queue_signals();
- scanhashtable(ht, 1, flags1, flags2, ht->printnode, printflags);
- unqueue_signals();
- return 0;
- }
-
- /* With the -m option, treat the arguments as *
- * glob patterns of aliases to display. */
- if (OPT_ISSET(ops,'m')) {
- for (; *argv; argv++) {
- queue_signals();
- tokenize(*argv); /* expand argument */
- if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
- /* display the matching aliases */
- scanmatchtable(ht, pprog, 1, flags1, flags2,
- ht->printnode, printflags);
- } else {
- untokenize(*argv);
- zwarnnam(name, "bad pattern : %s", *argv);
- returnval = 1;
- }
- unqueue_signals();
- }
- return returnval;
- }
-
- /* Take arguments literally. Don't glob */
- queue_signals();
- while ((asg = getasg(&argv, NULL))) {
- if (asg->value.scalar && !OPT_ISSET(ops,'L')) {
- /* The argument is of the form foo=bar and we are not *
- * forcing a listing with -L, so define an alias */
- ht->addnode(ht, ztrdup(asg->name),
- createaliasnode(ztrdup(asg->value.scalar), flags1));
- } else if ((a = (Alias) ht->getnode(ht, asg->name))) {
- /* display alias if appropriate */
- if (!type_opts || ht == sufaliastab ||
- (OPT_ISSET(ops,'r') &&
- !(a->node.flags & (ALIAS_GLOBAL|ALIAS_SUFFIX))) ||
- (OPT_ISSET(ops,'g') && (a->node.flags & ALIAS_GLOBAL)))
- ht->printnode(&a->node, printflags);
- } else
- returnval = 1;
- }
- unqueue_signals();
- return returnval;
-}
-
-
-/**** miscellaneous builtins ****/
-
-/* true, : (colon) */
-
-/**/
-int
-bin_true(UNUSED(char *name), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func))
-{
- return 0;
-}
-
-/* false builtin */
-
-/**/
-int
-bin_false(UNUSED(char *name), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func))
-{
- return 1;
-}
-
-/* the zle buffer stack */
-
-/**/
-mod_export LinkList bufstack;
-
-/* echo, print, printf, pushln */
-
-#define print_val(VAL) \
- if (prec >= 0) \
- count += fprintf(fout, spec, width, prec, VAL); \
- else \
- count += fprintf(fout, spec, width, VAL);
-
-/*
- * Because of the use of getkeystring() to interpret the arguments,
- * the elements of args spend a large part of the function unmetafied
- * with the lengths in len. This may have seemed a good idea once.
- * As we are stuck with this for now, we need to be very careful
- * deciding what state args is in.
- */
-
-/**/
-int
-bin_print(char *name, char **args, Options ops, int func)
-{
- int flen, width, prec, type, argc, n, narg, curlen = 0;
- int nnl = 0, fmttrunc = 0, ret = 0, maxarg = 0, nc = 0;
- int flags[6], *len, visarr = 0;
- char *start, *endptr, *c, *d, *flag, *buf = NULL, spec[14], *fmt = NULL;
- char **first, **argp, *curarg, *flagch = "'0+- #", save = '\0', nullstr = '\0';
- size_t rcount = 0, count = 0;
- size_t *cursplit = 0, *splits = 0;
- FILE *fout = stdout;
-#ifdef HAVE_OPEN_MEMSTREAM
- size_t mcount;
-#define ASSIGN_MSTREAM(BUF,FOUT) \
- do { \
- if ((FOUT = open_memstream(&BUF, &mcount)) == NULL) { \
- zwarnnam(name, "open_memstream failed"); \
- return 1; \
- } \
- } while (0)
- /*
- * Some implementations of open_memstream() have a bug such that,
- * if fflush() is followed by fclose(), another NUL byte is written
- * to the buffer at the wrong position. Therefore we must fclose()
- * before reading.
- */
-#define READ_MSTREAM(BUF,FOUT) \
- ((fclose(FOUT) == 0) ? mcount : (size_t)-1)
-#define CLOSE_MSTREAM(FOUT) 0
-
-#else /* simulate HAVE_OPEN_MEMSTREAM */
-
-#define ASSIGN_MSTREAM(BUF,FOUT) \
- do { \
- int tempfd; \
- char *tmpf; \
- if ((tempfd = gettempfile(NULL, 1, &tmpf)) < 0) { \
- zwarnnam(name, "can't open temp file: %e", errno); \
- return 1; \
- } \
- unlink(tmpf); \
- if ((FOUT = fdopen(tempfd, "w+")) == NULL) { \
- close(tempfd); \
- zwarnnam(name, "can't open temp file: %e", errno); \
- return 1; \
- } \
- } while (0)
-#define READ_MSTREAM(BUF,FOUT) \
- ((((count = ftell(FOUT)), (BUF = (char *)zalloc(count + 1))) && \
- ((fseek(FOUT, 0L, SEEK_SET) == 0) && !(BUF[count] = '\0')) && \
- (fread(BUF, 1, count, FOUT) == count)) ? count : (size_t)-1)
-#define CLOSE_MSTREAM(FOUT) fclose(FOUT)
-
-#endif
-
-#define IS_MSTREAM(FOUT) \
- (FOUT != stdout && \
- (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s') || OPT_ISSET(ops,'v')))
-
- /* Testing EBADF special-cases >&- redirections */
-#define CLOSE_CLEANLY(FOUT) \
- (IS_MSTREAM(FOUT) ? CLOSE_MSTREAM(FOUT) == 0 : \
- ((FOUT == stdout) ? (fflush(FOUT) == 0 || errno == EBADF) : \
- (fclose(FOUT) == 0))) /* implies error for -u on a closed fd */
-
- Histent ent;
- mnumber mnumval;
- double doubleval;
- int intval;
- zlong zlongval;
- zulong zulongval;
- char *stringval;
-
- /* Error check option combinations and option arguments */
-
- if (OPT_ISSET(ops, 'z') +
- OPT_ISSET(ops, 's') + OPT_ISSET(ops, 'S') +
- OPT_ISSET(ops, 'v') > 1) {
- zwarnnam(name, "only one of -s, -S, -v, or -z allowed");
- return 1;
- }
- if ((OPT_ISSET(ops, 'z') | OPT_ISSET(ops, 's') | OPT_ISSET(ops, 'S')) +
- (OPT_ISSET(ops, 'c') | OPT_ISSET(ops, 'C')) > 1) {
- zwarnnam(name, "-c or -C not allowed with -s, -S, or -z");
- return 1;
- }
- if ((OPT_ISSET(ops, 'z') | OPT_ISSET(ops, 'v') |
- OPT_ISSET(ops, 's') | OPT_ISSET(ops, 'S')) +
- (OPT_ISSET(ops, 'p') | OPT_ISSET(ops, 'u')) > 1) {
- zwarnnam(name, "-p or -u not allowed with -s, -S, -v, or -z");
- return 1;
- }
- /*
- if (OPT_ISSET(ops, 'f') &&
- (OPT_ISSET(ops, 'S') || OPT_ISSET(ops, 'c') || OPT_ISSET(ops, 'C'))) {
- zwarnnam(name, "-f not allowed with -c, -C, or -S");
- return 1;
- }
- */
-
- /* -C -- number of columns */
- if (!fmt && OPT_ISSET(ops,'C')) {
- char *eptr, *argptr = OPT_ARG(ops,'C');
- nc = (int)zstrtol(argptr, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expected after -%c: %s", 'C', argptr);
- return 1;
- }
- if (nc <= 0) {
- zwarnnam(name, "invalid number of columns: %s", argptr);
- return 1;
- }
- }
-
- if (func == BIN_PRINTF) {
- if (!strcmp(*args, "--") && !*++args) {
- zwarnnam(name, "not enough arguments");
- return 1;
- }
- fmt = *args++;
- } else if (func == BIN_ECHO && isset(BSDECHO))
- ops->ind['E'] = 1;
- else if (OPT_HASARG(ops,'f'))
- fmt = OPT_ARG(ops,'f');
- if (fmt)
- fmt = getkeystring(fmt, &flen, OPT_ISSET(ops,'b') ? GETKEYS_BINDKEY :
- GETKEYS_PRINTF_FMT, &fmttrunc);
-
- first = args;
-
- /* -m option -- treat the first argument as a pattern and remove
- * arguments not matching */
- if (OPT_ISSET(ops,'m')) {
- Patprog pprog;
- char **t, **p;
-
- if (!*args) {
- zwarnnam(name, "no pattern specified");
- return 1;
- }
- queue_signals();
- tokenize(*args);
- if (!(pprog = patcompile(*args, PAT_STATIC, NULL))) {
- untokenize(*args);
- zwarnnam(name, "bad pattern: %s", *args);
- unqueue_signals();
- return 1;
- }
- for (t = p = ++args; *p; p++)
- if (pattry(pprog, *p))
- *t++ = *p;
- *t = NULL;
- first = args;
- unqueue_signals();
- if (fmt && !*args) return 0;
- }
- /* compute lengths, and interpret according to -P, -D, -e, etc. */
- argc = arrlen(args);
- len = (int *) hcalloc(argc * sizeof(int));
- for (n = 0; n < argc; n++) {
- /* first \ sequences */
- if (fmt ||
- (!OPT_ISSET(ops,'e') &&
- (OPT_ISSET(ops,'R') || OPT_ISSET(ops,'r') || OPT_ISSET(ops,'E'))))
- unmetafy(args[n], &len[n]);
- else {
- int escape_how;
- if (OPT_ISSET(ops,'b'))
- escape_how = GETKEYS_BINDKEY;
- else if (func != BIN_ECHO && !OPT_ISSET(ops,'e'))
- escape_how = GETKEYS_PRINT;
- else
- escape_how = GETKEYS_ECHO;
- args[n] = getkeystring(args[n], &len[n], escape_how, &nnl);
- if (nnl) {
- /* If there was a \c escape, make this the last arg. */
- argc = n + 1;
- args[argc] = NULL;
- }
- }
- /* -P option -- interpret as a prompt sequence */
- if (OPT_ISSET(ops,'P')) {
- /*
- * promptexpand uses permanent storage: to avoid
- * messy memory management, stick it on the heap
- * instead.
- */
- char *str = unmetafy(
- promptexpand(metafy(args[n], len[n], META_NOALLOC),
- 0, NULL, NULL, NULL),
- &len[n]);
- args[n] = dupstrpfx(str, len[n]);
- free(str);
- }
- /* -D option -- interpret as a directory, and use ~ */
- if (OPT_ISSET(ops,'D')) {
- Nameddir d;
-
- queue_signals();
- /* TODO: finddir takes a metafied file */
- d = finddir(args[n]);
- if (d) {
- int dirlen = strlen(d->dir);
- char *arg = zhalloc(len[n] - dirlen + strlen(d->node.nam) + 2);
- sprintf(arg, "~%s%s", d->node.nam, args[n] + dirlen);
- args[n] = arg;
- len[n] = strlen(args[n]);
- }
- unqueue_signals();
- }
- }
-
- /* -o and -O -- sort the arguments */
- if (OPT_ISSET(ops,'o') || OPT_ISSET(ops,'O')) {
- int flags;
-
- if (fmt && !*args)
- return 0;
- flags = OPT_ISSET(ops,'i') ? SORTIT_IGNORING_CASE : 0;
- if (OPT_ISSET(ops,'O'))
- flags |= SORTIT_BACKWARDS;
- strmetasort(args, flags, len);
- }
-
- /* -u and -p -- output to other than standard output */
- if ((OPT_HASARG(ops,'u') || OPT_ISSET(ops,'p')) &&
- /* rule out conflicting options -- historical precedence */
- ((!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) ||
- !(OPT_ISSET(ops, 'z') || OPT_ISSET(ops, 'v') ||
- OPT_ISSET(ops, 's') || OPT_ISSET(ops, 'S')))) {
- int fdarg, fd;
-
- if (OPT_ISSET(ops, 'p')) {
- fdarg = coprocout;
- if (fdarg < 0) {
- zwarnnam(name, "-p: no coprocess");
- return 1;
- }
- } else {
- char *argptr = OPT_ARG(ops,'u'), *eptr;
- /* Handle undocumented feature that -up worked */
- if (!strcmp(argptr, "p")) {
- fdarg = coprocout;
- if (fdarg < 0) {
- zwarnnam(name, "-p: no coprocess");
- return 1;
- }
- } else {
- fdarg = (int)zstrtol(argptr, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expected after -u: %s", argptr);
- return 1;
- }
- }
- }
-
- if ((fd = dup(fdarg)) < 0) {
- zwarnnam(name, "bad file number: %d", fdarg);
- return 1;
- }
- if ((fout = fdopen(fd, "w")) == 0) {
- close(fd);
- zwarnnam(name, "bad mode on fd %d", fd);
- return 1;
- }
- }
-
- if (OPT_ISSET(ops, 'v') ||
- (fmt && (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s'))))
- ASSIGN_MSTREAM(buf,fout);
-
- /* -c -- output in columns */
- if (!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) {
- int l, nr, sc, n, t, i;
-#ifdef MULTIBYTE_SUPPORT
- int *widths;
-
- if (isset(MULTIBYTE)) {
- int *wptr;
-
- /*
- * We need the character widths to align output in
- * columns.
- */
- wptr = widths = (int *) zhalloc(argc * sizeof(int));
- for (i = 0; i < argc && args[i]; i++, wptr++) {
- int l = len[i], width = 0;
- char *aptr = args[i];
- mbstate_t mbs;
-
- memset(&mbs, 0, sizeof(mbstate_t));
- while (l > 0) {
- wchar_t wc;
- size_t cnt;
- int wcw;
-
- /*
- * Prevent misaligned columns due to escape sequences by
- * skipping over them. Octals \033 and \233 are the
- * possible escape characters recognized by ANSI.
- *
- * It ought to be possible to do this in the case
- * of prompt expansion by propagating the information
- * about escape sequences (currently we strip this
- * out).
- */
- if (*aptr == '\033' || *aptr == '\233') {
- for (aptr++, l--;
- l && !isalpha(STOUC(*aptr));
- aptr++, l--)
- ;
- aptr++;
- l--;
- continue;
- }
-
- cnt = mbrtowc(&wc, aptr, l, &mbs);
-
- if (cnt == MB_INCOMPLETE || cnt == MB_INVALID)
- {
- /* treat as ordinary string */
- width += l;
- break;
- }
- wcw = WCWIDTH(wc);
- /* treat unprintable as 0 */
- if (wcw > 0)
- width += wcw;
- /* skip over NUL normally */
- if (cnt == 0)
- cnt = 1;
- aptr += cnt;
- l -= cnt;
- }
- widths[i] = width;
- }
- }
- else
- widths = len;
-#else
- int *widths = len;
-#endif
-
- if (OPT_ISSET(ops,'C')) {
- /*
- * n: number of elements
- * nc: number of columns (above)
- * nr: number of rows
- */
- n = arrlen(args);
- nr = (n + nc - 1) / nc;
-
- /*
- * i: loop counter
- * l: maximum length seen
- *
- * Ignore lengths in last column since they don't affect
- * the separation.
- */
- for (i = l = 0; i < argc; i++) {
- if (OPT_ISSET(ops, 'a')) {
- if ((i % nc) == nc - 1)
- continue;
- } else {
- if (i >= nr * (nc - 1))
- break;
- }
- if (l < widths[i])
- l = widths[i];
- }
- sc = l + 2;
- }
- else
- {
- /*
- * n: loop counter
- * l: maximum length seen
- */
- for (n = l = 0; n < argc; n++)
- if (l < widths[n])
- l = widths[n];
-
- /*
- * sc: column width
- * nc: number of columns (at least one)
- */
- sc = l + 2;
- nc = (zterm_columns + 1) / sc;
- if (!nc)
- nc = 1;
- nr = (n + nc - 1) / nc;
- }
-
- if (OPT_ISSET(ops,'a')) /* print across, i.e. columns first */
- n = 0;
- for (i = 0; i < nr; i++) {
- if (OPT_ISSET(ops,'a'))
- {
- int ic;
- for (ic = 0; ic < nc && n < argc; ic++, n++)
- {
- fwrite(args[n], len[n], 1, fout);
- l = widths[n];
- if (n < argc)
- for (; l < sc; l++)
- fputc(' ', fout);
- }
- }
- else
- {
- n = i;
- do {
- fwrite(args[n], len[n], 1, fout);
- l = widths[n];
- for (t = nr; t && n < argc; t--, n++);
- if (n < argc)
- for (; l < sc; l++)
- fputc(' ', fout);
- } while (n < argc);
- }
- fputc(OPT_ISSET(ops,'N') ? '\0' : '\n', fout);
- }
- if (IS_MSTREAM(fout) && (rcount = READ_MSTREAM(buf,fout)) == -1)
- ret = 1;
- if (!CLOSE_CLEANLY(fout) || ret) {
- zwarnnam(name, "write error: %e", errno);
- ret = 1;
- }
- if (buf) {
- /* assert: we must be doing -v at this point */
- queue_signals();
- if (ret)
- free(buf);
- else
- setsparam(OPT_ARG(ops, 'v'),
- metafy(buf, rcount, META_REALLOC));
- unqueue_signals();
- }
- return ret;
- }
-
- /* normal output */
- if (!fmt) {
- if (OPT_ISSET(ops, 'z') || OPT_ISSET(ops, 'v') ||
- OPT_ISSET(ops, 's') || OPT_ISSET(ops, 'S')) {
- /*
- * We don't want the arguments unmetafied after all.
- */
- for (n = 0; n < argc; n++)
- metafy(args[n], len[n], META_NOALLOC);
- }
-
- /* -z option -- push the arguments onto the editing buffer stack */
- if (OPT_ISSET(ops,'z')) {
- queue_signals();
- zpushnode(bufstack, sepjoin(args, NULL, 0));
- unqueue_signals();
- return 0;
- }
- /* -s option -- add the arguments to the history list */
- if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'S')) {
- int nwords = 0, nlen, iwords;
- char **pargs = args;
-
- queue_signals();
- while (*pargs++)
- nwords++;
- if (nwords) {
- if (OPT_ISSET(ops,'S')) {
- int wordsize;
- short *words;
- if (nwords > 1) {
- zwarnnam(name, "option -S takes a single argument");
- unqueue_signals();
- return 1;
- }
- words = NULL;
- wordsize = 0;
- histsplitwords(*args, &words, &wordsize, &nwords, 1);
- ent = prepnexthistent();
- ent->words = (short *)zalloc(nwords*sizeof(short));
- memcpy(ent->words, words, nwords*sizeof(short));
- free(words);
- ent->nwords = nwords/2;
- } else {
- ent = prepnexthistent();
- ent->words = (short *)zalloc(nwords*2*sizeof(short));
- ent->nwords = nwords;
- nlen = iwords = 0;
- for (pargs = args; *pargs; pargs++) {
- ent->words[iwords++] = nlen;
- nlen += strlen(*pargs);
- ent->words[iwords++] = nlen;
- nlen++;
- }
- }
- } else {
- ent = prepnexthistent();
- ent->words = (short *)NULL;
- }
- ent->node.nam = zjoin(args, ' ', 0);
- ent->stim = ent->ftim = time(NULL);
- ent->node.flags = 0;
- addhistnode(histtab, ent->node.nam, ent);
- unqueue_signals();
- return 0;
- }
-
- if (OPT_HASARG(ops, 'x') || OPT_HASARG(ops, 'X')) {
- char *eptr;
- int expand, startpos = 0;
- int all = OPT_HASARG(ops, 'X');
- char *xarg = all ? OPT_ARG(ops, 'X') : OPT_ARG(ops, 'x');
-
- expand = (int)zstrtol(xarg, &eptr, 10);
- if (*eptr || expand <= 0) {
- zwarnnam(name, "positive integer expected after -%c: %s", 'x',
- xarg);
- return 1;
- }
- for (; *args; args++, len++) {
- startpos = zexpandtabs(*args, *len, expand, startpos, fout,
- all);
- if (args[1]) {
- if (OPT_ISSET(ops, 'l')) {
- fputc('\n', fout);
- startpos = 0;
- } else if (OPT_ISSET(ops,'N')) {
- fputc('\0', fout);
- } else {
- fputc(' ', fout);
- startpos++;
- }
- }
- }
- } else {
- for (; *args; args++, len++) {
- fwrite(*args, *len, 1, fout);
- if (args[1])
- fputc(OPT_ISSET(ops,'l') ? '\n' :
- OPT_ISSET(ops,'N') ? '\0' : ' ', fout);
- }
- }
- if (!(OPT_ISSET(ops,'n') || nnl ||
- (OPT_ISSET(ops, 'v') && !OPT_ISSET(ops, 'l'))))
- fputc(OPT_ISSET(ops,'N') ? '\0' : '\n', fout);
- if (IS_MSTREAM(fout) && (rcount = READ_MSTREAM(buf,fout)) == -1)
- ret = 1;
- if (!CLOSE_CLEANLY(fout) || ret) {
- zwarnnam(name, "write error: %e", errno);
- ret = 1;
- }
- if (buf) {
- /* assert: we must be doing -v at this point */
- queue_signals();
- if (ret)
- free(buf);
- else
- setsparam(OPT_ARG(ops, 'v'),
- metafy(buf, rcount, META_REALLOC));
- unqueue_signals();
- }
- return ret;
- }
-
- /*
- * All the remaining code in this function is for printf-style
- * output (printf itself, or print -f). We still have to handle
- * special cases of printing to a ZLE buffer or the history, however.
- */
-
- if (OPT_ISSET(ops,'v')) {
- struct value vbuf;
- char* s = OPT_ARG(ops,'v');
- Value v = getvalue(&vbuf, &s, 0);
- visarr = v && PM_TYPE(v->pm->node.flags) == PM_ARRAY;
- }
- /* printf style output */
- *spec = '%';
- argp = args;
- do {
- rcount = count;
- if (argp > args && visarr) { /* reusing format string */
- if (!splits)
- cursplit = splits = (size_t *)zhalloc(sizeof(size_t) *
- (arrlen(args) / (argp - args) + 1));
- *cursplit++ = count;
- }
- if (maxarg) {
- first += maxarg;
- argc -= maxarg;
- maxarg = 0;
- }
- for (c = fmt; c-fmt < flen; c++) {
- if (*c != '%') {
- putc(*c, fout);
- ++count;
- continue;
- }
-
- start = c++;
- if (*c == '%') {
- putc('%', fout);
- ++count;
- continue;
- }
-
- type = prec = -1;
- width = 0;
- curarg = NULL;
- d = spec + 1;
-
- if (*c >= '1' && *c <= '9') {
- narg = strtoul(c, &endptr, 0);
- if (*endptr == '$') {
- c = endptr + 1;
- DPUTS(narg <= 0, "specified zero or negative arg");
- if (narg > argc) {
- zwarnnam(name, "%d: argument specifier out of range",
- narg);
- if (fout != stdout)
- fclose(fout);
-#ifdef HAVE_OPEN_MEMSTREAM
- if (buf)
- free(buf);
-#endif
- return 1;
- } else {
- if (narg > maxarg) maxarg = narg;
- curarg = *(first + narg - 1);
- curlen = len[first - args + narg - 1];
- }
- }
- }
-
- /* copy only one of each flag as spec has finite size */
- memset(flags, 0, sizeof(flags));
- while (*c && (flag = strchr(flagch, *c))) {
- if (!flags[flag - flagch]) {
- flags[flag - flagch] = 1;
- *d++ = *c;
- }
- c++;
- }
-
- if (idigit(*c)) {
- width = strtoul(c, &endptr, 0);
- c = endptr;
- } else if (*c == '*') {
- if (idigit(*++c)) {
- narg = strtoul(c, &endptr, 0);
- if (*endptr == '$') {
- c = endptr + 1;
- if (narg > argc || narg <= 0) {
- zwarnnam(name,
- "%d: argument specifier out of range",
- narg);
- if (fout != stdout)
- fclose(fout);
-#ifdef HAVE_OPEN_MEMSTREAM
- if (buf)
- free(buf);
-#endif
- return 1;
- } else {
- if (narg > maxarg) maxarg = narg;
- argp = first + narg - 1;
- }
- }
- }
- if (*argp) {
- width = (int)mathevali(*argp++);
- if (errflag) {
- errflag &= ~ERRFLAG_ERROR;
- ret = 1;
- }
- }
- }
- *d++ = '*';
-
- if (*c == '.') {
- if (*++c == '*') {
- if (idigit(*++c)) {
- narg = strtoul(c, &endptr, 0);
- if (*endptr == '$') {
- c = endptr + 1;
- if (narg > argc || narg <= 0) {
- zwarnnam(name,
- "%d: argument specifier out of range",
- narg);
- if (fout != stdout)
- fclose(fout);
-#ifdef HAVE_OPEN_MEMSTREAM
- if (buf)
- free(buf);
-#endif
- return 1;
- } else {
- if (narg > maxarg) maxarg = narg;
- argp = first + narg - 1;
- }
- }
- }
-
- if (*argp) {
- prec = (int)mathevali(*argp++);
- if (errflag) {
- errflag &= ~ERRFLAG_ERROR;
- ret = 1;
- }
- }
- } else if (idigit(*c)) {
- prec = strtoul(c, &endptr, 0);
- c = endptr;
- } else
- prec = 0;
- if (prec >= 0) *d++ = '.', *d++ = '*';
- }
-
- /* ignore any size modifier */
- if (*c == 'l' || *c == 'L' || *c == 'h') c++;
-
- if (!curarg && *argp) {
- curarg = *argp;
- curlen = len[argp++ - args];
- }
- d[1] = '\0';
- switch (*d = *c) {
- case 'c':
- if (curarg)
- intval = *curarg;
- else
- intval = 0;
- print_val(intval);
- break;
- case 's':
- case 'b':
- if (curarg) {
- char *b, *ptr;
- int lbytes, lchars, lleft;
-#ifdef MULTIBYTE_SUPPORT
- mbstate_t mbs;
-#endif
-
- if (*c == 'b') {
- b = getkeystring(metafy(curarg, curlen, META_USEHEAP),
- &lbytes,
- OPT_ISSET(ops,'b') ? GETKEYS_BINDKEY :
- GETKEYS_PRINTF_ARG, &nnl);
- } else {
- b = curarg;
- lbytes = curlen;
- }
- /*
- * Handle width/precision here and use fwrite so that
- * nul characters can be output.
- *
- * First, examine width of string given that it
- * may contain multibyte characters. The output
- * widths are for characters, so we need to count
- * (in lchars). However, if we need to truncate
- * the string we need the width in bytes (in lbytes).
- */
- ptr = b;
-#ifdef MULTIBYTE_SUPPORT
- memset(&mbs, 0, sizeof(mbs));
-#endif
-
- for (lchars = 0, lleft = lbytes; lleft > 0; lchars++) {
- int chars;
-
- if (lchars == prec) {
- /* Truncate at this point. */
- lbytes = ptr - b;
- break;
- }
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- chars = mbrlen(ptr, lleft, &mbs);
- if (chars < 0) {
- /*
- * Invalid/incomplete character at this
- * point. Assume all the rest are a
- * single byte. That's about the best we
- * can do.
- */
- lchars += lleft;
- lbytes = (ptr - b) + lleft;
- break;
- } else if (chars == 0) {
- /* NUL, handle as real character */
- chars = 1;
- }
- }
- else /* use the non-multibyte code below */
-#endif
- chars = 1; /* compiler can optimise this...*/
- lleft -= chars;
- ptr += chars;
- }
- if (width > 0 && flags[3]) width = -width;
- if (width > 0 && lchars < width)
- count += fprintf(fout, "%*c", width - lchars, ' ');
- count += fwrite(b, 1, lbytes, fout);
- if (width < 0 && lchars < -width)
- count += fprintf(fout, "%*c", -width - lchars, ' ');
- if (nnl) {
- /* If the %b arg had a \c escape, truncate the fmt. */
- flen = c - fmt + 1;
- fmttrunc = 1;
- }
- } else if (width)
- count += fprintf(fout, "%*c", width, ' ');
- break;
- case 'q':
- stringval = curarg ?
- quotestring(metafy(curarg, curlen, META_USEHEAP),
- QT_BACKSLASH_SHOWNULL) : &nullstr;
- *d = 's';
- print_val(unmetafy(stringval, &curlen));
- break;
- case 'd':
- case 'i':
- type=1;
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- type=2;
- break;
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- type=3;
- break;
- case 'n':
- if (curarg) setiparam(curarg, count - rcount);
- break;
- default:
- if (*c) {
- save = c[1];
- c[1] = '\0';
- }
- zwarnnam(name, "%s: invalid directive", start);
- if (*c) c[1] = save;
- /* Why do we care about a clean close here? */
- if (!CLOSE_CLEANLY(fout))
- zwarnnam(name, "write error: %e", errno);
-#ifdef HAVE_OPEN_MEMSTREAM
- if (buf)
- free(buf);
-#endif
- return 1;
- }
-
- if (type > 0) {
- if (curarg && (*curarg == '\'' || *curarg == '"' )) {
- convchar_t cc;
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- mb_charinit();
- (void)mb_metacharlenconv(metafy(curarg+1, curlen-1,
- META_USEHEAP), &cc);
- }
- else
- cc = WEOF;
- if (cc == WEOF)
- cc = (curlen > 1) ? STOUC(curarg[1]) : 0;
-#else
- cc = (curlen > 1) ? STOUC(curarg[1]) : 0;
-#endif
- if (type == 2) {
- doubleval = cc;
- print_val(doubleval);
- } else {
- intval = cc;
- print_val(intval);
- }
- } else {
- switch (type) {
- case 1:
-#ifdef ZSH_64_BIT_TYPE
- *d++ = 'l';
-#endif
- *d++ = 'l', *d++ = *c, *d = '\0';
- zlongval = (curarg) ? mathevali(curarg) : 0;
- if (errflag) {
- zlongval = 0;
- errflag &= ~ERRFLAG_ERROR;
- ret = 1;
- }
- print_val(zlongval)
- break;
- case 2:
- if (curarg) {
- char *eptr;
- /*
- * First attempt to parse as a floating
- * point constant. If we go through
- * a math evaluation, we can lose
- * mostly unimportant information
- * that people in standards organizations
- * worry about.
- */
- doubleval = strtod(curarg, &eptr);
- /*
- * If it didn't parse as a constant,
- * parse it as an expression.
- */
- if (*eptr != '\0') {
- mnumval = matheval(curarg);
- doubleval = (mnumval.type & MN_FLOAT) ?
- mnumval.u.d : (double)mnumval.u.l;
- }
- } else doubleval = 0;
- if (errflag) {
- doubleval = 0;
- errflag &= ~ERRFLAG_ERROR;
- ret = 1;
- }
- /* force consistent form for Inf/NaN output */
- if (isnan(doubleval))
- count += fputs("nan", fout);
- else if (isinf(doubleval))
- count += fputs((doubleval < 0.0) ? "-inf" : "inf", fout);
- else
- print_val(doubleval)
- break;
- case 3:
-#ifdef ZSH_64_BIT_UTYPE
- *d++ = 'l';
-#endif
- *d++ = 'l', *d++ = *c, *d = '\0';
- if (!curarg)
- zulongval = (zulong)0;
- else if (!zstrtoul_underscore(curarg, &zulongval))
- zulongval = mathevali(curarg);
- if (errflag) {
- zulongval = 0;
- errflag &= ~ERRFLAG_ERROR;
- ret = 1;
- }
- print_val(zulongval)
- }
- }
- }
- if (maxarg && (argp - first > maxarg))
- maxarg = argp - first;
- }
-
- if (maxarg) argp = first + maxarg;
- /* if there are remaining args, reuse format string */
- } while (*argp && argp != first && !fmttrunc && !OPT_ISSET(ops,'r'));
-
- if (IS_MSTREAM(fout)) {
- queue_signals();
- if ((rcount = READ_MSTREAM(buf,fout)) == -1) {
- zwarnnam(name, "i/o error: %e", errno);
- if (buf)
- free(buf);
- } else {
- if (visarr && splits) {
- char **arrayval = zshcalloc((cursplit - splits + 2) * sizeof(char *));
- for (;cursplit >= splits; cursplit--) {
- int start = cursplit == splits ? 0 : cursplit[-1];
- arrayval[cursplit - splits] =
- metafy(buf + start, count - start, META_DUP);
- count = start;
- }
- setaparam(OPT_ARG(ops, 'v'), arrayval);
- free(buf);
- } else {
- stringval = metafy(buf, rcount, META_REALLOC);
- if (OPT_ISSET(ops,'z')) {
- zpushnode(bufstack, stringval);
- } else if (OPT_ISSET(ops,'v')) {
- setsparam(OPT_ARG(ops, 'v'), stringval);
- } else {
- ent = prepnexthistent();
- ent->node.nam = stringval;
- ent->stim = ent->ftim = time(NULL);
- ent->node.flags = 0;
- ent->words = (short *)NULL;
- addhistnode(histtab, ent->node.nam, ent);
- }
- }
- }
- unqueue_signals();
- }
-
- if (!CLOSE_CLEANLY(fout))
- {
- zwarnnam(name, "write error: %e", errno);
- ret = 1;
- }
- return ret;
-}
-
-/* shift builtin */
-
-/**/
-int
-bin_shift(char *name, char **argv, Options ops, UNUSED(int func))
-{
- int num = 1, l, ret = 0;
- char **s;
-
- /* optional argument can be either numeric or an array */
- queue_signals();
- if (*argv && !getaparam(*argv)) {
- num = mathevali(*argv++);
- if (errflag) {
- unqueue_signals();
- return 1;
- }
- }
-
- if (num < 0) {
- unqueue_signals();
- zwarnnam(name, "argument to shift must be non-negative");
- return 1;
- }
-
- if (*argv) {
- for (; *argv; argv++)
- if ((s = getaparam(*argv))) {
- if (arrlen_lt(s, num)) {
- zwarnnam(name, "shift count must be <= $#");
- ret++;
- continue;
- }
- if (OPT_ISSET(ops,'p')) {
- char **s2, **src, **dst;
- int count;
- l = arrlen(s);
- src = s;
- dst = s2 = (char **)zalloc((l - num + 1) * sizeof(char *));
- for (count = l - num; count; count--)
- *dst++ = ztrdup(*src++);
- *dst = NULL;
- s = s2;
- } else {
- s = zarrdup(s + num);
- }
- setaparam(*argv, s);
- }
- } else {
- if (num > (l = arrlen(pparams))) {
- zwarnnam(name, "shift count must be <= $#");
- ret = 1;
- } else {
- s = zalloc((l - num + 1) * sizeof(char *));
- if (OPT_ISSET(ops,'p')) {
- memcpy(s, pparams, (l - num) * sizeof(char *));
- s[l-num] = NULL;
- while (num--)
- zsfree(pparams[l-1-num]);
- } else {
- memcpy(s, pparams + num, (l - num + 1) * sizeof(char *));
- while (num--)
- zsfree(pparams[num]);
- }
- zfree(pparams, (l + 1) * sizeof(char *));
- pparams = s;
- }
- }
- unqueue_signals();
- return ret;
-}
-
-/*
- * Position of getopts option within OPTIND argument with multiple options.
- */
-
-/**/
-int optcind;
-
-/* getopts: automagical option handling for shell scripts */
-
-/**/
-int
-bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- int lenstr, lenoptstr, quiet, lenoptbuf;
- char *optstr = unmetafy(*argv++, &lenoptstr), *var = *argv++;
- char **args = (*argv) ? argv : pparams;
- char *str, optbuf[2] = " ", *p, opch;
-
- /* zoptind keeps count of the current argument number. The *
- * user can set it to zero to start a new option parse. */
- if (zoptind < 1) {
- /* first call */
- zoptind = 1;
- optcind = 0;
- }
- if (arrlen_lt(args, zoptind))
- /* no more options */
- return 1;
-
- /* leading ':' in optstr means don't print an error message */
- quiet = *optstr == ':';
- optstr += quiet;
- lenoptstr -= quiet;
-
- /* find place in relevant argument */
- str = unmetafy(dupstring(args[zoptind - 1]), &lenstr);
- if (!lenstr) /* Definitely not an option. */
- return 1;
- if(optcind >= lenstr) {
- optcind = 0;
- if(!args[zoptind++])
- return 1;
- str = unmetafy(dupstring(args[zoptind - 1]), &lenstr);
- }
- if(!optcind) {
- if(lenstr < 2 || (*str != '-' && *str != '+'))
- return 1;
- if(lenstr == 2 && str[0] == '-' && str[1] == '-') {
- zoptind++;
- return 1;
- }
- optcind++;
- }
- opch = str[optcind++];
- if(str[0] == '+') {
- optbuf[0] = '+';
- lenoptbuf = 2;
- } else
- lenoptbuf = 1;
- optbuf[lenoptbuf - 1] = opch;
-
- /* check for legality */
- if(opch == ':' || !(p = memchr(optstr, opch, lenoptstr))) {
- p = "?";
- err:
- zsfree(zoptarg);
- setsparam(var, ztrdup(p));
- if(quiet) {
- zoptarg = metafy(optbuf, lenoptbuf, META_DUP);
- } else {
- zwarn(*p == '?' ? "bad option: %c%c" :
- "argument expected after %c%c option",
- "?-+"[lenoptbuf], opch);
- zoptarg=ztrdup("");
- }
- return 0;
- }
-
- /* check for required argument */
- if(p[1] == ':') {
- if(optcind == lenstr) {
- if(!args[zoptind]) {
- p = ":";
- goto err;
- }
- p = ztrdup(args[zoptind++]);
- } else
- p = metafy(str+optcind, lenstr-optcind, META_DUP);
- /*
- * Careful: I've just changed the following two lines from
- * optcind = ztrlen(args[zoptind - 1]);
- * and it's a rigorous theorem that every change in getopts breaks
- * something. See zsh-workers/9095 for the bug fixed here.
- * PWS 2000/05/02
- */
- optcind = 0;
- zoptind++;
- zsfree(zoptarg);
- zoptarg = p;
- } else {
- zsfree(zoptarg);
- zoptarg = ztrdup("");
- }
-
- setsparam(var, metafy(optbuf, lenoptbuf, META_DUP));
- return 0;
-}
-
-/* Flag that we should exit the shell as soon as all functions return. */
-/**/
-mod_export int
-exit_pending;
-
-/* Shell level at which we exit if exit_pending */
-/**/
-mod_export int
-exit_level;
-
-/* break, bye, continue, exit, logout, return -- most of these take *
- * one numeric argument, and the other (logout) is related to return. *
- * (return is treated as a logout when in a login shell.) */
-
-/**/
-int
-bin_break(char *name, char **argv, UNUSED(Options ops), int func)
-{
- int num = lastval, nump = 0, implicit;
-
- /* handle one optional numeric argument */
- implicit = !*argv;
- if (*argv) {
- num = mathevali(*argv++);
- nump = 1;
- }
-
- if (nump > 0 && (func == BIN_CONTINUE || func == BIN_BREAK) && num <= 0) {
- zerrnam(name, "argument is not positive: %d", num);
- return 1;
- }
-
- switch (func) {
- case BIN_CONTINUE:
- if (!loops) { /* continue is only permitted in loops */
- zerrnam(name, "not in while, until, select, or repeat loop");
- return 1;
- }
- contflag = 1; /* FALLTHROUGH */
- case BIN_BREAK:
- if (!loops) { /* break is only permitted in loops */
- zerrnam(name, "not in while, until, select, or repeat loop");
- return 1;
- }
- breaks = nump ? minimum(num,loops) : 1;
- break;
- case BIN_RETURN:
- if ((isset(INTERACTIVE) && isset(SHINSTDIN))
- || locallevel || sourcelevel) {
- retflag = 1;
- breaks = loops;
- lastval = num;
- if (trap_state == TRAP_STATE_PRIMED && trap_return == -2
- /*
- * With POSIX, "return" on its own in a trap doesn't
- * update $? --- we keep the status from before the
- * trap.
- */
- && !(isset(POSIXTRAPS) && implicit)) {
- trap_state = TRAP_STATE_FORCE_RETURN;
- trap_return = lastval;
- }
- return lastval;
- }
- zexit(num, 0); /* else treat return as logout/exit */
- break;
- case BIN_LOGOUT:
- if (unset(LOGINSHELL)) {
- zerrnam(name, "not login shell");
- return 1;
- }
- /*FALLTHROUGH*/
- case BIN_EXIT:
- if (locallevel > forklevel && shell_exiting != -1) {
- /*
- * We don't exit directly from functions to allow tidying
- * up, in particular EXIT traps. We still need to perform
- * the usual interactive tests to see if we can exit at
- * all, however.
- *
- * If we are forked, we exit the shell at the function depth
- * at which we became a subshell, hence the comparison.
- *
- * If we are already exiting... give this all up as
- * a bad job.
- */
- if (stopmsg || (zexit(0,2), !stopmsg)) {
- retflag = 1;
- breaks = loops;
- exit_pending = (num << 1) | 1;
- exit_level = locallevel;
- }
- } else
- zexit(num, 0);
- break;
- }
- return 0;
-}
-
-/* we have printed a 'you have stopped (running) jobs.' message */
-
-/**/
-mod_export int stopmsg;
-
-/* check to see if user has jobs running/stopped */
-
-/**/
-static void
-checkjobs(void)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if (i != thisjob && (jobtab[i].stat & STAT_LOCKED) &&
- !(jobtab[i].stat & STAT_NOPRINT) &&
- (isset(CHECKRUNNINGJOBS) || jobtab[i].stat & STAT_STOPPED))
- break;
- if (i <= maxjob) {
- if (jobtab[i].stat & STAT_STOPPED) {
-
-#ifdef USE_SUSPENDED
- zerr("you have suspended jobs.");
-#else
- zerr("you have stopped jobs.");
-#endif
-
- } else
- zerr("you have running jobs.");
- stopmsg = 1;
- }
-}
-
-/*
- * -1 if the shell is already committed to exit.
- * positive if zexit() was already called.
- */
-
-/**/
-int shell_exiting;
-
-/* exit the shell. val is the return value of the shell. *
- * from_where is
- * 1 if zexit is called because of a signal
- * 2 if we can't actually exit yet (e.g. functions need
- * terminating) but should perform the usual interactive tests.
- */
-
-/**/
-mod_export void
-zexit(int val, int from_where)
-{
- /* Don't do anything recursively: see below */
- if (shell_exiting == -1)
- return;
-
- if (isset(MONITOR) && !stopmsg && from_where != 1) {
- scanjobs(); /* check if jobs need printing */
- if (isset(CHECKJOBS))
- checkjobs(); /* check if any jobs are running/stopped */
- if (stopmsg) {
- stopmsg = 2;
- return;
- }
- }
- /* Positive in_exit means we have been here before */
- if (from_where == 2 || (shell_exiting++ && from_where))
- return;
-
- /*
- * We're now committed to exiting. Set shell_exiting to -1 to
- * indicate we shouldn't do any recursive processing.
- */
- shell_exiting = -1;
- /*
- * We want to do all remaining processing regardless of preceding
- * errors, even user interrupts.
- */
- errflag = 0;
-
- if (isset(MONITOR)) {
- /* send SIGHUP to any jobs left running */
- killrunjobs(from_where == 1);
- }
- if (isset(RCS) && interact) {
- if (!nohistsave) {
- int writeflags = HFILE_USE_OPTIONS;
- if (from_where == 1)
- writeflags |= HFILE_NO_REWRITE;
- saveandpophiststack(1, writeflags);
- savehistfile(NULL, 1, writeflags);
- }
- if (islogin && !subsh) {
- sourcehome(".zlogout");
-#ifdef GLOBAL_ZLOGOUT
- if (isset(RCS) && isset(GLOBALRCS))
- source(GLOBAL_ZLOGOUT);
-#endif
- }
- }
- lastval = val;
- /*
- * Now we are committed to exiting any previous state
- * is irrelevant. Ensure trap can run.
- */
- errflag = intrap = 0;
- if (sigtrapped[SIGEXIT])
- dotrap(SIGEXIT);
- callhookfunc("zshexit", NULL, 1, NULL);
- runhookdef(EXITHOOK, NULL);
- if (opts[MONITOR] && interact && (SHTTY != -1)) {
- release_pgrp();
- }
- if (mypid != getpid())
- _exit(val);
- else
- exit(val);
-}
-
-/* . (dot), source */
-
-/**/
-int
-bin_dot(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- char **old, *old0 = NULL;
- int diddot = 0, dotdot = 0;
- char *s, **t, *enam, *arg0, *buf;
- struct stat st;
- enum source_return ret;
-
- if (!*argv)
- return 0;
- old = pparams;
- /* get arguments for the script */
- if (argv[1])
- pparams = zarrdup(argv + 1);
-
- enam = arg0 = ztrdup(*argv);
- if (isset(FUNCTIONARGZERO)) {
- old0 = argzero;
- argzero = ztrdup(arg0);
- }
- s = unmeta(enam);
- errno = ENOENT;
- ret = SOURCE_NOT_FOUND;
- /* for source only, check in current directory first */
- if (*name != '.' && access(s, F_OK) == 0
- && stat(s, &st) >= 0 && !S_ISDIR(st.st_mode)) {
- diddot = 1;
- ret = source(enam);
- }
- if (ret == SOURCE_NOT_FOUND) {
- /* use a path with / in it */
- for (s = arg0; *s; s++)
- if (*s == '/') {
- if (*arg0 == '.') {
- if (arg0 + 1 == s)
- ++diddot;
- else if (arg0[1] == '.' && arg0 + 2 == s)
- ++dotdot;
- }
- ret = source(arg0);
- break;
- }
- if (!*s || (ret == SOURCE_NOT_FOUND &&
- isset(PATHDIRS) && diddot < 2 && dotdot == 0)) {
- pushheap();
- /* search path for script */
- for (t = path; *t; t++) {
- if (!(*t)[0] || ((*t)[0] == '.' && !(*t)[1])) {
- if (diddot)
- continue;
- diddot = 1;
- buf = dupstring(arg0);
- } else
- buf = zhtricat(*t, "/", arg0);
-
- s = unmeta(buf);
- if (access(s, F_OK) == 0 && stat(s, &st) >= 0
- && !S_ISDIR(st.st_mode)) {
- ret = source(enam = buf);
- break;
- }
- }
- popheap();
- }
- }
- /* clean up and return */
- if (argv[1]) {
- freearray(pparams);
- pparams = old;
- }
- if (ret == SOURCE_NOT_FOUND) {
- if (isset(POSIXBUILTINS)) {
- /* hard error in POSIX (we'll exit later) */
- zerrnam(name, "%e: %s", errno, enam);
- } else {
- zwarnnam(name, "%e: %s", errno, enam);
- }
- }
- zsfree(arg0);
- if (old0) {
- zsfree(argzero);
- argzero = old0;
- }
- return ret == SOURCE_OK ? lastval : 128 - ret;
-}
-
-/*
- * common for bin_emulate and bin_eval
- */
-
-static int
-eval(char **argv)
-{
- Eprog prog;
- char *oscriptname = scriptname;
- int oineval = ineval, fpushed;
- struct funcstack fstack;
-
- /*
- * If EVALLINENO is not set, we use the line number of the
- * environment and must flag this up to exec.c. Otherwise,
- * we use a special script name to indicate the special line number.
- */
- ineval = !isset(EVALLINENO);
- if (!ineval) {
- scriptname = "(eval)";
- fstack.prev = funcstack;
- fstack.name = scriptname;
- fstack.caller = funcstack ? funcstack->name : dupstring(argzero);
- fstack.lineno = lineno;
- fstack.tp = FS_EVAL;
-
- /*
- * To get file line numbers, we need to know if parent is
- * the original script/shell or a sourced file, in which
- * case we use the line number raw, or a function or eval,
- * in which case we need to deduce where that came from.
- *
- * This replicates the logic for working out the information
- * for $funcfiletrace---eval is similar to an inlined function
- * call from a tracing perspective.
- */
- if (!funcstack || funcstack->tp == FS_SOURCE) {
- fstack.flineno = fstack.lineno;
- fstack.filename = fstack.caller;
- } else {
- fstack.flineno = funcstack->flineno + lineno;
- /*
- * Line numbers in eval start from 1, not zero,
- * so offset by one to get line in file.
- */
- if (funcstack->tp == FS_EVAL)
- fstack.flineno--;
- fstack.filename = funcstack->filename;
- if (!fstack.filename)
- fstack.filename = "";
- }
- funcstack = &fstack;
-
- fpushed = 1;
- } else
- fpushed = 0;
-
- prog = parse_string(zjoin(argv, ' ', 1), 1);
- if (prog) {
- if (wc_code(*prog->prog) != WC_LIST) {
- /* No code to execute */
- lastval = 0;
- } else {
- execode(prog, 1, 0, "eval");
-
- if (errflag && !lastval)
- lastval = errflag;
- }
- } else {
- lastval = 1;
- }
-
- if (fpushed)
- funcstack = funcstack->prev;
-
- errflag &= ~ERRFLAG_ERROR;
- scriptname = oscriptname;
- ineval = oineval;
-
- return lastval;
-}
-
-/* emulate: set emulation mode and optionally evaluate shell code */
-
-/**/
-int
-bin_emulate(char *nam, char **argv, Options ops, UNUSED(int func))
-{
- int opt_L = OPT_ISSET(ops, 'L');
- int opt_R = OPT_ISSET(ops, 'R');
- int opt_l = OPT_ISSET(ops, 'l');
- int saveemulation, savehackchar;
- int ret = 1, new_emulation;
- unsigned int savepatterns;
- char saveopts[OPT_SIZE], new_opts[OPT_SIZE];
- char *cmd = 0;
- const char *shname = *argv;
- LinkList optlist;
- LinkNode optnode;
- Emulation_options save_sticky;
- OptIndex *on_ptr, *off_ptr;
-
- /* without arguments just print current emulation */
- if (!shname) {
- if (opt_L || opt_R) {
- zwarnnam(nam, "not enough arguments");
- return 1;
- }
-
- switch(SHELL_EMULATION()) {
- case EMULATE_CSH:
- shname = "csh";
- break;
-
- case EMULATE_KSH:
- shname = "ksh";
- break;
-
- case EMULATE_SH:
- shname = "sh";
- break;
-
- default:
- shname = "zsh";
- break;
- }
-
- printf("%s\n", shname);
- return 0;
- }
-
- /* with single argument set current emulation */
- if (!argv[1]) {
- char *cmdopts;
- if (opt_l) {
- cmdopts = (char *)zhalloc(OPT_SIZE);
- memcpy(cmdopts, opts, OPT_SIZE);
- } else
- cmdopts = opts;
- emulate(shname, opt_R, &emulation, cmdopts);
- if (opt_L)
- cmdopts[LOCALOPTIONS] = cmdopts[LOCALTRAPS] =
- cmdopts[LOCALPATTERNS] = 1;
- if (opt_l) {
- list_emulate_options(cmdopts, opt_R);
- return 0;
- }
- clearpatterndisables();
- return 0;
- }
-
- if (opt_l) {
- zwarnnam(nam, "too many arguments for -l");
- return 1;
- }
-
- argv++;
- memcpy(saveopts, opts, sizeof(opts));
- memcpy(new_opts, opts, sizeof(opts));
- savehackchar = keyboardhackchar;
- emulate(shname, opt_R, &new_emulation, new_opts);
- optlist = newlinklist();
- if (parseopts(nam, &argv, new_opts, &cmd, optlist, 0)) {
- ret = 1;
- goto restore;
- }
-
- /* parseopts() has consumed anything that looks like an option */
- if (*argv) {
- zwarnnam(nam, "unknown argument %s", *argv);
- goto restore;
- }
-
- savepatterns = savepatterndisables();
- /*
- * All emulations start with an empty set of pattern disables,
- * hence no special "sticky" behaviour is required.
- */
- clearpatterndisables();
-
- saveemulation = emulation;
- emulation = new_emulation;
- memcpy(opts, new_opts, sizeof(opts));
- /* If "-c command" is given, evaluate command using specified
- * emulation mode.
- */
- if (cmd) {
- if (opt_L) {
- zwarnnam(nam, "option -L incompatible with -c");
- goto restore2;
- }
- *--argv = cmd; /* on stack, never free()d, see execbuiltin() */
- } else {
- if (opt_L)
- opts[LOCALOPTIONS] = opts[LOCALTRAPS] = opts[LOCALPATTERNS] = 1;
- return 0;
- }
-
- save_sticky = sticky;
- sticky = hcalloc(sizeof(*sticky));
- sticky->emulation = emulation;
- for (optnode = firstnode(optlist); optnode; incnode(optnode)) {
- /* Data is index into new_opts */
- char *optptr = (char *)getdata(optnode);
- if (*optptr)
- sticky->n_on_opts++;
- else
- sticky->n_off_opts++;
- }
- if (sticky->n_on_opts)
- on_ptr = sticky->on_opts =
- zhalloc(sticky->n_on_opts * sizeof(*sticky->on_opts));
- else
- on_ptr = NULL;
- if (sticky->n_off_opts)
- off_ptr = sticky->off_opts = zhalloc(sticky->n_off_opts *
- sizeof(*sticky->off_opts));
- else
- off_ptr = NULL;
- for (optnode = firstnode(optlist); optnode; incnode(optnode)) {
- /* Data is index into new_opts */
- char *optptr = (char *)getdata(optnode);
- int optno = optptr - new_opts;
- if (*optptr)
- *on_ptr++ = optno;
- else
- *off_ptr++ = optno;
- }
- ret = eval(argv);
- sticky = save_sticky;
-restore2:
- emulation = saveemulation;
- memcpy(opts, saveopts, sizeof(opts));
- restorepatterndisables(savepatterns);
-restore:
- keyboardhackchar = savehackchar;
- inittyptab(); /* restore banghist */
- return ret;
-}
-
-/* eval: simple evaluation */
-
-/**/
-mod_export int ineval;
-
-/**/
-int
-bin_eval(UNUSED(char *nam), char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- return eval(argv);
-}
-
-static char *zbuf;
-static int readfd;
-
-/* Read a character from readfd, or from the buffer zbuf. Return EOF on end of
-file/buffer. */
-
-/* read: get a line of input, or (for compctl functions) return some *
- * useful data about the state of the editing line. The -E and -e *
- * options mean that the result should be sent to stdout. -e means, *
- * in addition, that the result should not actually be assigned to *
- * the specified parameters. */
-
-/**/
-int
-bin_read(char *name, char **args, Options ops, UNUSED(int func))
-{
- char *reply, *readpmpt;
- int bsiz, c = 0, gotnl = 0, al = 0, first, nchars = 1, bslash, keys = 0;
- int haso = 0; /* true if /dev/tty has been opened specially */
- int isem = !strcmp(term, "emacs"), izle = zleactive;
- char *buf, *bptr, *firstarg, *zbuforig;
- LinkList readll = newlinklist();
- FILE *oshout = NULL;
- int readchar = -1, val, resettty = 0;
- struct ttyinfo saveti;
- char d;
- long izle_timeout = 0;
-#ifdef MULTIBYTE_SUPPORT
- wchar_t delim = L'\n', wc;
- mbstate_t mbs;
- char *laststart;
- size_t ret;
-#else
- char delim = '\n';
-#endif
-
- if (OPT_HASARG(ops,c='k')) {
- char *eptr, *optarg = OPT_ARG(ops,c);
- nchars = (int)zstrtol(optarg, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expected after -%c: %s", c, optarg);
- return 1;
- }
- }
- /* This `*args++ : *args' looks a bit weird, but it works around a bug
- * in gcc-2.8.1 under DU 4.0. */
- firstarg = (*args && **args == '?' ? *args++ : *args);
- reply = *args ? *args++ : OPT_ISSET(ops,'A') ? "reply" : "REPLY";
-
- if (OPT_ISSET(ops,'A') && *args) {
- zwarnnam(name, "only one array argument allowed");
- return 1;
- }
-
- /* handle compctl case */
- if(OPT_ISSET(ops,'l') || OPT_ISSET(ops,'c'))
- return compctlreadptr(name, args, ops, reply);
-
- if ((OPT_ISSET(ops,'k') || OPT_ISSET(ops,'q')) &&
- !OPT_ISSET(ops,'u') && !OPT_ISSET(ops,'p')) {
- if (!zleactive) {
- if (SHTTY == -1) {
- /* need to open /dev/tty specially */
- if ((SHTTY = open("/dev/tty", O_RDWR|O_NOCTTY)) != -1) {
- haso = 1;
- oshout = shout;
- init_shout();
- }
- } else if (!shout) {
- /* We need an output FILE* on the tty */
- init_shout();
- }
- /* We should have a SHTTY opened by now. */
- if (SHTTY == -1) {
- /* Unfortunately, we didn't. */
- fprintf(stderr, "not interactive and can't open terminal\n");
- fflush(stderr);
- return 1;
- }
- if (unset(INTERACTIVE))
- gettyinfo(&shttyinfo);
- /* attach to the tty */
- attachtty(mypgrp);
- if (!isem)
- setcbreak();
- readfd = SHTTY;
- }
- keys = 1;
- } else if (OPT_HASARG(ops,'u') && !OPT_ISSET(ops,'p')) {
- /* -u means take input from the specified file descriptor. */
- char *eptr, *argptr = OPT_ARG(ops,'u');
- /* The old code handled -up, but that was never documented. Still...*/
- if (!strcmp(argptr, "p")) {
- readfd = coprocin;
- if (readfd < 0) {
- zwarnnam(name, "-p: no coprocess");
- return 1;
- }
- } else {
- readfd = (int)zstrtol(argptr, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expected after -%c: %s", 'u', argptr);
- return 1;
- }
- }
-#if 0
- /* This code is left as a warning to future generations --- pws. */
- for (readfd = 9; readfd && !OPT_ISSET(ops,readfd + '0'); --readfd);
-#endif
- izle = 0;
- } else if (OPT_ISSET(ops,'p')) {
- readfd = coprocin;
- if (readfd < 0) {
- zwarnnam(name, "-p: no coprocess");
- return 1;
- }
- izle = 0;
- } else
- readfd = izle = 0;
-
- if (OPT_ISSET(ops,'s') && SHTTY != -1) {
- struct ttyinfo ti;
- gettyinfo(&ti);
- saveti = ti;
- resettty = 1;
-#ifdef HAS_TIO
- ti.tio.c_lflag &= ~ECHO;
-#else
- ti.sgttyb.sg_flags &= ~ECHO;
-#endif
- settyinfo(&ti);
- }
-
- /* handle prompt */
- if (firstarg) {
- for (readpmpt = firstarg;
- *readpmpt && *readpmpt != '?'; readpmpt++);
- if (*readpmpt++) {
- if (keys || isatty(0)) {
- zputs(readpmpt, (shout ? shout : stderr));
- fflush(shout ? shout : stderr);
- }
- readpmpt[-1] = '\0';
- }
- }
-
- if (OPT_ISSET(ops,'d')) {
- char *delimstr = OPT_ARG(ops,'d');
-#ifdef MULTIBYTE_SUPPORT
- wint_t wi;
-
- if (isset(MULTIBYTE)) {
- mb_charinit();
- (void)mb_metacharlenconv(delimstr, &wi);
- }
- else
- wi = WEOF;
- if (wi != WEOF)
- delim = (wchar_t)wi;
- else
- delim = (wchar_t)((delimstr[0] == Meta) ?
- delimstr[1] ^ 32 : delimstr[0]);
-#else
- delim = (delimstr[0] == Meta) ? delimstr[1] ^ 32 : delimstr[0];
-#endif
- if (SHTTY != -1) {
- struct ttyinfo ti;
- gettyinfo(&ti);
- if (! resettty) {
- saveti = ti;
- resettty = 1;
- }
-#ifdef HAS_TIO
- ti.tio.c_lflag &= ~ICANON;
- ti.tio.c_cc[VMIN] = 1;
- ti.tio.c_cc[VTIME] = 0;
-#else
- ti.sgttyb.sg_flags |= CBREAK;
-#endif
- settyinfo(&ti);
- }
- }
- if (OPT_ISSET(ops,'t')) {
- zlong timeout = 0;
- if (OPT_HASARG(ops,'t')) {
- mnumber mn = zero_mnumber;
- mn = matheval(OPT_ARG(ops,'t'));
- if (errflag)
- return 1;
- if (mn.type == MN_FLOAT) {
- mn.u.d *= 1e6;
- timeout = (zlong)mn.u.d;
- } else {
- timeout = (zlong)mn.u.l * (zlong)1000000;
- }
- }
- if (izle) {
- /*
- * Timeout is in 100ths of a second rather than us.
- * See calc_timeout() in zle_main for format of this.
- */
- timeout = -(timeout/(zlong)10000 + 1L);
- izle_timeout = (long)timeout;
-#ifdef LONG_MAX
- /* saturate if range exceeded */
- if ((zlong)izle_timeout != timeout)
- izle_timeout = LONG_MAX;
-#endif
- } else {
- if (readfd == -1 ||
- !read_poll(readfd, &readchar, keys && !zleactive,
- timeout)) {
- if (keys && !zleactive && !isem)
- settyinfo(&shttyinfo);
- else if (resettty && SHTTY != -1)
- settyinfo(&saveti);
- if (haso) {
- fclose(shout);
- shout = oshout;
- SHTTY = -1;
- }
- return OPT_ISSET(ops,'q') ? 2 : 1;
- }
- }
- }
-
-#ifdef MULTIBYTE_SUPPORT
- memset(&mbs, 0, sizeof(mbs));
-#endif
-
- /*
- * option -k means read only a given number of characters (default 1)
- * option -q means get one character, and interpret it as a Y or N
- */
- if (OPT_ISSET(ops,'k') || OPT_ISSET(ops,'q')) {
- int eof = 0;
- /* allocate buffer space for result */
-#ifdef MULTIBYTE_SUPPORT
- bptr = buf = (char *)zalloc(nchars*MB_CUR_MAX+1);
-#else
- bptr = buf = (char *)zalloc(nchars+1);
-#endif
-
- do {
- if (izle) {
- zleentry(ZLE_CMD_GET_KEY, izle_timeout, NULL, &val);
- if (val < 0) {
- eof = 1;
- break;
- }
- *bptr = (char) val;
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- ret = mbrlen(bptr++, 1, &mbs);
- if (ret == MB_INVALID)
- memset(&mbs, 0, sizeof(mbs));
- /* treat invalid as single character */
- if (ret != MB_INCOMPLETE)
- nchars--;
- continue;
- } else {
- bptr++;
- nchars--;
- }
-#else
- bptr++;
- nchars--;
-#endif
- } else {
- /* If read returns 0, is end of file */
- if (readchar >= 0) {
- *bptr = readchar;
- val = 1;
- readchar = -1;
- } else {
- while ((val = read(readfd, bptr, nchars)) < 0) {
- if (errno != EINTR ||
- errflag || retflag || breaks || contflag)
- break;
- }
- if (val <= 0) {
- eof = 1;
- break;
- }
- }
-
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- while (val > 0) {
- ret = mbrlen(bptr, val, &mbs);
- if (ret == MB_INCOMPLETE) {
- bptr += val;
- break;
- } else {
- if (ret == MB_INVALID) {
- memset(&mbs, 0, sizeof(mbs));
- /* treat as single byte */
- ret = 1;
- }
- else if (ret == 0) /* handle null as normal char */
- ret = 1;
- else if (ret > (size_t)val) {
- /* Some mbrlen()s return the full char len */
- ret = val;
- }
- nchars--;
- val -= ret;
- bptr += ret;
- }
- }
- continue;
- }
-#endif
- /* decrement number of characters read from number required */
- nchars -= val;
-
- /* increment pointer past read characters */
- bptr += val;
- }
- } while (nchars > 0);
-
- if (!izle && !OPT_ISSET(ops,'u') && !OPT_ISSET(ops,'p')) {
- /* dispose of result appropriately, etc. */
- if (isem)
- while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
- else {
- settyinfo(&shttyinfo);
- resettty = 0;
- }
- if (haso) {
- fclose(shout); /* close(SHTTY) */
- shout = oshout;
- SHTTY = -1;
- }
- }
-
- if (OPT_ISSET(ops,'q'))
- {
- /*
- * Keep eof as status but status is now whether we read
- * 'y' or 'Y'. If we timed out, status is 2.
- */
- if (eof)
- eof = 2;
- else
- eof = (bptr - buf != 1 || (buf[0] != 'y' && buf[0] != 'Y'));
- buf[0] = eof ? 'n' : 'y';
- bptr = buf + 1;
- }
- if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E'))
- fwrite(buf, bptr - buf, 1, stdout);
- if (!OPT_ISSET(ops,'e'))
- setsparam(reply, metafy(buf, bptr - buf, META_REALLOC));
- else
- zfree(buf, bptr - buf + 1);
- if (resettty && SHTTY != -1)
- settyinfo(&saveti);
- return eof;
- }
-
- /* All possible special types of input have been exhausted. Take one line,
- and assign words to the parameters until they run out. Leftover words go
- onto the last parameter. If an array is specified, all the words become
- separate elements of the array. */
-
- zbuforig = zbuf = (!OPT_ISSET(ops,'z')) ? NULL :
- (nonempty(bufstack)) ? (char *) getlinknode(bufstack) : ztrdup("");
- first = 1;
- bslash = 0;
- while (*args || (OPT_ISSET(ops,'A') && !gotnl)) {
- sigset_t s = child_unblock();
- buf = bptr = (char *)zalloc(bsiz = 64);
-#ifdef MULTIBYTE_SUPPORT
- laststart = buf;
- ret = MB_INCOMPLETE;
-#endif
- /* get input, a character at a time */
- while (!gotnl) {
- c = zread(izle, &readchar, izle_timeout);
- /* \ at the end of a line indicates a continuation *
- * line, except in raw mode (-r option) */
-#ifdef MULTIBYTE_SUPPORT
- if (c == EOF) {
- /* not waiting to be completed any more */
- ret = 0;
- break;
- }
- *bptr = (char)c;
- if (isset(MULTIBYTE)) {
- ret = mbrtowc(&wc, bptr, 1, &mbs);
- if (!ret) /* NULL */
- ret = 1;
- } else {
- ret = 1;
- wc = (wchar_t)c;
- }
- if (ret != MB_INCOMPLETE) {
- if (ret == MB_INVALID) {
- memset(&mbs, 0, sizeof(mbs));
- /* Treat this as a single character */
- wc = (wchar_t)c;
- laststart = bptr;
- }
- if (bslash && wc == delim) {
- bslash = 0;
- continue;
- }
- if (wc == delim)
- break;
- /*
- * `first' is non-zero if any separator we encounter is a
- * non-whitespace separator, which means that anything
- * (even an empty string) between, before or after separators
- * is significant. If it is zero, we have a whitespace
- * separator, which shouldn't cause extra empty strings to
- * be emitted. Hence the test for (*buf || first) when
- * we assign the result of reading a word.
- */
- if (!bslash && wcsitype(wc, ISEP)) {
- if (bptr != buf ||
- (!(c < 128 && iwsep(c)) && first)) {
- first |= !(c < 128 && iwsep(c));
- break;
- }
- first |= !(c < 128 && iwsep(c));
- continue;
- }
- bslash = (wc == L'\\' && !bslash && !OPT_ISSET(ops,'r'));
- if (bslash)
- continue;
- first = 0;
- }
- if (imeta(STOUC(*bptr))) {
- bptr[1] = bptr[0] ^ 32;
- bptr[0] = Meta;
- bptr += 2;
- }
- else
- bptr++;
- if (ret != MB_INCOMPLETE)
- laststart = bptr;
-#else
- if (c == EOF)
- break;
- if (bslash && c == delim) {
- bslash = 0;
- continue;
- }
- if (c == delim)
- break;
- /*
- * `first' is non-zero if any separator we encounter is a
- * non-whitespace separator, which means that anything
- * (even an empty string) between, before or after separators
- * is significant. If it is zero, we have a whitespace
- * separator, which shouldn't cause extra empty strings to
- * be emitted. Hence the test for (*buf || first) when
- * we assign the result of reading a word.
- */
- if (!bslash && isep(c)) {
- if (bptr != buf || (!iwsep(c) && first)) {
- first |= !iwsep(c);
- break;
- }
- first |= !iwsep(c);
- continue;
- }
- bslash = c == '\\' && !bslash && !OPT_ISSET(ops,'r');
- if (bslash)
- continue;
- first = 0;
- if (imeta(c)) {
- *bptr++ = Meta;
- *bptr++ = c ^ 32;
- } else
- *bptr++ = c;
-#endif
- /* increase the buffer size, if necessary */
- if (bptr >= buf + bsiz - 1) {
- int blen = bptr - buf;
-#ifdef MULTIBYTE_SUPPORT
- int llen = laststart - buf;
-#endif
-
- buf = realloc(buf, bsiz *= 2);
- bptr = buf + blen;
-#ifdef MULTIBYTE_SUPPORT
- laststart = buf + llen;
-#endif
- }
- }
- signal_setmask(s);
-#ifdef MULTIBYTE_SUPPORT
- if (c == EOF) {
- gotnl = 1;
- *bptr = '\0'; /* see below */
- } else if (ret == MB_INCOMPLETE) {
- /*
- * We can only get here if there is an EOF in the
- * middle of a character... safest to keep the debris,
- * I suppose.
- */
- *bptr = '\0';
- } else {
- if (wc == delim)
- gotnl = 1;
- *laststart = '\0';
- }
-#else
- if (c == delim || c == EOF)
- gotnl = 1;
- *bptr = '\0';
-#endif
- /* dispose of word appropriately */
- if (OPT_ISSET(ops,'e') ||
- /*
- * When we're doing an array assignment, we'll
- * handle echoing at that point. In all other
- * cases (including -A with no assignment)
- * we'll do it here.
- */
- (OPT_ISSET(ops,'E') && !OPT_ISSET(ops,'A'))) {
- zputs(buf, stdout);
- putchar('\n');
- }
- if (!OPT_ISSET(ops,'e') && (*buf || first || gotnl)) {
- if (OPT_ISSET(ops,'A')) {
- addlinknode(readll, buf);
- al++;
- } else
- setsparam(reply, buf);
- } else
- free(buf);
- if (!OPT_ISSET(ops,'A'))
- reply = *args++;
- }
- /* handle EOF */
- if (c == EOF) {
- if (readfd == coprocin) {
- close(coprocin);
- close(coprocout);
- coprocin = coprocout = -1;
- }
- }
- /* final assignment (and display) of array parameter */
- if (OPT_ISSET(ops,'A')) {
- char **pp, **p = NULL;
- LinkNode n;
-
- p = (OPT_ISSET(ops,'e') ? (char **)NULL
- : (char **)zalloc((al + 1) * sizeof(char *)));
-
- for (pp = p, n = firstnode(readll); n; incnode(n)) {
- if (OPT_ISSET(ops,'E')) {
- zputs((char *) getdata(n), stdout);
- putchar('\n');
- }
- if (p)
- *pp++ = (char *)getdata(n);
- else
- zsfree(getdata(n));
- }
- if (p) {
- *pp++ = NULL;
- setaparam(reply, p);
- }
- if (resettty && SHTTY != -1)
- settyinfo(&saveti);
- return c == EOF;
- }
- buf = bptr = (char *)zalloc(bsiz = 64);
-#ifdef MULTIBYTE_SUPPORT
- laststart = buf;
- ret = MB_INCOMPLETE;
-#endif
- /* any remaining part of the line goes into one parameter */
- bslash = 0;
- if (!gotnl) {
- sigset_t s = child_unblock();
- for (;;) {
- c = zread(izle, &readchar, izle_timeout);
-#ifdef MULTIBYTE_SUPPORT
- if (c == EOF) {
- /* not waiting to be completed any more */
- ret = 0;
- break;
- }
- *bptr = (char)c;
- if (isset(MULTIBYTE)) {
- ret = mbrtowc(&wc, bptr, 1, &mbs);
- if (!ret) /* NULL */
- ret = 1;
- } else {
- ret = 1;
- wc = (wchar_t)c;
- }
- if (ret != MB_INCOMPLETE) {
- if (ret == MB_INVALID) {
- memset(&mbs, 0, sizeof(mbs));
- /* Treat this as a single character */
- wc = (wchar_t)c;
- laststart = bptr;
- }
- /*
- * \ at the end of a line introduces a continuation line,
- * except in raw mode (-r option)
- */
- if (bslash && wc == delim) {
- bslash = 0;
- continue;
- }
- if (wc == delim && !zbuf)
- break;
- if (!bslash && bptr == buf && wcsitype(wc, ISEP)) {
- if (c < 128 && iwsep(c))
- continue;
- else if (!first) {
- first = 1;
- continue;
- }
- }
- bslash = (wc == L'\\' && !bslash && !OPT_ISSET(ops,'r'));
- if (bslash)
- continue;
- }
- if (imeta(STOUC(*bptr))) {
- bptr[1] = bptr[0] ^ 32;
- bptr[0] = Meta;
- bptr += 2;
- }
- else
- bptr++;
- if (ret != MB_INCOMPLETE)
- laststart = bptr;
-#else
- /* \ at the end of a line introduces a continuation line, except in
- raw mode (-r option) */
- if (bslash && c == delim) {
- bslash = 0;
- continue;
- }
- if (c == EOF || (c == delim && !zbuf))
- break;
- if (!bslash && isep(c) && bptr == buf) {
- if (iwsep(c))
- continue;
- else if (!first) {
- first = 1;
- continue;
- }
- }
- bslash = c == '\\' && !bslash && !OPT_ISSET(ops,'r');
- if (bslash)
- continue;
- if (imeta(c)) {
- *bptr++ = Meta;
- *bptr++ = c ^ 32;
- } else
- *bptr++ = c;
-#endif
- /* increase the buffer size, if necessary */
- if (bptr >= buf + bsiz - 1) {
- int blen = bptr - buf;
-#ifdef MULTIBYTE_SUPPORT
- int llen = laststart - buf;
-#endif
-
- buf = realloc(buf, bsiz *= 2);
- bptr = buf + blen;
-#ifdef MULTIBYTE_SUPPORT
- laststart = buf + llen;
-#endif
- }
- }
- signal_setmask(s);
- }
-#ifdef MULTIBYTE_SUPPORT
- if (ret != MB_INCOMPLETE)
- bptr = laststart;
-#endif
- /*
- * Strip trailing IFS whitespace.
- * iwsep can only be certain single-byte ASCII bytes, but we
- * must check the byte isn't metafied.
- */
- while (bptr > buf) {
- if (bptr > buf + 1 && bptr[-2] == Meta) {
- /* non-ASCII, can't be IWSEP */
- break;
- } else if (iwsep(bptr[-1]))
- bptr--;
- else
- break;
- }
- *bptr = '\0';
- if (resettty && SHTTY != -1)
- settyinfo(&saveti);
- /* final assignment of reply, etc. */
- if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E')) {
- zputs(buf, stdout);
- putchar('\n');
- }
- if (!OPT_ISSET(ops,'e'))
- setsparam(reply, buf);
- else
- zsfree(buf);
- if (zbuforig) {
- char first = *zbuforig;
-
- zsfree(zbuforig);
- if (!first)
- return 1;
- } else if (c == EOF) {
- if (readfd == coprocin) {
- close(coprocin);
- close(coprocout);
- coprocin = coprocout = -1;
- }
- return 1;
- }
- /*
- * The following is to ensure a failure to set the parameter
- * causes a non-zero status return. There are arguments for
- * turning a non-zero status into errflag more widely.
- */
- return errflag;
-}
-
-/**/
-static int
-zread(int izle, int *readchar, long izle_timeout)
-{
- char cc, retry = 0;
- int ret;
-
- if (izle) {
- int c;
- zleentry(ZLE_CMD_GET_KEY, izle_timeout, NULL, &c);
-
- return (c < 0 ? EOF : c);
- }
- /* use zbuf if possible */
- if (zbuf) {
- /* If zbuf points to anything, it points to the next character in the
- buffer. This may be a null byte to indicate EOF. If reading from the
- buffer, move on the buffer pointer. */
- if (*zbuf == Meta)
- return zbuf++, STOUC(*zbuf++ ^ 32);
- else
- return (*zbuf) ? STOUC(*zbuf++) : EOF;
- }
- if (*readchar >= 0) {
- cc = *readchar;
- *readchar = -1;
- return STOUC(cc);
- }
- for (;;) {
- /* read a character from readfd */
- ret = read(readfd, &cc, 1);
- switch (ret) {
- case 1:
- /* return the character read */
- return STOUC(cc);
- case -1:
-#if defined(EAGAIN) || defined(EWOULDBLOCK)
- if (!retry && readfd == 0 && (
-# ifdef EAGAIN
- errno == EAGAIN
-# ifdef EWOULDBLOCK
- ||
-# endif /* EWOULDBLOCK */
-# endif /* EAGAIN */
-# ifdef EWOULDBLOCK
- errno == EWOULDBLOCK
-# endif /* EWOULDBLOCK */
- ) && setblock_stdin()) {
- retry = 1;
- continue;
- } else
-#endif /* EAGAIN || EWOULDBLOCK */
- if (errno == EINTR && !(errflag || retflag || breaks || contflag))
- continue;
- break;
- }
- return EOF;
- }
-}
-
-/* holds arguments for testlex() */
-/**/
-char **testargs, **curtestarg;
-
-/* test, [: the old-style general purpose logical expression builtin */
-
-/**/
-void
-testlex(void)
-{
- if (tok == LEXERR)
- return;
-
- tokstr = *(curtestarg = testargs);
- if (!*testargs) {
- /* if tok is already zero, reading past the end: error */
- tok = tok ? NULLTOK : LEXERR;
- return;
- } else if (!strcmp(*testargs, "-o"))
- tok = DBAR;
- else if (!strcmp(*testargs, "-a"))
- tok = DAMPER;
- else if (!strcmp(*testargs, "!"))
- tok = BANG;
- else if (!strcmp(*testargs, "("))
- tok = INPAR;
- else if (!strcmp(*testargs, ")"))
- tok = OUTPAR;
- else
- tok = STRING;
- testargs++;
-}
-
-/**/
-int
-bin_test(char *name, char **argv, UNUSED(Options ops), int func)
-{
- char **s;
- Eprog prog;
- struct estate state;
- int nargs, sense = 0, ret;
-
- /* if "test" was invoked as "[", it needs a matching "]" *
- * which is subsequently ignored */
- if (func == BIN_BRACKET) {
- for (s = argv; *s; s++);
- if (s == argv || strcmp(s[-1], "]")) {
- zwarnnam(name, "']' expected");
- return 2;
- }
- s[-1] = NULL;
- }
- /* an empty argument list evaluates to false (1) */
- if (!*argv)
- return 1;
-
- /*
- * Implement some XSI extensions to POSIX here.
- * See
- * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
- */
- nargs = arrlen(argv);
- if (nargs == 3 || nargs == 4)
- {
- /*
- * As parentheses are an extension, we need to be careful ---
- * if this is a three-argument expression that could
- * be a binary operator, prefer that.
- */
- if (!strcmp(argv[0], "(") && !strcmp(argv[nargs-1],")") &&
- (nargs != 3 || !is_cond_binary_op(argv[1]))) {
- argv[nargs-1] = NULL;
- argv++;
- }
- if (nargs == 4 && !strcmp("!", argv[0])) {
- sense = 1;
- argv++;
- }
- }
-
- zcontext_save();
- testargs = argv;
- tok = NULLTOK;
- condlex = testlex;
- testlex();
- prog = parse_cond();
- condlex = zshlex;
-
- if (errflag) {
- errflag &= ~ERRFLAG_ERROR;
- zcontext_restore();
- return 2;
- }
-
- if (!prog || tok == LEXERR) {
- zwarnnam(name, tokstr ? "parse error" : "argument expected");
- zcontext_restore();
- return 2;
- }
- zcontext_restore();
-
- if (*curtestarg) {
- zwarnnam(name, "too many arguments");
- return 2;
- }
-
- /* syntax is OK, so evaluate */
-
- state.prog = prog;
- state.pc = prog->prog;
- state.strs = prog->strs;
-
- ret = evalcond(&state, name);
- if (ret < 2 && sense)
- ret = ! ret;
-
- return ret;
-}
-
-/* display a time, provided in units of 1/60s, as minutes and seconds */
-#define pttime(X) printf("%ldm%ld.%02lds",((long) (X))/(60 * clktck),\
- ((long) (X))/clktck%clktck,\
- ((long) (X))*100/clktck%100)
-
-/* times: display, in a two-line format, the times provided by times(3) */
-
-/**/
-int
-bin_times(UNUSED(char *name), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func))
-{
- struct tms buf;
- long clktck = get_clktck();
-
- /* get time accounting information */
- if (times(&buf) == -1)
- return 1;
- pttime(buf.tms_utime); /* user time */
- putchar(' ');
- pttime(buf.tms_stime); /* system time */
- putchar('\n');
- pttime(buf.tms_cutime); /* user time, children */
- putchar(' ');
- pttime(buf.tms_cstime); /* system time, children */
- putchar('\n');
- return 0;
-}
-
-/* trap: set/unset signal traps */
-
-/**/
-int
-bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- Eprog prog;
- char *arg, *s;
- int sig;
-
- if (*argv && !strcmp(*argv, "--"))
- argv++;
-
- /* If given no arguments, list all currently-set traps */
- if (!*argv) {
- queue_signals();
- for (sig = 0; sig < VSIGCOUNT; sig++) {
- if (sigtrapped[sig] & ZSIG_FUNC) {
- HashNode hn;
-
- if ((hn = gettrapnode(sig, 0)))
- shfunctab->printnode(hn, 0);
- DPUTS(!hn, "BUG: I did not find any trap functions!");
- } else if (sigtrapped[sig]) {
- const char *name = getsigname(sig);
- if (!siglists[sig])
- printf("trap -- '' %s\n", name);
- else {
- s = getpermtext(siglists[sig], NULL, 0);
- printf("trap -- ");
- quotedzputs(s, stdout);
- printf(" %s\n", name);
- zsfree(s);
- }
- }
- }
- unqueue_signals();
- return 0;
- }
-
- /* If we have a signal number, unset the specified *
- * signals. With only -, remove all traps. */
- if ((getsignum(*argv) != -1) || (!strcmp(*argv, "-") && argv++)) {
- if (!*argv) {
- for (sig = 0; sig < VSIGCOUNT; sig++)
- unsettrap(sig);
- } else {
- for (; *argv; argv++) {
- sig = getsignum(*argv);
- if (sig == -1) {
- zwarnnam(name, "undefined signal: %s", *argv);
- break;
- }
- unsettrap(sig);
- }
- }
- return *argv != NULL;
- }
-
- /* Sort out the command to execute on trap */
- arg = *argv++;
- if (!*arg)
- prog = &dummy_eprog;
- else if (!(prog = parse_string(arg, 1))) {
- zwarnnam(name, "couldn't parse trap command");
- return 1;
- }
-
- /* set traps */
- for (; *argv; argv++) {
- Eprog t;
- int flags;
-
- sig = getsignum(*argv);
- if (sig == -1) {
- zwarnnam(name, "undefined signal: %s", *argv);
- break;
- }
- if (idigit(**argv) ||
- !strcmp(sigs[sig], *argv) ||
- (!strncmp("SIG", *argv, 3) && !strcmp(sigs[sig], *argv+3))) {
- /* The signal was specified by number or by canonical name (with
- * or without SIG prefix).
- */
- flags = 0;
- }
- else {
- /*
- * Record that the signal is used under an assumed name.
- * If we ever have more than one alias per signal this
- * will need improving.
- */
- flags = ZSIG_ALIAS;
- }
- t = dupeprog(prog, 0);
- if (settrap(sig, t, flags))
- freeeprog(t);
- }
- return *argv != NULL;
-}
-
-/**/
-int
-bin_ttyctl(UNUSED(char *name), UNUSED(char **argv), Options ops, UNUSED(int func))
-{
- if (OPT_ISSET(ops,'f'))
- ttyfrozen = 1;
- else if (OPT_ISSET(ops,'u'))
- ttyfrozen = 0;
- else
- printf("tty is %sfrozen\n", ttyfrozen ? "" : "not ");
- return 0;
-}
-
-/* let -- mathematical evaluation */
-
-/**/
-int
-bin_let(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- mnumber val = zero_mnumber;
-
- while (*argv)
- val = matheval(*argv++);
- /* Errors in math evaluation in let are non-fatal. */
- errflag &= ~ERRFLAG_ERROR;
- /* should test for fabs(val.u.d) < epsilon? */
- return (val.type == MN_INTEGER) ? val.u.l == 0 : val.u.d == 0.0;
-}
-
-/* umask command. umask may be specified as octal digits, or in the *
- * symbolic form that chmod(1) uses. Well, a subset of it. Remember *
- * that only the bottom nine bits of umask are used, so there's no *
- * point allowing the set{u,g}id and sticky bits to be specified. */
-
-/**/
-int
-bin_umask(char *nam, char **args, Options ops, UNUSED(int func))
-{
- mode_t um;
- char *s = *args;
-
- /* Get the current umask. */
- um = umask(0);
- umask(um);
- /* No arguments means to display the current setting. */
- if (!s) {
- if (OPT_ISSET(ops,'S')) {
- char *who = "ugo";
-
- while (*who) {
- char *what = "rwx";
- printf("%c=", *who++);
- while (*what) {
- if (!(um & 0400))
- putchar(*what);
- um <<= 1;
- what++;
- }
- putchar(*who ? ',' : '\n');
- }
- } else {
- if (um & 0700)
- putchar('0');
- printf("%03o\n", (unsigned)um);
- }
- return 0;
- }
-
- if (idigit(*s)) {
- /* Simple digital umask. */
- um = zstrtol(s, &s, 8);
- if (*s) {
- zwarnnam(nam, "bad umask");
- return 1;
- }
- } else {
- /* Symbolic notation -- slightly complicated. */
- int whomask, umaskop, mask;
-
- /* More than one symbolic argument may be used at once, each separated
- by commas. */
- for (;;) {
- /* First part of the argument -- who does this apply to?
- u=owner, g=group, o=other. */
- whomask = 0;
- while (*s == 'u' || *s == 'g' || *s == 'o' || *s == 'a')
- if (*s == 'u')
- s++, whomask |= 0700;
- else if (*s == 'g')
- s++, whomask |= 0070;
- else if (*s == 'o')
- s++, whomask |= 0007;
- else if (*s == 'a')
- s++, whomask |= 0777;
- /* Default whomask is everyone. */
- if (!whomask)
- whomask = 0777;
- /* Operation may be +, - or =. */
- umaskop = (int)*s;
- if (!(umaskop == '+' || umaskop == '-' || umaskop == '=')) {
- if (umaskop)
- zwarnnam(nam, "bad symbolic mode operator: %c", umaskop);
- else
- zwarnnam(nam, "bad umask");
- return 1;
- }
- /* Permissions mask -- r=read, w=write, x=execute. */
- mask = 0;
- while (*++s && *s != ',')
- if (*s == 'r')
- mask |= 0444 & whomask;
- else if (*s == 'w')
- mask |= 0222 & whomask;
- else if (*s == 'x')
- mask |= 0111 & whomask;
- else {
- zwarnnam(nam, "bad symbolic mode permission: %c", *s);
- return 1;
- }
- /* Apply parsed argument to um. */
- if (umaskop == '+')
- um &= ~mask;
- else if (umaskop == '-')
- um |= mask;
- else /* umaskop == '=' */
- um = (um | (whomask)) & ~mask;
- if (*s == ',')
- s++;
- else
- break;
- }
- if (*s) {
- zwarnnam(nam, "bad character in symbolic mode: %c", *s);
- return 1;
- }
- }
-
- /* Finally, set the new umask. */
- umask(um);
- return 0;
-}
-
-/* Generic builtin for facilities not available on this OS */
-
-/**/
-mod_export int
-bin_notavail(char *nam, UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func))
-{
- zwarnnam(nam, "not available on this system");
- return 1;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/compat.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/compat.c
deleted file mode 100644
index 7b5c4411..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/compat.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * compat.c - compatibility routines for the deprived
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zsh.mdh"
-#include "compat.pro"
-
-/* Return pointer to first occurence of string t *
- * in string s. Return NULL if not present. */
-
-/**/
-#ifndef HAVE_STRSTR
-
-/**/
-char *
-strstr(const char *s, const char *t)
-{
- const char *p1, *p2;
-
- for (; *s; s++) {
- for (p1 = s, p2 = t; *p2; p1++, p2++)
- if (*p1 != *p2)
- break;
- if (!*p2)
- return (char *)s;
- }
- return NULL;
-}
-
-/**/
-#endif
-
-
-/**/
-#ifndef HAVE_GETHOSTNAME
-
-/**/
-int
-gethostname(char *name, size_t namelen)
-{
- struct utsname uts;
-
- uname(&uts);
- if(strlen(uts.nodename) >= namelen) {
- errno = EINVAL;
- return -1;
- }
- strcpy(name, uts.nodename);
- return 0;
-}
-
-/**/
-#endif
-
-
-/**/
-#ifndef HAVE_GETTIMEOFDAY
-
-/**/
-int
-gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- tv->tv_usec = 0;
- tv->tv_sec = (long)time((time_t) 0);
- return 0;
-}
-
-/**/
-#endif
-
-
-/* Provide clock time with nanoseconds */
-
-/**/
-mod_export int
-zgettime(struct timespec *ts)
-{
- int ret = -1;
-
-#ifdef HAVE_CLOCK_GETTIME
- struct timespec dts;
- if (clock_gettime(CLOCK_REALTIME, &dts) < 0) {
- zwarn("unable to retrieve time: %e", errno);
- ret--;
- } else {
- ret++;
- ts->tv_sec = (time_t) dts.tv_sec;
- ts->tv_nsec = (long) dts.tv_nsec;
- }
-#endif
-
- if (ret) {
- struct timeval dtv;
- struct timezone dtz;
- gettimeofday(&dtv, &dtz);
- ret++;
- ts->tv_sec = (time_t) dtv.tv_sec;
- ts->tv_nsec = (long) dtv.tv_usec * 1000;
- }
-
- return ret;
-}
-
-
-/* compute the difference between two calendar times */
-
-/**/
-#ifndef HAVE_DIFFTIME
-
-/**/
-double
-difftime(time_t t2, time_t t1)
-{
- return ((double)t2 - (double)t1);
-}
-
-/**/
-#endif
-
-
-/**/
-#ifndef HAVE_STRERROR
-extern char *sys_errlist[];
-
-/* Get error message string associated with a particular *
- * error number, and returns a pointer to that string. *
- * This is not a particularly robust version of strerror. */
-
-/**/
-char *
-strerror(int errnum)
-{
- return (sys_errlist[errnum]);
-}
-
-/**/
-#endif
-
-
-#if 0
-/* pathconf(_PC_PATH_MAX) is not currently useful to zsh. The value *
- * returned varies depending on a number of factors, e.g. the amount *
- * of memory available to the operating system at a given time; thus *
- * it can't be used for buffer allocation, or even as an indication *
- * of whether an attempt to use or create a given pathname may fail *
- * at any future time. *
- * *
- * The call is also permitted to fail if the argument path is not an *
- * existing directory, so even to make sense of that one must search *
- * for a valid directory somewhere in the path and adjust. Even if *
- * it succeeds, the return value is relative to the input directory, *
- * and therefore potentially relative to the length of the shortest *
- * path either to that directory or to our working directory. *
- * *
- * Finally, see the note below for glibc; detection of pathconf() is *
- * not by itself an indication that it works reliably. */
-
-/* The documentation for pathconf() says something like: *
- * The limit is returned, if one exists. If the system does *
- * not have a limit for the requested resource, -1 is *
- * returned, and errno is unchanged. If there is an error, *
- * -1 is returned, and errno is set to reflect the nature of *
- * the error. *
- * *
- * System calls are not permitted to set errno to 0; but we must (or *
- * some other flag value) in order to determine that the resource is *
- * unlimited. What use is leaving errno unchanged? Instead, define *
- * a wrapper that resets errno to 0 and returns 0 for "the system *
- * does not have a limit," so that -1 always means a real error. */
-
-/**/
-mod_export long
-zpathmax(char *dir)
-{
-#ifdef HAVE_PATHCONF
- long pathmax;
-
- errno = 0;
- if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
- /* Some versions of glibc pathconf return a hardwired value! */
- return pathmax;
- } else if (errno == EINVAL || errno == ENOENT || errno == ENOTDIR) {
- /* Work backward to find a directory, until we run out of path. */
- char *tail = strrchr(dir, '/');
- while (tail > dir && tail[-1] == '/')
- --tail;
- if (tail > dir) {
- *tail = 0;
- pathmax = zpathmax(dir);
- *tail = '/';
- } else {
- errno = 0;
- if (tail)
- pathmax = pathconf("/", _PC_PATH_MAX);
- else
- pathmax = pathconf(".", _PC_PATH_MAX);
- }
- if (pathmax > 0) {
- long taillen = (tail ? strlen(tail) : (strlen(dir) + 1));
- if (taillen < pathmax)
- return pathmax - taillen;
- else
- errno = ENAMETOOLONG;
- }
- }
- if (errno)
- return -1;
- else
- return 0; /* pathmax should be considered unlimited */
-#else
- long dirlen = strlen(dir);
-
- /* The following is wrong if dir is not an absolute path. */
- return ((long) ((dirlen >= PATH_MAX) ?
- ((errno = ENAMETOOLONG), -1) :
- ((errno = 0), PATH_MAX - dirlen)));
-#endif
-}
-#endif /* 0 */
-
-/**/
-#ifdef HAVE_SYSCONF
-/*
- * This is replaced by a macro from system.h if not HAVE_SYSCONF.
- * 0 is returned by sysconf if _SC_OPEN_MAX is unavailable;
- * -1 is returned on error
- *
- * Neither of these should happen, but resort to OPEN_MAX rather
- * than return 0 or -1 just in case.
- *
- * We'll limit the open maximum to ZSH_INITIAL_OPEN_MAX to
- * avoid probing ridiculous numbers of file descriptors.
- */
-
-/**/
-mod_export long
-zopenmax(void)
-{
- long openmax;
-
- if ((openmax = sysconf(_SC_OPEN_MAX)) < 1) {
- openmax = OPEN_MAX;
- } else if (openmax > OPEN_MAX) {
- /* On some systems, "limit descriptors unlimited" or the *
- * equivalent will set openmax to a huge number. Unless *
- * there actually is a file descriptor > OPEN_MAX already *
- * open, nothing in zsh requires the true maximum, and in *
- * fact it causes inefficiency elsewhere if we report it. *
- * So, report the maximum of OPEN_MAX or the largest open *
- * descriptor (is there a better way to find that?). */
- long i, j = OPEN_MAX;
- if (openmax > ZSH_INITIAL_OPEN_MAX)
- openmax = ZSH_INITIAL_OPEN_MAX;
- for (i = j; i < openmax; i += (errno != EINTR)) {
- errno = 0;
- if (fcntl(i, F_GETFL, 0) < 0 &&
- (errno == EBADF || errno == EINTR))
- continue;
- j = i;
- }
- openmax = j;
- }
-
- return (max_zsh_fd > openmax) ? max_zsh_fd : openmax;
-}
-
-/**/
-#endif
-
-/*
- * Rationalise the current directory, returning the string.
- *
- * If "d" is not NULL, it is used to store information about the
- * directory. The returned name is also present in d->dirname and is in
- * permanently allocated memory. The handling of this case depends on
- * whether the fchdir() system call is available; if it is, it is assumed
- * the caller is able to restore the current directory. On successfully
- * identifying the directory the function returns immediately rather
- * than ascending the hierarchy.
- *
- * If "d" is NULL, no assumption about the caller's behaviour is
- * made. The returned string is in heap memory. This case is
- * always handled by changing directory up the hierarchy.
- *
- * On Cygwin or other systems where USE_GETCWD is defined (at the
- * time of writing only QNX), we skip all the above and use the
- * getcwd() system call.
- */
-
-/**/
-mod_export char *
-zgetdir(struct dirsav *d)
-{
- char nbuf[PATH_MAX+3];
- char *buf;
- int bufsiz, pos;
- struct stat sbuf;
- ino_t pino;
- dev_t pdev;
-#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
- struct dirent *de;
- DIR *dir;
- dev_t dev;
- ino_t ino;
- int len;
-#endif
-
- buf = zhalloc(bufsiz = PATH_MAX+1);
- pos = bufsiz - 1;
- buf[pos] = '\0';
- strcpy(nbuf, "../");
- if (stat(".", &sbuf) < 0) {
- return NULL;
- }
-
- /* Record the initial inode and device */
- pino = sbuf.st_ino;
- pdev = sbuf.st_dev;
- if (d)
- d->ino = pino, d->dev = pdev;
-#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
-#ifdef HAVE_FCHDIR
- else
-#endif
- holdintr();
-
- for (;;) {
- /* Examine the parent of the current directory. */
- if (stat("..", &sbuf) < 0)
- break;
-
- /* Inode and device of curtent directory */
- ino = pino;
- dev = pdev;
- /* Inode and device of current directory's parent */
- pino = sbuf.st_ino;
- pdev = sbuf.st_dev;
-
- /* If they're the same, we've reached the root directory. */
- if (ino == pino && dev == pdev) {
- if (!buf[pos])
- buf[--pos] = '/';
- if (d) {
-#ifndef HAVE_FCHDIR
- zchdir(buf + pos);
- noholdintr();
-#endif
- return d->dirname = ztrdup(buf + pos);
- }
- zchdir(buf + pos);
- noholdintr();
- return buf + pos;
- }
-
- /* Search the parent for the current directory. */
- if (!(dir = opendir("..")))
- break;
-
- while ((de = readdir(dir))) {
- char *fn = de->d_name;
- /* Ignore `.' and `..'. */
- if (fn[0] == '.' &&
- (fn[1] == '\0' ||
- (fn[1] == '.' && fn[2] == '\0')))
- continue;
-#ifdef HAVE_STRUCT_DIRENT_D_STAT
- if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
- /* Found the directory we're currently in */
- strncpy(nbuf + 3, fn, PATH_MAX);
- break;
- }
-#else /* !HAVE_STRUCT_DIRENT_D_STAT */
-# ifdef HAVE_STRUCT_DIRENT_D_INO
- if (dev != pdev || (ino_t) de->d_ino == ino)
-# endif /* HAVE_STRUCT_DIRENT_D_INO */
- {
- /* Maybe found directory, need to check device & inode */
- strncpy(nbuf + 3, fn, PATH_MAX);
- lstat(nbuf, &sbuf);
- if (sbuf.st_dev == dev && sbuf.st_ino == ino)
- break;
- }
-#endif /* !HAVE_STRUCT_DIRENT_D_STAT */
- }
- closedir(dir);
- if (!de)
- break; /* Not found */
- /*
- * We get the "/" free just by copying from nbuf+2 instead
- * of nbuf+3, which is where we copied the path component.
- * This means buf[pos] is always a "/".
- */
- len = strlen(nbuf + 2);
- pos -= len;
- while (pos <= 1) {
- char *newbuf = zhalloc(2*bufsiz);
- memcpy(newbuf + bufsiz, buf, bufsiz);
- buf = newbuf;
- pos += bufsiz;
- bufsiz *= 2;
- }
- memcpy(buf + pos, nbuf + 2, len);
-#ifdef HAVE_FCHDIR
- if (d)
- return d->dirname = ztrdup(buf + pos + 1);
-#endif
- if (chdir(".."))
- break;
- }
-
- /*
- * Fix up the directory, if necessary.
- * We're changing back down the hierarchy, ignore the
- * "/" at buf[pos].
- */
- if (d) {
-#ifndef HAVE_FCHDIR
- if (buf[pos])
- zchdir(buf + pos + 1);
- noholdintr();
-#endif
- return NULL;
- }
-
- if (buf[pos])
- zchdir(buf + pos + 1);
- noholdintr();
-
-#else /* __CYGWIN__, USE_GETCWD cases */
-
- if (!getcwd(buf, bufsiz)) {
- if (d) {
- return NULL;
- }
- } else {
- if (d) {
- return d->dirname = ztrdup(buf);
- }
- return buf;
- }
-#endif
-
- /*
- * Something bad happened.
- * This has been seen when inside a special directory,
- * such as the Netapp .snapshot directory, that doesn't
- * appear as a directory entry in the parent directory.
- * We'll just need our best guess.
- *
- * We only get here from zgetcwd(); let that fall back to pwd.
- */
-
- return NULL;
-}
-
-/*
- * Try to find the current directory.
- * If we couldn't work it out internally, fall back to getcwd().
- * If it fails, fall back to pwd; if zgetcwd() is being used
- * to set pwd, pwd should be NULL and we just return ".".
- */
-
-/**/
-char *
-zgetcwd(void)
-{
- char *ret = zgetdir(NULL);
-#ifdef HAVE_GETCWD
- if (!ret) {
-#ifdef GETCWD_CALLS_MALLOC
- char *cwd = getcwd(NULL, 0);
- if (cwd) {
- ret = dupstring(cwd);
- free(cwd);
- }
-#else
- char *cwdbuf = zalloc(PATH_MAX+1);
- ret = getcwd(cwdbuf, PATH_MAX);
- if (ret)
- ret = dupstring(ret);
- zfree(cwdbuf, PATH_MAX+1);
-#endif /* GETCWD_CALLS_MALLOC */
- }
-#endif /* HAVE_GETCWD */
- if (!ret)
- ret = unmeta(pwd);
- if (!ret)
- ret = dupstring(".");
- return ret;
-}
-
-/*
- * chdir with arbitrary long pathname. Returns 0 on success, -1 on normal *
- * failure and -2 when chdir failed and the current directory is lost.
- *
- * This is to be treated as if at system level, so dir is unmetafied but
- * terminated by a NULL.
- */
-
-/**/
-mod_export int
-zchdir(char *dir)
-{
- char *s;
- int currdir = -2;
-
- for (;;) {
- if (!*dir || chdir(dir) == 0) {
-#ifdef HAVE_FCHDIR
- if (currdir >= 0)
- close(currdir);
-#endif
- return 0;
- }
- if ((errno != ENAMETOOLONG && errno != ENOMEM) ||
- strlen(dir) < PATH_MAX)
- break;
- for (s = dir + PATH_MAX - 1; s > dir && *s != '/'; s--)
- ;
- if (s == dir)
- break;
-#ifdef HAVE_FCHDIR
- if (currdir == -2)
- currdir = open(".", O_RDONLY|O_NOCTTY);
-#endif
- *s = '\0';
- if (chdir(dir) < 0) {
- *s = '/';
- break;
- }
-#ifndef HAVE_FCHDIR
- currdir = -1;
-#endif
- *s = '/';
- while (*++s == '/')
- ;
- dir = s;
- }
-#ifdef HAVE_FCHDIR
- if (currdir >= 0) {
- if (fchdir(currdir) < 0) {
- close(currdir);
- return -2;
- }
- close(currdir);
- return -1;
- }
-#endif
- return currdir == -2 ? -1 : -2;
-}
-
-/*
- * How to print out a 64 bit integer. This isn't needed (1) if longs
- * are 64 bit, since ordinary %ld will work (2) if we couldn't find a
- * 64 bit type anyway.
- */
-/**/
-#ifdef ZSH_64_BIT_TYPE
-/**/
-mod_export char *
-output64(zlong val)
-{
- static char llbuf[DIGBUFSIZE];
- convbase(llbuf, val, 0);
- return llbuf;
-}
-/**/
-#endif /* ZSH_64_BIT_TYPE */
-
-/**/
-#ifndef HAVE_STRTOUL
-
-/*
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Convert a string to an unsigned long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-
-/**/
-unsigned long
-strtoul(nptr, endptr, base)
- const char *nptr;
- char **endptr;
- int base;
-{
- const char *s;
- unsigned long acc, cutoff;
- int c;
- int neg, any, cutlim;
-
- /* endptr may be NULL */
-
- s = nptr;
- do {
- c = (unsigned char) *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
-
- cutoff = ULONG_MAX / (unsigned long)base;
- cutlim = (int)(ULONG_MAX % (unsigned long)base);
- for (acc = 0, any = 0;; c = (unsigned char) *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c)) {
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- } else
- break;
- if (c >= base)
- break;
- if (any < 0)
- continue;
- if (acc > cutoff || (acc == cutoff && c > cutlim)) {
- any = -1;
- acc = ULONG_MAX;
- errno = ERANGE;
- } else {
- any = 1;
- acc *= (unsigned long)base;
- acc += c;
- }
- }
- if (neg && any > 0)
- acc = -acc;
- if (endptr != NULL)
- *endptr = any ? s - 1 : nptr;
- return (acc);
-}
-
-/**/
-#endif /* HAVE_STRTOUL */
-
-/**/
-#ifdef ENABLE_UNICODE9
-#include "./wcwidth9.h"
-
-/**/
-int
-u9_wcwidth(wchar_t ucs)
-{
- int w = wcwidth9(ucs);
- if (w < -1)
- return 1;
- return w;
-}
-
-/**/
-int
-u9_iswprint(wint_t ucs)
-{
- if (ucs == 0)
- return 0;
- return wcwidth9(ucs) != -1;
-}
-
-/**/
-#endif /* ENABLE_UNICODE9 */
-
-/**/
-#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
-
-/**/
-int
-isprint_ascii(int c)
-{
- if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
- return (c >= 0x20 && c <= 0x7e);
- else
- return isprint(c);
-}
-
-/**/
-#endif /* __APPLE__ && BROKEN_ISPRINT */
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/exec.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/exec.c
deleted file mode 100644
index 615a5086..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/exec.c
+++ /dev/null
@@ -1,6250 +0,0 @@
-/*
- * exec.c - command 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 "exec.pro"
-
-/* Flags for last argument of addvars */
-
-enum {
- /* Export the variable for "VAR=val cmd ..." */
- ADDVAR_EXPORT = 1 << 0,
- /* Apply restrictions for variable */
- ADDVAR_RESTRICT = 1 << 1,
- /* Variable list is being restored later */
- ADDVAR_RESTORE = 1 << 2
-};
-
-/* Structure in which to save values around shell function call */
-
-struct funcsave {
- char opts[OPT_SIZE];
- char *argv0;
- int zoptind, lastval, optcind, numpipestats;
- int *pipestats;
- char *scriptname;
- int breaks, contflag, loops, emulation, noerrexit, oflags, restore_sticky;
- Emulation_options sticky;
- struct funcstack fstack;
-};
-typedef struct funcsave *Funcsave;
-
-/*
- * used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT.
- * Bits from noerrexit_bits.
- */
-
-/**/
-int noerrexit;
-
-/* used to suppress ERREXIT or ERRRETURN for one occurrence: 0 or 1 */
-
-/**/
-int this_noerrexit;
-
-/*
- * noerrs = 1: suppress error messages
- * noerrs = 2: don't set errflag on parse error, either
- */
-
-/**/
-mod_export int noerrs;
-
-/* do not save history on exec and exit */
-
-/**/
-int nohistsave;
-
-/* error flag: bits from enum errflag_bits */
-
-/**/
-mod_export int errflag;
-
-/*
- * State of trap return value. Value is from enum trap_state.
- */
-
-/**/
-int trap_state;
-
-/*
- * Value associated with return from a trap.
- * This is only active if we are inside a trap, else its value
- * is irrelevant. It is initialised to -1 for a function trap and
- * -2 for a non-function trap and if negative is decremented as
- * we go deeper into functions and incremented as we come back up.
- * The value is used to decide if an explicit "return" should cause
- * a return from the caller of the trap; it does this by setting
- * trap_return to a status (i.e. a non-negative value).
- *
- * In summary, trap_return is
- * - zero unless we are in a trap
- * - negative in a trap unless it has triggered. Code uses this
- * to detect an active trap.
- * - non-negative in a trap once it was triggered. It should remain
- * non-negative until restored after execution of the trap.
- */
-
-/**/
-int trap_return;
-
-/* != 0 if this is a subshell */
-
-/**/
-int subsh;
-
-/* != 0 if we have a return pending */
-
-/**/
-mod_export int retflag;
-
-/**/
-long lastval2;
-
-/* The table of file descriptors. A table element is zero if the *
- * corresponding fd is not used by the shell. It is greater than *
- * 1 if the fd is used by a <(...) or >(...) substitution and 1 if *
- * it is an internal file descriptor which must be closed before *
- * executing an external command. The first ten elements of the *
- * table is not used. A table element is set by movefd and cleard *
- * by zclose. */
-
-/**/
-mod_export unsigned char *fdtable;
-
-/* The allocated size of fdtable */
-
-/**/
-int fdtable_size;
-
-/* The highest fd that marked with nonzero in fdtable */
-
-/**/
-mod_export int max_zsh_fd;
-
-/* input fd from the coprocess */
-
-/**/
-mod_export int coprocin;
-
-/* output fd from the coprocess */
-
-/**/
-mod_export int coprocout;
-
-/* count of file locks recorded in fdtable */
-
-/**/
-int fdtable_flocks;
-
-
-/* != 0 if the line editor is active */
-
-/**/
-mod_export int zleactive;
-
-/* pid of process undergoing 'process substitution' */
-
-/**/
-pid_t cmdoutpid;
-
-/* pid of last process started by <(...), >(...) */
-
-/**/
-mod_export pid_t procsubstpid;
-
-/* exit status of process undergoing 'process substitution' */
-
-/**/
-int cmdoutval;
-
-/*
- * This is set by an exiting $(...) substitution to indicate we need
- * to retain the status. We initialize it to zero if we think we need
- * to reset the status for a command.
- */
-
-/**/
-int use_cmdoutval;
-
-/* The context in which a shell function is called, see SFC_* in zsh.h. */
-
-/**/
-mod_export int sfcontext;
-
-/* Stack to save some variables before executing a signal handler function */
-
-/**/
-struct execstack *exstack;
-
-/* Stack with names of function calls, 'source' calls, and 'eval' calls
- * currently active. */
-
-/**/
-mod_export Funcstack funcstack;
-
-#define execerr() \
- do { \
- if (!forked) { \
- redir_err = lastval = 1; \
- goto done; \
- } else { \
- _exit(1); \
- } \
- } while (0)
-
-static int doneps4;
-static char *STTYval;
-static char *blank_env[] = { NULL };
-
-/* Execution functions. */
-
-static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = {
- execcursh, exectime, NULL /* execfuncdef handled specially */,
- execfor, execselect,
- execwhile, execrepeat, execcase, execif, execcond,
- execarith, execautofn, exectry
-};
-
-/* structure for command builtin for when it is used with -v or -V */
-static struct builtin commandbn =
- BUILTIN("command", 0, bin_whence, 0, -1, BIN_COMMAND, "pvV", NULL);
-
-/* parse string into a list */
-
-/**/
-mod_export Eprog
-parse_string(char *s, int reset_lineno)
-{
- Eprog p;
- zlong oldlineno;
-
- zcontext_save();
- inpush(s, INP_LINENO, NULL);
- strinbeg(0);
- oldlineno = lineno;
- if (reset_lineno)
- lineno = 1;
- p = parse_list();
- lineno = oldlineno;
- if (tok == LEXERR && !lastval)
- lastval = 1;
- strinend();
- inpop();
- zcontext_restore();
- return p;
-}
-
-/**/
-#ifdef HAVE_GETRLIMIT
-
-/* the resource limits for the shell and its children */
-
-/**/
-mod_export struct rlimit current_limits[RLIM_NLIMITS], limits[RLIM_NLIMITS];
-
-/**/
-mod_export int
-zsetlimit(int limnum, char *nam)
-{
- if (limits[limnum].rlim_max != current_limits[limnum].rlim_max ||
- limits[limnum].rlim_cur != current_limits[limnum].rlim_cur) {
- if (setrlimit(limnum, limits + limnum)) {
- if (nam)
- zwarnnam(nam, "setrlimit failed: %e", errno);
- limits[limnum] = current_limits[limnum];
- return -1;
- }
- current_limits[limnum] = limits[limnum];
- }
- return 0;
-}
-
-/**/
-mod_export int
-setlimits(char *nam)
-{
- int limnum;
- int ret = 0;
-
- for (limnum = 0; limnum < RLIM_NLIMITS; limnum++)
- if (zsetlimit(limnum, nam))
- ret++;
- return ret;
-}
-
-/**/
-#endif /* HAVE_GETRLIMIT */
-
-/* fork and set limits */
-
-/**/
-static pid_t
-zfork(struct timeval *tv)
-{
- pid_t pid;
- struct timezone dummy_tz;
-
- /*
- * Is anybody willing to explain this test?
- */
- if (thisjob != -1 && thisjob >= jobtabsize - 1 && !expandjobtab()) {
- zerr("job table full");
- return -1;
- }
- if (tv)
- gettimeofday(tv, &dummy_tz);
- /*
- * Queueing signals is necessary on Linux because fork()
- * manipulates mutexes, leading to deadlock in memory
- * allocation. We don't expect fork() to be particularly
- * zippy anyway.
- */
- queue_signals();
- pid = fork();
- unqueue_signals();
- if (pid == -1) {
- zerr("fork failed: %e", errno);
- return -1;
- }
-#ifdef HAVE_GETRLIMIT
- if (!pid)
- /* set resource limits for the child process */
- setlimits(NULL);
-#endif
- return pid;
-}
-
-/*
- * Allen Edeln gebiet ich Andacht,
- * Hohen und Niedern von Heimdalls Geschlecht;
- * Ich will list_pipe's Wirken kuenden
- * Die aeltesten Sagen, der ich mich entsinne...
- *
- * In most shells, if you do something like:
- *
- * cat foo | while read a; do grep $a bar; done
- *
- * the shell forks and executes the loop in the sub-shell thus created.
- * In zsh this traditionally executes the loop in the current shell, which
- * is nice to have if the loop does something to change the shell, like
- * setting parameters or calling builtins.
- * Putting the loop in a sub-shell makes life easy, because the shell only
- * has to put it into the job-structure and then treats it as a normal
- * process. Suspending and interrupting is no problem then.
- * Some years ago, zsh either couldn't suspend such things at all, or
- * it got really messed up when users tried to do it. As a solution, we
- * implemented the list_pipe-stuff, which has since then become a reason
- * for many nightmares.
- * Pipelines like the one above are executed by the functions in this file
- * which call each other (and sometimes recursively). The one above, for
- * example would lead to a function call stack roughly like:
- *
- * execlist->execpline->execcmd->execwhile->execlist->execpline
- *
- * (when waiting for the grep, ignoring execpline2 for now). At this time,
- * zsh has built two job-table entries for it: one for the cat and one for
- * the grep. If the user hits ^Z at this point (and jobbing is used), the
- * shell is notified that the grep was suspended. The list_pipe flag is
- * used to tell the execpline where it was waiting that it was in a pipeline
- * with a shell construct at the end (which may also be a shell function or
- * several other things). When zsh sees the suspended grep, it forks to let
- * the sub-shell execute the rest of the while loop. The parent shell walks
- * up in the function call stack to the first execpline. There it has to find
- * out that it has just forked and then has to add information about the sub-
- * shell (its pid and the text for it) in the job entry of the cat. The pid
- * is passed down in the list_pipe_pid variable.
- * But there is a problem: the suspended grep is a child of the parent shell
- * and can't be adopted by the sub-shell. So the parent shell also has to
- * keep the information about this process (more precisely: this pipeline)
- * by keeping the job table entry it created for it. The fact that there
- * are two jobs which have to be treated together is remembered by setting
- * the STAT_SUPERJOB flag in the entry for the cat-job (which now also
- * contains a process-entry for the whole loop -- the sub-shell) and by
- * setting STAT_SUBJOB in the job of the grep-job. With that we can keep
- * sub-jobs from being displayed and we can handle an fg/bg on the super-
- * job correctly. When the super-job is continued, the shell also wakes up
- * the sub-job. But then, the grep will exit sometime. Now the parent shell
- * has to remember not to try to wake it up again (in case of another ^Z).
- * It also has to wake up the sub-shell (which suspended itself immediately
- * after creation), so that the rest of the loop is executed by it.
- * But there is more: when the sub-shell is created, the cat may already
- * have exited, so we can't put the sub-shell in the process group of it.
- * In this case, we put the sub-shell in the process group of the parent
- * shell and in any case, the sub-shell has to put all commands executed
- * by it into its own process group, because only this way the parent
- * shell can control them since it only knows the process group of the sub-
- * shell. Of course, this information is also important when putting a job
- * in the foreground, where we have to attach its process group to the
- * controlling tty.
- * All this is made more difficult because we have to handle return values
- * correctly. If the grep is signaled, its exit status has to be propagated
- * back to the parent shell which needs it to set the exit status of the
- * super-job. And of course, when the grep is signaled (including ^C), the
- * loop has to be stopped, etc.
- * The code for all this is distributed over three files (exec.c, jobs.c,
- * and signals.c) and none of them is a simple one. So, all in all, there
- * may still be bugs, but considering the complexity (with race conditions,
- * signal handling, and all that), this should probably be expected.
- */
-
-/**/
-int list_pipe = 0, simple_pline = 0;
-
-static pid_t list_pipe_pid;
-static struct timeval list_pipe_start;
-static int nowait, pline_level = 0;
-static int list_pipe_child = 0, list_pipe_job;
-static char list_pipe_text[JOBTEXTSIZE];
-
-/* execute a current shell command */
-
-/**/
-static int
-execcursh(Estate state, int do_exec)
-{
- Wordcode end = state->pc + WC_CURSH_SKIP(state->pc[-1]);
-
- /* Skip word only used for try/always */
- state->pc++;
-
- /*
- * The test thisjob != -1 was added because sometimes thisjob
- * can be invalid at this point. The case in question was
- * in a precmd function after operations involving background
- * jobs.
- *
- * This is because sometimes we bypass job control to execute
- * very simple functions via execssimple().
- */
- if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
- !hasprocs(thisjob))
- deletejob(jobtab + thisjob, 0);
- cmdpush(CS_CURSH);
- execlist(state, 1, do_exec);
- cmdpop();
-
- state->pc = end;
- this_noerrexit = 1;
-
- return lastval;
-}
-
-/* execve after handling $_ and #! */
-
-#define POUNDBANGLIMIT 64
-
-/**/
-static int
-zexecve(char *pth, char **argv, char **newenvp)
-{
- int eno;
- static char buf[PATH_MAX * 2+1];
- char **eep;
-
- unmetafy(pth, NULL);
- for (eep = argv; *eep; eep++)
- if (*eep != pth)
- unmetafy(*eep, NULL);
- buf[0] = '_';
- buf[1] = '=';
- if (*pth == '/')
- strcpy(buf + 2, pth);
- else
- sprintf(buf + 2, "%s/%s", pwd, pth);
- zputenv(buf);
-#ifndef FD_CLOEXEC
- closedumps();
-#endif
-
- if (newenvp == NULL)
- newenvp = environ;
- winch_unblock();
- execve(pth, argv, newenvp);
-
- /* If the execve returns (which in general shouldn't happen), *
- * then check for an errno equal to ENOEXEC. This errno is set *
- * if the process file has the appropriate access permission, *
- * but has an invalid magic number in its header. */
- if ((eno = errno) == ENOEXEC || eno == ENOENT) {
- char execvebuf[POUNDBANGLIMIT + 1], *ptr, *ptr2, *argv0;
- int fd, ct, t0;
-
- if ((fd = open(pth, O_RDONLY|O_NOCTTY)) >= 0) {
- argv0 = *argv;
- *argv = pth;
- execvebuf[0] = '\0';
- ct = read(fd, execvebuf, POUNDBANGLIMIT);
- close(fd);
- if (ct >= 0) {
- if (execvebuf[0] == '#') {
- if (execvebuf[1] == '!') {
- for (t0 = 0; t0 != ct; t0++)
- if (execvebuf[t0] == '\n')
- break;
- while (inblank(execvebuf[t0]))
- execvebuf[t0--] = '\0';
- execvebuf[POUNDBANGLIMIT] = '\0';
- for (ptr = execvebuf + 2; *ptr && *ptr == ' '; ptr++);
- for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++);
- if (eno == ENOENT) {
- char *pprog;
- if (*ptr)
- *ptr = '\0';
- if (*ptr2 != '/' &&
- (pprog = pathprog(ptr2, NULL))) {
- argv[-2] = ptr2;
- argv[-1] = ptr + 1;
- winch_unblock();
- execve(pprog, argv - 2, newenvp);
- }
- zerr("%s: bad interpreter: %s: %e", pth, ptr2,
- eno);
- } else if (*ptr) {
- *ptr = '\0';
- argv[-2] = ptr2;
- argv[-1] = ptr + 1;
- winch_unblock();
- execve(ptr2, argv - 2, newenvp);
- } else {
- argv[-1] = ptr2;
- winch_unblock();
- execve(ptr2, argv - 1, newenvp);
- }
- } else if (eno == ENOEXEC) {
- argv[-1] = "sh";
- winch_unblock();
- execve("/bin/sh", argv - 1, newenvp);
- }
- } else if (eno == ENOEXEC) {
- for (t0 = 0; t0 != ct; t0++)
- if (!execvebuf[t0])
- break;
- if (t0 == ct) {
- argv[-1] = "sh";
- winch_unblock();
- execve("/bin/sh", argv - 1, newenvp);
- }
- }
- } else
- eno = errno;
- *argv = argv0;
- } else
- eno = errno;
- }
- /* restore the original arguments and path but do not bother with *
- * null characters as these cannot be passed to external commands *
- * anyway. So the result is truncated at the first null char. */
- pth = metafy(pth, -1, META_NOALLOC);
- for (eep = argv; *eep; eep++)
- if (*eep != pth)
- (void) metafy(*eep, -1, META_NOALLOC);
- return eno;
-}
-
-#define MAXCMDLEN (PATH_MAX*4)
-
-/* test whether we really want to believe the error number */
-
-/**/
-static int
-isgooderr(int e, char *dir)
-{
- /*
- * Maybe the directory was unreadable, or maybe it wasn't
- * even a directory.
- */
- return ((e != EACCES || !access(dir, X_OK)) &&
- e != ENOENT && e != ENOTDIR);
-}
-
-/*
- * Attempt to handle command not found.
- * Return 0 if the condition was handled, non-zero otherwise.
- */
-
-/**/
-static int
-commandnotfound(char *arg0, LinkList args)
-{
- Shfunc shf = (Shfunc)
- shfunctab->getnode(shfunctab, "command_not_found_handler");
-
- if (!shf) {
- lastval = 127;
- return 1;
- }
-
- pushnode(args, arg0);
- lastval = doshfunc(shf, args, 1);
- return 0;
-}
-
-/*
- * Search the default path for cmd.
- * pbuf of length plen is the buffer to use.
- * Return NULL if not found.
- */
-
-static char *
-search_defpath(char *cmd, char *pbuf, int plen)
-{
- char *ps = DEFAULT_PATH, *pe = NULL, *s;
-
- for (ps = DEFAULT_PATH; ps; ps = pe ? pe+1 : NULL) {
- pe = strchr(ps, ':');
- if (*ps == '/') {
- s = pbuf;
- if (pe) {
- if (pe - ps >= plen)
- continue;
- struncpy(&s, ps, pe-ps);
- } else {
- if (strlen(ps) >= plen)
- continue;
- strucpy(&s, ps);
- }
- *s++ = '/';
- if ((s - pbuf) + strlen(cmd) >= plen)
- continue;
- strucpy(&s, cmd);
- if (iscom(pbuf))
- return pbuf;
- }
- }
- return NULL;
-}
-
-/* execute an external command */
-
-/**/
-static void
-execute(LinkList args, int flags, int defpath)
-{
- Cmdnam cn;
- char buf[MAXCMDLEN+1], buf2[MAXCMDLEN+1];
- char *s, *z, *arg0;
- char **argv, **pp, **newenvp = NULL;
- int eno = 0, ee;
-
- arg0 = (char *) peekfirst(args);
- if (isset(RESTRICTED) && (strchr(arg0, '/') || defpath)) {
- zerr("%s: restricted", arg0);
- _exit(1);
- }
-
- /* If the parameter STTY is set in the command's environment, *
- * we first run the stty command with the value of this *
- * parameter as it arguments. */
- if ((s = STTYval) && isatty(0) && (GETPGRP() == getpid())) {
- char *t = tricat("stty", " ", s);
-
- STTYval = 0; /* this prevents infinite recursion */
- zsfree(s);
- execstring(t, 1, 0, "stty");
- zsfree(t);
- } else if (s) {
- STTYval = 0;
- zsfree(s);
- }
-
- /* If ARGV0 is in the commands environment, we use *
- * that as argv[0] for this external command */
- if (unset(RESTRICTED) && (z = zgetenv("ARGV0"))) {
- setdata(firstnode(args), (void *) ztrdup(z));
- /*
- * Note we don't do anything with the parameter structure
- * for ARGV0: that's OK since we're about to exec or exit
- * on failure.
- */
-#ifdef USE_SET_UNSET_ENV
- unsetenv("ARGV0");
-#else
- delenvvalue(z - 6);
-#endif
- } else if (flags & BINF_DASH) {
- /* Else if the pre-command `-' was given, we add `-' *
- * to the front of argv[0] for this command. */
- sprintf(buf2, "-%s", arg0);
- setdata(firstnode(args), (void *) ztrdup(buf2));
- }
-
- argv = makecline(args);
- if (flags & BINF_CLEARENV)
- newenvp = blank_env;
-
- /*
- * Note that we don't close fd's attached to process substitution
- * here, which should be visible to external processes.
- */
- closem(FDT_XTRACE, 0);
-#ifndef FD_CLOEXEC
- if (SHTTY != -1) {
- close(SHTTY);
- SHTTY = -1;
- }
-#endif
- child_unblock();
- if ((int) strlen(arg0) >= PATH_MAX) {
- zerr("command too long: %s", arg0);
- _exit(1);
- }
- for (s = arg0; *s; s++)
- if (*s == '/') {
- int lerrno = zexecve(arg0, argv, newenvp);
- if (arg0 == s || unset(PATHDIRS) ||
- (arg0[0] == '.' && (arg0 + 1 == s ||
- (arg0[1] == '.' && arg0 + 2 == s)))) {
- zerr("%e: %s", lerrno, arg0);
- _exit((lerrno == EACCES || lerrno == ENOEXEC) ? 126 : 127);
- }
- break;
- }
-
- /* for command -p, search the default path */
- if (defpath) {
- char pbuf[PATH_MAX+1];
- char *dptr;
-
- if (!search_defpath(arg0, pbuf, PATH_MAX)) {
- if (commandnotfound(arg0, args) == 0)
- _exit(lastval);
- zerr("command not found: %s", arg0);
- _exit(127);
- }
-
- ee = zexecve(pbuf, argv, newenvp);
-
- if ((dptr = strrchr(pbuf, '/')))
- *dptr = '\0';
- if (isgooderr(ee, *pbuf ? pbuf : "/"))
- eno = ee;
-
- } else {
-
- if ((cn = (Cmdnam) cmdnamtab->getnode(cmdnamtab, arg0))) {
- char nn[PATH_MAX+1], *dptr;
-
- if (cn->node.flags & HASHED)
- strcpy(nn, cn->u.cmd);
- else {
- for (pp = path; pp < cn->u.name; pp++)
- if (!**pp || (**pp == '.' && (*pp)[1] == '\0')) {
- ee = zexecve(arg0, argv, newenvp);
- if (isgooderr(ee, *pp))
- eno = ee;
- } else if (**pp != '/') {
- z = buf;
- strucpy(&z, *pp);
- *z++ = '/';
- strcpy(z, arg0);
- ee = zexecve(buf, argv, newenvp);
- if (isgooderr(ee, *pp))
- eno = ee;
- }
- strcpy(nn, cn->u.name ? *(cn->u.name) : "");
- strcat(nn, "/");
- strcat(nn, cn->node.nam);
- }
- ee = zexecve(nn, argv, newenvp);
-
- if ((dptr = strrchr(nn, '/')))
- *dptr = '\0';
- if (isgooderr(ee, *nn ? nn : "/"))
- eno = ee;
- }
- for (pp = path; *pp; pp++)
- if (!(*pp)[0] || ((*pp)[0] == '.' && !(*pp)[1])) {
- ee = zexecve(arg0, argv, newenvp);
- if (isgooderr(ee, *pp))
- eno = ee;
- } else {
- z = buf;
- strucpy(&z, *pp);
- *z++ = '/';
- strcpy(z, arg0);
- ee = zexecve(buf, argv, newenvp);
- if (isgooderr(ee, *pp))
- eno = ee;
- }
- }
-
- if (eno)
- zerr("%e: %s", eno, arg0);
- else if (commandnotfound(arg0, args) == 0)
- _exit(lastval);
- else
- zerr("command not found: %s", arg0);
- _exit((eno == EACCES || eno == ENOEXEC) ? 126 : 127);
-}
-
-#define RET_IF_COM(X) { if (iscom(X)) return docopy ? dupstring(X) : arg0; }
-
-/*
- * Get the full pathname of an external command.
- * If the second argument is zero, return the first argument if found;
- * if non-zero, return the path using heap memory. (RET_IF_COM(X),
- * above).
- * If the third argument is non-zero, use the system default path
- * instead of the current path.
- */
-
-/**/
-mod_export char *
-findcmd(char *arg0, int docopy, int default_path)
-{
- char **pp;
- char *z, *s, buf[MAXCMDLEN];
- Cmdnam cn;
-
- if (default_path)
- {
- if (search_defpath(arg0, buf, MAXCMDLEN))
- return docopy ? dupstring(buf) : arg0;
- return NULL;
- }
- cn = (Cmdnam) cmdnamtab->getnode(cmdnamtab, arg0);
- if (!cn && isset(HASHCMDS) && !isrelative(arg0))
- cn = hashcmd(arg0, path);
- if ((int) strlen(arg0) > PATH_MAX)
- return NULL;
- if ((s = strchr(arg0, '/'))) {
- RET_IF_COM(arg0);
- if (arg0 == s || unset(PATHDIRS) || !strncmp(arg0, "./", 2) ||
- !strncmp(arg0, "../", 3)) {
- return NULL;
- }
- }
- if (cn) {
- char nn[PATH_MAX+1];
-
- if (cn->node.flags & HASHED)
- strcpy(nn, cn->u.cmd);
- else {
- for (pp = path; pp < cn->u.name; pp++)
- if (**pp != '/') {
- z = buf;
- if (**pp) {
- strucpy(&z, *pp);
- *z++ = '/';
- }
- strcpy(z, arg0);
- RET_IF_COM(buf);
- }
- strcpy(nn, cn->u.name ? *(cn->u.name) : "");
- strcat(nn, "/");
- strcat(nn, cn->node.nam);
- }
- RET_IF_COM(nn);
- }
- for (pp = path; *pp; pp++) {
- z = buf;
- if (**pp) {
- strucpy(&z, *pp);
- *z++ = '/';
- }
- strcpy(z, arg0);
- RET_IF_COM(buf);
- }
- return NULL;
-}
-
-/*
- * Return TRUE if the given path denotes an executable regular file, or a
- * symlink to one.
- */
-
-/**/
-int
-iscom(char *s)
-{
- struct stat statbuf;
- char *us = unmeta(s);
-
- return (access(us, X_OK) == 0 && stat(us, &statbuf) >= 0 &&
- S_ISREG(statbuf.st_mode));
-}
-
-/**/
-int
-isreallycom(Cmdnam cn)
-{
- char fullnam[MAXCMDLEN];
-
- if (cn->node.flags & HASHED)
- strcpy(fullnam, cn->u.cmd);
- else if (!cn->u.name)
- return 0;
- else {
- strcpy(fullnam, *(cn->u.name));
- strcat(fullnam, "/");
- strcat(fullnam, cn->node.nam);
- }
- return iscom(fullnam);
-}
-
-/*
- * Return TRUE if the given path contains a dot or dot-dot component
- * and does not start with a slash.
- */
-
-/**/
-int
-isrelative(char *s)
-{
- if (*s != '/')
- return 1;
- for (; *s; s++)
- if (*s == '.' && s[-1] == '/' &&
- (s[1] == '/' || s[1] == '\0' ||
- (s[1] == '.' && (s[2] == '/' || s[2] == '\0'))))
- return 1;
- return 0;
-}
-
-/**/
-mod_export Cmdnam
-hashcmd(char *arg0, char **pp)
-{
- Cmdnam cn;
- char *s, buf[PATH_MAX+1];
- char **pq;
-
- for (; *pp; pp++)
- if (**pp == '/') {
- s = buf;
- struncpy(&s, *pp, PATH_MAX);
- *s++ = '/';
- if ((s - buf) + strlen(arg0) >= PATH_MAX)
- continue;
- strcpy(s, arg0);
- if (iscom(buf))
- break;
- }
-
- if (!*pp)
- return NULL;
-
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = pp;
- cmdnamtab->addnode(cmdnamtab, ztrdup(arg0), cn);
-
- if (isset(HASHDIRS)) {
- for (pq = pathchecked; pq <= pp; pq++)
- hashdir(pq);
- pathchecked = pp + 1;
- }
-
- return cn;
-}
-
-/**/
-int
-forklevel;
-
-/* Arguments to entersubsh() */
-enum {
- /* Subshell is to be run asynchronously (else synchronously) */
- ESUB_ASYNC = 0x01,
- /*
- * Perform process group and tty handling and clear the
- * (real) job table, since it won't be any longer valid
- */
- ESUB_PGRP = 0x02,
- /* Don't unset traps */
- ESUB_KEEPTRAP = 0x04,
- /* This is only a fake entry to a subshell */
- ESUB_FAKE = 0x08,
- /* Release the process group if pid is the shell's process group */
- ESUB_REVERTPGRP = 0x10,
- /* Don't handle the MONITOR option even if previously set */
- ESUB_NOMONITOR = 0x20,
- /* This is a subshell where job control is allowed */
- ESUB_JOB_CONTROL = 0x40
-};
-
-/**/
-static void
-entersubsh(int flags)
-{
- int i, sig, monitor, job_control_ok;
-
- if (!(flags & ESUB_KEEPTRAP))
- for (sig = 0; sig < SIGCOUNT; sig++)
- if (!(sigtrapped[sig] & ZSIG_FUNC))
- unsettrap(sig);
- monitor = isset(MONITOR);
- job_control_ok = monitor && (flags & ESUB_JOB_CONTROL) && isset(POSIXJOBS);
- if (flags & ESUB_NOMONITOR)
- opts[MONITOR] = 0;
- if (!isset(MONITOR)) {
- if (flags & ESUB_ASYNC) {
- settrap(SIGINT, NULL, 0);
- settrap(SIGQUIT, NULL, 0);
- if (isatty(0)) {
- close(0);
- if (open("/dev/null", O_RDWR | O_NOCTTY)) {
- zerr("can't open /dev/null: %e", errno);
- _exit(1);
- }
- }
- }
- } else if (thisjob != -1 && (flags & ESUB_PGRP)) {
- if (jobtab[list_pipe_job].gleader && (list_pipe || list_pipe_child)) {
- if (setpgrp(0L, jobtab[list_pipe_job].gleader) == -1 ||
- killpg(jobtab[list_pipe_job].gleader, 0) == -1) {
- jobtab[list_pipe_job].gleader =
- jobtab[thisjob].gleader = (list_pipe_child ? mypgrp : getpid());
- setpgrp(0L, jobtab[list_pipe_job].gleader);
- if (!(flags & ESUB_ASYNC))
- attachtty(jobtab[thisjob].gleader);
- }
- }
- else if (!jobtab[thisjob].gleader ||
- setpgrp(0L, jobtab[thisjob].gleader) == -1) {
- /*
- * This is the standard point at which a newly started
- * process gets put into the foreground by taking over
- * the terminal. Note that in normal circumstances we do
- * this only from the process itself. This only works if
- * we are still ignoring SIGTTOU at this point; in this
- * case ignoring the signal has the special effect that
- * the operation is allowed to work (in addition to not
- * causing the shell to be suspended).
- */
- jobtab[thisjob].gleader = getpid();
- if (list_pipe_job != thisjob &&
- !jobtab[list_pipe_job].gleader)
- jobtab[list_pipe_job].gleader = jobtab[thisjob].gleader;
- setpgrp(0L, jobtab[thisjob].gleader);
- if (!(flags & ESUB_ASYNC))
- attachtty(jobtab[thisjob].gleader);
- }
- }
- if (!(flags & ESUB_FAKE))
- subsh = 1;
- /*
- * Increment the visible parameter ZSH_SUBSHELL even if this
- * is a fake subshell because we are exec'ing at the end.
- * Logically this should be equivalent to a real subshell so
- * we don't hang out the dirty washing.
- */
- zsh_subshell++;
- if ((flags & ESUB_REVERTPGRP) && getpid() == mypgrp)
- release_pgrp();
- shout = NULL;
- if (flags & ESUB_NOMONITOR) {
- /*
- * Allowing any form of interactive signalling here is
- * actively harmful as we are in a context where there is no
- * control over the process.
- */
- signal_ignore(SIGTTOU);
- signal_ignore(SIGTTIN);
- signal_ignore(SIGTSTP);
- } else if (!job_control_ok) {
- /*
- * If this process is not going to be doing job control,
- * we don't want to do special things with the corresponding
- * signals. If it is, we need to keep the special behaviour:
- * see note about attachtty() above.
- */
- signal_default(SIGTTOU);
- signal_default(SIGTTIN);
- signal_default(SIGTSTP);
- }
- if (interact) {
- signal_default(SIGTERM);
- if (!(sigtrapped[SIGINT] & ZSIG_IGNORED))
- signal_default(SIGINT);
- if (!(sigtrapped[SIGPIPE]))
- signal_default(SIGPIPE);
- }
- if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
- signal_default(SIGQUIT);
- /*
- * sigtrapped[sig] == ZSIG_IGNORED for signals that remain ignored,
- * but other trapped signals are temporarily blocked when intrap,
- * and must be unblocked before continuing into the subshell. This
- * is orthogonal to what the default handler for the signal may be.
- *
- * Start loop at 1 because 0 is SIGEXIT
- */
- if (intrap)
- for (sig = 1; sig < SIGCOUNT; sig++)
- if (sigtrapped[sig] && sigtrapped[sig] != ZSIG_IGNORED)
- signal_unblock(signal_mask(sig));
- if (!job_control_ok)
- opts[MONITOR] = 0;
- opts[USEZLE] = 0;
- zleactive = 0;
- /*
- * If we've saved fd's for later restoring, we're never going
- * to restore them now, so just close them.
- */
- for (i = 10; i <= max_zsh_fd; i++) {
- if (fdtable[i] & FDT_SAVED_MASK)
- zclose(i);
- }
- if (flags & ESUB_PGRP)
- clearjobtab(monitor);
- get_usage();
- forklevel = locallevel;
-}
-
-/* execute a string */
-
-/**/
-mod_export void
-execstring(char *s, int dont_change_job, int exiting, char *context)
-{
- Eprog prog;
-
- pushheap();
- if (isset(VERBOSE)) {
- zputs(s, stderr);
- fputc('\n', stderr);
- fflush(stderr);
- }
- if ((prog = parse_string(s, 0)))
- execode(prog, dont_change_job, exiting, context);
- popheap();
-}
-
-/**/
-mod_export void
-execode(Eprog p, int dont_change_job, int exiting, char *context)
-{
- struct estate s;
- static int zsh_eval_context_len;
- int alen;
-
- if (!zsh_eval_context_len) {
- zsh_eval_context_len = 16;
- alen = 0;
- zsh_eval_context = (char **)zalloc(zsh_eval_context_len *
- sizeof(*zsh_eval_context));
- } else {
- alen = arrlen(zsh_eval_context);
- if (zsh_eval_context_len == alen + 1) {
- zsh_eval_context_len *= 2;
- zsh_eval_context = zrealloc(zsh_eval_context,
- zsh_eval_context_len *
- sizeof(*zsh_eval_context));
- }
- }
- zsh_eval_context[alen] = context;
- zsh_eval_context[alen+1] = NULL;
-
- s.prog = p;
- s.pc = p->prog;
- s.strs = p->strs;
- useeprog(p); /* Mark as in use */
-
- execlist(&s, dont_change_job, exiting);
-
- freeeprog(p); /* Free if now unused */
-
- /*
- * zsh_eval_context may have been altered by a recursive
- * call, but that's OK since we're using the global value.
- */
- zsh_eval_context[alen] = NULL;
-}
-
-/* Execute a simplified command. This is used to execute things that
- * will run completely in the shell, so that we can by-pass all that
- * nasty job-handling and redirection stuff in execpline and execcmd. */
-
-/**/
-static int
-execsimple(Estate state)
-{
- wordcode code = *state->pc++;
- int lv, otj;
-
- if (errflag)
- return (lastval = 1);
-
- if (!isset(EXECOPT))
- return lastval = 0;
-
- /* In evaluated traps, don't modify the line number. */
- if (!IN_EVAL_TRAP() && !ineval && code)
- lineno = code - 1;
-
- code = wc_code(*state->pc++);
-
- /*
- * Because we're bypassing job control, ensure the called
- * code doesn't see the current job.
- */
- otj = thisjob;
- thisjob = -1;
-
- if (code == WC_ASSIGN) {
- cmdoutval = 0;
- addvars(state, state->pc - 1, 0);
- setunderscore("");
- if (isset(XTRACE)) {
- fputc('\n', xtrerr);
- fflush(xtrerr);
- }
- lv = (errflag ? errflag : cmdoutval);
- } else {
- int q = queue_signal_level();
- dont_queue_signals();
- if (code == WC_FUNCDEF)
- lv = execfuncdef(state, NULL);
- else
- lv = (execfuncs[code - WC_CURSH])(state, 0);
- restore_queue_signals(q);
- }
-
- thisjob = otj;
-
- return lastval = lv;
-}
-
-/* Main routine for executing a list. *
- * exiting means that the (sub)shell we are in is a definite goner *
- * after the current list is finished, so we may be able to exec the *
- * last command directly instead of forking. If dont_change_job is *
- * nonzero, then restore the current job number after executing the *
- * list. */
-
-/**/
-void
-execlist(Estate state, int dont_change_job, int exiting)
-{
- static int donetrap;
- Wordcode next;
- wordcode code;
- int ret, cj, csp, ltype;
- int old_pline_level, old_list_pipe, old_list_pipe_job;
- char *old_list_pipe_text;
- zlong oldlineno;
- /*
- * ERREXIT only forces the shell to exit if the last command in a &&
- * or || fails. This is the case even if an earlier command is a
- * shell function or other current shell structure, so we have to set
- * noerrexit here if the sublist is not of type END.
- */
- int oldnoerrexit = noerrexit;
-
- queue_signals();
-
- cj = thisjob;
- old_pline_level = pline_level;
- old_list_pipe = list_pipe;
- old_list_pipe_job = list_pipe_job;
- if (*list_pipe_text)
- old_list_pipe_text = ztrdup(list_pipe_text);
- else
- old_list_pipe_text = NULL;
- oldlineno = lineno;
-
- if (sourcelevel && unset(SHINSTDIN)) {
- pline_level = list_pipe = list_pipe_job = 0;
- *list_pipe_text = '\0';
- }
-
- /* Loop over all sets of comands separated by newline, *
- * semi-colon or ampersand (`sublists'). */
- code = *state->pc++;
- if (wc_code(code) != WC_LIST) {
- /* Empty list; this returns status zero. */
- lastval = 0;
- }
- while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) {
- int donedebug;
- int this_donetrap = 0;
- this_noerrexit = 0;
-
- ltype = WC_LIST_TYPE(code);
- csp = cmdsp;
-
- if (!IN_EVAL_TRAP() && !ineval) {
- /*
- * Ensure we have a valid line number for debugging,
- * unless we are in an evaluated trap in which case
- * we retain the line number from the context.
- * This was added for DEBUGBEFORECMD but I've made
- * it unconditional to keep dependencies to a minimum.
- *
- * The line number is updated for individual pipelines.
- * This isn't necessary for debug traps since they only
- * run once per sublist.
- */
- wordcode code2 = *state->pc, lnp1 = 0;
- if (ltype & Z_SIMPLE) {
- lnp1 = code2;
- } else if (wc_code(code2) == WC_SUBLIST) {
- if (WC_SUBLIST_FLAGS(code2) == WC_SUBLIST_SIMPLE)
- lnp1 = state->pc[1];
- else
- lnp1 = WC_PIPE_LINENO(state->pc[1]);
- }
- if (lnp1)
- lineno = lnp1 - 1;
- }
-
- if (sigtrapped[SIGDEBUG] && isset(DEBUGBEFORECMD) && !intrap) {
- Wordcode pc2 = state->pc;
- int oerrexit_opt = opts[ERREXIT];
- Param pm;
- opts[ERREXIT] = 0;
- noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
- if (ltype & Z_SIMPLE) /* skip the line number */
- pc2++;
- pm = assignsparam("ZSH_DEBUG_CMD",
- getpermtext(state->prog, pc2, 0),
- 0);
-
- exiting = donetrap;
- ret = lastval;
- dotrap(SIGDEBUG);
- if (!retflag)
- lastval = ret;
- donetrap = exiting;
- noerrexit = oldnoerrexit;
- /*
- * Only execute the trap once per sublist, even
- * if the DEBUGBEFORECMD option changes.
- */
- donedebug = isset(ERREXIT) ? 2 : 1;
- opts[ERREXIT] = oerrexit_opt;
- if (pm)
- unsetparam_pm(pm, 0, 1);
- } else
- donedebug = intrap ? 1 : 0;
-
- /* Reset donetrap: this ensures that a trap is only *
- * called once for each sublist that fails. */
- donetrap = 0;
- if (ltype & Z_SIMPLE) {
- next = state->pc + WC_LIST_SKIP(code);
- if (donedebug != 2)
- execsimple(state);
- state->pc = next;
- goto sublist_done;
- }
-
- /* Loop through code followed by &&, ||, or end of sublist. */
- code = *state->pc++;
- if (donedebug == 2) {
- /* Skip sublist. */
- while (wc_code(code) == WC_SUBLIST) {
- state->pc = state->pc + WC_SUBLIST_SKIP(code);
- if (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END)
- break;
- code = *state->pc++;
- }
- donetrap = 1;
- /* yucky but consistent... */
- goto sublist_done;
- }
- while (wc_code(code) == WC_SUBLIST) {
- int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END);
- next = state->pc + WC_SUBLIST_SKIP(code);
- if (!oldnoerrexit)
- noerrexit = isend ? 0 : NOERREXIT_EXIT | NOERREXIT_RETURN;
- if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) {
- /* suppress errexit for "! this_command" */
- if (isend)
- this_noerrexit = 1;
- /* suppress errexit for ! */
- noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
- }
- switch (WC_SUBLIST_TYPE(code)) {
- case WC_SUBLIST_END:
- /* End of sublist; just execute, ignoring status. */
- if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE)
- execsimple(state);
- else
- execpline(state, code, ltype, (ltype & Z_END) && exiting);
- state->pc = next;
- goto sublist_done;
- break;
- case WC_SUBLIST_AND:
- /* If the return code is non-zero, we skip pipelines until *
- * we find a sublist followed by ORNEXT. */
- if ((ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
- execsimple(state) :
- execpline(state, code, Z_SYNC, 0)))) {
- state->pc = next;
- code = *state->pc++;
- next = state->pc + WC_SUBLIST_SKIP(code);
- while (wc_code(code) == WC_SUBLIST &&
- WC_SUBLIST_TYPE(code) == WC_SUBLIST_AND) {
- state->pc = next;
- code = *state->pc++;
- next = state->pc + WC_SUBLIST_SKIP(code);
- }
- if (wc_code(code) != WC_SUBLIST) {
- /* We've skipped to the end of the list, not executing *
- * the final pipeline, so don't perform error handling *
- * for this sublist. */
- this_donetrap = 1;
- goto sublist_done;
- } else if (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END) {
- this_donetrap = 1;
- /*
- * Treat this in the same way as if we reached
- * the end of the sublist normally.
- */
- state->pc = next;
- goto sublist_done;
- }
- }
- cmdpush(CS_CMDAND);
- break;
- case WC_SUBLIST_OR:
- /* If the return code is zero, we skip pipelines until *
- * we find a sublist followed by ANDNEXT. */
- if (!(ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
- execsimple(state) :
- execpline(state, code, Z_SYNC, 0)))) {
- state->pc = next;
- code = *state->pc++;
- next = state->pc + WC_SUBLIST_SKIP(code);
- while (wc_code(code) == WC_SUBLIST &&
- WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR) {
- state->pc = next;
- code = *state->pc++;
- next = state->pc + WC_SUBLIST_SKIP(code);
- }
- if (wc_code(code) != WC_SUBLIST) {
- /* We've skipped to the end of the list, not executing *
- * the final pipeline, so don't perform error handling *
- * for this sublist. */
- this_donetrap = 1;
- goto sublist_done;
- } else if (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END) {
- this_donetrap = 1;
- /*
- * Treat this in the same way as if we reached
- * the end of the sublist normally.
- */
- state->pc = next;
- goto sublist_done;
- }
- }
- cmdpush(CS_CMDOR);
- break;
- }
- state->pc = next;
- code = *state->pc++;
- }
- state->pc--;
-sublist_done:
-
- /*
- * See hairy code near the end of execif() for the
- * following. "noerrexit " only applies until
- * we hit execcmd on the way down. We're now
- * on the way back up, so don't restore it.
- */
- if (!(oldnoerrexit & NOERREXIT_UNTIL_EXEC))
- noerrexit = oldnoerrexit;
-
- if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) {
- /*
- * Save and restore ERREXIT for consistency with
- * DEBUGBEFORECMD, even though it's not used.
- */
- int oerrexit_opt = opts[ERREXIT];
- opts[ERREXIT] = 0;
- noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
- exiting = donetrap;
- ret = lastval;
- dotrap(SIGDEBUG);
- if (!retflag)
- lastval = ret;
- donetrap = exiting;
- noerrexit = oldnoerrexit;
- opts[ERREXIT] = oerrexit_opt;
- }
-
- cmdsp = csp;
-
- /* Check whether we are suppressing traps/errexit *
- * (typically in init scripts) and if we haven't *
- * already performed them for this sublist. */
- if (!this_noerrexit && !donetrap && !this_donetrap) {
- if (sigtrapped[SIGZERR] && lastval &&
- !(noerrexit & NOERREXIT_EXIT)) {
- dotrap(SIGZERR);
- donetrap = 1;
- }
- if (lastval) {
- int errreturn = isset(ERRRETURN) &&
- (isset(INTERACTIVE) || locallevel || sourcelevel) &&
- !(noerrexit & NOERREXIT_RETURN);
- int errexit = (isset(ERREXIT) ||
- (isset(ERRRETURN) && !errreturn)) &&
- !(noerrexit & NOERREXIT_EXIT);
- if (errexit) {
- if (sigtrapped[SIGEXIT])
- dotrap(SIGEXIT);
- if (mypid != getpid())
- _exit(lastval);
- else
- exit(lastval);
- }
- if (errreturn) {
- retflag = 1;
- breaks = loops;
- }
- }
- }
- if (ltype & Z_END)
- break;
- code = *state->pc++;
- }
- pline_level = old_pline_level;
- list_pipe = old_list_pipe;
- list_pipe_job = old_list_pipe_job;
- if (old_list_pipe_text) {
- strcpy(list_pipe_text, old_list_pipe_text);
- zsfree(old_list_pipe_text);
- } else {
- *list_pipe_text = '\0';
- }
- lineno = oldlineno;
- if (dont_change_job)
- thisjob = cj;
-
- if (exiting && sigtrapped[SIGEXIT]) {
- dotrap(SIGEXIT);
- /* Make sure this doesn't get executed again. */
- sigtrapped[SIGEXIT] = 0;
- }
-
- unqueue_signals();
-}
-
-/* Execute a pipeline. *
- * last1 is a flag that this command is the last command in a shell *
- * that is about to exit, so we can exec instead of forking. It gets *
- * passed all the way down to execcmd() which actually makes the *
- * decision. A 0 is always passed if the command is not the last in *
- * the pipeline. This function assumes that the sublist is not NULL. *
- * If last1 is zero but the command is at the end of a pipeline, we *
- * pass 2 down to execcmd(). *
- */
-
-/**/
-static int
-execpline(Estate state, wordcode slcode, int how, int last1)
-{
- int ipipe[2], opipe[2];
- int pj, newjob;
- int old_simple_pline = simple_pline;
- int slflags = WC_SUBLIST_FLAGS(slcode);
- wordcode code = *state->pc++;
- static int lastwj, lpforked;
-
- if (wc_code(code) != WC_PIPE)
- return lastval = (slflags & WC_SUBLIST_NOT) != 0;
- else if (slflags & WC_SUBLIST_NOT)
- last1 = 0;
-
- /* If trap handlers are allowed to run here, they may start another
- * external job in the middle of us starting this one, which can
- * result in jobs being reaped before their job table entries have
- * been initialized, which in turn leads to waiting forever for
- * jobs that no longer exist. So don't do that.
- */
- queue_signals();
-
- pj = thisjob;
- ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
- child_block();
-
- /*
- * Get free entry in job table and initialize it. This is currently
- * the only call to initjob() (apart from a minor exception in
- * clearjobtab()), so this is also the only place where we can
- * expand the job table under us.
- */
- if ((thisjob = newjob = initjob()) == -1) {
- child_unblock();
- unqueue_signals();
- return 1;
- }
- if (how & Z_TIMED)
- jobtab[thisjob].stat |= STAT_TIMED;
-
- if (slflags & WC_SUBLIST_COPROC) {
- how = Z_ASYNC;
- if (coprocin >= 0) {
- zclose(coprocin);
- zclose(coprocout);
- }
- if (mpipe(ipipe) < 0) {
- coprocin = coprocout = -1;
- slflags &= ~WC_SUBLIST_COPROC;
- } else if (mpipe(opipe) < 0) {
- close(ipipe[0]);
- close(ipipe[1]);
- coprocin = coprocout = -1;
- slflags &= ~WC_SUBLIST_COPROC;
- } else {
- coprocin = ipipe[0];
- coprocout = opipe[1];
- fdtable[coprocin] = fdtable[coprocout] = FDT_UNUSED;
- }
- }
- /* This used to set list_pipe_pid=0 unconditionally, but in things
- * like `ls|if true; then sleep 20; cat; fi' where the sleep was
- * stopped, the top-level execpline() didn't get the pid for the
- * sub-shell because it was overwritten. */
- if (!pline_level++) {
- list_pipe_pid = 0;
- nowait = 0;
- simple_pline = (WC_PIPE_TYPE(code) == WC_PIPE_END);
- list_pipe_job = newjob;
- }
- lastwj = lpforked = 0;
- execpline2(state, code, how, opipe[0], ipipe[1], last1);
- pline_level--;
- if (how & Z_ASYNC) {
- lastwj = newjob;
-
- if (thisjob == list_pipe_job)
- list_pipe_job = 0;
- jobtab[thisjob].stat |= STAT_NOSTTY;
- if (slflags & WC_SUBLIST_COPROC) {
- zclose(ipipe[1]);
- zclose(opipe[0]);
- }
- if (how & Z_DISOWN) {
- pipecleanfilelist(jobtab[thisjob].filelist, 0);
- deletejob(jobtab + thisjob, 1);
- thisjob = -1;
- }
- else
- spawnjob();
- child_unblock();
- unqueue_signals();
- /* Executing background code resets shell status */
- return lastval = 0;
- } else {
- if (newjob != lastwj) {
- Job jn = jobtab + newjob;
- int updated;
-
- if (newjob == list_pipe_job && list_pipe_child)
- _exit(0);
-
- lastwj = thisjob = newjob;
-
- if (list_pipe || (pline_level && !(how & Z_TIMED)))
- jn->stat |= STAT_NOPRINT;
-
- if (nowait) {
- if(!pline_level) {
- int jobsub;
- struct process *pn, *qn;
-
- curjob = newjob;
- DPUTS(!list_pipe_pid, "invalid list_pipe_pid");
- addproc(list_pipe_pid, list_pipe_text, 0,
- &list_pipe_start);
-
- /* If the super-job contains only the sub-shell, the
- sub-shell is the group leader. */
- if (!jn->procs->next || lpforked == 2) {
- jn->gleader = list_pipe_pid;
- jn->stat |= STAT_SUBLEADER;
- /*
- * Pick up any subjob that's still lying around
- * as it's now our responsibility.
- * If we find it we're a SUPERJOB.
- */
- for (jobsub = 1; jobsub <= maxjob; jobsub++) {
- Job jnsub = jobtab + jobsub;
- if (jnsub->stat & STAT_SUBJOB_ORPHANED) {
- jn->other = jobsub;
- jn->stat |= STAT_SUPERJOB;
- jnsub->stat &= ~STAT_SUBJOB_ORPHANED;
- jnsub->other = list_pipe_pid;
- }
- }
- }
- for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
- if (WIFSTOPPED(pn->status))
- break;
-
- if (pn) {
- for (qn = jn->procs; qn->next; qn = qn->next);
- qn->status = pn->status;
- }
-
- jn->stat &= ~(STAT_DONE | STAT_NOPRINT);
- jn->stat |= STAT_STOPPED | STAT_CHANGED | STAT_LOCKED |
- STAT_INUSE;
- printjob(jn, !!isset(LONGLISTJOBS), 1);
- }
- else if (newjob != list_pipe_job)
- deletejob(jn, 0);
- else
- lastwj = -1;
- }
-
- errbrk_saved = 0;
- for (; !nowait;) {
- if (list_pipe_child) {
- jn->stat |= STAT_NOPRINT;
- makerunning(jn);
- }
- if (!(jn->stat & STAT_LOCKED)) {
- updated = hasprocs(thisjob);
- waitjobs(); /* deals with signal queue */
- child_block();
- } else
- updated = 0;
- if (!updated &&
- list_pipe_job && hasprocs(list_pipe_job) &&
- !(jobtab[list_pipe_job].stat & STAT_STOPPED)) {
- int q = queue_signal_level();
- child_unblock();
- child_block();
- dont_queue_signals();
- restore_queue_signals(q);
- }
- if (list_pipe_child &&
- jn->stat & STAT_DONE &&
- lastval2 & 0200)
- killpg(mypgrp, lastval2 & ~0200);
- if (!list_pipe_child && !lpforked && !subsh && jobbing &&
- (list_pipe || last1 || pline_level) &&
- ((jn->stat & STAT_STOPPED) ||
- (list_pipe_job && pline_level &&
- (jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
- pid_t pid = 0;
- int synch[2];
- struct timeval bgtime;
-
- /*
- * A pipeline with the shell handling the right
- * hand side was stopped. We'll fork to allow
- * it to continue.
- */
- if (pipe(synch) < 0 || (pid = zfork(&bgtime)) == -1) {
- /* Failure */
- if (pid < 0) {
- close(synch[0]);
- close(synch[1]);
- } else
- zerr("pipe failed: %e", errno);
- zleentry(ZLE_CMD_TRASH);
- fprintf(stderr, "zsh: job can't be suspended\n");
- fflush(stderr);
- makerunning(jn);
- killjb(jn, SIGCONT);
- thisjob = newjob;
- }
- else if (pid) {
- /*
- * Parent: job control is here. If the job
- * started for the RHS of the pipeline is still
- * around, then its a SUBJOB and the job for
- * earlier parts of the pipeeline is its SUPERJOB.
- * The newly forked shell isn't recorded as a
- * separate job here, just as list_pipe_pid.
- * If the superjob exits (it may already have
- * done so, see child branch below), we'll use
- * list_pipe_pid to form the basis of a
- * replacement job --- see SUBLEADER code above.
- */
- char dummy;
-
- lpforked =
- (killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1);
- list_pipe_pid = pid;
- list_pipe_start = bgtime;
- nowait = 1;
- errflag |= ERRFLAG_ERROR;
- breaks = loops;
- close(synch[1]);
- read_loop(synch[0], &dummy, 1);
- close(synch[0]);
- /* If this job has finished, we leave it as a
- * normal (non-super-) job. */
- if (!(jn->stat & STAT_DONE)) {
- jobtab[list_pipe_job].other = newjob;
- jobtab[list_pipe_job].stat |= STAT_SUPERJOB;
- jn->stat |= STAT_SUBJOB | STAT_NOPRINT;
- jn->other = list_pipe_pid; /* see zsh.h */
- if (hasprocs(list_pipe_job))
- jn->gleader = jobtab[list_pipe_job].gleader;
- }
- if ((list_pipe || last1) && hasprocs(list_pipe_job))
- killpg(jobtab[list_pipe_job].gleader, SIGSTOP);
- break;
- }
- else {
- close(synch[0]);
- entersubsh(ESUB_ASYNC);
- /*
- * At this point, we used to attach this process
- * to the process group of list_pipe_job (the
- * new superjob) any time that was still available.
- * That caused problems in at least two
- * cases because this forked shell was then
- * suspended with the right hand side of the
- * pipeline, and the SIGSTOP below suspended
- * it a second time when it was continued.
- *
- * It's therefore not clear entirely why you'd ever
- * do anything other than the following, but no
- * doubt we'll find out...
- */
- setpgrp(0L, mypgrp = getpid());
- close(synch[1]);
- kill(getpid(), SIGSTOP);
- list_pipe = 0;
- list_pipe_child = 1;
- opts[INTERACTIVE] = 0;
- if (errbrk_saved) {
- /*
- * Keep any user interrupt bit in errflag.
- */
- errflag = prev_errflag | (errflag & ERRFLAG_INT);
- breaks = prev_breaks;
- }
- break;
- }
- }
- else if (subsh && jn->stat & STAT_STOPPED)
- thisjob = newjob;
- else
- break;
- }
- child_unblock();
- unqueue_signals();
-
- if (list_pipe && (lastval & 0200) && pj >= 0 &&
- (!(jn->stat & STAT_INUSE) || (jn->stat & STAT_DONE))) {
- deletejob(jn, 0);
- jn = jobtab + pj;
- if (jn->gleader)
- killjb(jn, lastval & ~0200);
- }
- if (list_pipe_child ||
- ((jn->stat & STAT_DONE) &&
- (list_pipe || (pline_level && !(jn->stat & STAT_SUBJOB)))))
- deletejob(jn, 0);
- thisjob = pj;
- }
- else
- unqueue_signals();
- if ((slflags & WC_SUBLIST_NOT) && !errflag)
- lastval = !lastval;
- }
- if (!pline_level)
- simple_pline = old_simple_pline;
- return lastval;
-}
-
-/* execute pipeline. This function assumes the `pline' is not NULL. */
-
-/**/
-static void
-execpline2(Estate state, wordcode pcode,
- int how, int input, int output, int last1)
-{
- struct execcmd_params eparams;
-
- if (breaks || retflag)
- return;
-
- /* In evaluated traps, don't modify the line number. */
- if (!IN_EVAL_TRAP() && !ineval && WC_PIPE_LINENO(pcode))
- lineno = WC_PIPE_LINENO(pcode) - 1;
-
- if (pline_level == 1) {
- if ((how & Z_ASYNC) || !sfcontext)
- strcpy(list_pipe_text,
- getjobtext(state->prog,
- state->pc + (WC_PIPE_TYPE(pcode) == WC_PIPE_END ?
- 0 : 1)));
- else
- list_pipe_text[0] = '\0';
- }
- if (WC_PIPE_TYPE(pcode) == WC_PIPE_END) {
- execcmd_analyse(state, &eparams);
- execcmd_exec(state, &eparams, input, output, how, last1 ? 1 : 2, -1);
- } else {
- int pipes[2];
- int old_list_pipe = list_pipe;
- Wordcode next = state->pc + (*state->pc);
-
- ++state->pc;
- execcmd_analyse(state, &eparams);
-
- if (mpipe(pipes) < 0) {
- /* FIXME */
- }
-
- addfilelist(NULL, pipes[0]);
- execcmd_exec(state, &eparams, input, pipes[1], how, 0, pipes[0]);
- zclose(pipes[1]);
- state->pc = next;
-
- /* if another execpline() is invoked because the command is *
- * a list it must know that we're already in a pipeline */
- cmdpush(CS_PIPE);
- list_pipe = 1;
- execpline2(state, *state->pc++, how, pipes[0], output, last1);
- list_pipe = old_list_pipe;
- cmdpop();
- }
-}
-
-/* make the argv array */
-
-/**/
-static char **
-makecline(LinkList list)
-{
- LinkNode node;
- char **argv, **ptr;
-
- /* A bigger argv is necessary for executing scripts */
- ptr = argv = 2 + (char **) hcalloc((countlinknodes(list) + 4) *
- sizeof(char *));
-
- if (isset(XTRACE)) {
- if (!doneps4)
- printprompt4();
-
- for (node = firstnode(list); node; incnode(node)) {
- *ptr++ = (char *)getdata(node);
- quotedzputs(getdata(node), xtrerr);
- if (nextnode(node))
- fputc(' ', xtrerr);
- }
- fputc('\n', xtrerr);
- fflush(xtrerr);
- } else {
- for (node = firstnode(list); node; incnode(node))
- *ptr++ = (char *)getdata(node);
- }
- *ptr = NULL;
- return (argv);
-}
-
-/**/
-mod_export void
-untokenize(char *s)
-{
- if (*s) {
- int c;
-
- while ((c = *s++))
- if (itok(c)) {
- char *p = s - 1;
-
- if (c != Nularg)
- *p++ = ztokens[c - Pound];
-
- while ((c = *s++)) {
- if (itok(c)) {
- if (c != Nularg)
- *p++ = ztokens[c - Pound];
- } else
- *p++ = c;
- }
- *p = '\0';
- break;
- }
- }
-}
-
-
-/*
- * Given a tokenized string, output it to standard output in
- * such a way that it's clear which tokens are active.
- * Hence Star becomes an unquoted "*", while a "*" becomes "\*".
- *
- * The code here is a kind of amalgamation of the tests in
- * zshtokenize() and untokenize() with some outputting.
- */
-
-/**/
-void
-quote_tokenized_output(char *str, FILE *file)
-{
- char *s = str;
-
- for (; *s; s++) {
- switch (*s) {
- case Meta:
- putc(*++s ^ 32, file);
- continue;
-
- case Nularg:
- /* Do nothing. I think. */
- continue;
-
- case '\\':
- case '<':
- case '>':
- case '(':
- case '|':
- case ')':
- case '^':
- case '#':
- case '~':
- case '[':
- case ']':
- case '*':
- case '?':
- case '$':
- case ' ':
- putc('\\', file);
- break;
-
- case '\t':
- fputs("$'\\t'", file);
- continue;
-
- case '\n':
- fputs("$'\\n'", file);
- continue;
-
- case '\r':
- fputs("$'\\r'", file);
- continue;
-
- case '=':
- if (s == str)
- putc('\\', file);
- break;
-
- default:
- if (itok(*s)) {
- putc(ztokens[*s - Pound], file);
- continue;
- }
- break;
- }
-
- putc(*s, file);
- }
-}
-
-/* Check that we can use a parameter for allocating a file descriptor. */
-
-static int
-checkclobberparam(struct redir *f)
-{
- struct value vbuf;
- Value v;
- char *s = f->varid;
- int fd;
-
- if (!s)
- return 1;
-
- if (!(v = getvalue(&vbuf, &s, 0)))
- return 1;
-
- if (v->pm->node.flags & PM_READONLY) {
- zwarn("can't allocate file descriptor to readonly parameter %s",
- f->varid);
- /* don't flag a system error for this */
- errno = 0;
- return 0;
- }
-
- /*
- * We can't clobber the value in the parameter if it's
- * already an opened file descriptor --- that means it's a decimal
- * integer corresponding to an opened file descriptor,
- * not merely an expression that evaluates to a file descriptor.
- */
- if (!isset(CLOBBER) && (s = getstrvalue(v)) &&
- (fd = (int)zstrtol(s, &s, 10)) >= 0 && !*s &&
- fd <= max_zsh_fd && fdtable[fd] == FDT_EXTERNAL) {
- zwarn("can't clobber parameter %s containing file descriptor %d",
- f->varid, fd);
- /* don't flag a system error for this */
- errno = 0;
- return 0;
- }
- return 1;
-}
-
-/* Open a file for writing redirection */
-
-/**/
-static int
-clobber_open(struct redir *f)
-{
- struct stat buf;
- int fd, oerrno;
-
- /* If clobbering, just open. */
- if (isset(CLOBBER) || IS_CLOBBER_REDIR(f->type))
- return open(unmeta(f->name),
- O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666);
-
- /* If not clobbering, attempt to create file exclusively. */
- if ((fd = open(unmeta(f->name),
- O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0666)) >= 0)
- return fd;
-
- /* If that fails, we are still allowed to open non-regular files. *
- * Try opening, and if it's a regular file then close it again *
- * because we weren't supposed to open it. */
- oerrno = errno;
- if ((fd = open(unmeta(f->name), O_WRONLY | O_NOCTTY)) != -1) {
- if(!fstat(fd, &buf) && !S_ISREG(buf.st_mode))
- return fd;
- close(fd);
- }
- errno = oerrno;
- return -1;
-}
-
-/* size of buffer for tee and cat processes */
-#define TCBUFSIZE 4092
-
-/* close an multio (success) */
-
-/**/
-static void
-closemn(struct multio **mfds, int fd, int type)
-{
- if (fd >= 0 && mfds[fd] && mfds[fd]->ct >= 2) {
- struct multio *mn = mfds[fd];
- char buf[TCBUFSIZE];
- int len, i;
- pid_t pid;
- struct timeval bgtime;
-
- /*
- * We need to block SIGCHLD in case the process
- * we are spawning terminates before the job table
- * is set up to handle it.
- */
- child_block();
- if ((pid = zfork(&bgtime))) {
- for (i = 0; i < mn->ct; i++)
- zclose(mn->fds[i]);
- zclose(mn->pipe);
- if (pid == -1) {
- mfds[fd] = NULL;
- child_unblock();
- return;
- }
- mn->ct = 1;
- mn->fds[0] = fd;
- addproc(pid, NULL, 1, &bgtime);
- child_unblock();
- return;
- }
- /* pid == 0 */
- child_unblock();
- closeallelse(mn);
- if (mn->rflag) {
- /* tee process */
- while ((len = read(mn->pipe, buf, TCBUFSIZE)) != 0) {
- if (len < 0) {
- if (errno == EINTR)
- continue;
- else
- break;
- }
- for (i = 0; i < mn->ct; i++)
- write_loop(mn->fds[i], buf, len);
- }
- } else {
- /* cat process */
- for (i = 0; i < mn->ct; i++)
- while ((len = read(mn->fds[i], buf, TCBUFSIZE)) != 0) {
- if (len < 0) {
- if (errno == EINTR)
- continue;
- else
- break;
- }
- write_loop(mn->pipe, buf, len);
- }
- }
- _exit(0);
- } else if (fd >= 0 && type == REDIR_CLOSE)
- mfds[fd] = NULL;
-}
-
-/* close all the mnodes (failure) */
-
-/**/
-static void
-closemnodes(struct multio **mfds)
-{
- int i, j;
-
- for (i = 0; i < 10; i++)
- if (mfds[i]) {
- for (j = 0; j < mfds[i]->ct; j++)
- zclose(mfds[i]->fds[j]);
- mfds[i] = NULL;
- }
-}
-
-/**/
-static void
-closeallelse(struct multio *mn)
-{
- int i, j;
- long openmax;
-
- openmax = fdtable_size;
-
- for (i = 0; i < openmax; i++)
- if (mn->pipe != i) {
- for (j = 0; j < mn->ct; j++)
- if (mn->fds[j] == i)
- break;
- if (j == mn->ct)
- zclose(i);
- }
-}
-
-/*
- * A multio is a list of fds associated with a certain fd.
- * Thus if you do "foo >bar >ble", the multio for fd 1 will have
- * two fds, the result of open("bar",...), and the result of
- * open("ble",....).
- */
-
-/*
- * Add a fd to an multio. fd1 must be < 10, and may be in any state.
- * fd2 must be open, and is `consumed' by this function. Note that
- * fd1 == fd2 is possible, and indicates that fd1 was really closed.
- * We effectively do `fd2 = movefd(fd2)' at the beginning of this
- * function, but in most cases we can avoid an extra dup by delaying
- * the movefd: we only >need< to move it if we're actually doing a
- * multiple redirection.
- *
- * If varid is not NULL, we open an fd above 10 and set the parameter
- * named varid to that value. fd1 is not used.
- */
-
-/**/
-static void
-addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
- char *varid)
-{
- int pipes[2];
-
- if (varid) {
- /* fd will be over 10, don't touch mfds */
- fd1 = movefd(fd2);
- if (fd1 == -1) {
- zerr("cannot moved fd %d: %e", fd2, errno);
- return;
- } else {
- fdtable[fd1] = FDT_EXTERNAL;
- setiparam(varid, (zlong)fd1);
- /*
- * If setting the parameter failed, close the fd else
- * it will leak.
- */
- if (errflag)
- zclose(fd1);
- }
- } else if (!mfds[fd1] || unset(MULTIOS)) {
- if(!mfds[fd1]) { /* starting a new multio */
- mfds[fd1] = (struct multio *) zhalloc(sizeof(struct multio));
- if (!forked && save[fd1] == -2) {
- if (fd1 == fd2)
- save[fd1] = -1;
- else {
- int fdN = movefd(fd1);
- /*
- * fd1 may already be closed here, so
- * ignore bad file descriptor error
- */
- if (fdN < 0) {
- if (errno != EBADF) {
- zerr("cannot duplicate fd %d: %e", fd1, errno);
- mfds[fd1] = NULL;
- closemnodes(mfds);
- return;
- }
- } else {
- DPUTS(fdtable[fdN] != FDT_INTERNAL,
- "Saved file descriptor not marked as internal");
- fdtable[fdN] |= FDT_SAVED_MASK;
- }
- save[fd1] = fdN;
- }
- }
- }
- if (!varid)
- redup(fd2, fd1);
- mfds[fd1]->ct = 1;
- mfds[fd1]->fds[0] = fd1;
- mfds[fd1]->rflag = rflag;
- } else {
- if (mfds[fd1]->rflag != rflag) {
- zerr("file mode mismatch on fd %d", fd1);
- closemnodes(mfds);
- return;
- }
- if (mfds[fd1]->ct == 1) { /* split the stream */
- int fdN = movefd(fd1);
- if (fdN < 0) {
- zerr("multio failed for fd %d: %e", fd1, errno);
- closemnodes(mfds);
- return;
- }
- mfds[fd1]->fds[0] = fdN;
- fdN = movefd(fd2);
- if (fdN < 0) {
- zerr("multio failed for fd %d: %e", fd2, errno);
- closemnodes(mfds);
- return;
- }
- mfds[fd1]->fds[1] = fdN;
- if (mpipe(pipes) < 0) {
- zerr("multio failed for fd %d: %e", fd2, errno);
- closemnodes(mfds);
- return;
- }
- mfds[fd1]->pipe = pipes[1 - rflag];
- redup(pipes[rflag], fd1);
- mfds[fd1]->ct = 2;
- } else { /* add another fd to an already split stream */
- int fdN;
- if(!(mfds[fd1]->ct % MULTIOUNIT)) {
- int new = sizeof(struct multio) + sizeof(int) * mfds[fd1]->ct;
- int old = new - sizeof(int) * MULTIOUNIT;
- mfds[fd1] = hrealloc((char *)mfds[fd1], old, new);
- }
- if ((fdN = movefd(fd2)) < 0) {
- zerr("multio failed for fd %d: %e", fd2, errno);
- closemnodes(mfds);
- return;
- }
- mfds[fd1]->fds[mfds[fd1]->ct++] = fdN;
- }
- }
-}
-
-/**/
-static void
-addvars(Estate state, Wordcode pc, int addflags)
-{
- LinkList vl;
- int xtr, isstr, htok = 0;
- char **arr, **ptr, *name;
- int flags;
-
- Wordcode opc = state->pc;
- wordcode ac;
- local_list1(svl);
-
- /*
- * Warn when creating a global without using typeset -g in a
- * function. Don't do this if there is a list of variables marked
- * to be restored after the command, since then the assignment
- * is implicitly scoped.
- */
- flags = !(addflags & ADDVAR_RESTORE) ? ASSPM_WARN : 0;
- xtr = isset(XTRACE);
- if (xtr) {
- printprompt4();
- doneps4 = 1;
- }
- state->pc = pc;
- while (wc_code(ac = *state->pc++) == WC_ASSIGN) {
- int myflags = flags;
- name = ecgetstr(state, EC_DUPTOK, &htok);
- if (htok)
- untokenize(name);
- if (WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC)
- myflags |= ASSPM_AUGMENT;
- if (xtr)
- fprintf(xtrerr,
- WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC ? "%s+=" : "%s=", name);
- if ((isstr = (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR))) {
- init_list1(svl, ecgetstr(state, EC_DUPTOK, &htok));
- vl = &svl;
- } else {
- vl = ecgetlist(state, WC_ASSIGN_NUM(ac), EC_DUPTOK, &htok);
- if (errflag) {
- state->pc = opc;
- return;
- }
- }
-
- if (vl && htok) {
- int prefork_ret = 0;
- prefork(vl, (isstr ? (PREFORK_SINGLE|PREFORK_ASSIGN) :
- PREFORK_ASSIGN), &prefork_ret);
- if (errflag) {
- state->pc = opc;
- return;
- }
- if (prefork_ret & PREFORK_KEY_VALUE)
- myflags |= ASSPM_KEY_VALUE;
- if (!isstr || (isset(GLOBASSIGN) && isstr &&
- haswilds((char *)getdata(firstnode(vl))))) {
- globlist(vl, prefork_ret);
- /* Unset the parameter to force it to be recreated
- * as either scalar or array depending on how many
- * matches were found for the glob.
- */
- if (isset(GLOBASSIGN) && isstr)
- unsetparam(name);
- if (errflag) {
- state->pc = opc;
- return;
- }
- }
- }
- if (isstr && (empty(vl) || !nextnode(firstnode(vl)))) {
- Param pm;
- char *val;
- int allexp;
-
- if (empty(vl))
- val = ztrdup("");
- else {
- untokenize(peekfirst(vl));
- val = ztrdup(ugetnode(vl));
- }
- if (xtr) {
- quotedzputs(val, xtrerr);
- fputc(' ', xtrerr);
- }
- if ((addflags & ADDVAR_EXPORT) && !strchr(name, '[')) {
- if ((addflags & ADDVAR_RESTRICT) && isset(RESTRICTED) &&
- (pm = (Param) paramtab->removenode(paramtab, name)) &&
- (pm->node.flags & PM_RESTRICTED)) {
- zerr("%s: restricted", pm->node.nam);
- zsfree(val);
- state->pc = opc;
- return;
- }
- if (strcmp(name, "STTY") == 0) {
- zsfree(STTYval);
- STTYval = ztrdup(val);
- }
- allexp = opts[ALLEXPORT];
- opts[ALLEXPORT] = 1;
- if (isset(KSHARRAYS))
- unsetparam(name);
- pm = assignsparam(name, val, myflags);
- opts[ALLEXPORT] = allexp;
- } else
- pm = assignsparam(name, val, myflags);
- if (errflag) {
- state->pc = opc;
- return;
- }
- continue;
- }
- if (vl) {
- ptr = arr = (char **) zalloc(sizeof(char *) *
- (countlinknodes(vl) + 1));
-
- while (nonempty(vl))
- *ptr++ = ztrdup((char *) ugetnode(vl));
- } else
- ptr = arr = (char **) zalloc(sizeof(char *));
-
- *ptr = NULL;
- if (xtr) {
- fprintf(xtrerr, "( ");
- for (ptr = arr; *ptr; ptr++) {
- quotedzputs(*ptr, xtrerr);
- fputc(' ', xtrerr);
- }
- fprintf(xtrerr, ") ");
- }
- assignaparam(name, arr, myflags);
- if (errflag) {
- state->pc = opc;
- return;
- }
- }
- state->pc = opc;
-}
-
-/**/
-void
-setunderscore(char *str)
-{
- queue_signals();
- if (str && *str) {
- int l = strlen(str) + 1, nl = (l + 31) & ~31;
-
- if (nl > underscorelen || (underscorelen - nl) > 64) {
- zfree(zunderscore, underscorelen);
- zunderscore = (char *) zalloc(underscorelen = nl);
- }
- strcpy(zunderscore, str);
- underscoreused = l;
- } else {
- if (underscorelen > 128) {
- zfree(zunderscore, underscorelen);
- zunderscore = (char *) zalloc(underscorelen = 32);
- }
- *zunderscore = '\0';
- underscoreused = 1;
- }
- unqueue_signals();
-}
-
-/* These describe the type of expansions that need to be done on the words
- * used in the thing we are about to execute. They are set in execcmd() and
- * used in execsubst() which might be called from one of the functions
- * called from execcmd() (like execfor() and so on). */
-
-static int esprefork, esglob = 1;
-
-/**/
-void
-execsubst(LinkList strs)
-{
- if (strs) {
- prefork(strs, esprefork, NULL);
- if (esglob && !errflag) {
- LinkList ostrs = strs;
- globlist(strs, 0);
- strs = ostrs;
- }
- }
-}
-
-/*
- * Check if a builtin requires an autoload and if so
- * deal with it. This may return NULL.
- */
-
-/**/
-static HashNode
-resolvebuiltin(const char *cmdarg, HashNode hn)
-{
- if (!((Builtin) hn)->handlerfunc) {
- char *modname = dupstring(((Builtin) hn)->optstr);
- /*
- * Ensure the module is loaded and the
- * feature corresponding to the builtin
- * is enabled.
- */
- (void)ensurefeature(modname, "b:",
- (hn->flags & BINF_AUTOALL) ? NULL :
- hn->nam);
- hn = builtintab->getnode(builtintab, cmdarg);
- if (!hn) {
- lastval = 1;
- zerr("autoloading module %s failed to define builtin: %s",
- modname, cmdarg);
- return NULL;
- }
- }
- return hn;
-}
-
-/*
- * We are about to execute a command at the lowest level of the
- * hierarchy. Analyse the parameters from the wordcode.
- */
-
-/**/
-static void
-execcmd_analyse(Estate state, Execcmd_params eparams)
-{
- wordcode code;
- int i;
-
- eparams->beg = state->pc;
- eparams->redir =
- (wc_code(*state->pc) == WC_REDIR ? ecgetredirs(state) : NULL);
- if (wc_code(*state->pc) == WC_ASSIGN) {
- cmdoutval = 0;
- eparams->varspc = state->pc;
- while (wc_code((code = *state->pc)) == WC_ASSIGN)
- state->pc += (WC_ASSIGN_TYPE(code) == WC_ASSIGN_SCALAR ?
- 3 : WC_ASSIGN_NUM(code) + 2);
- } else
- eparams->varspc = NULL;
-
- code = *state->pc++;
-
- eparams->type = wc_code(code);
- eparams->postassigns = 0;
-
- /* It would be nice if we could use EC_DUPTOK instead of EC_DUP here.
- * But for that we would need to check/change all builtins so that
- * they don't modify their argument strings. */
- switch (eparams->type) {
- case WC_SIMPLE:
- eparams->args = ecgetlist(state, WC_SIMPLE_ARGC(code), EC_DUP,
- &eparams->htok);
- eparams->assignspc = NULL;
- break;
-
- case WC_TYPESET:
- eparams->args = ecgetlist(state, WC_TYPESET_ARGC(code), EC_DUP,
- &eparams->htok);
- eparams->postassigns = *state->pc++;
- eparams->assignspc = state->pc;
- for (i = 0; i < eparams->postassigns; i++) {
- code = *state->pc;
- DPUTS(wc_code(code) != WC_ASSIGN,
- "BUG: miscounted typeset assignments");
- state->pc += (WC_ASSIGN_TYPE(code) == WC_ASSIGN_SCALAR ?
- 3 : WC_ASSIGN_NUM(code) + 2);
- }
- break;
-
- default:
- eparams->args = NULL;
- eparams->assignspc = NULL;
- eparams->htok = 0;
- break;
- }
-}
-
-/*
- * Transfer the first node of args to preargs, performing
- * prefork expansion on the way if necessary.
- */
-static void execcmd_getargs(LinkList preargs, LinkList args, int expand)
-{
- if (!firstnode(args)) {
- return;
- } else if (expand) {
- local_list0(svl);
- init_list0(svl);
- /* not init_list1, as we need real nodes */
- addlinknode(&svl, uremnode(args, firstnode(args)));
- /* Analysing commands, so vanilla options to prefork */
- prefork(&svl, 0, NULL);
- joinlists(preargs, &svl);
- } else {
- addlinknode(preargs, uremnode(args, firstnode(args)));
- }
-}
-
-/**/
-static int
-execcmd_fork(Estate state, int how, int type, Wordcode varspc,
- LinkList *filelistp, char *text, int oautocont,
- int close_if_forked)
-{
- pid_t pid;
- int synch[2], flags;
- char dummy;
- struct timeval bgtime;
-
- child_block();
-
- if (pipe(synch) < 0) {
- zerr("pipe failed: %e", errno);
- return -1;
- } else if ((pid = zfork(&bgtime)) == -1) {
- close(synch[0]);
- close(synch[1]);
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- return -1;
- }
- if (pid) {
- close(synch[1]);
- read_loop(synch[0], &dummy, 1);
- close(synch[0]);
- if (how & Z_ASYNC) {
- lastpid = (zlong) pid;
- } else if (!jobtab[thisjob].stty_in_env && varspc) {
- /* search for STTY=... */
- Wordcode p = varspc;
- wordcode ac;
-
- while (wc_code(ac = *p) == WC_ASSIGN) {
- if (!strcmp(ecrawstr(state->prog, p + 1, NULL), "STTY")) {
- jobtab[thisjob].stty_in_env = 1;
- break;
- }
- p += (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR ?
- 3 : WC_ASSIGN_NUM(ac) + 2);
- }
- }
- addproc(pid, text, 0, &bgtime);
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- pipecleanfilelist(jobtab[thisjob].filelist, 1);
- return pid;
- }
-
- /* pid == 0 */
- close(synch[0]);
- flags = ((how & Z_ASYNC) ? ESUB_ASYNC : 0) | ESUB_PGRP;
- if ((type != WC_SUBSH) && !(how & Z_ASYNC))
- flags |= ESUB_KEEPTRAP;
- if (type == WC_SUBSH && !(how & Z_ASYNC))
- flags |= ESUB_JOB_CONTROL;
- *filelistp = jobtab[thisjob].filelist;
- entersubsh(flags);
- close(synch[1]);
- zclose(close_if_forked);
-
- if (sigtrapped[SIGINT] & ZSIG_IGNORED)
- holdintr();
- /*
- * EXIT traps shouldn't be called even if we forked to run
- * shell code as this isn't the main shell.
- */
- sigtrapped[SIGEXIT] = 0;
-#ifdef HAVE_NICE
- /* Check if we should run background jobs at a lower priority. */
- if ((how & Z_ASYNC) && isset(BGNICE))
- if (nice(5) < 0)
- zwarn("nice(5) failed: %e", errno);
-#endif /* HAVE_NICE */
-
- return 0;
-}
-
-/*
- * Execute a command at the lowest level of the hierarchy.
- */
-
-/**/
-static void
-execcmd_exec(Estate state, Execcmd_params eparams,
- int input, int output, int how, int last1, int close_if_forked)
-{
- HashNode hn = NULL;
- LinkList filelist = NULL;
- LinkNode node;
- Redir fn;
- struct multio *mfds[10];
- char *text;
- int save[10];
- int fil, dfil, is_cursh, do_exec = 0, redir_err = 0, i;
- int nullexec = 0, magic_assign = 0, forked = 0, old_lastval;
- int is_shfunc = 0, is_builtin = 0, is_exec = 0, use_defpath = 0;
- /* Various flags to the command. */
- int cflags = 0, orig_cflags = 0, checked = 0, oautocont = -1;
- FILE *oxtrerr = xtrerr, *newxtrerr = NULL;
- /*
- * Retrieve parameters for quick reference (they are unique
- * to us so we can modify the structure if we want).
- */
- LinkList args = eparams->args;
- LinkList redir = eparams->redir;
- Wordcode varspc = eparams->varspc;
- int type = eparams->type;
- /*
- * preargs comes from expanding the head of the args list
- * in order to check for prefix commands.
- */
- LinkList preargs;
-
- doneps4 = 0;
-
- /*
- * If assignment but no command get the status from variable
- * assignment.
- */
- old_lastval = lastval;
- if (!args && varspc)
- lastval = errflag ? errflag : cmdoutval;
- /*
- * If there are arguments, we should reset the status for the
- * command before execution---unless we are using the result of a
- * command substitution, which will be indicated by setting
- * use_cmdoutval to 1. We haven't kicked those off yet, so
- * there's no race.
- */
- use_cmdoutval = !args;
-
- for (i = 0; i < 10; i++) {
- save[i] = -2;
- mfds[i] = NULL;
- }
-
- /* If the command begins with `%', then assume it is a *
- * reference to a job in the job table. */
- if ((type == WC_SIMPLE || type == WC_TYPESET) && args && nonempty(args) &&
- *(char *)peekfirst(args) == '%') {
- if (how & Z_DISOWN) {
- oautocont = opts[AUTOCONTINUE];
- opts[AUTOCONTINUE] = 1;
- }
- pushnode(args, dupstring((how & Z_DISOWN)
- ? "disown" : (how & Z_ASYNC) ? "bg" : "fg"));
- how = Z_SYNC;
- }
-
- /* If AUTORESUME is set, the command is SIMPLE, and doesn't have *
- * any redirections, then check if it matches as a prefix of a *
- * job currently in the job table. If it does, then we treat it *
- * as a command to resume this job. */
- if (isset(AUTORESUME) && type == WC_SIMPLE && (how & Z_SYNC) &&
- args && nonempty(args) && (!redir || empty(redir)) && !input &&
- !nextnode(firstnode(args))) {
- if (unset(NOTIFY))
- scanjobs();
- if (findjobnam(peekfirst(args)) != -1)
- pushnode(args, dupstring("fg"));
- }
-
- if ((how & Z_ASYNC) || output) {
- /*
- * If running in the background, or not the last command in a
- * pipeline, we don't need any of the rest of this function to
- * affect the state in the main shell, so fork immediately.
- *
- * In other cases we may need to process the command line
- * a bit further before we make the decision.
- */
- text = getjobtext(state->prog, eparams->beg);
- switch (execcmd_fork(state, how, type, varspc, &filelist,
- text, oautocont, close_if_forked)) {
- case -1:
- goto fatal;
- case 0:
- break;
- default:
- return;
- }
- last1 = forked = 1;
- } else
- text = NULL;
-
- /* Check if it's a builtin needing automatic MAGIC_EQUALS_SUBST *
- * handling. Things like typeset need this. We can't detect the *
- * command if it contains some tokens (e.g. x=ex; ${x}port), so this *
- * only works in simple cases. has_token() is called to make sure *
- * this really is a simple case. */
- if ((type == WC_SIMPLE || type == WC_TYPESET) && args) {
- /*
- * preargs contains args that have been expanded by prefork.
- * Running execcmd_getargs() causes any argument available
- * in args to be exanded where necessary and transferred to
- * preargs. We call execcmd_getargs() every time we need to
- * analyse an argument not available in preargs, though there is
- * no guarantee a further argument will be available.
- */
- preargs = newlinklist();
- execcmd_getargs(preargs, args, eparams->htok);
- while (nonempty(preargs)) {
- char *cmdarg = (char *) peekfirst(preargs);
- checked = !has_token(cmdarg);
- if (!checked)
- break;
- if (type == WC_TYPESET &&
- (hn = builtintab->getnode2(builtintab, cmdarg))) {
- /*
- * If reserved word for typeset command found (and so
- * enabled), use regardless of whether builtin is
- * enabled as we share the implementation.
- *
- * Reserved words take precedence over shell functions.
- */
- checked = 1;
- } else if (isset(POSIXBUILTINS) && (cflags & BINF_EXEC)) {
- /*
- * POSIX doesn't allow "exec" to operate on builtins
- * or shell functions.
- */
- break;
- } else {
- if (!(cflags & (BINF_BUILTIN | BINF_COMMAND)) &&
- (hn = shfunctab->getnode(shfunctab, cmdarg))) {
- is_shfunc = 1;
- break;
- }
- if (!(hn = builtintab->getnode(builtintab, cmdarg))) {
- checked = !(cflags & BINF_BUILTIN);
- break;
- }
- }
- orig_cflags |= cflags;
- cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
- cflags |= hn->flags;
- if (!(hn->flags & BINF_PREFIX)) {
- is_builtin = 1;
-
- /* autoload the builtin if necessary */
- if (!(hn = resolvebuiltin(cmdarg, hn))) {
- if (forked)
- _exit(lastval);
- return;
- }
- if (type != WC_TYPESET)
- magic_assign = (hn->flags & BINF_MAGICEQUALS);
- break;
- }
- checked = 0;
- /*
- * We usually don't need the argument containing the
- * precommand modifier itself. Exception: when "command"
- * will implemented by a call to "whence", in which case
- * we'll simply re-insert the argument.
- */
- uremnode(preargs, firstnode(preargs));
- if (!firstnode(preargs)) {
- execcmd_getargs(preargs, args, eparams->htok);
- if (!firstnode(preargs))
- break;
- }
- if ((cflags & BINF_COMMAND)) {
- /*
- * Check for options to "command".
- * If just -p, this is handled here: use the default
- * path to execute.
- * If -v or -V, possibly with -p, dispatch to bin_whence
- * but with flag to indicate special handling of -p.
- * Otherwise, just leave marked as BINF_COMMAND
- * modifier with no additional action.
- */
- LinkNode argnode, oldnode, pnode = NULL;
- char *argdata, *cmdopt;
- int has_p = 0, has_vV = 0, has_other = 0;
- argnode = firstnode(preargs);
- argdata = (char *) getdata(argnode);
- while (IS_DASH(*argdata)) {
- /* Just to be definite, stop on single "-", too, */
- if (!argdata[1] ||
- (IS_DASH(argdata[1]) && !argdata[2]))
- break;
- for (cmdopt = argdata+1; *cmdopt; cmdopt++) {
- switch (*cmdopt) {
- case 'p':
- /*
- * If we've got this multiple times (command
- * -p -p) we'll treat the second -p as a
- * command because we only remove one below.
- * Don't think that's a big issue, and it's
- * also traditional behaviour.
- */
- has_p = 1;
- pnode = argnode;
- break;
- case 'v':
- case 'V':
- has_vV = 1;
- break;
- default:
- has_other = 1;
- break;
- }
- }
- if (has_other) {
- /* Don't know how to handle this, so don't */
- has_p = has_vV = 0;
- break;
- }
-
- oldnode = argnode;
- argnode = nextnode(argnode);
- if (!argnode) {
- execcmd_getargs(preargs, args, eparams->htok);
- if (!(argnode = nextnode(oldnode)))
- break;
- }
- argdata = (char *) getdata(argnode);
- }
- if (has_vV) {
- /*
- * Leave everything alone, dispatch to whence.
- * We need to put the name back in the list.
- */
- pushnode(preargs, "command");
- hn = &commandbn.node;
- is_builtin = 1;
- break;
- } else if (has_p) {
- /* Use default path */
- use_defpath = 1;
- /*
- * We don't need this node as we're not treating
- * "command" as a builtin this time.
- */
- if (pnode)
- uremnode(preargs, pnode);
- }
- /*
- * Else just any trailing
- * end-of-options marker. This can only occur
- * if we just had -p or something including more
- * than just -p, -v and -V, in which case we behave
- * as if this is command [non-option-stuff]. This
- * isn't a good place for standard option handling.
- */
- if (IS_DASH(argdata[0]) && IS_DASH(argdata[1]) && !argdata[2])
- uremnode(preargs, argnode);
- } else if (cflags & BINF_EXEC) {
- /*
- * Check for compatibility options to exec builtin.
- * It would be nice to do these more generically,
- * but currently we don't have a mechanism for
- * precommand modifiers.
- */
- LinkNode argnode = firstnode(preargs), oldnode;
- char *argdata = (char *) getdata(argnode);
- char *cmdopt, *exec_argv0 = NULL;
- /*
- * Careful here: we want to make sure a final dash
- * is passed through in order that it still behaves
- * as a precommand modifier (zsh equivalent of -l).
- * It has to be last, but I think that's OK since
- * people aren't likely to mix the option style
- * with the zsh style.
- */
- while (argdata && IS_DASH(*argdata) && strlen(argdata) >= 2) {
- oldnode = argnode;
- argnode = nextnode(oldnode);
- if (!argnode) {
- execcmd_getargs(preargs, args, eparams->htok);
- argnode = nextnode(oldnode);
- }
- if (!argnode) {
- zerr("exec requires a command to execute");
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- goto done;
- }
- uremnode(preargs, oldnode);
- if (IS_DASH(argdata[0]) && IS_DASH(argdata[1]) && !argdata[2])
- break;
- for (cmdopt = &argdata[1]; *cmdopt; ++cmdopt) {
- switch (*cmdopt) {
- case 'a':
- /* argument is ARGV0 string */
- if (cmdopt[1]) {
- exec_argv0 = cmdopt+1;
- /* position on last non-NULL character */
- cmdopt += strlen(cmdopt+1);
- } else {
- if (!argnode) {
- zerr("exec requires a command to execute");
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- goto done;
- }
- if (!nextnode(argnode))
- execcmd_getargs(preargs, args,
- eparams->htok);
- if (!nextnode(argnode)) {
- zerr("exec flag -a requires a parameter");
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- goto done;
- }
- exec_argv0 = (char *) getdata(argnode);
- oldnode = argnode;
- argnode = nextnode(argnode);
- uremnode(args, oldnode);
- }
- break;
- case 'c':
- cflags |= BINF_CLEARENV;
- break;
- case 'l':
- cflags |= BINF_DASH;
- break;
- default:
- zerr("unknown exec flag -%c", *cmdopt);
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- if (forked)
- _exit(lastval);
- return;
- }
- }
- if (!argnode)
- break;
- argdata = (char *) getdata(argnode);
- }
- if (exec_argv0) {
- char *str, *s;
- exec_argv0 = dupstring(exec_argv0);
- remnulargs(exec_argv0);
- untokenize(exec_argv0);
- size_t sz = strlen(exec_argv0);
- str = s = zalloc(5 + 1 + sz + 1);
- strcpy(s, "ARGV0=");
- s+=6;
- strcpy(s, exec_argv0);
- zputenv(str);
- }
- }
- hn = NULL;
- if ((cflags & BINF_COMMAND) && unset(POSIXBUILTINS))
- break;
- if (!nonempty(preargs))
- execcmd_getargs(preargs, args, eparams->htok);
- }
- } else
- preargs = NULL;
-
- /* if we get this far, it is OK to pay attention to lastval again */
- if (noerrexit & NOERREXIT_UNTIL_EXEC)
- noerrexit = 0;
-
- /* Do prefork substitutions.
- *
- * Decide if we need "magic" handling of ~'s etc. in
- * assignment-like arguments.
- * - If magic_assign is set, we are using a builtin of the
- * tyepset family, but did not recognise this as a keyword,
- * so need guess-o-matic behaviour.
- * - Otherwise, if we did recognise the keyword, we never need
- * guess-o-matic behaviour as the argument was properly parsed
- * as such.
- * - Otherwise, use the behaviour specified by the MAGIC_EQUAL_SUBST
- * option.
- */
- esprefork = (magic_assign ||
- (isset(MAGICEQUALSUBST) && type != WC_TYPESET)) ?
- PREFORK_TYPESET : 0;
-
- if (args) {
- if (eparams->htok)
- prefork(args, esprefork, NULL);
- if (preargs)
- args = joinlists(preargs, args);
- }
-
- if (type == WC_SIMPLE || type == WC_TYPESET) {
- int unglobbed = 0;
-
- for (;;) {
- char *cmdarg;
-
- if (!(cflags & BINF_NOGLOB))
- while (!checked && !errflag && args && nonempty(args) &&
- has_token((char *) peekfirst(args)))
- zglob(args, firstnode(args), 0);
- else if (!unglobbed) {
- for (node = firstnode(args); node; incnode(node))
- untokenize((char *) getdata(node));
- unglobbed = 1;
- }
-
- /* Current shell should not fork unless the *
- * exec occurs at the end of a pipeline. */
- if ((cflags & BINF_EXEC) && last1)
- do_exec = 1;
-
- /* Empty command */
- if (!args || empty(args)) {
- if (redir && nonempty(redir)) {
- if (do_exec) {
- /* Was this "exec < foobar"? */
- nullexec = 1;
- break;
- } else if (varspc) {
- nullexec = 2;
- break;
- } else if (!nullcmd || !*nullcmd || opts[CSHNULLCMD] ||
- (cflags & BINF_PREFIX)) {
- zerr("redirection with no command");
- lastval = 1;
- errflag |= ERRFLAG_ERROR;
- if (forked)
- _exit(lastval);
- return;
- } else if (!nullcmd || !*nullcmd || opts[SHNULLCMD]) {
- if (!args)
- args = newlinklist();
- addlinknode(args, dupstring(":"));
- } else if (readnullcmd && *readnullcmd &&
- ((Redir) peekfirst(redir))->type == REDIR_READ &&
- !nextnode(firstnode(redir))) {
- if (!args)
- args = newlinklist();
- addlinknode(args, dupstring(readnullcmd));
- } else {
- if (!args)
- args = newlinklist();
- addlinknode(args, dupstring(nullcmd));
- }
- } else if ((cflags & BINF_PREFIX) && (cflags & BINF_COMMAND)) {
- lastval = 0;
- if (forked)
- _exit(lastval);
- return;
- } else {
- /*
- * No arguments. Reset the status if there were
- * arguments before and no command substitution
- * has provided a status.
- */
- if (badcshglob == 1) {
- zerr("no match");
- lastval = 1;
- if (forked)
- _exit(lastval);
- return;
- }
- cmdoutval = use_cmdoutval ? lastval : 0;
- if (varspc) {
- /* Make sure $? is still correct for assignment */
- lastval = old_lastval;
- addvars(state, varspc, 0);
- }
- if (errflag)
- lastval = 1;
- else
- lastval = cmdoutval;
- if (isset(XTRACE)) {
- fputc('\n', xtrerr);
- fflush(xtrerr);
- }
- if (forked)
- _exit(lastval);
- return;
- }
- } else if (isset(RESTRICTED) && (cflags & BINF_EXEC) && do_exec) {
- zerrnam("exec", "%s: restricted",
- (char *) getdata(firstnode(args)));
- lastval = 1;
- if (forked)
- _exit(lastval);
- return;
- }
-
- /*
- * Quit looking for a command if:
- * - there was an error; or
- * - we checked the simple cases needing MAGIC_EQUAL_SUBST; or
- * - we know we already found a builtin (because either:
- * - we loaded a builtin from a module, or
- * - we have determined there are options which would
- * require us to use the "command" builtin); or
- * - we aren't using POSIX and so BINF_COMMAND indicates a zsh
- * precommand modifier is being used in place of the
- * builtin
- * - we are using POSIX and this is an EXEC, so we can't
- * execute a builtin or function.
- */
- if (errflag || checked || is_builtin ||
- (isset(POSIXBUILTINS) ?
- (cflags & BINF_EXEC) : (cflags & BINF_COMMAND)))
- break;
-
- cmdarg = (char *) peekfirst(args);
- if (!(cflags & (BINF_BUILTIN | BINF_COMMAND)) &&
- (hn = shfunctab->getnode(shfunctab, cmdarg))) {
- is_shfunc = 1;
- break;
- }
- if (!(hn = builtintab->getnode(builtintab, cmdarg))) {
- if (cflags & BINF_BUILTIN) {
- zwarn("no such builtin: %s", cmdarg);
- lastval = 1;
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- if (forked)
- _exit(lastval);
- return;
- }
- break;
- }
- if (!(hn->flags & BINF_PREFIX)) {
- is_builtin = 1;
-
- /* autoload the builtin if necessary */
- if (!(hn = resolvebuiltin(cmdarg, hn))) {
- if (forked)
- _exit(lastval);
- return;
- }
- break;
- }
- cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
- cflags |= hn->flags;
- uremnode(args, firstnode(args));
- hn = NULL;
- }
- }
-
- if (errflag) {
- if (!lastval)
- lastval = 1;
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- if (forked)
- _exit(lastval);
- return;
- }
-
- /* Get the text associated with this command. */
- if (!text &&
- (!sfcontext && (jobbing || (how & Z_TIMED))))
- text = getjobtext(state->prog, eparams->beg);
-
- /*
- * Set up special parameter $_
- * For execfuncdef we may need to take account of an
- * anonymous function with arguments.
- */
- if (type != WC_FUNCDEF)
- setunderscore((args && nonempty(args)) ?
- ((char *) getdata(lastnode(args))) : "");
-
- /* Warn about "rm *" */
- if (type == WC_SIMPLE && interact && unset(RMSTARSILENT) &&
- isset(SHINSTDIN) && args && nonempty(args) &&
- nextnode(firstnode(args)) && !strcmp(peekfirst(args), "rm")) {
- LinkNode node, next;
-
- for (node = nextnode(firstnode(args)); node && !errflag; node = next) {
- char *s = (char *) getdata(node);
- int l = strlen(s);
-
- next = nextnode(node);
- if (s[0] == Star && !s[1]) {
- if (!checkrmall(pwd)) {
- errflag |= ERRFLAG_ERROR;
- break;
- }
- } else if (l >= 2 && s[l - 2] == '/' && s[l - 1] == Star) {
- char t = s[l - 2];
- int rmall;
-
- s[l - 2] = 0;
- rmall = checkrmall(s);
- s[l - 2] = t;
-
- if (!rmall) {
- errflag |= ERRFLAG_ERROR;
- break;
- }
- }
- }
- }
-
- if (type == WC_FUNCDEF) {
- /*
- * The first word of a function definition is a list of
- * names. If this is empty, we're doing an anonymous function:
- * in that case redirections are handled normally.
- * If not, it's a function definition: then we don't do
- * redirections here but pass in the list of redirections to
- * be stored for recall with the function.
- */
- if (*state->pc != 0) {
- /* Nonymous, don't do redirections here */
- redir = NULL;
- }
- } else if (is_shfunc || type == WC_AUTOFN) {
- Shfunc shf;
- if (is_shfunc)
- shf = (Shfunc)hn;
- else {
- shf = loadautofn(state->prog->shf, 1, 0, 0);
- if (shf)
- state->prog->shf = shf;
- else {
- /*
- * This doesn't set errflag, so just return now.
- */
- lastval = 1;
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- if (forked)
- _exit(lastval);
- return;
- }
- }
- /*
- * A function definition may have a list of additional
- * redirections to apply, so retrieve it.
- */
- if (shf->redir) {
- struct estate s;
- LinkList redir2;
-
- s.prog = shf->redir;
- s.pc = shf->redir->prog;
- s.strs = shf->redir->strs;
- redir2 = ecgetredirs(&s);
- if (!redir)
- redir = redir2;
- else {
- while (nonempty(redir2))
- addlinknode(redir, ugetnode(redir2));
- }
- }
- }
-
- if (errflag) {
- lastval = 1;
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- if (forked)
- _exit(lastval);
- return;
- }
-
- if ((type == WC_SIMPLE || type == WC_TYPESET) && !nullexec) {
- char *s;
- char trycd = (isset(AUTOCD) && isset(SHINSTDIN) &&
- (!redir || empty(redir)) && args && !empty(args) &&
- !nextnode(firstnode(args)) && *(char *)peekfirst(args));
-
- DPUTS((!args || empty(args)), "BUG: empty(args) in exec.c");
- if (!hn) {
- /* Resolve external commands */
- char *cmdarg = (char *) peekfirst(args);
- char **checkpath = pathchecked;
- int dohashcmd = isset(HASHCMDS);
-
- hn = cmdnamtab->getnode(cmdnamtab, cmdarg);
- if (hn && trycd && !isreallycom((Cmdnam)hn)) {
- if (!(((Cmdnam)hn)->node.flags & HASHED)) {
- checkpath = path;
- dohashcmd = 1;
- }
- cmdnamtab->removenode(cmdnamtab, cmdarg);
- cmdnamtab->freenode(hn);
- hn = NULL;
- }
- if (!hn && dohashcmd && strcmp(cmdarg, "..")) {
- for (s = cmdarg; *s && *s != '/'; s++);
- if (!*s)
- hn = (HashNode) hashcmd(cmdarg, checkpath);
- }
- }
-
- /* If no command found yet, see if it *
- * is a directory we should AUTOCD to. */
- if (!hn && trycd && (s = cancd(peekfirst(args)))) {
- peekfirst(args) = (void *) s;
- pushnode(args, dupstring("--"));
- pushnode(args, dupstring("cd"));
- if ((hn = builtintab->getnode(builtintab, "cd")))
- is_builtin = 1;
- }
- }
-
- /* This is nonzero if the command is a current shell procedure? */
- is_cursh = (is_builtin || is_shfunc || nullexec || type >= WC_CURSH);
-
- /**************************************************************************
- * Do we need to fork? We need to fork if: *
- * 1) The command is supposed to run in the background. This *
- * case is now handled above (forked = 1 here). (or) *
- * 2) There is no `exec' flag, and either: *
- * a) This is a builtin or shell function with output piped somewhere. *
- * b) This is an external command and we can't do a `fake exec'. *
- * *
- * A `fake exec' is possible if we have all the following conditions: *
- * 1) last1 flag is 1. This indicates that the current shell will not *
- * be needed after the current command. This is typically the case *
- * when the command is the last stage in a subshell, or is the *
- * last command after the option `-c'. *
- * 2) We don't have any traps set. *
- * 3) We don't have any files to delete. *
- * *
- * The condition above for a `fake exec' will also work for a current *
- * shell command such as a builtin, but doesn't really buy us anything *
- * (doesn't save us a process), since it is already running in the *
- * current shell. *
- **************************************************************************/
-
- if (!forked) {
- if (!do_exec &&
- (((is_builtin || is_shfunc) && output) ||
- (!is_cursh && (last1 != 1 || nsigtrapped || havefiles() ||
- fdtable_flocks)))) {
- switch (execcmd_fork(state, how, type, varspc, &filelist,
- text, oautocont, close_if_forked)) {
- case -1:
- goto fatal;
- case 0:
- break;
- default:
- return;
- }
- forked = 1;
- } else if (is_cursh) {
- /* This is a current shell procedure that didn't need to fork. *
- * This includes current shell procedures that are being exec'ed, *
- * as well as null execs. */
- jobtab[thisjob].stat |= STAT_CURSH;
- if (!jobtab[thisjob].procs)
- jobtab[thisjob].stat |= STAT_NOPRINT;
- if (is_builtin)
- jobtab[thisjob].stat |= STAT_BUILTIN;
- } else {
- /* This is an exec (real or fake) for an external command. *
- * Note that any form of exec means that the subshell is fake *
- * (but we may be in a subshell already). */
- is_exec = 1;
- /*
- * If we are in a subshell environment anyway, say we're forked,
- * even if we're actually not forked because we know the
- * subshell is exiting. This ensures SHLVL reflects the current
- * shell, and also optimises out any save/restore we'd need to
- * do if we were returning to the main shell.
- */
- if (type == WC_SUBSH)
- forked = 1;
- }
- }
-
- if ((esglob = !(cflags & BINF_NOGLOB)) && args && eparams->htok) {
- LinkList oargs = args;
- globlist(args, 0);
- args = oargs;
- }
- if (errflag) {
- lastval = 1;
- goto err;
- }
-
- /* Make a copy of stderr for xtrace output before redirecting */
- fflush(xtrerr);
- if (isset(XTRACE) && xtrerr == stderr &&
- (type < WC_SUBSH || type == WC_TIMED)) {
- if ((newxtrerr = fdopen(movefd(dup(fileno(stderr))), "w"))) {
- xtrerr = newxtrerr;
- fdtable[fileno(xtrerr)] = FDT_XTRACE;
- }
- }
-
- /* Add pipeline input/output to mnodes */
- if (input)
- addfd(forked, save, mfds, 0, input, 0, NULL);
- if (output)
- addfd(forked, save, mfds, 1, output, 1, NULL);
-
- /* Do process substitutions */
- if (redir)
- spawnpipes(redir, nullexec);
-
- /* Do io redirections */
- while (redir && nonempty(redir)) {
- fn = (Redir) ugetnode(redir);
-
- DPUTS(fn->type == REDIR_HEREDOC || fn->type == REDIR_HEREDOCDASH,
- "BUG: unexpanded here document");
- if (fn->type == REDIR_INPIPE) {
- if (!checkclobberparam(fn) || fn->fd2 == -1) {
- if (fn->fd2 != -1)
- zclose(fn->fd2);
- closemnodes(mfds);
- fixfds(save);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fn->fd2, 0, fn->varid);
- } else if (fn->type == REDIR_OUTPIPE) {
- if (!checkclobberparam(fn) || fn->fd2 == -1) {
- if (fn->fd2 != -1)
- zclose(fn->fd2);
- closemnodes(mfds);
- fixfds(save);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fn->fd2, 1, fn->varid);
- } else {
- int closed;
- if (fn->type != REDIR_HERESTR && xpandredir(fn, redir))
- continue;
- if (errflag) {
- closemnodes(mfds);
- fixfds(save);
- execerr();
- }
- if (isset(RESTRICTED) && IS_WRITE_FILE(fn->type)) {
- zwarn("writing redirection not allowed in restricted mode");
- execerr();
- }
- if (unset(EXECOPT))
- continue;
- switch(fn->type) {
- case REDIR_HERESTR:
- if (!checkclobberparam(fn))
- fil = -1;
- else
- fil = getherestr(fn);
- if (fil == -1) {
- if (errno && errno != EINTR)
- zwarn("can't create temp file for here document: %e",
- errno);
- closemnodes(mfds);
- fixfds(save);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fil, 0, fn->varid);
- break;
- case REDIR_READ:
- case REDIR_READWRITE:
- if (!checkclobberparam(fn))
- fil = -1;
- else if (fn->type == REDIR_READ)
- fil = open(unmeta(fn->name), O_RDONLY | O_NOCTTY);
- else
- fil = open(unmeta(fn->name),
- O_RDWR | O_CREAT | O_NOCTTY, 0666);
- if (fil == -1) {
- closemnodes(mfds);
- fixfds(save);
- if (errno != EINTR)
- zwarn("%e: %s", errno, fn->name);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fil, 0, fn->varid);
- /* If this is 'exec < file', read from stdin, *
- * not terminal, unless `file' is a terminal. */
- if (nullexec == 1 && fn->fd1 == 0 &&
- isset(SHINSTDIN) && interact && !zleactive)
- init_io(NULL);
- break;
- case REDIR_CLOSE:
- if (fn->varid) {
- char *s = fn->varid, *t;
- struct value vbuf;
- Value v;
- int bad = 0;
-
- if (!(v = getvalue(&vbuf, &s, 0))) {
- bad = 1;
- } else if (v->pm->node.flags & PM_READONLY) {
- bad = 2;
- } else {
- s = getstrvalue(v);
- if (errflag)
- bad = 1;
- else {
- fn->fd1 = zstrtol(s, &t, 0);
- if (s == t)
- bad = 1;
- else if (*t) {
- /* Check for base#number format */
- if (*t == '#' && *s != '0')
- fn->fd1 = zstrtol(s = t+1, &t, fn->fd1);
- if (s == t || *t)
- bad = 1;
- }
- if (!bad && fn->fd1 <= max_zsh_fd) {
- if (fn->fd1 >= 10 &&
- (fdtable[fn->fd1] & FDT_TYPE_MASK) ==
- FDT_INTERNAL)
- bad = 3;
- }
- }
- }
- if (bad) {
- const char *bad_msg[] = {
- "parameter %s does not contain a file descriptor",
- "can't close file descriptor from readonly parameter %s",
- "file descriptor %d used by shell, not closed"
- };
- if (bad > 2)
- zwarn(bad_msg[bad-1], fn->fd1);
- else
- zwarn(bad_msg[bad-1], fn->varid);
- execerr();
- }
- }
- /*
- * Note we may attempt to close an fd beyond max_zsh_fd:
- * OK as long as we never look in fdtable for it.
- */
- closed = 0;
- if (!forked && fn->fd1 < 10 && save[fn->fd1] == -2) {
- save[fn->fd1] = movefd(fn->fd1);
- if (save[fn->fd1] >= 0) {
- /*
- * The original fd is now closed, we don't need
- * to do it below.
- */
- closed = 1;
- }
- }
- if (fn->fd1 < 10)
- closemn(mfds, fn->fd1, REDIR_CLOSE);
- /*
- * Only report failures to close file descriptors
- * if they're under user control as we don't know
- * what the previous status of others was.
- */
- if (!closed && zclose(fn->fd1) < 0 && fn->varid) {
- zwarn("failed to close file descriptor %d: %e",
- fn->fd1, errno);
- }
- break;
- case REDIR_MERGEIN:
- case REDIR_MERGEOUT:
- if (fn->fd2 < 10)
- closemn(mfds, fn->fd2, fn->type);
- if (!checkclobberparam(fn))
- fil = -1;
- else if (fn->fd2 > 9 &&
- /*
- * If the requested fd is > max_zsh_fd,
- * the shell doesn't know about it.
- * Just assume the user knows what they're
- * doing.
- */
- (fn->fd2 <= max_zsh_fd &&
- ((fdtable[fn->fd2] != FDT_UNUSED &&
- fdtable[fn->fd2] != FDT_EXTERNAL) ||
- fn->fd2 == coprocin ||
- fn->fd2 == coprocout))) {
- fil = -1;
- errno = EBADF;
- } else {
- int fd = fn->fd2;
- if(fd == -2)
- fd = (fn->type == REDIR_MERGEOUT) ? coprocout : coprocin;
- fil = movefd(dup(fd));
- }
- if (fil == -1) {
- char fdstr[DIGBUFSIZE];
-
- closemnodes(mfds);
- fixfds(save);
- if (fn->fd2 != -2)
- sprintf(fdstr, "%d", fn->fd2);
- if (errno)
- zwarn("%s: %e", fn->fd2 == -2 ? "coprocess" : fdstr,
- errno);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fil,
- fn->type == REDIR_MERGEOUT, fn->varid);
- break;
- default:
- if (!checkclobberparam(fn))
- fil = -1;
- else if (IS_APPEND_REDIR(fn->type))
- fil = open(unmeta(fn->name),
- ((unset(CLOBBER) && unset(APPENDCREATE)) &&
- !IS_CLOBBER_REDIR(fn->type)) ?
- O_WRONLY | O_APPEND | O_NOCTTY :
- O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0666);
- else
- fil = clobber_open(fn);
- if(fil != -1 && IS_ERROR_REDIR(fn->type))
- dfil = movefd(dup(fil));
- else
- dfil = 0;
- if (fil == -1 || dfil == -1) {
- if(fil != -1)
- close(fil);
- closemnodes(mfds);
- fixfds(save);
- if (errno && errno != EINTR)
- zwarn("%e: %s", errno, fn->name);
- execerr();
- }
- addfd(forked, save, mfds, fn->fd1, fil, 1, fn->varid);
- if(IS_ERROR_REDIR(fn->type))
- addfd(forked, save, mfds, 2, dfil, 1, NULL);
- break;
- }
- /* May be error in addfd due to setting parameter. */
- if (errflag) {
- closemnodes(mfds);
- fixfds(save);
- execerr();
- }
- }
- }
-
- /* We are done with redirection. close the mnodes, *
- * spawning tee/cat processes as necessary. */
- for (i = 0; i < 10; i++)
- if (mfds[i] && mfds[i]->ct >= 2)
- closemn(mfds, i, REDIR_CLOSE);
-
- if (nullexec) {
- /*
- * If nullexec is 2, we have variables to add with the redirections
- * in place. If nullexec is 1, we may have variables but they
- * need the standard restore logic.
- */
- if (varspc) {
- LinkList restorelist = 0, removelist = 0;
- if (!isset(POSIXBUILTINS) && nullexec != 2)
- save_params(state, varspc, &restorelist, &removelist);
- addvars(state, varspc, 0);
- if (restorelist)
- restore_params(restorelist, removelist);
- }
- lastval = errflag ? errflag : cmdoutval;
- if (nullexec == 1) {
- /*
- * If nullexec is 1 we specifically *don't* restore the original
- * fd's before returning.
- */
- for (i = 0; i < 10; i++)
- if (save[i] != -2)
- zclose(save[i]);
- goto done;
- }
- if (isset(XTRACE)) {
- fputc('\n', xtrerr);
- fflush(xtrerr);
- }
- } else if (isset(EXECOPT) && !errflag) {
- int q = queue_signal_level();
- /*
- * We delay the entersubsh() to here when we are exec'ing
- * the current shell (including a fake exec to run a builtin then
- * exit) in case there is an error return.
- */
- if (is_exec) {
- int flags = ((how & Z_ASYNC) ? ESUB_ASYNC : 0) |
- ESUB_PGRP | ESUB_FAKE;
- if (type != WC_SUBSH)
- flags |= ESUB_KEEPTRAP;
- if ((do_exec || (type >= WC_CURSH && last1 == 1))
- && !forked)
- flags |= ESUB_REVERTPGRP;
- entersubsh(flags);
- }
- if (type == WC_FUNCDEF) {
- Eprog redir_prog;
- if (!redir && wc_code(*eparams->beg) == WC_REDIR) {
- /*
- * We're not using a redirection from the currently
- * parsed environment, which is what we'd do for an
- * anonymous function, but there are redirections we
- * should store with the new function.
- */
- struct estate s;
-
- s.prog = state->prog;
- s.pc = eparams->beg;
- s.strs = state->prog->strs;
-
- /*
- * The copy uses the wordcode parsing area, so save and
- * restore state.
- */
- zcontext_save();
- redir_prog = eccopyredirs(&s);
- zcontext_restore();
- } else
- redir_prog = NULL;
-
- dont_queue_signals();
- lastval = execfuncdef(state, redir_prog);
- restore_queue_signals(q);
- }
- else if (type >= WC_CURSH) {
- if (last1 == 1)
- do_exec = 1;
- dont_queue_signals();
- if (type == WC_AUTOFN) {
- /*
- * We pre-loaded this to get any redirs.
- * So we execuate a simplified function here.
- */
- lastval = execautofn_basic(state, do_exec);
- } else
- lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
- restore_queue_signals(q);
- } else if (is_builtin || is_shfunc) {
- LinkList restorelist = 0, removelist = 0;
- int do_save = 0;
- /* builtin or shell function */
-
- if (!forked) {
- if (isset(POSIXBUILTINS)) {
- /*
- * If it's a function or special builtin --- save
- * if it's got "command" in front.
- * If it's a normal command --- save.
- */
- if (is_shfunc || (hn->flags & (BINF_PSPECIAL|BINF_ASSIGN)))
- do_save = (orig_cflags & BINF_COMMAND);
- else
- do_save = 1;
- } else {
- /*
- * Save if it's got "command" in front or it's
- * not a magic-equals assignment.
- */
- if ((cflags & (BINF_COMMAND|BINF_ASSIGN)) || !magic_assign)
- do_save = 1;
- }
- if (do_save && varspc)
- save_params(state, varspc, &restorelist, &removelist);
- }
- if (varspc) {
- /* Export this if the command is a shell function,
- * but not if it's a builtin.
- */
- int flags = 0;
- if (is_shfunc)
- flags |= ADDVAR_EXPORT;
- if (restorelist)
- flags |= ADDVAR_RESTORE;
-
- addvars(state, varspc, flags);
- if (errflag) {
- if (restorelist)
- restore_params(restorelist, removelist);
- lastval = 1;
- fixfds(save);
- goto done;
- }
- }
-
- if (is_shfunc) {
- /* It's a shell function */
- pipecleanfilelist(filelist, 0);
- execshfunc((Shfunc) hn, args);
- } else {
- /* It's a builtin */
- LinkList assigns = (LinkList)0;
- int postassigns = eparams->postassigns;
- if (forked)
- closem(FDT_INTERNAL, 0);
- if (postassigns) {
- Wordcode opc = state->pc;
- state->pc = eparams->assignspc;
- assigns = newlinklist();
- while (postassigns--) {
- int htok;
- wordcode ac = *state->pc++;
- char *name = ecgetstr(state, EC_DUPTOK, &htok);
- Asgment asg;
- local_list1(svl);
-
- DPUTS(wc_code(ac) != WC_ASSIGN,
- "BUG: bad assignment list for typeset");
- if (htok) {
- init_list1(svl, name);
- if (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR &&
- WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC) {
- char *data;
- /*
- * Special case: this is a name only, so
- * it's not required to be a single
- * expansion. Furthermore, for
- * consistency with the builtin
- * interface, it may expand into
- * scalar assignments:
- * ass=(one=two three=four)
- * typeset a=b $ass
- */
- /* Unused dummy value for name */
- (void)ecgetstr(state, EC_DUPTOK, &htok);
- prefork(&svl, PREFORK_TYPESET, NULL);
- if (errflag) {
- state->pc = opc;
- break;
- }
- globlist(&svl, 0);
- if (errflag) {
- state->pc = opc;
- break;
- }
- while ((data = ugetnode(&svl))) {
- char *ptr;
- asg = (Asgment)zhalloc(sizeof(struct asgment));
- asg->flags = 0;
- if ((ptr = strchr(data, '='))) {
- *ptr++ = '\0';
- asg->name = data;
- asg->value.scalar = ptr;
- } else {
- asg->name = data;
- asg->value.scalar = NULL;
- }
- uaddlinknode(assigns, &asg->node);
- }
- continue;
- }
- prefork(&svl, PREFORK_SINGLE, NULL);
- name = empty(&svl) ? "" :
- (char *)getdata(firstnode(&svl));
- }
- untokenize(name);
- asg = (Asgment)zhalloc(sizeof(struct asgment));
- asg->name = name;
- if (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR) {
- char *val = ecgetstr(state, EC_DUPTOK, &htok);
- asg->flags = 0;
- if (WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC) {
- /* Fake assignment, no value */
- asg->value.scalar = NULL;
- } else {
- if (htok) {
- init_list1(svl, val);
- prefork(&svl,
- PREFORK_SINGLE|PREFORK_ASSIGN,
- NULL);
- if (errflag) {
- state->pc = opc;
- break;
- }
- /*
- * No globassign for typeset
- * arguments, thank you
- */
- val = empty(&svl) ? "" :
- (char *)getdata(firstnode(&svl));
- }
- untokenize(val);
- asg->value.scalar = val;
- }
- } else {
- asg->flags = ASG_ARRAY;
- asg->value.array =
- ecgetlist(state, WC_ASSIGN_NUM(ac),
- EC_DUPTOK, &htok);
- if (asg->value.array)
- {
- if (!errflag) {
- int prefork_ret = 0;
- prefork(asg->value.array, PREFORK_ASSIGN,
- &prefork_ret);
- if (errflag) {
- state->pc = opc;
- break;
- }
- if (prefork_ret & PREFORK_KEY_VALUE)
- asg->flags |= ASG_KEY_VALUE;
- globlist(asg->value.array, prefork_ret);
- }
- if (errflag) {
- state->pc = opc;
- break;
- }
- }
- }
-
- uaddlinknode(assigns, &asg->node);
- }
- state->pc = opc;
- }
- dont_queue_signals();
- if (!errflag) {
- int ret = execbuiltin(args, assigns, (Builtin) hn);
- /*
- * In case of interruption assume builtin status
- * is less useful than what interrupt set.
- */
- if (!(errflag & ERRFLAG_INT))
- lastval = ret;
- }
- if (do_save & BINF_COMMAND)
- errflag &= ~ERRFLAG_ERROR;
- restore_queue_signals(q);
- fflush(stdout);
- if (save[1] == -2) {
- if (ferror(stdout)) {
- zwarn("write error: %e", errno);
- clearerr(stdout);
- }
- } else
- clearerr(stdout);
- }
- if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
- lastval && !subsh) {
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- fprintf(stderr, "zsh: exit %lld\n", lastval);
-#else
- fprintf(stderr, "zsh: exit %ld\n", (long)lastval);
-#endif
- fflush(stderr);
- }
-
- if (do_exec) {
- if (subsh)
- _exit(lastval);
-
- /* If we are exec'ing a command, and we are not in a subshell, *
- * then check if we should save the history file. */
- if (isset(RCS) && interact && !nohistsave)
- savehistfile(NULL, 1, HFILE_USE_OPTIONS);
- exit(lastval);
- }
- if (restorelist)
- restore_params(restorelist, removelist);
-
- } else {
- if (!subsh) {
- /* for either implicit or explicit "exec", decrease $SHLVL
- * as we're now done as a shell */
- if (!forked)
- setiparam("SHLVL", --shlvl);
-
- /* If we are exec'ing a command, and we are not *
- * in a subshell, then save the history file. */
- if (do_exec && isset(RCS) && interact && !nohistsave)
- savehistfile(NULL, 1, HFILE_USE_OPTIONS);
- }
- if (type == WC_SIMPLE || type == WC_TYPESET) {
- if (varspc) {
- int addflags = ADDVAR_EXPORT|ADDVAR_RESTRICT;
- if (forked)
- addflags |= ADDVAR_RESTORE;
- addvars(state, varspc, addflags);
- if (errflag)
- _exit(1);
- }
- closem(FDT_INTERNAL, 0);
- if (coprocin != -1) {
- zclose(coprocin);
- coprocin = -1;
- }
- if (coprocout != -1) {
- zclose(coprocout);
- coprocout = -1;
- }
-#ifdef HAVE_GETRLIMIT
- if (!forked)
- setlimits(NULL);
-#endif
- if (how & Z_ASYNC) {
- zsfree(STTYval);
- STTYval = 0;
- }
- execute(args, cflags, use_defpath);
- } else { /* ( ... ) */
- DPUTS(varspc,
- "BUG: assignment before complex command");
- list_pipe = 0;
- pipecleanfilelist(filelist, 0);
- /* If we're forked (and we should be), no need to return */
- DPUTS(last1 != 1 && !forked, "BUG: not exiting?");
- DPUTS(type != WC_SUBSH, "Not sure what we're doing.");
- /* Skip word only used for try/always blocks */
- state->pc++;
- execlist(state, 0, 1);
- }
- }
- }
-
- err:
- if (forked) {
- /*
- * So what's going on here then? Well, I'm glad you asked.
- *
- * If we create multios for use in a subshell we do
- * this after forking, in this function above. That
- * means that the current (sub)process is responsible
- * for clearing them up. However, the processes won't
- * go away until we have closed the fd's talking to them.
- * Since we're about to exit the shell there's nothing
- * to stop us closing all fd's (including the ones 0 to 9
- * that we usually leave alone).
- *
- * Then we wait for any processes. When we forked,
- * we cleared the jobtable and started a new job just for
- * any oddments like this, so if there aren't any we won't
- * need to wait. The result of not waiting is that
- * the multios haven't flushed the fd's properly, leading
- * to obscure missing data.
- *
- * It would probably be cleaner to ensure that the
- * parent shell handled multios, but that requires
- * some architectural changes which are likely to be
- * hairy.
- */
- for (i = 0; i < 10; i++)
- if (fdtable[i] != FDT_UNUSED)
- close(i);
- closem(FDT_UNUSED, 1);
- if (thisjob != -1)
- waitjobs();
- _exit(lastval);
- }
- fixfds(save);
-
- done:
- if (isset(POSIXBUILTINS) &&
- (cflags & (BINF_PSPECIAL|BINF_EXEC)) &&
- !(orig_cflags & BINF_COMMAND)) {
- /*
- * For POSIX-compatible behaviour with special
- * builtins (including exec which we don't usually
- * classify as a builtin) we treat all errors as fatal.
- * The "command" builtin is not special so resets this behaviour.
- */
- forked |= zsh_subshell;
- fatal:
- if (redir_err || errflag) {
- if (!isset(INTERACTIVE)) {
- if (forked)
- _exit(1);
- else
- exit(1);
- }
- errflag |= ERRFLAG_ERROR;
- }
- }
- if (newxtrerr) {
- fil = fileno(newxtrerr);
- fclose(newxtrerr);
- xtrerr = oxtrerr;
- zclose(fil);
- }
-
- zsfree(STTYval);
- STTYval = 0;
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
-}
-
-/* Arrange to have variables restored. */
-
-/**/
-static void
-save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p)
-{
- Param pm;
- char *s;
- wordcode ac;
-
- *restore_p = newlinklist();
- *remove_p = newlinklist();
-
- while (wc_code(ac = *pc) == WC_ASSIGN) {
- s = ecrawstr(state->prog, pc + 1, NULL);
- if ((pm = (Param) paramtab->getnode(paramtab, s))) {
- Param tpm;
- if (pm->env)
- delenv(pm);
- if (!(pm->node.flags & PM_SPECIAL)) {
- /*
- * We used to remove ordinary parameters from the
- * table, but that meant "HELLO=$HELLO shellfunc"
- * failed because the expansion of $HELLO hasn't
- * been done at this point. Instead, copy the
- * parameter: in this case, we'll insert the
- * copied parameter straight back into the parameter
- * table so we want to be sure everything is
- * properly set up and in permanent memory.
- */
- tpm = (Param) zshcalloc(sizeof *tpm);
- tpm->node.nam = ztrdup(pm->node.nam);
- copyparam(tpm, pm, 0);
- pm = tpm;
- } else if (!(pm->node.flags & PM_READONLY) &&
- (unset(RESTRICTED) || !(pm->node.flags & PM_RESTRICTED))) {
- /*
- * In this case we're just saving parts of
- * the parameter in a tempory, so use heap allocation
- * and don't bother copying every detail.
- */
- tpm = (Param) hcalloc(sizeof *tpm);
- tpm->node.nam = pm->node.nam;
- copyparam(tpm, pm, 1);
- pm = tpm;
- }
- addlinknode(*remove_p, dupstring(s));
- addlinknode(*restore_p, pm);
- } else
- addlinknode(*remove_p, dupstring(s));
-
- pc += (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR ?
- 3 : WC_ASSIGN_NUM(ac) + 2);
- }
-}
-
-/* Restore saved parameters after executing a shfunc or builtin */
-
-/**/
-static void
-restore_params(LinkList restorelist, LinkList removelist)
-{
- Param pm;
- char *s;
-
- /* remove temporary parameters */
- while ((s = (char *) ugetnode(removelist))) {
- if ((pm = (Param) paramtab->getnode(paramtab, s)) &&
- !(pm->node.flags & PM_SPECIAL)) {
- pm->node.flags &= ~PM_READONLY;
- unsetparam_pm(pm, 0, 0);
- }
- }
-
- if (restorelist) {
- /* restore saved parameters */
- while ((pm = (Param) ugetnode(restorelist))) {
- if (pm->node.flags & PM_SPECIAL) {
- Param tpm = (Param) paramtab->getnode(paramtab, pm->node.nam);
-
- DPUTS(!tpm || PM_TYPE(pm->node.flags) != PM_TYPE(tpm->node.flags) ||
- !(pm->node.flags & PM_SPECIAL),
- "BUG: in restoring special parameters");
- if (!pm->env && tpm->env)
- delenv(tpm);
- tpm->node.flags = pm->node.flags;
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- tpm->gsu.s->setfn(tpm, pm->u.str);
- break;
- case PM_INTEGER:
- tpm->gsu.i->setfn(tpm, pm->u.val);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- tpm->gsu.f->setfn(tpm, pm->u.dval);
- break;
- case PM_ARRAY:
- tpm->gsu.a->setfn(tpm, pm->u.arr);
- break;
- case PM_HASHED:
- tpm->gsu.h->setfn(tpm, pm->u.hash);
- break;
- }
- pm = tpm;
- } else {
- paramtab->addnode(paramtab, pm->node.nam, pm);
- }
- if ((pm->node.flags & PM_EXPORTED) && ((s = getsparam(pm->node.nam))))
- addenv(pm, s);
- }
- }
-}
-
-/* restore fds after redirecting a builtin */
-
-/**/
-static void
-fixfds(int *save)
-{
- int old_errno = errno;
- int i;
-
- for (i = 0; i != 10; i++)
- if (save[i] != -2)
- redup(save[i], i);
- errno = old_errno;
-}
-
-/*
- * Close internal shell fds.
- *
- * Close any that are marked as used if "how" is FDT_UNUSED, else
- * close any with the value "how".
- *
- * If "all" is zero, we'll skip cases where we need the file
- * descriptor to be visible externally.
- */
-
-/**/
-mod_export void
-closem(int how, int all)
-{
- int i;
-
- for (i = 10; i <= max_zsh_fd; i++)
- if (fdtable[i] != FDT_UNUSED &&
- /*
- * Process substitution needs to be visible to user;
- * fd's are explicitly cleaned up by filelist handling.
- */
- (all || fdtable[i] != FDT_PROC_SUBST) &&
- (how == FDT_UNUSED || (fdtable[i] & FDT_TYPE_MASK) == how)) {
- if (i == SHTTY)
- SHTTY = -1;
- zclose(i);
- }
-}
-
-/* convert here document into a here string */
-
-/**/
-char *
-gethere(char **strp, int typ)
-{
- char *buf;
- int bsiz, qt = 0, strip = 0;
- char *s, *t, *bptr, c;
- char *str = *strp;
-
- for (s = str; *s; s++)
- if (inull(*s)) {
- qt = 1;
- break;
- }
- str = quotesubst(str);
- untokenize(str);
- if (typ == REDIR_HEREDOCDASH) {
- strip = 1;
- while (*str == '\t')
- str++;
- }
- *strp = str;
- bptr = buf = zalloc(bsiz = 256);
- for (;;) {
- t = bptr;
-
- while ((c = hgetc()) == '\t' && strip)
- ;
- for (;;) {
- if (bptr >= buf + bsiz - 2) {
- ptrdiff_t toff = t - buf;
- ptrdiff_t bptroff = bptr - buf;
- char *newbuf = realloc(buf, 2 * bsiz);
- if (!newbuf) {
- /* out of memory */
- zfree(buf, bsiz);
- return NULL;
- }
- buf = newbuf;
- t = buf + toff;
- bptr = buf + bptroff;
- bsiz *= 2;
- }
- if (lexstop || c == '\n')
- break;
- if (!qt && c == '\\') {
- *bptr++ = c;
- c = hgetc();
- if (c == '\n') {
- bptr--;
- c = hgetc();
- continue;
- }
- }
- *bptr++ = c;
- c = hgetc();
- }
- *bptr = '\0';
- if (!strcmp(t, str))
- break;
- if (lexstop) {
- t = bptr;
- break;
- }
- *bptr++ = '\n';
- }
- *t = '\0';
- s = buf;
- buf = dupstring(buf);
- zfree(s, bsiz);
- if (!qt) {
- int ef = errflag;
-
- parsestr(&buf);
-
- if (!(errflag & ERRFLAG_ERROR)) {
- /* Retain any user interrupt error */
- errflag = ef | (errflag & ERRFLAG_INT);
- }
- }
- return buf;
-}
-
-/* open here string fd */
-
-/**/
-static int
-getherestr(struct redir *fn)
-{
- char *s, *t;
- int fd, len;
-
- t = fn->name;
- singsub(&t);
- untokenize(t);
- unmetafy(t, &len);
- /*
- * For real here-strings we append a newline, as if the
- * string given was a complete command line.
- *
- * For here-strings from here documents, we use the original
- * text exactly.
- */
- if (!(fn->flags & REDIRF_FROM_HEREDOC))
- t[len++] = '\n';
- if ((fd = gettempfile(NULL, 1, &s)) < 0)
- return -1;
- write_loop(fd, t, len);
- close(fd);
- fd = open(s, O_RDONLY | O_NOCTTY);
- unlink(s);
- return fd;
-}
-
-/*
- * Test if some wordcode starts with a simple redirection of type
- * redir_type. If it does, return the name of the file, copied onto
- * the heap. If it doesn't, return NULL.
- */
-
-static char *
-simple_redir_name(Eprog prog, int redir_type)
-{
- Wordcode pc;
-
- pc = prog->prog;
- if (prog != &dummy_eprog &&
- wc_code(pc[0]) == WC_LIST && (WC_LIST_TYPE(pc[0]) & Z_END) &&
- wc_code(pc[1]) == WC_SUBLIST && !WC_SUBLIST_FLAGS(pc[1]) &&
- WC_SUBLIST_TYPE(pc[1]) == WC_SUBLIST_END &&
- wc_code(pc[2]) == WC_PIPE && WC_PIPE_TYPE(pc[2]) == WC_PIPE_END &&
- wc_code(pc[3]) == WC_REDIR && WC_REDIR_TYPE(pc[3]) == redir_type &&
- !WC_REDIR_VARID(pc[3]) &&
- !pc[4] &&
- wc_code(pc[6]) == WC_SIMPLE && !WC_SIMPLE_ARGC(pc[6])) {
- return dupstring(ecrawstr(prog, pc + 5, NULL));
- }
-
- return NULL;
-}
-
-/* $(...) */
-
-/**/
-LinkList
-getoutput(char *cmd, int qt)
-{
- Eprog prog;
- int pipes[2];
- pid_t pid;
- char *s;
-
- int onc = nocomments;
- nocomments = (interact && unset(INTERACTIVECOMMENTS));
- prog = parse_string(cmd, 0);
- nocomments = onc;
-
- if (!prog)
- return NULL;
-
- if ((s = simple_redir_name(prog, REDIR_READ))) {
- /* $(< word) */
- int stream;
- LinkList retval;
- int readerror;
-
- singsub(&s);
- if (errflag)
- return NULL;
- untokenize(s);
- if ((stream = open(unmeta(s), O_RDONLY | O_NOCTTY)) == -1) {
- zwarn("%e: %s", errno, s);
- lastval = cmdoutval = 1;
- return newlinklist();
- }
- retval = readoutput(stream, qt, &readerror);
- if (readerror) {
- zwarn("error when reading %s: %e", s, readerror);
- lastval = cmdoutval = 1;
- }
- return retval;
- }
- if (mpipe(pipes) < 0) {
- errflag |= ERRFLAG_ERROR;
- cmdoutpid = 0;
- return NULL;
- }
- child_block();
- cmdoutval = 0;
- if ((cmdoutpid = pid = zfork(NULL)) == -1) {
- /* fork error */
- zclose(pipes[0]);
- zclose(pipes[1]);
- errflag |= ERRFLAG_ERROR;
- cmdoutpid = 0;
- child_unblock();
- return NULL;
- } else if (pid) {
- LinkList retval;
-
- zclose(pipes[1]);
- retval = readoutput(pipes[0], qt, NULL);
- fdtable[pipes[0]] = FDT_UNUSED;
- waitforpid(pid, 0); /* unblocks */
- lastval = cmdoutval;
- return retval;
- }
- /* pid == 0 */
- child_unblock();
- zclose(pipes[0]);
- redup(pipes[1], 1);
- entersubsh(ESUB_PGRP|ESUB_NOMONITOR);
- cmdpush(CS_CMDSUBST);
- execode(prog, 0, 1, "cmdsubst");
- cmdpop();
- close(1);
- _exit(lastval);
- zerr("exit returned in child!!");
- kill(getpid(), SIGKILL);
- return NULL;
-}
-
-/* read output of command substitution */
-
-/**/
-mod_export LinkList
-readoutput(int in, int qt, int *readerror)
-{
- LinkList ret;
- char *buf, *ptr;
- int bsiz, c, cnt = 0;
- FILE *fin;
- int q = queue_signal_level();
-
- fin = fdopen(in, "r");
- ret = newlinklist();
- ptr = buf = (char *) hcalloc(bsiz = 64);
- /*
- * We need to be sensitive to SIGCHLD else we can be
- * stuck forever with important processes unreaped.
- * The case that triggered this was where the exiting
- * process is group leader of the foreground process and we need
- * to reclaim the terminal else ^C doesn't work.
- */
- dont_queue_signals();
- child_unblock();
- while ((c = fgetc(fin)) != EOF || errno == EINTR) {
- if (c == EOF) {
- errno = 0;
- clearerr(fin);
- continue;
- }
- if (imeta(c)) {
- *ptr++ = Meta;
- c ^= 32;
- cnt++;
- }
- if (++cnt >= bsiz) {
- char *pp;
- queue_signals();
- pp = (char *) hcalloc(bsiz *= 2);
- dont_queue_signals();
-
- memcpy(pp, buf, cnt - 1);
- ptr = (buf = pp) + cnt - 1;
- }
- *ptr++ = c;
- }
- child_block();
- restore_queue_signals(q);
- if (readerror)
- *readerror = ferror(fin) ? errno : 0;
- fclose(fin);
- while (cnt && ptr[-1] == '\n')
- ptr--, cnt--;
- *ptr = '\0';
- if (qt) {
- if (!cnt) {
- *ptr++ = Nularg;
- *ptr = '\0';
- }
- addlinknode(ret, buf);
- } else {
- char **words = spacesplit(buf, 0, 1, 0);
-
- while (*words) {
- if (isset(GLOBSUBST))
- shtokenize(*words);
- addlinknode(ret, *words++);
- }
- }
- return ret;
-}
-
-/**/
-static Eprog
-parsecmd(char *cmd, char **eptr)
-{
- char *str;
- Eprog prog;
-
- for (str = cmd + 2; *str && *str != Outpar; str++);
- if (!*str || cmd[1] != Inpar) {
- /*
- * This can happen if the expression is being parsed
- * inside another construct, e.g. as a value within ${..:..} etc.
- * So print a proper error message instead of the not very
- * useful but traditional "oops".
- */
- char *errstr = dupstrpfx(cmd, 2);
- untokenize(errstr);
- zerr("unterminated `%s...)'", errstr);
- return NULL;
- }
- *str = '\0';
- if (eptr)
- *eptr = str+1;
- if (!(prog = parse_string(cmd + 2, 0))) {
- zerr("parse error in process substitution");
- return NULL;
- }
- return prog;
-}
-
-/* =(...) */
-
-/**/
-char *
-getoutputfile(char *cmd, char **eptr)
-{
- pid_t pid;
- char *nam;
- Eprog prog;
- int fd;
- char *s;
-
- if (thisjob == -1){
- zerr("process substitution %s cannot be used here", cmd);
- return NULL;
- }
- if (!(prog = parsecmd(cmd, eptr)))
- return NULL;
- if (!(nam = gettempname(NULL, 1)))
- return NULL;
-
- if ((s = simple_redir_name(prog, REDIR_HERESTR))) {
- /*
- * =(<<(...) */
-
-/**/
-char *
-getproc(char *cmd, char **eptr)
-{
-#if !defined(HAVE_FIFOS) && !defined(PATH_DEV_FD)
- zerr("doesn't look like your system supports FIFOs.");
- return NULL;
-#else
- Eprog prog;
- int out = *cmd == Inang;
- char *pnam;
- pid_t pid;
- struct timeval bgtime;
-
-#ifndef PATH_DEV_FD
- int fd;
- if (thisjob == -1) {
- zerr("process substitution %s cannot be used here", cmd);
- return NULL;
- }
- if (!(pnam = namedpipe()))
- return NULL;
- if (!(prog = parsecmd(cmd, eptr)))
- return NULL;
- addfilelist(pnam, 0);
-
- if ((pid = zfork(&bgtime))) {
- if (pid == -1)
- return NULL;
- if (!out)
- addproc(pid, NULL, 1, &bgtime);
- procsubstpid = pid;
- return pnam;
- }
- closem(FDT_UNUSED, 0);
- fd = open(pnam, out ? O_WRONLY | O_NOCTTY : O_RDONLY | O_NOCTTY);
- if (fd == -1) {
- zerr("can't open %s: %e", pnam, errno);
- _exit(1);
- }
- entersubsh(ESUB_ASYNC|ESUB_PGRP);
- redup(fd, out);
-#else /* PATH_DEV_FD */
- int pipes[2], fd;
-
- if (thisjob == -1) {
- zerr("process substitution %s cannot be used here", cmd);
- return NULL;
- }
- pnam = zhalloc(strlen(PATH_DEV_FD) + 1 + DIGBUFSIZE);
- if (!(prog = parsecmd(cmd, eptr)))
- return NULL;
- if (mpipe(pipes) < 0)
- return NULL;
- if ((pid = zfork(&bgtime))) {
- sprintf(pnam, "%s/%d", PATH_DEV_FD, pipes[!out]);
- zclose(pipes[out]);
- if (pid == -1)
- {
- zclose(pipes[!out]);
- return NULL;
- }
- fd = pipes[!out];
- fdtable[fd] = FDT_PROC_SUBST;
- addfilelist(NULL, fd);
- if (!out)
- {
- addproc(pid, NULL, 1, &bgtime);
- }
- procsubstpid = pid;
- return pnam;
- }
- entersubsh(ESUB_ASYNC|ESUB_PGRP);
- redup(pipes[out], out);
- closem(FDT_UNUSED, 0); /* this closes pipes[!out] as well */
-#endif /* PATH_DEV_FD */
-
- cmdpush(CS_CMDSUBST);
- execode(prog, 0, 1, out ? "outsubst" : "insubst");
- cmdpop();
- zclose(out);
- _exit(lastval);
- return NULL;
-#endif /* HAVE_FIFOS and PATH_DEV_FD not defined */
-}
-
-/*
- * > >(...) or < <(...) (does not use named pipes)
- *
- * If the second argument is 1, this is part of
- * an "exec < <(...)" or "exec > >(...)" and we shouldn't
- * wait for the job to finish before continuing.
- */
-
-/**/
-static int
-getpipe(char *cmd, int nullexec)
-{
- Eprog prog;
- int pipes[2], out = *cmd == Inang;
- pid_t pid;
- struct timeval bgtime;
- char *ends;
-
- if (!(prog = parsecmd(cmd, &ends)))
- return -1;
- if (*ends) {
- zerr("invalid syntax for process substitution in redirection");
- return -1;
- }
- if (mpipe(pipes) < 0)
- return -1;
- if ((pid = zfork(&bgtime))) {
- zclose(pipes[out]);
- if (pid == -1) {
- zclose(pipes[!out]);
- return -1;
- }
- if (!nullexec)
- addproc(pid, NULL, 1, &bgtime);
- procsubstpid = pid;
- return pipes[!out];
- }
- entersubsh(ESUB_PGRP);
- redup(pipes[out], out);
- closem(FDT_UNUSED, 0); /* this closes pipes[!out] as well */
- cmdpush(CS_CMDSUBST);
- execode(prog, 0, 1, out ? "outsubst" : "insubst");
- cmdpop();
- _exit(lastval);
- return 0;
-}
-
-/* open pipes with fds >= 10 */
-
-/**/
-static int
-mpipe(int *pp)
-{
- if (pipe(pp) < 0) {
- zerr("pipe failed: %e", errno);
- return -1;
- }
- pp[0] = movefd(pp[0]);
- pp[1] = movefd(pp[1]);
- return 0;
-}
-
-/*
- * Do process substitution with redirection
- *
- * If the second argument is 1, this is part of
- * an "exec < <(...)" or "exec > >(...)" and we shouldn't
- * wait for the job to finish before continuing.
- * Likewise, we shouldn't wait if we are opening the file
- * descriptor using the {fd}>>(...) notation since it stays
- * valid for subsequent commands.
- */
-
-/**/
-static void
-spawnpipes(LinkList l, int nullexec)
-{
- LinkNode n;
- Redir f;
- char *str;
-
- n = firstnode(l);
- for (; n; incnode(n)) {
- f = (Redir) getdata(n);
- if (f->type == REDIR_OUTPIPE || f->type == REDIR_INPIPE) {
- str = f->name;
- f->fd2 = getpipe(str, nullexec || f->varid);
- }
- }
-}
-
-/* evaluate a [[ ... ]] */
-
-/**/
-static int
-execcond(Estate state, UNUSED(int do_exec))
-{
- int stat;
-
- state->pc--;
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "[[");
- tracingcond++;
- }
- cmdpush(CS_COND);
- stat = evalcond(state, NULL);
- /*
- * 2 indicates a syntax error. For compatibility, turn this
- * into a shell error.
- */
- if (stat == 2)
- errflag |= ERRFLAG_ERROR;
- cmdpop();
- if (isset(XTRACE)) {
- fprintf(xtrerr, " ]]\n");
- fflush(xtrerr);
- tracingcond--;
- }
- return stat;
-}
-
-/* evaluate a ((...)) arithmetic command */
-
-/**/
-static int
-execarith(Estate state, UNUSED(int do_exec))
-{
- char *e;
- mnumber val = zero_mnumber;
- int htok = 0;
-
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "((");
- }
- cmdpush(CS_MATH);
- e = ecgetstr(state, EC_DUPTOK, &htok);
- if (htok)
- singsub(&e);
- if (isset(XTRACE))
- fprintf(xtrerr, " %s", e);
-
- val = matheval(e);
-
- cmdpop();
-
- if (isset(XTRACE)) {
- fprintf(xtrerr, " ))\n");
- fflush(xtrerr);
- }
- if (errflag) {
- errflag &= ~ERRFLAG_ERROR;
- return 2;
- }
- /* should test for fabs(val.u.d) < epsilon? */
- return (val.type == MN_INTEGER) ? val.u.l == 0 : val.u.d == 0.0;
-}
-
-/* perform time ... command */
-
-/**/
-static int
-exectime(Estate state, UNUSED(int do_exec))
-{
- int jb;
-
- jb = thisjob;
- if (WC_TIMED_TYPE(state->pc[-1]) == WC_TIMED_EMPTY) {
- shelltime();
- return 0;
- }
- execpline(state, *state->pc++, Z_TIMED|Z_SYNC, 0);
- thisjob = jb;
- return lastval;
-}
-
-/* Define a shell function */
-
-static const char *const ANONYMOUS_FUNCTION_NAME = "(anon)";
-
-/**/
-static int
-execfuncdef(Estate state, Eprog redir_prog)
-{
- Shfunc shf;
- char *s = NULL;
- int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0;
- int anon_func = 0;
- Wordcode beg = state->pc, end;
- Eprog prog;
- Patprog *pp;
- LinkList names;
-
- end = beg + WC_FUNCDEF_SKIP(state->pc[-1]);
- names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
- nprg = end - beg;
- sbeg = *state->pc++;
- nstrs = *state->pc++;
- npats = *state->pc++;
-
- nprg = (end - state->pc);
- plen = nprg * sizeof(wordcode);
- len = plen + (npats * sizeof(Patprog)) + nstrs;
-
- if (htok && names) {
- execsubst(names);
- if (errflag) {
- state->pc = end;
- return 1;
- }
- }
-
- DPUTS(!names && redir_prog,
- "Passing redirection to anon function definition.");
- while (!names || (s = (char *) ugetnode(names))) {
- if (!names) {
- prog = (Eprog) zhalloc(sizeof(*prog));
- prog->nref = -1; /* on the heap */
- } else {
- prog = (Eprog) zalloc(sizeof(*prog));
- prog->nref = 1; /* allocated from permanent storage */
- }
- prog->npats = npats;
- prog->len = len;
- if (state->prog->dump || !names) {
- if (!names) {
- prog->flags = EF_HEAP;
- prog->dump = NULL;
- prog->pats = pp = (Patprog *) zhalloc(npats * sizeof(Patprog));
- } else {
- prog->flags = EF_MAP;
- incrdumpcount(state->prog->dump);
- prog->dump = state->prog->dump;
- prog->pats = pp = (Patprog *) zalloc(npats * sizeof(Patprog));
- }
- prog->prog = state->pc;
- prog->strs = state->strs + sbeg;
- } else {
- prog->flags = EF_REAL;
- prog->pats = pp = (Patprog *) zalloc(len);
- prog->prog = (Wordcode) (prog->pats + npats);
- prog->strs = (char *) (prog->prog + nprg);
- prog->dump = NULL;
- memcpy(prog->prog, state->pc, plen);
- memcpy(prog->strs, state->strs + sbeg, nstrs);
- }
- for (i = npats; i--; pp++)
- *pp = dummy_patprog1;
- prog->shf = NULL;
-
- shf = (Shfunc) zalloc(sizeof(*shf));
- shf->funcdef = prog;
- shf->node.flags = 0;
- /* No dircache here, not a directory */
- shf->filename = ztrdup(scriptfilename);
- shf->lineno =
- (funcstack && (funcstack->tp == FS_FUNC ||
- funcstack->tp == FS_EVAL)) ?
- funcstack->flineno + lineno :
- lineno;
- /*
- * redir_prog is permanently allocated --- but if
- * this function has multiple names we need an additional
- * one. Original redir_prog used with the last name
- * because earlier functions are freed in case of duplicate
- * names.
- */
- if (names && nonempty(names) && redir_prog)
- shf->redir = dupeprog(redir_prog, 0);
- else {
- shf->redir = redir_prog;
- redir_prog = 0;
- }
- shfunc_set_sticky(shf);
-
- if (!names) {
- /*
- * Anonymous function, execute immediately.
- * Function name is "(anon)".
- */
- LinkList args;
-
- anon_func = 1;
- shf->node.flags |= PM_ANONYMOUS;
-
- state->pc = end;
- end += *state->pc++;
- args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
-
- if (htok && args) {
- execsubst(args);
- if (errflag) {
- freeeprog(shf->funcdef);
- if (shf->redir) /* shouldn't be */
- freeeprog(shf->redir);
- dircache_set(&shf->filename, NULL);
- zfree(shf, sizeof(*shf));
- state->pc = end;
- return 1;
- }
- }
-
- setunderscore((args && nonempty(args)) ?
- ((char *) getdata(lastnode(args))) : "");
-
- if (!args)
- args = newlinklist();
- shf->node.nam = (char *) ANONYMOUS_FUNCTION_NAME;
- pushnode(args, shf->node.nam);
-
- execshfunc(shf, args);
- ret = lastval;
-
- if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
- lastval) {
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- fprintf(stderr, "zsh: exit %lld\n", lastval);
-#else
- fprintf(stderr, "zsh: exit %ld\n", (long)lastval);
-#endif
- fflush(stderr);
- }
-
- freeeprog(shf->funcdef);
- if (shf->redir) /* shouldn't be */
- freeeprog(shf->redir);
- dircache_set(&shf->filename, NULL);
- zfree(shf, sizeof(*shf));
- break;
- } else {
- /* is this shell function a signal trap? */
- if (!strncmp(s, "TRAP", 4) &&
- (signum = getsignum(s + 4)) != -1) {
- if (settrap(signum, NULL, ZSIG_FUNC)) {
- freeeprog(shf->funcdef);
- dircache_set(&shf->filename, NULL);
- zfree(shf, sizeof(*shf));
- state->pc = end;
- return 1;
- }
-
- /*
- * Remove the old node explicitly in case it has
- * an alternative name
- */
- removetrapnode(signum);
- }
- shfunctab->addnode(shfunctab, ztrdup(s), shf);
- }
- }
- if (!anon_func)
- setunderscore("");
- if (redir_prog) {
- /* For completeness, shouldn't happen */
- freeeprog(redir_prog);
- }
- state->pc = end;
- return ret;
-}
-
-/* Duplicate a sticky emulation */
-
-/**/
-
-mod_export Emulation_options
-sticky_emulation_dup(Emulation_options src, int useheap)
-{
- Emulation_options newsticky = useheap ?
- hcalloc(sizeof(*src)) : zshcalloc(sizeof(*src));
- newsticky->emulation = src->emulation;
- if (src->n_on_opts) {
- size_t sz = src->n_on_opts * sizeof(*src->on_opts);
- newsticky->n_on_opts = src->n_on_opts;
- newsticky->on_opts = useheap ? zhalloc(sz) : zalloc(sz);
- memcpy(newsticky->on_opts, src->on_opts, sz);
- }
- if (src->n_off_opts) {
- size_t sz = src->n_off_opts * sizeof(*src->off_opts);
- newsticky->n_off_opts = src->n_off_opts;
- newsticky->off_opts = useheap ? zhalloc(sz) : zalloc(sz);
- memcpy(newsticky->off_opts, src->off_opts, sz);
- }
-
- return newsticky;
-}
-
-/* Set the sticky emulation attributes for a shell function */
-
-/**/
-
-mod_export void
-shfunc_set_sticky(Shfunc shf)
-{
- if (sticky)
- shf->sticky = sticky_emulation_dup(sticky, 0);
- else
- shf->sticky = NULL;
-}
-
-
-/* Main entry point to execute a shell function. */
-
-/**/
-static void
-execshfunc(Shfunc shf, LinkList args)
-{
- LinkList last_file_list = NULL;
- unsigned char *ocs;
- int ocsp, osfc;
-
- if (errflag)
- return;
-
- /* thisjob may be invalid if we're called via execsimple: see execcursh */
- if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
- !hasprocs(thisjob)) {
- /* Without this deletejob the process table *
- * would be filled by a recursive function. */
- last_file_list = jobtab[thisjob].filelist;
- jobtab[thisjob].filelist = NULL;
- deletejob(jobtab + thisjob, 0);
- }
-
- if (isset(XTRACE)) {
- LinkNode lptr;
- printprompt4();
- if (args)
- for (lptr = firstnode(args); lptr; incnode(lptr)) {
- if (lptr != firstnode(args))
- fputc(' ', xtrerr);
- quotedzputs((char *)getdata(lptr), xtrerr);
- }
- fputc('\n', xtrerr);
- fflush(xtrerr);
- }
- queue_signals();
- ocs = cmdstack;
- ocsp = cmdsp;
- cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
- cmdsp = 0;
- if ((osfc = sfcontext) == SFC_NONE)
- sfcontext = SFC_DIRECT;
- xtrerr = stderr;
-
- doshfunc(shf, args, 0);
-
- sfcontext = osfc;
- free(cmdstack);
- cmdstack = ocs;
- cmdsp = ocsp;
-
- if (!list_pipe)
- deletefilelist(last_file_list, 0);
- unqueue_signals();
-}
-
-/*
- * Function to execute the special type of command that represents an
- * autoloaded shell function. The command structure tells us which
- * function it is. This function is actually called as part of the
- * execution of the autoloaded function itself, so when the function
- * has been autoloaded, its list is just run with no frills.
- *
- * There are two cases because if we are doing all-singing, all-dancing
- * non-simple code we load the shell function early in execcmd() (the
- * action also present in the non-basic version) to check if
- * there are redirections that need to be handled at that point.
- * Then we call execautofn_basic() to do the rest.
- */
-
-/**/
-static int
-execautofn_basic(Estate state, UNUSED(int do_exec))
-{
- Shfunc shf;
- char *oldscriptname, *oldscriptfilename;
-
- shf = state->prog->shf;
-
- /*
- * Probably we didn't know the filename where this function was
- * defined yet.
- */
- if (funcstack && !funcstack->filename)
- funcstack->filename = getshfuncfile(shf);
-
- oldscriptname = scriptname;
- oldscriptfilename = scriptfilename;
- scriptname = dupstring(shf->node.nam);
- scriptfilename = getshfuncfile(shf);
- execode(shf->funcdef, 1, 0, "loadautofunc");
- scriptname = oldscriptname;
- scriptfilename = oldscriptfilename;
-
- return lastval;
-}
-
-/**/
-static int
-execautofn(Estate state, UNUSED(int do_exec))
-{
- Shfunc shf;
-
- if (!(shf = loadautofn(state->prog->shf, 1, 0, 0)))
- return 1;
-
- state->prog->shf = shf;
- return execautofn_basic(state, 0);
-}
-
-/*
- * Helper function to install the source file name of a shell function
- * just autoloaded.
- *
- * We attempt to do this efficiently as the typical case is the
- * directory part is a well-known directory, which is cached, and
- * the non-directory part is the same as the node name.
- */
-
-/**/
-static void
-loadautofnsetfile(Shfunc shf, char *fdir)
-{
- /*
- * If shf->filename is already the load directory ---
- * keep it as we can still use it to get the load file.
- * This makes autoload with an absolute path particularly efficient.
- */
- if (!(shf->node.flags & PM_LOADDIR) ||
- strcmp(shf->filename, fdir) != 0) {
- /* Old directory name not useful... */
- dircache_set(&shf->filename, NULL);
- if (fdir) {
- /* ...can still cache directory */
- shf->node.flags |= PM_LOADDIR;
- dircache_set(&shf->filename, fdir);
- } else {
- /* ...no separate directory part to cache, for some reason. */
- shf->node.flags &= ~PM_LOADDIR;
- shf->filename = ztrdup(shf->node.nam);
- }
- }
-}
-
-/**/
-Shfunc
-loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
-{
- int noalias = noaliases, ksh = 1;
- Eprog prog;
- char *fdir; /* Directory path where func found */
-
- pushheap();
-
- noaliases = (shf->node.flags & PM_UNALIASED);
- if (shf->filename && shf->filename[0] == '/' &&
- (shf->node.flags & PM_LOADDIR))
- {
- char *spec_path[2];
- spec_path[0] = dupstring(shf->filename);
- spec_path[1] = NULL;
- prog = getfpfunc(shf->node.nam, &ksh, &fdir, spec_path, 0);
- if (prog == &dummy_eprog &&
- (current_fpath || (shf->node.flags & PM_CUR_FPATH)))
- prog = getfpfunc(shf->node.nam, &ksh, &fdir, NULL, 0);
- }
- else
- prog = getfpfunc(shf->node.nam, &ksh, &fdir, NULL, 0);
- noaliases = noalias;
-
- if (ksh == 1) {
- ksh = fksh;
- if (ksh == 1)
- ksh = (shf->node.flags & PM_KSHSTORED) ? 2 :
- (shf->node.flags & PM_ZSHSTORED) ? 0 : 1;
- }
-
- if (prog == &dummy_eprog) {
- /* We're not actually in the function; decrement locallevel */
- locallevel--;
- zwarn("%s: function definition file not found", shf->node.nam);
- locallevel++;
- popheap();
- return NULL;
- }
- if (!prog) {
- popheap();
- return NULL;
- }
- if (ksh == 2 || (ksh == 1 && isset(KSHAUTOLOAD))) {
- if (autol) {
- prog->flags |= EF_RUN;
-
- freeeprog(shf->funcdef);
- if (prog->flags & EF_MAP)
- shf->funcdef = prog;
- else
- shf->funcdef = dupeprog(prog, 0);
- shf->node.flags &= ~PM_UNDEFINED;
- loadautofnsetfile(shf, fdir);
- } else {
- VARARR(char, n, strlen(shf->node.nam) + 1);
- strcpy(n, shf->node.nam);
- execode(prog, 1, 0, "evalautofunc");
- shf = (Shfunc) shfunctab->getnode(shfunctab, n);
- if (!shf || (shf->node.flags & PM_UNDEFINED)) {
- /* We're not actually in the function; decrement locallevel */
- locallevel--;
- zwarn("%s: function not defined by file", n);
- locallevel++;
- popheap();
- return NULL;
- }
- }
- } else {
- freeeprog(shf->funcdef);
- if (prog->flags & EF_MAP)
- shf->funcdef = stripkshdef(prog, shf->node.nam);
- else
- shf->funcdef = dupeprog(stripkshdef(prog, shf->node.nam), 0);
- shf->node.flags &= ~PM_UNDEFINED;
- loadautofnsetfile(shf, fdir);
- }
- popheap();
-
- return shf;
-}
-
-/*
- * Check if a sticky emulation differs from the current one.
- */
-
-/**/
-
-int sticky_emulation_differs(Emulation_options sticky2)
-{
- /* If no new sticky emulation, not a different emulation */
- if (!sticky2)
- return 0;
- /* If no current sticky emulation, different */
- if (!sticky)
- return 1;
- /* If basic emulation different, different */
- if (sticky->emulation != sticky2->emulation)
- return 1;
- /* If differing numbers of options, different */
- if (sticky->n_on_opts != sticky2->n_on_opts ||
- sticky->n_off_opts != sticky2->n_off_opts)
- return 1;
- /*
- * We need to compare option arrays, if non-null.
- * We made parseopts() create the list of options in option
- * order to make this easy.
- */
- /* If different options turned on, different */
- if (sticky->n_on_opts &&
- memcmp(sticky->on_opts, sticky2->on_opts,
- sticky->n_on_opts * sizeof(*sticky->on_opts)) != 0)
- return 1;
- /* If different options turned on, different */
- if (sticky->n_off_opts &&
- memcmp(sticky->off_opts, sticky2->off_opts,
- sticky->n_off_opts * sizeof(*sticky->off_opts)) != 0)
- return 1;
- return 0;
-}
-
-/*
- * execute a shell function
- *
- * name is the name of the function
- *
- * prog is the code to execute
- *
- * doshargs, if set, are parameters to pass to the function,
- * in which the first element is the function name (even if
- * FUNCTIONARGZERO is set as this is handled inside this function).
- *
- * If noreturnval is nonzero, then reset the current return
- * value (lastval) to its value before the shell function
- * was executed. However, in any case return the status value
- * from the function (i.e. if noreturnval is not set, this
- * will be the same as lastval).
- */
-
-/**/
-mod_export int
-doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
-{
- char **pptab, **x;
- int ret;
- char *name = shfunc->node.nam;
- int flags = shfunc->node.flags;
- char *fname = dupstring(name);
- Eprog prog;
- static int oflags;
- static int funcdepth;
- Heap funcheap;
-
- queue_signals(); /* Lots of memory and global state changes coming */
-
- NEWHEAPS(funcheap) {
- /*
- * Save data in heap rather than on stack to keep recursive
- * function cost down --- use of heap memory should be efficient
- * at this point. Saving is not actually massive.
- */
- Funcsave funcsave = zhalloc(sizeof(struct funcsave));
- funcsave->scriptname = scriptname;
- funcsave->argv0 = NULL;
- funcsave->breaks = breaks;
- funcsave->contflag = contflag;
- funcsave->loops = loops;
- funcsave->lastval = lastval;
- funcsave->pipestats = NULL;
- funcsave->numpipestats = numpipestats;
- funcsave->noerrexit = noerrexit;
- if (trap_state == TRAP_STATE_PRIMED)
- trap_return--;
- /*
- * Suppression of ERR_RETURN is turned off in function scope.
- */
- noerrexit &= ~NOERREXIT_RETURN;
- if (noreturnval) {
- /*
- * Easiest to use the heap here since we're bracketed
- * immediately by a pushheap/popheap pair.
- */
- size_t bytes = sizeof(int)*numpipestats;
- funcsave->pipestats = (int *)zhalloc(bytes);
- memcpy(funcsave->pipestats, pipestats, bytes);
- }
-
- starttrapscope();
- startpatternscope();
-
- pptab = pparams;
- if (!(flags & PM_UNDEFINED))
- scriptname = dupstring(name);
- funcsave->zoptind = zoptind;
- funcsave->optcind = optcind;
- if (!isset(POSIXBUILTINS)) {
- zoptind = 1;
- optcind = 0;
- }
-
- /* We need to save the current options even if LOCALOPTIONS is *
- * not currently set. That's because if it gets set in the *
- * function we need to restore the original options on exit. */
- memcpy(funcsave->opts, opts, sizeof(opts));
- funcsave->emulation = emulation;
- funcsave->sticky = sticky;
-
- if (sticky_emulation_differs(shfunc->sticky)) {
- /*
- * Function is marked for sticky emulation.
- * Enable it now.
- *
- * We deliberately do not do this if the sticky emulation
- * in effect is the same as that requested. This enables
- * option setting naturally within emulation environments.
- * Note that a difference in EMULATE_FULLY (emulate with
- * or without -R) counts as a different environment.
- *
- * This propagates the sticky emulation to subfunctions.
- */
- sticky = sticky_emulation_dup(shfunc->sticky, 1);
- emulation = sticky->emulation;
- funcsave->restore_sticky = 1;
- installemulation(emulation, opts);
- if (sticky->n_on_opts) {
- OptIndex *onptr;
- for (onptr = sticky->on_opts;
- onptr < sticky->on_opts + sticky->n_on_opts;
- onptr++)
- opts[*onptr] = 1;
- }
- if (sticky->n_off_opts) {
- OptIndex *offptr;
- for (offptr = sticky->off_opts;
- offptr < sticky->off_opts + sticky->n_off_opts;
- offptr++)
- opts[*offptr] = 0;
- }
- /* All emulations start with pattern disables clear */
- clearpatterndisables();
- } else
- funcsave->restore_sticky = 0;
-
- if (flags & (PM_TAGGED|PM_TAGGED_LOCAL))
- opts[XTRACE] = 1;
- else if (oflags & PM_TAGGED_LOCAL) {
- if (shfunc->node.nam == ANONYMOUS_FUNCTION_NAME /* pointer comparison */)
- flags |= PM_TAGGED_LOCAL;
- else
- opts[XTRACE] = 0;
- }
- if (flags & PM_WARNNESTED)
- opts[WARNNESTEDVAR] = 1;
- else if (oflags & PM_WARNNESTED) {
- if (shfunc->node.nam == ANONYMOUS_FUNCTION_NAME)
- flags |= PM_WARNNESTED;
- else
- opts[WARNNESTEDVAR] = 0;
- }
- funcsave->oflags = oflags;
- /*
- * oflags is static, because we compare it on the next recursive
- * call. Hence also we maintain a saved version for restoring
- * the previous value of oflags after the call.
- */
- oflags = flags;
- opts[PRINTEXITVALUE] = 0;
- if (doshargs) {
- LinkNode node;
-
- node = firstnode(doshargs);
- pparams = x = (char **) zshcalloc(((sizeof *x) *
- (1 + countlinknodes(doshargs))));
- if (isset(FUNCTIONARGZERO)) {
- funcsave->argv0 = argzero;
- argzero = ztrdup(getdata(node));
- }
- /* first node contains name regardless of option */
- node = node->next;
- for (; node; node = node->next, x++)
- *x = ztrdup(getdata(node));
- } else {
- pparams = (char **) zshcalloc(sizeof *pparams);
- if (isset(FUNCTIONARGZERO)) {
- funcsave->argv0 = argzero;
- argzero = ztrdup(argzero);
- }
- }
- ++funcdepth;
- if (zsh_funcnest >= 0 && funcdepth > zsh_funcnest) {
- zerr("maximum nested function level reached; increase FUNCNEST?");
- lastval = 1;
- goto undoshfunc;
- }
- funcsave->fstack.name = dupstring(name);
- /*
- * The caller is whatever is immediately before on the stack,
- * unless we're at the top, in which case it's the script
- * or interactive shell name.
- */
- funcsave->fstack.caller = funcstack ? funcstack->name :
- dupstring(funcsave->argv0 ? funcsave->argv0 : argzero);
- funcsave->fstack.lineno = lineno;
- funcsave->fstack.prev = funcstack;
- funcsave->fstack.tp = FS_FUNC;
- funcstack = &funcsave->fstack;
-
- funcsave->fstack.flineno = shfunc->lineno;
- funcsave->fstack.filename = getshfuncfile(shfunc);
-
- prog = shfunc->funcdef;
- if (prog->flags & EF_RUN) {
- Shfunc shf;
-
- prog->flags &= ~EF_RUN;
-
- runshfunc(prog, NULL, funcsave->fstack.name);
-
- if (!(shf = (Shfunc) shfunctab->getnode(shfunctab,
- (name = fname)))) {
- zwarn("%s: function not defined by file", name);
- if (noreturnval)
- errflag |= ERRFLAG_ERROR;
- else
- lastval = 1;
- goto doneshfunc;
- }
- prog = shf->funcdef;
- }
- runshfunc(prog, wrappers, funcsave->fstack.name);
- doneshfunc:
- funcstack = funcsave->fstack.prev;
- undoshfunc:
- --funcdepth;
- if (retflag) {
- /*
- * This function is forced to return.
- */
- retflag = 0;
- /*
- * The calling function isn't necessarily forced to return,
- * but it should be made sensitive to ERR_EXIT and
- * ERR_RETURN as the assumptions we made at the end of
- * constructs within this function no longer apply. If
- * there are cases where this is not true, they need adding
- * to C03traps.ztst.
- */
- this_noerrexit = 0;
- breaks = funcsave->breaks;
- }
- freearray(pparams);
- if (funcsave->argv0) {
- zsfree(argzero);
- argzero = funcsave->argv0;
- }
- pparams = pptab;
- if (!isset(POSIXBUILTINS)) {
- zoptind = funcsave->zoptind;
- optcind = funcsave->optcind;
- }
- scriptname = funcsave->scriptname;
- oflags = funcsave->oflags;
-
- endpatternscope(); /* before restoring old LOCALPATTERNS */
-
- if (funcsave->restore_sticky) {
- /*
- * If we switched to an emulation environment just for
- * this function, we interpret the option and emulation
- * switch as being a firewall between environments.
- */
- memcpy(opts, funcsave->opts, sizeof(opts));
- emulation = funcsave->emulation;
- sticky = funcsave->sticky;
- } else if (isset(LOCALOPTIONS)) {
- /* restore all shell options except PRIVILEGED and RESTRICTED */
- funcsave->opts[PRIVILEGED] = opts[PRIVILEGED];
- funcsave->opts[RESTRICTED] = opts[RESTRICTED];
- memcpy(opts, funcsave->opts, sizeof(opts));
- emulation = funcsave->emulation;
- } else {
- /* just restore a couple. */
- opts[XTRACE] = funcsave->opts[XTRACE];
- opts[PRINTEXITVALUE] = funcsave->opts[PRINTEXITVALUE];
- opts[LOCALOPTIONS] = funcsave->opts[LOCALOPTIONS];
- opts[LOCALLOOPS] = funcsave->opts[LOCALLOOPS];
- opts[WARNNESTEDVAR] = funcsave->opts[WARNNESTEDVAR];
- }
-
- if (opts[LOCALLOOPS]) {
- if (contflag)
- zwarn("`continue' active at end of function scope");
- if (breaks)
- zwarn("`break' active at end of function scope");
- breaks = funcsave->breaks;
- contflag = funcsave->contflag;
- loops = funcsave->loops;
- }
-
- endtrapscope();
-
- if (trap_state == TRAP_STATE_PRIMED)
- trap_return++;
- ret = lastval;
- noerrexit = funcsave->noerrexit;
- if (noreturnval) {
- lastval = funcsave->lastval;
- numpipestats = funcsave->numpipestats;
- memcpy(pipestats, funcsave->pipestats, sizeof(int)*numpipestats);
- }
- } OLDHEAPS;
-
- unqueue_signals();
-
- /*
- * Exit with a tidy up.
- * Only leave if we're at the end of the appropriate function ---
- * not a nested function. As we usually skip the function body,
- * the only likely case where we need that second test is
- * when we have an "always" block. The endparamscope() has
- * already happened, hence the "+1" here.
- *
- * If we are in an exit trap, finish it first... we wouldn't set
- * exit_pending if we were already in one.
- */
- if (exit_pending && exit_level >= locallevel+1 && !in_exit_trap) {
- if (locallevel > forklevel) {
- /* Still functions to return: force them to do so. */
- retflag = 1;
- breaks = loops;
- } else {
- /*
- * All functions finished: time to exit the shell.
- * We already did the `stopmsg' test when the
- * exit command was handled.
- */
- stopmsg = 1;
- zexit(exit_pending >> 1, 0);
- }
- }
-
- return ret;
-}
-
-/* This finally executes a shell function and any function wrappers *
- * defined by modules. This works by calling the wrapper function which *
- * in turn has to call back this function with the arguments it gets. */
-
-/**/
-mod_export void
-runshfunc(Eprog prog, FuncWrap wrap, char *name)
-{
- int cont, ouu;
- char *ou;
-
- queue_signals();
-
- ou = zalloc(ouu = underscoreused);
- if (ou)
- memcpy(ou, zunderscore, underscoreused);
-
- while (wrap) {
- wrap->module->wrapper++;
- cont = wrap->handler(prog, wrap->next, name);
- wrap->module->wrapper--;
-
- if (!wrap->module->wrapper &&
- (wrap->module->node.flags & MOD_UNLOAD))
- unload_module(wrap->module);
-
- if (!cont) {
- if (ou)
- zfree(ou, ouu);
- unqueue_signals();
- return;
- }
- wrap = wrap->next;
- }
- startparamscope();
- execode(prog, 1, 0, "shfunc"); /* handles signal unqueueing */
- if (ou) {
- setunderscore(ou);
- zfree(ou, ouu);
- }
- endparamscope();
-
- unqueue_signals();
-}
-
-/*
- * Search fpath for an undefined function. Finds the file, and returns the
- * list of its contents.
- *
- * If test is 0, load the function.
- *
- * If test_only is 1, don't load function, just test for it:
- * Non-null return means function was found
- *
- * *fdir points to path at which found (as passed in, not duplicated)
- */
-
-/**/
-Eprog
-getfpfunc(char *s, int *ksh, char **fdir, char **alt_path, int test_only)
-{
- char **pp, buf[PATH_MAX+1];
- off_t len;
- off_t rlen;
- char *d;
- Eprog r;
- int fd;
-
- pp = alt_path ? alt_path : fpath;
- for (; *pp; pp++) {
- if (strlen(*pp) + strlen(s) + 1 >= PATH_MAX)
- continue;
- if (**pp)
- sprintf(buf, "%s/%s", *pp, s);
- else
- strcpy(buf, s);
- if ((r = try_dump_file(*pp, s, buf, ksh, test_only))) {
- if (fdir)
- *fdir = *pp;
- return r;
- }
- unmetafy(buf, NULL);
- if (!access(buf, R_OK) && (fd = open(buf, O_RDONLY | O_NOCTTY)) != -1) {
- struct stat st;
- if (!fstat(fd, &st) && S_ISREG(st.st_mode) &&
- (len = lseek(fd, 0, 2)) != -1) {
- if (test_only) {
- close(fd);
- if (fdir)
- *fdir = *pp;
- return &dummy_eprog;
- }
- d = (char *) zalloc(len + 1);
- lseek(fd, 0, 0);
- if ((rlen = read(fd, d, len)) >= 0) {
- char *oldscriptname = scriptname;
-
- close(fd);
- d[rlen] = '\0';
- d = metafy(d, rlen, META_REALLOC);
-
- scriptname = dupstring(s);
- r = parse_string(d, 1);
- scriptname = oldscriptname;
-
- if (fdir)
- *fdir = *pp;
-
- zfree(d, len + 1);
-
- return r;
- } else
- close(fd);
-
- zfree(d, len + 1);
- } else
- close(fd);
- }
- }
- return test_only ? NULL : &dummy_eprog;
-}
-
-/* Handle the most common type of ksh-style autoloading, when doing a *
- * zsh-style autoload. Given the list read from an autoload file, and the *
- * name of the function being defined, check to see if the file consists *
- * entirely of a single definition for that function. If so, use the *
- * contents of that definition. Otherwise, use the entire file. */
-
-/**/
-Eprog
-stripkshdef(Eprog prog, char *name)
-{
- Wordcode pc;
- wordcode code;
- char *ptr1, *ptr2;
-
- if (!prog)
- return NULL;
- pc = prog->prog;
- code = *pc++;
- if (wc_code(code) != WC_LIST ||
- (WC_LIST_TYPE(code) & (Z_SYNC|Z_END|Z_SIMPLE)) != (Z_SYNC|Z_END|Z_SIMPLE))
- return prog;
- pc++;
- code = *pc++;
- if (wc_code(code) != WC_FUNCDEF || *pc != 1)
- return prog;
-
- /*
- * See if name of function requested (name) is same as
- * name of function in word code. name may still have "-"
- * tokenised. The word code shouldn't, as function names should be
- * untokenised, but reports say it sometimes does.
- */
- ptr1 = name;
- ptr2 = ecrawstr(prog, pc + 1, NULL);
- while (*ptr1 && *ptr2) {
- if (*ptr1 != *ptr2 && *ptr1 != Dash && *ptr1 != '-' &&
- *ptr2 != Dash && *ptr2 != '-')
- break;
- ptr1++;
- ptr2++;
- }
- if (*ptr1 || *ptr2)
- return prog;
-
- {
- Eprog ret;
- Wordcode end = pc + WC_FUNCDEF_SKIP(code);
- int sbeg = pc[2], nstrs = pc[3], nprg, npats = pc[4], plen, len, i;
- Patprog *pp;
-
- pc += 5;
-
- nprg = end - pc;
- plen = nprg * sizeof(wordcode);
- len = plen + (npats * sizeof(Patprog)) + nstrs;
-
- if (prog->flags & EF_MAP) {
- ret = prog;
- free(prog->pats);
- ret->pats = pp = (Patprog *) zalloc(npats * sizeof(Patprog));
- ret->prog = pc;
- ret->strs = prog->strs + sbeg;
- } else {
- ret = (Eprog) zhalloc(sizeof(*ret));
- ret->flags = EF_HEAP;
- ret->pats = pp = (Patprog *) zhalloc(len);
- ret->prog = (Wordcode) (ret->pats + npats);
- ret->strs = (char *) (ret->prog + nprg);
- memcpy(ret->prog, pc, plen);
- memcpy(ret->strs, prog->strs + sbeg, nstrs);
- ret->dump = NULL;
- }
- ret->len = len;
- ret->npats = npats;
- for (i = npats; i--; pp++)
- *pp = dummy_patprog1;
- ret->shf = NULL;
-
- return ret;
- }
-}
-
-/* check to see if AUTOCD applies here */
-
-/**/
-static char *
-cancd(char *s)
-{
- int nocdpath = s[0] == '.' &&
- (s[1] == '/' || !s[1] || (s[1] == '.' && (s[2] == '/' || !s[1])));
- char *t;
-
- if (*s != '/') {
- char sbuf[PATH_MAX+1], **cp;
-
- if (cancd2(s))
- return s;
- if (access(unmeta(s), X_OK) == 0)
- return NULL;
- if (!nocdpath)
- for (cp = cdpath; *cp; cp++) {
- if (strlen(*cp) + strlen(s) + 1 >= PATH_MAX)
- continue;
- if (**cp)
- sprintf(sbuf, "%s/%s", *cp, s);
- else
- strcpy(sbuf, s);
- if (cancd2(sbuf)) {
- doprintdir = -1;
- return dupstring(sbuf);
- }
- }
- if ((t = cd_able_vars(s))) {
- if (cancd2(t)) {
- doprintdir = -1;
- return t;
- }
- }
- return NULL;
- }
- return cancd2(s) ? s : NULL;
-}
-
-/**/
-static int
-cancd2(char *s)
-{
- struct stat buf;
- char *us, *us2 = NULL;
- int ret;
-
- /*
- * If CHASEDOTS and CHASELINKS are not set, we want to rationalize the
- * path by removing foo/.. combinations in the logical rather than
- * the physical path. If either is set, we test the physical path.
- */
- if (!isset(CHASEDOTS) && !isset(CHASELINKS)) {
- if (*s != '/')
- us = tricat(pwd[1] ? pwd : "", "/", s);
- else
- us = ztrdup(s);
- fixdir(us2 = us);
- } else
- us = unmeta(s);
- ret = !(access(us, X_OK) || stat(us, &buf) || !S_ISDIR(buf.st_mode));
- if (us2)
- free(us2);
- return ret;
-}
-
-/**/
-void
-execsave(void)
-{
- struct execstack *es;
-
- es = (struct execstack *) zalloc(sizeof(struct execstack));
- es->list_pipe_pid = list_pipe_pid;
- es->nowait = nowait;
- es->pline_level = pline_level;
- es->list_pipe_child = list_pipe_child;
- es->list_pipe_job = list_pipe_job;
- strcpy(es->list_pipe_text, list_pipe_text);
- es->lastval = lastval;
- es->noeval = noeval;
- es->badcshglob = badcshglob;
- es->cmdoutpid = cmdoutpid;
- es->cmdoutval = cmdoutval;
- es->use_cmdoutval = use_cmdoutval;
- es->procsubstpid = procsubstpid;
- es->trap_return = trap_return;
- es->trap_state = trap_state;
- es->trapisfunc = trapisfunc;
- es->traplocallevel = traplocallevel;
- es->noerrs = noerrs;
- es->this_noerrexit = this_noerrexit;
- es->underscore = ztrdup(zunderscore);
- es->next = exstack;
- exstack = es;
- noerrs = cmdoutpid = 0;
-}
-
-/**/
-void
-execrestore(void)
-{
- struct execstack *en = exstack;
-
- DPUTS(!exstack, "BUG: execrestore() without execsave()");
-
- queue_signals();
- exstack = exstack->next;
-
- list_pipe_pid = en->list_pipe_pid;
- nowait = en->nowait;
- pline_level = en->pline_level;
- list_pipe_child = en->list_pipe_child;
- list_pipe_job = en->list_pipe_job;
- strcpy(list_pipe_text, en->list_pipe_text);
- lastval = en->lastval;
- noeval = en->noeval;
- badcshglob = en->badcshglob;
- cmdoutpid = en->cmdoutpid;
- cmdoutval = en->cmdoutval;
- use_cmdoutval = en->use_cmdoutval;
- procsubstpid = en->procsubstpid;
- trap_return = en->trap_return;
- trap_state = en->trap_state;
- trapisfunc = en->trapisfunc;
- traplocallevel = en->traplocallevel;
- noerrs = en->noerrs;
- this_noerrexit = en->this_noerrexit;
- setunderscore(en->underscore);
- zsfree(en->underscore);
- free(en);
-
- unqueue_signals();
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/glob.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/glob.c
deleted file mode 100644
index ed2c90bd..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/glob.c
+++ /dev/null
@@ -1,3913 +0,0 @@
-/*
- * glob.c - filename generation
- *
- * 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 "glob.pro"
-
-#if defined(OFF_T_IS_64_BIT) && defined(__GNUC__)
-# define ALIGN64 __attribute__((aligned(8)))
-#else
-# define ALIGN64
-#endif
-
-/* flag for CSHNULLGLOB */
-
-typedef struct gmatch *Gmatch;
-
-struct gmatch {
- /* Metafied file name */
- char *name;
- /* Unmetafied file name; embedded nulls can't occur in file names */
- char *uname;
- /*
- * Array of sort strings: one for each GS_EXEC sort type in
- * the glob qualifiers.
- */
- char **sortstrs;
- off_t size ALIGN64;
- long atime;
- long mtime;
- long ctime;
- long links;
- off_t _size ALIGN64;
- long _atime;
- long _mtime;
- long _ctime;
- long _links;
-#ifdef GET_ST_ATIME_NSEC
- long ansec;
- long _ansec;
-#endif
-#ifdef GET_ST_MTIME_NSEC
- long mnsec;
- long _mnsec;
-#endif
-#ifdef GET_ST_CTIME_NSEC
- long cnsec;
- long _cnsec;
-#endif
-};
-
-#define GS_NAME 1
-#define GS_DEPTH 2
-#define GS_EXEC 4
-
-#define GS_SHIFT_BASE 8
-
-#define GS_SIZE (GS_SHIFT_BASE)
-#define GS_ATIME (GS_SHIFT_BASE << 1)
-#define GS_MTIME (GS_SHIFT_BASE << 2)
-#define GS_CTIME (GS_SHIFT_BASE << 3)
-#define GS_LINKS (GS_SHIFT_BASE << 4)
-
-#define GS_SHIFT 5
-#define GS__SIZE (GS_SIZE << GS_SHIFT)
-#define GS__ATIME (GS_ATIME << GS_SHIFT)
-#define GS__MTIME (GS_MTIME << GS_SHIFT)
-#define GS__CTIME (GS_CTIME << GS_SHIFT)
-#define GS__LINKS (GS_LINKS << GS_SHIFT)
-
-#define GS_DESC (GS_SHIFT_BASE << (2*GS_SHIFT))
-#define GS_NONE (GS_SHIFT_BASE << (2*GS_SHIFT+1))
-
-#define GS_NORMAL (GS_SIZE | GS_ATIME | GS_MTIME | GS_CTIME | GS_LINKS)
-#define GS_LINKED (GS_NORMAL << GS_SHIFT)
-
-/**/
-int badcshglob;
-
-/**/
-int pathpos; /* position in pathbuf (needed by pattern code) */
-
-/*
- * pathname buffer (needed by pattern code).
- * It is currently believed the string in here is stored metafied and is
- * unmetafied temporarily as needed by system calls.
- */
-
-/**/
-char *pathbuf;
-
-typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figure. */
-
-/* modifier for unit conversions */
-
-#define TT_DAYS 0
-#define TT_HOURS 1
-#define TT_MINS 2
-#define TT_WEEKS 3
-#define TT_MONTHS 4
-#define TT_SECONDS 5
-
-#define TT_BYTES 0
-#define TT_POSIX_BLOCKS 1
-#define TT_KILOBYTES 2
-#define TT_MEGABYTES 3
-#define TT_GIGABYTES 4
-#define TT_TERABYTES 5
-
-
-typedef int (*TestMatchFunc) _((char *, struct stat *, off_t, char *));
-
-struct qual {
- struct qual *next; /* Next qualifier, must match */
- struct qual *or; /* Alternative set of qualifiers to match */
- TestMatchFunc func; /* Function to call to test match */
- off_t data ALIGN64; /* Argument passed to function */
- int sense; /* Whether asserting or negating */
- int amc; /* Flag for which time to test (a, m, c) */
- int range; /* Whether to test <, > or = (as per signum) */
- int units; /* Multiplier for time or size, respectively */
- char *sdata; /* currently only: expression to eval */
-};
-
-/* Prefix, suffix for doing zle trickery */
-
-/**/
-mod_export char *glob_pre, *glob_suf;
-
-/* Element of a glob sort */
-struct globsort {
- /* Sort type */
- int tp;
- /* Sort code to eval, if type is GS_EXEC */
- char *exec;
-};
-
-/* Maximum entries in sort array */
-#define MAX_SORTS (12)
-
-/* struct to easily save/restore current state */
-
-struct globdata {
- int gd_pathpos;
- char *gd_pathbuf;
-
- int gd_matchsz; /* size of matchbuf */
- int gd_matchct; /* number of matches found */
- int gd_pathbufsz; /* size of pathbuf */
- int gd_pathbufcwd; /* where did we chdir()'ed */
- Gmatch gd_matchbuf; /* array of matches */
- Gmatch gd_matchptr; /* &matchbuf[matchct] */
- char *gd_colonmod; /* colon modifiers in qualifier list */
-
- /* Qualifiers pertaining to current pattern */
- struct qual *gd_quals;
-
- /* Other state values for current pattern */
- int gd_qualct, gd_qualorct;
- int gd_range, gd_amc, gd_units;
- int gd_gf_nullglob, gd_gf_markdirs, gd_gf_noglobdots, gd_gf_listtypes;
- int gd_gf_numsort;
- int gd_gf_follow, gd_gf_sorts, gd_gf_nsorts;
- struct globsort gd_gf_sortlist[MAX_SORTS];
- LinkList gd_gf_pre_words, gd_gf_post_words;
-
- char *gd_glob_pre, *gd_glob_suf;
-};
-
-/* The variable with the current globbing state and convenience macros */
-
-static struct globdata curglobdata;
-
-#define matchsz (curglobdata.gd_matchsz)
-#define matchct (curglobdata.gd_matchct)
-#define pathbufsz (curglobdata.gd_pathbufsz)
-#define pathbufcwd (curglobdata.gd_pathbufcwd)
-#define matchbuf (curglobdata.gd_matchbuf)
-#define matchptr (curglobdata.gd_matchptr)
-#define colonmod (curglobdata.gd_colonmod)
-#define quals (curglobdata.gd_quals)
-#define qualct (curglobdata.gd_qualct)
-#define qualorct (curglobdata.gd_qualorct)
-#define g_range (curglobdata.gd_range)
-#define g_amc (curglobdata.gd_amc)
-#define g_units (curglobdata.gd_units)
-#define gf_nullglob (curglobdata.gd_gf_nullglob)
-#define gf_markdirs (curglobdata.gd_gf_markdirs)
-#define gf_noglobdots (curglobdata.gd_gf_noglobdots)
-#define gf_listtypes (curglobdata.gd_gf_listtypes)
-#define gf_numsort (curglobdata.gd_gf_numsort)
-#define gf_follow (curglobdata.gd_gf_follow)
-#define gf_sorts (curglobdata.gd_gf_sorts)
-#define gf_nsorts (curglobdata.gd_gf_nsorts)
-#define gf_sortlist (curglobdata.gd_gf_sortlist)
-#define gf_pre_words (curglobdata.gd_gf_pre_words)
-#define gf_post_words (curglobdata.gd_gf_post_words)
-
-/* and macros for save/restore */
-
-#define save_globstate(N) \
- do { \
- queue_signals(); \
- memcpy(&(N), &curglobdata, sizeof(struct globdata)); \
- (N).gd_pathpos = pathpos; \
- (N).gd_pathbuf = pathbuf; \
- (N).gd_glob_pre = glob_pre; \
- (N).gd_glob_suf = glob_suf; \
- pathbuf = NULL; \
- unqueue_signals(); \
- } while (0)
-
-#define restore_globstate(N) \
- do { \
- queue_signals(); \
- zfree(pathbuf, pathbufsz); \
- memcpy(&curglobdata, &(N), sizeof(struct globdata)); \
- pathpos = (N).gd_pathpos; \
- pathbuf = (N).gd_pathbuf; \
- glob_pre = (N).gd_glob_pre; \
- glob_suf = (N).gd_glob_suf; \
- unqueue_signals(); \
- } while (0)
-
-/* pathname component in filename patterns */
-
-struct complist {
- Complist next;
- Patprog pat;
- int closure; /* 1 if this is a (foo/)# */
- int follow; /* 1 to go thru symlinks */
-};
-
-/* Add a component to pathbuf: This keeps track of how *
- * far we are into a file name, since each path component *
- * must be matched separately. */
-
-/**/
-static void
-addpath(char *s, int l)
-{
- DPUTS(!pathbuf, "BUG: pathbuf not initialised");
- while (pathpos + l + 1 >= pathbufsz)
- pathbuf = zrealloc(pathbuf, pathbufsz *= 2);
- while (l--)
- pathbuf[pathpos++] = *s++;
- pathbuf[pathpos++] = '/';
- pathbuf[pathpos] = '\0';
-}
-
-/* stat the filename s appended to pathbuf. l should be true for lstat, *
- * false for stat. If st is NULL, the file is only checked for existance. *
- * s == "" is treated as s == ".". This is necessary since on most systems *
- * foo/ can be used to reference a non-directory foo. Returns nonzero if *
- * the file does not exists. */
-
-/**/
-static int
-statfullpath(const char *s, struct stat *st, int l)
-{
- char buf[PATH_MAX+1];
-
- DPUTS(strlen(s) + !*s + pathpos - pathbufcwd >= PATH_MAX,
- "BUG: statfullpath(): pathname too long");
- strcpy(buf, pathbuf + pathbufcwd);
- strcpy(buf + pathpos - pathbufcwd, s);
- if (!*s && *buf) {
- /*
- * Don't add the '.' if the path so far is empty, since
- * then we get bogus empty strings inserted as files.
- */
- buf[pathpos - pathbufcwd] = '.';
- buf[pathpos - pathbufcwd + 1] = '\0';
- l = 0;
- }
- unmetafy(buf, NULL);
- if (!st) {
- char lbuf[1];
- return access(buf, F_OK) && (!l || readlink(buf, lbuf, 1) < 0);
- }
- return l ? lstat(buf, st) : stat(buf, st);
-}
-
-/* This may be set by qualifier functions to an array of strings to insert
- * into the list instead of the original string. */
-
-static char **inserts;
-
-/* add a match to the list */
-
-/**/
-static void
-insert(char *s, int checked)
-{
- struct stat buf, buf2, *bp;
- char *news = s;
- int statted = 0;
-
- queue_signals();
- inserts = NULL;
-
- if (gf_listtypes || gf_markdirs) {
- /* Add the type marker to the end of the filename */
- mode_t mode;
- checked = statted = 1;
- if (statfullpath(s, &buf, 1)) {
- unqueue_signals();
- return;
- }
- mode = buf.st_mode;
- if (gf_follow) {
- if (!S_ISLNK(mode) || statfullpath(s, &buf2, 0))
- memcpy(&buf2, &buf, sizeof(buf));
- statted |= 2;
- mode = buf2.st_mode;
- }
- if (gf_listtypes || S_ISDIR(mode)) {
- int ll = strlen(s);
-
- news = (char *) hcalloc(ll + 2);
- strcpy(news, s);
- news[ll] = file_type(mode);
- news[ll + 1] = '\0';
- }
- }
- if (qualct || qualorct) {
- /* Go through the qualifiers, rejecting the file if appropriate */
- struct qual *qo, *qn;
-
- if (!statted && statfullpath(s, &buf, 1)) {
- unqueue_signals();
- return;
- }
- news = dyncat(pathbuf, news);
-
- statted = 1;
- qo = quals;
- for (qn = qo; qn && qn->func;) {
- g_range = qn->range;
- g_amc = qn->amc;
- g_units = qn->units;
- if ((qn->sense & 2) && !(statted & 2)) {
- /* If (sense & 2), we're following links */
- if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
- memcpy(&buf2, &buf, sizeof(buf));
- statted |= 2;
- }
- bp = (qn->sense & 2) ? &buf2 : &buf;
- /* Reject the file if the function returned zero *
- * and the sense was positive (sense&1 == 0), or *
- * vice versa. */
- if ((!((qn->func) (news, bp, qn->data, qn->sdata))
- ^ qn->sense) & 1) {
- /* Try next alternative, or return if there are no more */
- if (!(qo = qo->or)) {
- unqueue_signals();
- return;
- }
- qn = qo;
- continue;
- }
- qn = qn->next;
- }
- } else if (!checked) {
- if (statfullpath(s, &buf, 1)) {
- unqueue_signals();
- return;
- }
- statted = 1;
- news = dyncat(pathbuf, news);
- } else
- news = dyncat(pathbuf, news);
-
- while (!inserts || (news = dupstring(*inserts++))) {
- if (colonmod) {
- /* Handle the remainder of the qualifier: e.g. (:r:s/foo/bar/). */
- char *mod = colonmod;
- modify(&news, &mod);
- }
- if (!statted && (gf_sorts & GS_NORMAL)) {
- statfullpath(s, &buf, 1);
- statted = 1;
- }
- if (!(statted & 2) && (gf_sorts & GS_LINKED)) {
- if (statted) {
- if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
- memcpy(&buf2, &buf, sizeof(buf));
- } else if (statfullpath(s, &buf2, 0))
- statfullpath(s, &buf2, 1);
- statted |= 2;
- }
- matchptr->name = news;
- if (statted & 1) {
- matchptr->size = buf.st_size;
- matchptr->atime = buf.st_atime;
- matchptr->mtime = buf.st_mtime;
- matchptr->ctime = buf.st_ctime;
- matchptr->links = buf.st_nlink;
-#ifdef GET_ST_ATIME_NSEC
- matchptr->ansec = GET_ST_ATIME_NSEC(buf);
-#endif
-#ifdef GET_ST_MTIME_NSEC
- matchptr->mnsec = GET_ST_MTIME_NSEC(buf);
-#endif
-#ifdef GET_ST_CTIME_NSEC
- matchptr->cnsec = GET_ST_CTIME_NSEC(buf);
-#endif
- }
- if (statted & 2) {
- matchptr->_size = buf2.st_size;
- matchptr->_atime = buf2.st_atime;
- matchptr->_mtime = buf2.st_mtime;
- matchptr->_ctime = buf2.st_ctime;
- matchptr->_links = buf2.st_nlink;
-#ifdef GET_ST_ATIME_NSEC
- matchptr->_ansec = GET_ST_ATIME_NSEC(buf2);
-#endif
-#ifdef GET_ST_MTIME_NSEC
- matchptr->_mnsec = GET_ST_MTIME_NSEC(buf2);
-#endif
-#ifdef GET_ST_CTIME_NSEC
- matchptr->_cnsec = GET_ST_CTIME_NSEC(buf2);
-#endif
- }
- matchptr++;
-
- if (++matchct == matchsz) {
- matchbuf = (Gmatch)zrealloc((char *)matchbuf,
- sizeof(struct gmatch) * (matchsz *= 2));
-
- matchptr = matchbuf + matchct;
- }
- if (!inserts)
- break;
- }
- unqueue_signals();
- return;
-}
-
-/* Do the globbing: scanner is called recursively *
- * with successive bits of the path until we've *
- * tried all of it. */
-
-/**/
-static void
-scanner(Complist q, int shortcircuit)
-{
- Patprog p;
- int closure;
- int pbcwdsav = pathbufcwd;
- int errssofar = errsfound;
- struct dirsav ds;
-
- if (!q || errflag)
- return;
- init_dirsav(&ds);
-
- if ((closure = q->closure)) {
- /* (foo/)# - match zero or more dirs */
- if (q->closure == 2) /* (foo/)## - match one or more dirs */
- q->closure = 1;
- else {
- scanner(q->next, shortcircuit);
- if (shortcircuit && shortcircuit == matchct)
- return;
- }
- }
- p = q->pat;
- /* Now the actual matching for the current path section. */
- if (p->flags & PAT_PURES) {
- /*
- * It's a straight string to the end of the path section.
- */
- char *str = (char *)p + p->startoff;
- int l = p->patmlen;
-
- if (l + !l + pathpos - pathbufcwd >= PATH_MAX) {
- int err;
-
- if (l >= PATH_MAX)
- return;
- err = lchdir(unmeta(pathbuf + pathbufcwd), &ds, 0);
- if (err == -1)
- return;
- if (err) {
- zerr("current directory lost during glob");
- return;
- }
- pathbufcwd = pathpos;
- }
- if (q->next) {
- /* Not the last path section. Just add it to the path. */
- int oppos = pathpos;
-
- if (!errflag) {
- int add = 1;
-
- if (q->closure && *pathbuf) {
- if (!strcmp(str, "."))
- add = 0;
- else if (!strcmp(str, "..")) {
- struct stat sc, sr;
-
- add = (stat("/", &sr) || stat(unmeta(pathbuf), &sc) ||
- sr.st_ino != sc.st_ino ||
- sr.st_dev != sc.st_dev);
- }
- }
- if (add) {
- addpath(str, l);
- if (!closure || !statfullpath("", NULL, 1)) {
- scanner((q->closure) ? q : q->next, shortcircuit);
- if (shortcircuit && shortcircuit == matchct)
- return;
- }
- pathbuf[pathpos = oppos] = '\0';
- }
- }
- } else {
- if (str[l])
- str = dupstrpfx(str, l);
- insert(str, 0);
- if (shortcircuit && shortcircuit == matchct)
- return;
- }
- } else {
- /* Do pattern matching on current path section. */
- char *fn = pathbuf[pathbufcwd] ? unmeta(pathbuf + pathbufcwd) : ".";
- int dirs = !!q->next;
- DIR *lock = opendir(fn);
- char *subdirs = NULL;
- int subdirlen = 0;
-
- if (lock == NULL)
- return;
- while ((fn = zreaddir(lock, 1)) && !errflag) {
- /* prefix and suffix are zle trickery */
- if (!dirs && !colonmod &&
- ((glob_pre && !strpfx(glob_pre, fn))
- || (glob_suf && !strsfx(glob_suf, fn))))
- continue;
- errsfound = errssofar;
- if (pattry(p, fn)) {
- /* if this name matchs the pattern... */
- if (pbcwdsav == pathbufcwd &&
- strlen(fn) + pathpos - pathbufcwd >= PATH_MAX) {
- int err;
-
- DPUTS(pathpos == pathbufcwd,
- "BUG: filename longer than PATH_MAX");
- err = lchdir(unmeta(pathbuf + pathbufcwd), &ds, 0);
- if (err == -1)
- break;
- if (err) {
- zerr("current directory lost during glob");
- break;
- }
- pathbufcwd = pathpos;
- }
- if (dirs) {
- int l;
-
- /*
- * If not the last component in the path:
- *
- * If we made an approximation in the new path segment,
- * then it is possible we made too many errors. For
- * example, (ab)#(cb)# will match the directory abcb
- * with one error if allowed to, even though it can
- * match with none. This will stop later parts of the
- * path matching, so we need to check by reducing the
- * maximum number of errors and seeing if the directory
- * still matches. Luckily, this is not a terribly
- * common case, since complex patterns typically occur
- * in the last part of the path which is not affected
- * by this problem.
- */
- if (errsfound > errssofar) {
- forceerrs = errsfound - 1;
- while (forceerrs >= errssofar) {
- errsfound = errssofar;
- if (!pattry(p, fn))
- break;
- forceerrs = errsfound - 1;
- }
- errsfound = forceerrs + 1;
- forceerrs = -1;
- }
- if (closure) {
- /* if matching multiple directories */
- struct stat buf;
-
- if (statfullpath(fn, &buf, !q->follow)) {
- if (errno != ENOENT && errno != EINTR &&
- errno != ENOTDIR && !errflag) {
- zwarn("%e: %s", errno, fn);
- }
- continue;
- }
- if (!S_ISDIR(buf.st_mode))
- continue;
- }
- l = strlen(fn) + 1;
- subdirs = hrealloc(subdirs, subdirlen, subdirlen + l
- + sizeof(int));
- strcpy(subdirs + subdirlen, fn);
- subdirlen += l;
- /* store the count of errors made so far, too */
- memcpy(subdirs + subdirlen, (char *)&errsfound,
- sizeof(int));
- subdirlen += sizeof(int);
- } else {
- /* if the last filename component, just add it */
- insert(fn, 1);
- if (shortcircuit && shortcircuit == matchct) {
- closedir(lock);
- return;
- }
- }
- }
- }
- closedir(lock);
- if (subdirs) {
- int oppos = pathpos;
-
- for (fn = subdirs; fn < subdirs+subdirlen; ) {
- int l = strlen(fn);
- addpath(fn, l);
- fn += l + 1;
- memcpy((char *)&errsfound, fn, sizeof(int));
- fn += sizeof(int);
- /* scan next level */
- scanner((q->closure) ? q : q->next, shortcircuit);
- if (shortcircuit && shortcircuit == matchct)
- return;
- pathbuf[pathpos = oppos] = '\0';
- }
- hrealloc(subdirs, subdirlen, 0);
- }
- }
- if (pbcwdsav < pathbufcwd) {
- if (restoredir(&ds))
- zerr("current directory lost during glob");
- zsfree(ds.dirname);
- if (ds.dirfd >= 0)
- close(ds.dirfd);
- pathbufcwd = pbcwdsav;
- }
- return;
-}
-
-/* This function tokenizes a zsh glob pattern */
-
-/**/
-static Complist
-parsecomplist(char *instr)
-{
- Patprog p1;
- Complist l1;
- char *str;
- int compflags = gf_noglobdots ? (PAT_FILE|PAT_NOGLD) : PAT_FILE;
-
- if (instr[0] == Star && instr[1] == Star) {
- int shortglob = 0;
- if (instr[2] == '/' || (instr[2] == Star && instr[3] == '/')
- || (shortglob = isset(GLOBSTARSHORT))) {
- /* Match any number of directories. */
- int follow;
-
- /* with three stars, follow symbolic links */
- follow = (instr[2] == Star);
- /*
- * With GLOBSTARSHORT, leave a star in place for the
- * pattern inside the directory.
- */
- instr += ((shortglob ? 1 : 3) + follow);
-
- /* Now get the next path component if there is one. */
- l1 = (Complist) zhalloc(sizeof *l1);
- if ((l1->next = parsecomplist(instr)) == NULL) {
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL);
- l1->closure = 1; /* ...zero or more times. */
- l1->follow = follow;
- return l1;
- }
- }
-
- /* Parse repeated directories such as (dir/)# and (dir/)## */
- if (*(str = instr) == zpc_special[ZPC_INPAR] &&
- !skipparens(Inpar, Outpar, (char **)&str) &&
- *str == zpc_special[ZPC_HASH] && str[-2] == '/') {
- instr++;
- if (!(p1 = patcompile(instr, compflags, &instr)))
- return NULL;
- if (instr[0] == '/' && instr[1] == Outpar && instr[2] == Pound) {
- int pdflag = 0;
-
- instr += 3;
- if (*instr == Pound) {
- pdflag = 1;
- instr++;
- }
- l1 = (Complist) zhalloc(sizeof *l1);
- l1->pat = p1;
- /* special case (/)# to avoid infinite recursion */
- l1->closure = (*((char *)p1 + p1->startoff)) ? 1 + pdflag : 0;
- l1->follow = 0;
- l1->next = parsecomplist(instr);
- return (l1->pat) ? l1 : NULL;
- }
- } else {
- /* parse single path component */
- if (!(p1 = patcompile(instr, compflags|PAT_FILET, &instr)))
- return NULL;
- /* then do the remaining path components */
- if (*instr == '/' || !*instr) {
- int ef = *instr == '/';
-
- l1 = (Complist) zhalloc(sizeof *l1);
- l1->pat = p1;
- l1->closure = 0;
- l1->next = ef ? parsecomplist(instr+1) : NULL;
- return (ef && !l1->next) ? NULL : l1;
- }
- }
- errflag |= ERRFLAG_ERROR;
- return NULL;
-}
-
-/* turn a string into a Complist struct: this has path components */
-
-/**/
-static Complist
-parsepat(char *str)
-{
- long assert;
- int ignore;
-
- patcompstart();
- /*
- * Check for initial globbing flags, so that they don't form
- * a bogus path component.
- */
- if ((*str == zpc_special[ZPC_INPAR] && str[1] == zpc_special[ZPC_HASH]) ||
- (*str == zpc_special[ZPC_KSH_AT] && str[1] == Inpar &&
- str[2] == zpc_special[ZPC_HASH])) {
- str += (*str == Inpar) ? 2 : 3;
- if (!patgetglobflags(&str, &assert, &ignore))
- return NULL;
- }
-
- /* Now there is no (#X) in front, we can check the path. */
- if (!pathbuf)
- pathbuf = zalloc(pathbufsz = PATH_MAX+1);
- DPUTS(pathbufcwd, "BUG: glob changed directory");
- if (*str == '/') { /* pattern has absolute path */
- str++;
- pathbuf[0] = '/';
- pathbuf[pathpos = 1] = '\0';
- } else /* pattern is relative to pwd */
- pathbuf[pathpos = 0] = '\0';
-
- return parsecomplist(str);
-}
-
-/* get number after qualifier */
-
-/**/
-static off_t
-qgetnum(char **s)
-{
- off_t v = 0;
-
- if (!idigit(**s)) {
- zerr("number expected");
- return 0;
- }
- while (idigit(**s))
- v = v * 10 + *(*s)++ - '0';
- return v;
-}
-
-/* get mode spec after qualifier */
-
-/**/
-static zlong
-qgetmodespec(char **s)
-{
- zlong yes = 0, no = 0, val, mask, t;
- char *p = *s, c, how, end;
-
- if ((c = *p) == '=' || c == Equals || c == '+' || c == '-' ||
- c == '?' || c == Quest || (c >= '0' && c <= '7')) {
- end = 0;
- c = 0;
- } else {
- end = (c == '<' ? '>' :
- (c == '[' ? ']' :
- (c == '{' ? '}' :
- (c == Inang ? Outang :
- (c == Inbrack ? Outbrack :
- (c == Inbrace ? Outbrace : c))))));
- p++;
- }
- do {
- mask = 0;
- while (((c = *p) == 'u' || c == 'g' || c == 'o' || c == 'a') && end) {
- switch (c) {
- case 'o': mask |= 01007; break;
- case 'g': mask |= 02070; break;
- case 'u': mask |= 04700; break;
- case 'a': mask |= 07777; break;
- }
- p++;
- }
- how = ((c == '+' || c == '-') ? c : '=');
- if (c == '+' || c == '-' || c == '=' || c == Equals)
- p++;
- val = 0;
- if (mask) {
- while ((c = *p++) != ',' && c != end) {
- switch (c) {
- case 'x': val |= 00111; break;
- case 'w': val |= 00222; break;
- case 'r': val |= 00444; break;
- case 's': val |= 06000; break;
- case 't': val |= 01000; break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- t = ((zlong) c - '0');
- val |= t | (t << 3) | (t << 6);
- break;
- default:
- zerr("invalid mode specification");
- return 0;
- }
- }
- if (how == '=' || how == '+') {
- yes |= val & mask;
- val = ~val;
- }
- if (how == '=' || how == '-')
- no |= val & mask;
- } else if (!(end && c == end) && c != ',' && c) {
- t = 07777;
- while ((c = *p) == '?' || c == Quest ||
- (c >= '0' && c <= '7')) {
- if (c == '?' || c == Quest) {
- t = (t << 3) | 7;
- val <<= 3;
- } else {
- t <<= 3;
- val = (val << 3) | ((zlong) c - '0');
- }
- p++;
- }
- if (end && c != end && c != ',') {
- zerr("invalid mode specification");
- return 0;
- }
- if (how == '=') {
- yes = (yes & ~t) | val;
- no = (no & ~t) | (~val & ~t);
- } else if (how == '+')
- yes |= val;
- else
- no |= val;
- } else {
- zerr("invalid mode specification");
- return 0;
- }
- } while (end && c != end);
-
- *s = p;
- return ((yes & 07777) | ((no & 07777) << 12));
-}
-
-static int
-gmatchcmp(Gmatch a, Gmatch b)
-{
- int i;
- off_t r = 0L;
- struct globsort *s;
- char **asortstrp = NULL, **bsortstrp = NULL;
-
- for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
- switch (s->tp & ~GS_DESC) {
- case GS_NAME:
- r = zstrcmp(b->uname, a->uname,
- gf_numsort ? SORTIT_NUMERICALLY : 0);
- break;
- case GS_DEPTH:
- {
- char *aptr = a->name, *bptr = b->name;
- int slasha = 0, slashb = 0;
- /* Count slashes. Trailing slashes don't count. */
- while (*aptr && *aptr == *bptr)
- aptr++, bptr++;
- /* Like I just said... */
- if ((!*aptr || !*bptr) && aptr > a->name && aptr[-1] == '/')
- aptr--, bptr--;
- if (*aptr)
- for (; aptr[1]; aptr++)
- if (*aptr == '/') {
- slasha = 1;
- break;
- }
- if (*bptr)
- for (; bptr[1]; bptr++)
- if (*bptr == '/') {
- slashb = 1;
- break;
- }
- r = slasha - slashb;
- }
- break;
- case GS_EXEC:
- if (!asortstrp) {
- asortstrp = a->sortstrs;
- bsortstrp = b->sortstrs;
- } else {
- asortstrp++;
- bsortstrp++;
- }
- r = zstrcmp(*bsortstrp, *asortstrp,
- gf_numsort ? SORTIT_NUMERICALLY : 0);
- break;
- case GS_SIZE:
- r = b->size - a->size;
- break;
- case GS_ATIME:
- r = a->atime - b->atime;
-#ifdef GET_ST_ATIME_NSEC
- if (!r)
- r = a->ansec - b->ansec;
-#endif
- break;
- case GS_MTIME:
- r = a->mtime - b->mtime;
-#ifdef GET_ST_MTIME_NSEC
- if (!r)
- r = a->mnsec - b->mnsec;
-#endif
- break;
- case GS_CTIME:
- r = a->ctime - b->ctime;
-#ifdef GET_ST_CTIME_NSEC
- if (!r)
- r = a->cnsec - b->cnsec;
-#endif
- break;
- case GS_LINKS:
- r = b->links - a->links;
- break;
- case GS__SIZE:
- r = b->_size - a->_size;
- break;
- case GS__ATIME:
- r = a->_atime - b->_atime;
-#ifdef GET_ST_ATIME_NSEC
- if (!r)
- r = a->_ansec - b->_ansec;
-#endif
- break;
- case GS__MTIME:
- r = a->_mtime - b->_mtime;
-#ifdef GET_ST_MTIME_NSEC
- if (!r)
- r = a->_mnsec - b->_mnsec;
-#endif
- break;
- case GS__CTIME:
- r = a->_ctime - b->_ctime;
-#ifdef GET_ST_CTIME_NSEC
- if (!r)
- r = a->_cnsec - b->_cnsec;
-#endif
- break;
- case GS__LINKS:
- r = b->_links - a->_links;
- break;
- }
- if (r)
- return (s->tp & GS_DESC) ?
- (r < 0L ? 1 : -1) :
- (r > 0L ? 1 : -1);
- }
- return 0;
-}
-
-/*
- * Duplicate a list of qualifiers using the `next' linkage (not the
- * `or' linkage). Return the head element and set *last (if last non-NULL)
- * to point to the last element of the new list. All allocation is on the
- * heap (or off the heap?)
- */
-static struct qual *dup_qual_list(struct qual *orig, struct qual **lastp)
-{
- struct qual *qfirst = NULL, *qlast = NULL;
-
- while (orig) {
- struct qual *qnew = (struct qual *)zhalloc(sizeof(struct qual));
- *qnew = *orig;
- qnew->next = qnew->or = NULL;
-
- if (!qfirst)
- qfirst = qnew;
- if (qlast)
- qlast->next = qnew;
- qlast = qnew;
-
- orig = orig->next;
- }
-
- if (lastp)
- *lastp = qlast;
- return qfirst;
-}
-
-
-/*
- * Get a glob string for execution, following e, P or + qualifiers.
- * Pointer is character after the e, P or +.
- */
-
-/**/
-static char *
-glob_exec_string(char **sp)
-{
- char sav, *tt, *sdata, *s = *sp;
- int plus;
-
- if (s[-1] == '+') {
- plus = 0;
- tt = itype_end(s, IIDENT, 0);
- if (tt == s)
- {
- zerr("missing identifier after `+'");
- return NULL;
- }
- } else {
- tt = get_strarg(s, &plus);
- if (!*tt)
- {
- zerr("missing end of string");
- return NULL;
- }
- }
-
- sav = *tt;
- *tt = '\0';
- sdata = dupstring(s + plus);
- untokenize(sdata);
- *tt = sav;
- if (sav)
- *sp = tt + plus;
- else
- *sp = tt;
-
- return sdata;
-}
-
-/*
- * Insert a glob match.
- * If there were words to prepend given by the P glob qualifier, do so.
- */
-static void
-insert_glob_match(LinkList list, LinkNode next, char *data)
-{
- if (gf_pre_words) {
- LinkNode added;
- for (added = firstnode(gf_pre_words); added; incnode(added)) {
- next = insertlinknode(list, next, dupstring(getdata(added)));
- }
- }
-
- next = insertlinknode(list, next, data);
-
- if (gf_post_words) {
- LinkNode added;
- for (added = firstnode(gf_post_words); added; incnode(added)) {
- next = insertlinknode(list, next, dupstring(getdata(added)));
- }
- }
-}
-
-/*
- * Return
- * 1 if str ends in bare glob qualifiers
- * 2 if str ends in non-bare glob qualifiers (#q)
- * 0 otherwise.
- *
- * str is the string to check.
- * sl is its length (to avoid recalculation).
- * nobareglob is 1 if bare glob qualifiers are not allowed.
- * *sp, if sp is not null, will be a pointer to the opening parenthesis.
- */
-
-/**/
-int
-checkglobqual(char *str, int sl, int nobareglob, char **sp)
-{
- char *s;
- int paren, ret = 1;
-
- if (str[sl - 1] != Outpar)
- return 0;
-
- /* Check these are really qualifiers, not a set of *
- * alternatives or exclusions. We can be more *
- * lenient with an explicit (#q) than with a bare *
- * set of qualifiers. */
- paren = 0;
- for (s = str + sl - 2; *s && (*s != Inpar || paren); s--) {
- switch (*s) {
- case Outpar:
- paren++; /*FALLTHROUGH*/
- case Bar:
- if (!zpc_disables[ZPC_BAR])
- nobareglob = 1;
- break;
- case Tilde:
- if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE])
- nobareglob = 1;
- break;
- case Inpar:
- paren--;
- break;
- }
- if (s == str)
- break;
- }
- if (*s != Inpar)
- return 0;
- if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) {
- if (s[2] != 'q')
- return 0;
- ret = 2;
- } else if (nobareglob)
- return 0;
-
- if (sp)
- *sp = s;
-
- return ret;
-}
-
-/* Main entry point to the globbing code for filename globbing. *
- * np points to a node in the list which will be expanded *
- * into a series of nodes. */
-
-/**/
-void
-zglob(LinkList list, LinkNode np, int nountok)
-{
- struct qual *qo, *qn, *ql;
- LinkNode node = prevnode(np);
- char *str; /* the pattern */
- int sl; /* length of the pattern */
- Complist q; /* pattern after parsing */
- char *ostr = (char *)getdata(np); /* the pattern before the parser */
- /* chops it up */
- int first = 0, end = -1; /* index of first match to return */
- /* and index+1 of the last match */
- struct globdata saved; /* saved glob state */
- int nobareglob = !isset(BAREGLOBQUAL);
- int shortcircuit = 0; /* How many files to match; */
- /* 0 means no limit */
-
- if (unset(GLOBOPT) || !haswilds(ostr) || unset(EXECOPT)) {
- if (!nountok)
- untokenize(ostr);
- return;
- }
- save_globstate(saved);
-
- str = dupstring(ostr);
- uremnode(list, np);
-
- /* quals will hold the complete list of qualifiers (file static). */
- quals = NULL;
- /*
- * qualct and qualorct indicate we have qualifiers in the last
- * alternative, or a set of alternatives, respectively. They
- * are not necessarily an accurate count, however.
- */
- qualct = qualorct = 0;
- /*
- * colonmod is a concatenated list of all colon modifiers found in
- * all sets of qualifiers.
- */
- colonmod = NULL;
- /* The gf_* flags are qualifiers which are applied globally. */
- gf_nullglob = isset(NULLGLOB);
- gf_markdirs = isset(MARKDIRS);
- gf_listtypes = gf_follow = 0;
- gf_noglobdots = unset(GLOBDOTS);
- gf_numsort = isset(NUMERICGLOBSORT);
- gf_sorts = gf_nsorts = 0;
- gf_pre_words = gf_post_words = NULL;
-
- /* Check for qualifiers */
- while (!nobareglob ||
- (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH])) {
- struct qual *newquals;
- char *s;
- int sense, qualsfound;
- off_t data;
- char *sdata, *newcolonmod, *ptr;
- int (*func) _((char *, Statptr, off_t, char *));
-
- /*
- * Initialise state variables for current file pattern.
- * newquals is the root for the linked list of all qualifiers.
- * qo is the root of the current list of alternatives.
- * ql is the end of the current alternative where the `next' will go.
- * qn is the current qualifier node to be added.
- *
- * Here is an attempt at a diagram. An `or' is added horizontally
- * to the top line, a `next' at the bottom of the right hand line.
- * `qn' is usually NULL unless a new `or' has just been added.
- *
- * quals -> x -> x -> qo
- * | | |
- * x x x
- * | |
- * x ql
- *
- * In fact, after each loop the complete set is in the file static
- * `quals'. Then, if we have a second set of qualifiers, we merge
- * the lists together. This is only tricky if one or both have an
- * `or' in them; then we need to distribute over all alternatives.
- */
- newquals = qo = qn = ql = NULL;
-
- sl = strlen(str);
- if (!(qualsfound = checkglobqual(str, sl, nobareglob, &s)))
- break;
-
- /* Real qualifiers found. */
- nobareglob = 1;
- sense = 0; /* bit 0 for match (0)/don't match (1) */
- /* bit 1 for follow links (2), don't (0) */
- data = 0; /* Any numerical argument required */
- sdata = NULL; /* Any list argument required */
- newcolonmod = NULL; /* Contains trailing colon modifiers */
-
- str[sl-1] = 0;
- *s++ = 0;
- if (qualsfound == 2)
- s += 2;
- for (ptr = s; *ptr; ptr++)
- if (*ptr == Dash)
- *ptr = '-';
- while (*s && !newcolonmod) {
- func = (int (*) _((char *, Statptr, off_t, char *)))0;
- if (*s == ',') {
- /* A comma separates alternative sets of qualifiers */
- s++;
- sense = 0;
- if (qualct) {
- qn = (struct qual *)hcalloc(sizeof *qn);
- qo->or = qn;
- qo = qn;
- qualorct++;
- qualct = 0;
- ql = NULL;
- }
- } else {
- switch (*s++) {
- case ':':
- /* Remaining arguments are history-type *
- * colon substitutions, handled separately. */
- newcolonmod = s - 1;
- untokenize(newcolonmod);
- if (colonmod) {
- /* remember we're searching backwards */
- colonmod = dyncat(newcolonmod, colonmod);
- } else
- colonmod = newcolonmod;
- break;
- case Hat:
- case '^':
- /* Toggle sense: go from positive to *
- * negative match and vice versa. */
- sense ^= 1;
- break;
- case '-':
- case Dash:
- /* Toggle matching of symbolic links */
- sense ^= 2;
- break;
- case '@':
- /* Match symbolic links */
- func = qualislnk;
- break;
- case Equals:
- case '=':
- /* Match sockets */
- func = qualissock;
- break;
- case 'p':
- /* Match named pipes */
- func = qualisfifo;
- break;
- case '/':
- /* Match directories */
- func = qualisdir;
- break;
- case '.':
- /* Match regular files */
- func = qualisreg;
- break;
- case '%':
- /* Match special files: block, *
- * character or any device */
- if (*s == 'b')
- s++, func = qualisblk;
- else if (*s == 'c')
- s++, func = qualischr;
- else
- func = qualisdev;
- break;
- case Star:
- /* Match executable plain files */
- func = qualiscom;
- break;
- case 'R':
- /* Match world-readable files */
- func = qualflags;
- data = 0004;
- break;
- case 'W':
- /* Match world-writeable files */
- func = qualflags;
- data = 0002;
- break;
- case 'X':
- /* Match world-executable files */
- func = qualflags;
- data = 0001;
- break;
- case 'A':
- func = qualflags;
- data = 0040;
- break;
- case 'I':
- func = qualflags;
- data = 0020;
- break;
- case 'E':
- func = qualflags;
- data = 0010;
- break;
- case 'r':
- /* Match files readable by current process */
- func = qualflags;
- data = 0400;
- break;
- case 'w':
- /* Match files writeable by current process */
- func = qualflags;
- data = 0200;
- break;
- case 'x':
- /* Match files executable by current process */
- func = qualflags;
- data = 0100;
- break;
- case 's':
- /* Match setuid files */
- func = qualflags;
- data = 04000;
- break;
- case 'S':
- /* Match setgid files */
- func = qualflags;
- data = 02000;
- break;
- case 't':
- func = qualflags;
- data = 01000;
- break;
- case 'd':
- /* Match device files by device number *
- * (as given by stat's st_dev element). */
- func = qualdev;
- data = qgetnum(&s);
- break;
- case 'l':
- /* Match files with the given no. of hard links */
- func = qualnlink;
- g_amc = -1;
- goto getrange;
- case 'U':
- /* Match files owned by effective user ID */
- func = qualuid;
- data = geteuid();
- break;
- case 'G':
- /* Match files owned by effective group ID */
- func = qualgid;
- data = getegid();
- break;
- case 'u':
- /* Match files owned by given user id */
- func = qualuid;
- /* either the actual uid... */
- if (idigit(*s))
- data = qgetnum(&s);
- else {
- /* ... or a user name */
- char sav, *tt;
- int arglen;
-
- /* Find matching delimiters */
- tt = get_strarg(s, &arglen);
- if (!*tt) {
- zerr("missing delimiter for 'u' glob qualifier");
- data = 0;
- } else {
-#ifdef USE_GETPWNAM
- struct passwd *pw;
- sav = *tt;
- *tt = '\0';
-
- if ((pw = getpwnam(s + arglen)))
- data = pw->pw_uid;
- else {
- zerr("unknown username '%s'", s + arglen);
- data = 0;
- }
- *tt = sav;
-#else /* !USE_GETPWNAM */
- sav = *tt;
- *tt = '\0';
- zerr("unable to resolve non-numeric username '%s'", s + arglen);
- *tt = sav;
- data = 0;
-#endif /* !USE_GETPWNAM */
- if (sav)
- s = tt + arglen;
- else
- s = tt;
- }
- }
- break;
- case 'g':
- /* Given gid or group id... works like `u' */
- func = qualgid;
- /* either the actual gid... */
- if (idigit(*s))
- data = qgetnum(&s);
- else {
- /* ...or a delimited group name. */
- char sav, *tt;
- int arglen;
-
- tt = get_strarg(s, &arglen);
- if (!*tt) {
- zerr("missing delimiter for 'g' glob qualifier");
- data = 0;
- } else {
-#ifdef USE_GETGRNAM
- struct group *gr;
- sav = *tt;
- *tt = '\0';
-
- if ((gr = getgrnam(s + arglen)))
- data = gr->gr_gid;
- else {
- zerr("unknown group");
- data = 0;
- }
- *tt = sav;
-#else /* !USE_GETGRNAM */
- sav = *tt;
- zerr("unknown group");
- data = 0;
-#endif /* !USE_GETGRNAM */
- if (sav)
- s = tt + arglen;
- else
- s = tt;
- }
- }
- break;
- case 'f':
- /* Match modes with chmod-spec. */
- func = qualmodeflags;
- data = qgetmodespec(&s);
- break;
- case 'F':
- func = qualnonemptydir;
- break;
- case 'M':
- /* Mark directories with a / */
- if ((gf_markdirs = !(sense & 1)))
- gf_follow = sense & 2;
- break;
- case 'T':
- /* Mark types in a `ls -F' type fashion */
- if ((gf_listtypes = !(sense & 1)))
- gf_follow = sense & 2;
- break;
- case 'N':
- /* Nullglob: remove unmatched patterns. */
- gf_nullglob = !(sense & 1);
- break;
- case 'D':
- /* Glob dots: match leading dots implicitly */
- gf_noglobdots = sense & 1;
- break;
- case 'n':
- /* Numeric glob sort */
- gf_numsort = !(sense & 1);
- break;
- case 'Y':
- {
- /* Short circuit: limit number of matches */
- const char *s_saved = s;
- shortcircuit = !(sense & 1);
- if (shortcircuit) {
- /* Parse the argument. */
- data = qgetnum(&s);
- if ((shortcircuit = data) != data) {
- /* Integer overflow */
- zerr("value too big: Y%s", s_saved);
- restore_globstate(saved);
- return;
- }
- }
- break;
- }
- case 'a':
- /* Access time in given range */
- g_amc = 0;
- func = qualtime;
- goto getrange;
- case 'm':
- /* Modification time in given range */
- g_amc = 1;
- func = qualtime;
- goto getrange;
- case 'c':
- /* Inode creation time in given range */
- g_amc = 2;
- func = qualtime;
- goto getrange;
- case 'L':
- /* File size (Length) in given range */
- func = qualsize;
- g_amc = -1;
- /* Get size multiplier */
- g_units = TT_BYTES;
- if (*s == 'p' || *s == 'P')
- g_units = TT_POSIX_BLOCKS, ++s;
- else if (*s == 'k' || *s == 'K')
- g_units = TT_KILOBYTES, ++s;
- else if (*s == 'm' || *s == 'M')
- g_units = TT_MEGABYTES, ++s;
-#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
- else if (*s == 'g' || *s == 'G')
- g_units = TT_GIGABYTES, ++s;
- else if (*s == 't' || *s == 'T')
- g_units = TT_TERABYTES, ++s;
-#endif
- getrange:
- /* Get time multiplier */
- if (g_amc >= 0) {
- g_units = TT_DAYS;
- if (*s == 'h')
- g_units = TT_HOURS, ++s;
- else if (*s == 'm')
- g_units = TT_MINS, ++s;
- else if (*s == 'w')
- g_units = TT_WEEKS, ++s;
- else if (*s == 'M')
- g_units = TT_MONTHS, ++s;
- else if (*s == 's')
- g_units = TT_SECONDS, ++s;
- else if (*s == 'd')
- ++s;
- }
- /* See if it's greater than, equal to, or less than */
- if ((g_range = *s == '+' ? 1 : IS_DASH(*s) ? -1 : 0))
- ++s;
- data = qgetnum(&s);
- break;
-
- case 'o':
- case 'O':
- {
- int t;
- char *send;
-
- if (gf_nsorts == MAX_SORTS) {
- zerr("too many glob sort specifiers");
- restore_globstate(saved);
- return;
- }
-
- /* usually just one character */
- send = s+1;
- switch (*s) {
- case 'n': t = GS_NAME; break;
- case 'L': t = GS_SIZE; break;
- case 'l': t = GS_LINKS; break;
- case 'a': t = GS_ATIME; break;
- case 'm': t = GS_MTIME; break;
- case 'c': t = GS_CTIME; break;
- case 'd': t = GS_DEPTH; break;
- case 'N': t = GS_NONE; break;
- case 'e':
- case '+':
- {
- t = GS_EXEC;
- if ((gf_sortlist[gf_nsorts].exec =
- glob_exec_string(&send)) == NULL)
- {
- restore_globstate(saved);
- return;
- }
- break;
- }
- default:
- zerr("unknown sort specifier");
- restore_globstate(saved);
- return;
- }
- if ((sense & 2) &&
- (t & (GS_SIZE|GS_ATIME|GS_MTIME|GS_CTIME|GS_LINKS)))
- t <<= GS_SHIFT; /* HERE: GS_EXEC? */
- if (t != GS_EXEC) {
- if (gf_sorts & t) {
- zerr("doubled sort specifier");
- restore_globstate(saved);
- return;
- }
- }
- gf_sorts |= t;
- gf_sortlist[gf_nsorts++].tp = t |
- (((sense & 1) ^ (s[-1] == 'O')) ? GS_DESC : 0);
- s = send;
- break;
- }
- case '+':
- case 'e':
- {
- char *tt;
-
- tt = glob_exec_string(&s);
-
- if (tt == NULL) {
- data = 0;
- } else {
- func = qualsheval;
- sdata = tt;
- }
- break;
- }
- case '[':
- case Inbrack:
- {
- char *os = --s;
- struct value v;
-
- v.isarr = SCANPM_WANTVALS;
- v.pm = NULL;
- v.end = -1;
- v.flags = 0;
- if (getindex(&s, &v, 0) || s == os) {
- zerr("invalid subscript");
- restore_globstate(saved);
- return;
- }
- first = v.start;
- end = v.end;
- break;
- }
- case 'P':
- {
- char *tt;
- tt = glob_exec_string(&s);
-
- if (tt != NULL)
- {
- LinkList *words = sense & 1 ? &gf_post_words : &gf_pre_words;
- if (!*words)
- *words = newlinklist();
- addlinknode(*words, tt);
- }
- break;
- }
- default:
- untokenize(--s);
- zerr("unknown file attribute: %c", *s);
- restore_globstate(saved);
- return;
- }
- }
- if (func) {
- /* Requested test is performed by function func */
- if (!qn)
- qn = (struct qual *)hcalloc(sizeof *qn);
- if (ql)
- ql->next = qn;
- ql = qn;
- if (!newquals)
- newquals = qo = qn;
- qn->func = func;
- qn->sense = sense;
- qn->data = data;
- qn->sdata = sdata;
- qn->range = g_range;
- qn->units = g_units;
- qn->amc = g_amc;
-
- qn = NULL;
- qualct++;
- }
- if (errflag) {
- restore_globstate(saved);
- return;
- }
- }
-
- if (quals && newquals) {
- /* Merge previous group of qualifiers with new set. */
- if (quals->or || newquals->or) {
- /* The hard case. */
- struct qual *qorhead = NULL, *qortail = NULL;
- /*
- * Distribute in the most trivial way, by creating
- * all possible combinations of the two sets and chaining
- * these into one long set of alternatives given
- * by qorhead and qortail.
- */
- for (qn = newquals; qn; qn = qn->or) {
- for (qo = quals; qo; qo = qo->or) {
- struct qual *qfirst, *qlast;
- int islast = !qn->or && !qo->or;
- /* Generate first set of qualifiers... */
- if (islast) {
- /* Last time round: don't bother copying. */
- qfirst = qn;
- for (qlast = qfirst; qlast->next;
- qlast = qlast->next)
- ;
- } else
- qfirst = dup_qual_list(qn, &qlast);
- /* ... link into new `or' chain ... */
- if (!qorhead)
- qorhead = qfirst;
- if (qortail)
- qortail->or = qfirst;
- qortail = qfirst;
- /* ... and concatenate second set. */
- qlast->next = islast ? qo : dup_qual_list(qo, NULL);
- }
- }
- quals = qorhead;
- } else {
- /*
- * Easy: we can just chain the qualifiers together.
- * This is an optimisation; the code above will work, too.
- * We retain the original left to right ordering --- remember
- * we are searching for sets of qualifiers from the right.
- */
- qn = newquals;
- for ( ; newquals->next; newquals = newquals->next)
- ;
- newquals->next = quals;
- quals = qn;
- }
- } else if (newquals)
- quals = newquals;
- }
- q = parsepat(str);
- if (!q || errflag) { /* if parsing failed */
- restore_globstate(saved);
- if (unset(BADPATTERN)) {
- if (!nountok)
- untokenize(ostr);
- insertlinknode(list, node, ostr);
- return;
- }
- errflag &= ~ERRFLAG_ERROR;
- zerr("bad pattern: %s", ostr);
- return;
- }
- if (!gf_nsorts) {
- gf_sortlist[0].tp = gf_sorts = (shortcircuit ? GS_NONE : GS_NAME);
- gf_nsorts = 1;
- }
- /* Initialise receptacle for matched files, *
- * expanded by insert() where necessary. */
- matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
- sizeof(struct gmatch));
- matchct = 0;
- pattrystart();
-
- /* The actual processing takes place here: matches go into *
- * matchbuf. This is the only top-level call to scanner(). */
- scanner(q, shortcircuit);
-
- /* Deal with failures to match depending on options */
- if (matchct)
- badcshglob |= 2; /* at least one cmd. line expansion O.K. */
- else if (!gf_nullglob) {
- if (isset(CSHNULLGLOB)) {
- badcshglob |= 1; /* at least one cmd. line expansion failed */
- } else if (isset(NOMATCH)) {
- zerr("no matches found: %s", ostr);
- zfree(matchbuf, 0);
- restore_globstate(saved);
- return;
- } else {
- /* treat as an ordinary string */
- untokenize(matchptr->name = dupstring(ostr));
- matchptr++;
- matchct = 1;
- }
- }
-
- if (!(gf_sortlist[0].tp & GS_NONE)) {
- /*
- * Get the strings to use for sorting by executing
- * the code chunk. We allow more than one of these.
- */
- int nexecs = 0;
- struct globsort *sortp;
- struct globsort *lastsortp = gf_sortlist + gf_nsorts;
- Gmatch gmptr;
-
- /* First find out if there are any GS_EXECs, counting them. */
- for (sortp = gf_sortlist; sortp < lastsortp; sortp++)
- {
- if (sortp->tp & GS_EXEC)
- nexecs++;
- }
-
- if (nexecs) {
- Gmatch tmpptr;
- int iexec = 0;
-
- /* Yes; allocate enough space for strings for each */
- for (tmpptr = matchbuf; tmpptr < matchptr; tmpptr++)
- tmpptr->sortstrs = (char **)zhalloc(nexecs*sizeof(char*));
-
- /* Loop over each one, incrementing iexec */
- for (sortp = gf_sortlist; sortp < lastsortp; sortp++)
- {
- /* Ignore unless this is a GS_EXEC */
- if (sortp->tp & GS_EXEC) {
- Eprog prog;
-
- if ((prog = parse_string(sortp->exec, 0))) {
- int ef = errflag, lv = lastval;
-
- /* Parsed OK, execute for each name */
- for (tmpptr = matchbuf; tmpptr < matchptr; tmpptr++) {
- setsparam("REPLY", ztrdup(tmpptr->name));
- execode(prog, 1, 0, "globsort");
- if (!errflag)
- tmpptr->sortstrs[iexec] =
- dupstring(getsparam("REPLY"));
- else
- tmpptr->sortstrs[iexec] = tmpptr->name;
- }
-
- /* Retain any user interrupt error status */
- errflag = ef | (errflag & ERRFLAG_INT);
- lastval = lv;
- } else {
- /* Failed, let's be safe */
- for (tmpptr = matchbuf; tmpptr < matchptr; tmpptr++)
- tmpptr->sortstrs[iexec] = tmpptr->name;
- }
-
- iexec++;
- }
- }
- }
-
- /*
- * Where necessary, create unmetafied version of names
- * for comparison. If no Meta characters just point
- * to original string. All on heap.
- */
- for (gmptr = matchbuf; gmptr < matchptr; gmptr++)
- {
- if (strchr(gmptr->name, Meta))
- {
- int dummy;
- gmptr->uname = dupstring(gmptr->name);
- unmetafy(gmptr->uname, &dummy);
- } else {
- gmptr->uname = gmptr->name;
- }
- }
-
- /* Sort arguments in to lexical (and possibly numeric) order. *
- * This is reversed to facilitate insertion into the list. */
- qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
- (int (*) _((const void *, const void *)))gmatchcmp);
- }
-
- if (first < 0) {
- first += matchct;
- if (first < 0)
- first = 0;
- }
- if (end < 0)
- end += matchct + 1;
- else if (end > matchct)
- end = matchct;
- if ((end -= first) > 0) {
- if (gf_sortlist[0].tp & GS_NONE) {
- /* Match list was never reversed, so insert back to front. */
- matchptr = matchbuf + matchct - first - 1;
- while (end-- > 0) {
- /* insert matches in the arg list */
- insert_glob_match(list, node, matchptr->name);
- matchptr--;
- }
- } else {
- matchptr = matchbuf + matchct - first - end;
- while (end-- > 0) {
- /* insert matches in the arg list */
- insert_glob_match(list, node, matchptr->name);
- matchptr++;
- }
- }
- } else if (!badcshglob && !isset(NOMATCH) && matchct == 1) {
- insert_glob_match(list, node, (--matchptr)->name);
- }
- zfree(matchbuf, 0);
-
- restore_globstate(saved);
-}
-
-/* Return the trailing character for marking file types */
-
-/**/
-mod_export char
-file_type(mode_t filemode)
-{
- 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))
- return '@';
- else if(S_ISREG(filemode))
- return (filemode & S_IXUGO) ? '*' : ' ';
- else if(S_ISSOCK(filemode))
- return '=';
- else
- return '?';
-}
-
-/* check to see if str is eligible for brace expansion */
-
-/**/
-mod_export int
-hasbraces(char *str)
-{
- char *lbr, *mbr, *comma;
-
- if (isset(BRACECCL)) {
- /* In this case, any properly formed brace expression *
- * will match and expand to the characters in between. */
- int bc, c;
-
- for (bc = 0; (c = *str); ++str)
- if (c == Inbrace) {
- if (!bc && str[1] == Outbrace)
- *str++ = '{', *str = '}';
- else
- bc++;
- } else if (c == Outbrace) {
- if (!bc)
- *str = '}';
- else if (!--bc)
- return 1;
- }
- return 0;
- }
- /* Otherwise we need to look for... */
- lbr = mbr = comma = NULL;
- for (;;) {
- switch (*str++) {
- case Inbrace:
- if (!lbr) {
- if (bracechardots(str-1, NULL, NULL))
- return 1;
- lbr = str - 1;
- if (IS_DASH(*str))
- str++;
- while (idigit(*str))
- str++;
- if (*str == '.' && str[1] == '.') {
- str++; str++;
- if (IS_DASH(*str))
- str++;
- while (idigit(*str))
- str++;
- if (*str == Outbrace &&
- (idigit(lbr[1]) || idigit(str[-1])))
- return 1;
- else if (*str == '.' && str[1] == '.') {
- str++; str++;
- if (IS_DASH(*str))
- str++;
- while (idigit(*str))
- str++;
- if (*str == Outbrace &&
- (idigit(lbr[1]) || idigit(str[-1])))
- return 1;
- }
- }
- } else {
- char *s = --str;
-
- if (skipparens(Inbrace, Outbrace, &str)) {
- *lbr = *s = '{';
- if (comma)
- str = comma;
- if (mbr && mbr < str)
- str = mbr;
- lbr = mbr = comma = NULL;
- } else if (!mbr)
- mbr = s;
- }
- break;
- case Outbrace:
- if (!lbr)
- str[-1] = '}';
- else if (comma)
- return 1;
- else {
- *lbr = '{';
- str[-1] = '}';
- if (mbr)
- str = mbr;
- mbr = lbr = NULL;
- }
- break;
- case Comma:
- if (!lbr)
- str[-1] = ',';
- else if (!comma)
- comma = str - 1;
- break;
- case '\0':
- if (lbr)
- *lbr = '{';
- if (!mbr && !comma)
- return 0;
- if (comma)
- str = comma;
- if (mbr && mbr < str)
- str = mbr;
- lbr = mbr = comma = NULL;
- break;
- }
- }
-}
-
-/* expand stuff like >>*.c */
-
-/**/
-int
-xpandredir(struct redir *fn, LinkList redirtab)
-{
- char *nam;
- struct redir *ff;
- int ret = 0;
- local_list1(fake);
-
- /* Stick the name in a list... */
- init_list1(fake, fn->name);
- /* ...which undergoes all the usual shell expansions */
- prefork(&fake, isset(MULTIOS) ? 0 : PREFORK_SINGLE, NULL);
- /* Globbing is only done for multios. */
- if (!errflag && isset(MULTIOS))
- globlist(&fake, 0);
- if (errflag)
- return 0;
- if (nonempty(&fake) && !nextnode(firstnode(&fake))) {
- /* Just one match, the usual case. */
- char *s = peekfirst(&fake);
- fn->name = s;
- untokenize(s);
- if (fn->type == REDIR_MERGEIN || fn->type == REDIR_MERGEOUT) {
- if (IS_DASH(s[0]) && !s[1])
- fn->type = REDIR_CLOSE;
- else if (s[0] == 'p' && !s[1])
- fn->fd2 = -2;
- else {
- while (idigit(*s))
- s++;
- if (!*s && s > fn->name)
- fn->fd2 = zstrtol(fn->name, NULL, 10);
- else if (fn->type == REDIR_MERGEIN)
- zerr("file number expected");
- else
- fn->type = REDIR_ERRWRITE;
- }
- }
- } else if (fn->type == REDIR_MERGEIN)
- zerr("file number expected");
- else {
- if (fn->type == REDIR_MERGEOUT)
- fn->type = REDIR_ERRWRITE;
- while ((nam = (char *)ugetnode(&fake))) {
- /* Loop over matches, duplicating the *
- * redirection for each file found. */
- ff = (struct redir *) zhalloc(sizeof *ff);
- *ff = *fn;
- ff->name = nam;
- addlinknode(redirtab, ff);
- ret = 1;
- }
- }
- return ret;
-}
-
-/*
- * Check for a brace expansion of the form {..}.
- * On input str must be positioned at an Inbrace, but the sequence
- * of characters beyond that has not necessarily been checked.
- * Return 1 if found else 0.
- *
- * The other parameters are optionaland if the function returns 1 are
- * used to return:
- * - *c1p: the first character in the expansion.
- * - *c2p: the final character in the expansion.
- */
-
-/**/
-static int
-bracechardots(char *str, convchar_t *c1p, convchar_t *c2p)
-{
- convchar_t cstart, cend;
- char *pnext = str + 1, *pconv, convstr[2];
- if (itok(*pnext)) {
- if (*pnext == Inbrace)
- return 0;
- convstr[0] = ztokens[*pnext - Pound];
- convstr[1] = '\0';
- pconv = convstr;
- } else
- pconv = pnext;
- MB_METACHARINIT();
- pnext += MB_METACHARLENCONV(pconv, &cstart);
- if (
-#ifdef MULTIBYTE_SUPPORT
- cstart == WEOF ||
-#else
- !cstart ||
-#endif
- pnext[0] != '.' || pnext[1] != '.')
- return 0;
- pnext += 2;
- if (!*pnext)
- return 0;
- if (itok(*pnext)) {
- if (*pnext == Inbrace)
- return 0;
- convstr[0] = ztokens[*pnext - Pound];
- convstr[1] = '\0';
- pconv = convstr;
- } else
- pconv = pnext;
- MB_METACHARINIT();
- pnext += MB_METACHARLENCONV(pconv, &cend);
- if (
-#ifdef MULTIBYTE_SUPPORT
- cend == WEOF ||
-#else
- !cend ||
-#endif
- *pnext != Outbrace)
- return 0;
- if (c1p)
- *c1p = cstart;
- if (c2p)
- *c2p = cend;
- return 1;
-}
-
-/* brace expansion */
-
-/**/
-mod_export void
-xpandbraces(LinkList list, LinkNode *np)
-{
- LinkNode node = (*np), last = prevnode(node);
- char *str = (char *)getdata(node), *str3 = str, *str2;
- int prev, bc, comma, dotdot;
-
- for (; *str != Inbrace; str++);
- /* First, match up braces and see what we have. */
- for (str2 = str, bc = comma = dotdot = 0; *str2; ++str2)
- if (*str2 == Inbrace)
- ++bc;
- else if (*str2 == Outbrace) {
- if (--bc == 0)
- break;
- } else if (bc == 1) {
- if (*str2 == Comma)
- ++comma; /* we have {foo,bar} */
- else if (*str2 == '.' && str2[1] == '.') {
- dotdot++; /* we have {num1..num2} */
- ++str2;
- }
- }
- DPUTS(bc, "BUG: unmatched brace in xpandbraces()");
- if (!comma && dotdot) {
- /* Expand range like 0..10 numerically: comma or recursive
- brace expansion take precedence. */
- char *dots, *p, *dots2 = NULL;
- LinkNode olast = last;
- /* Get the first number of the range */
- zlong rstart, rend;
- int err = 0, rev = 0, rincr = 1;
- int wid1, wid2, wid3, strp;
- convchar_t cstart, cend;
-
- if (bracechardots(str, &cstart, &cend)) {
- int lenalloc;
- /*
- * This is a character range.
- */
- if (cend < cstart) {
- convchar_t ctmp = cend;
- cend = cstart;
- cstart = ctmp;
- rev = 1;
- }
- uremnode(list, node);
- strp = str - str3;
- lenalloc = strp + strlen(str2+1) + 1;
- do {
-#ifdef MULTIBYTE_SUPPORT
- char *ncptr;
- int nclen;
- mb_charinit();
- ncptr = wcs_nicechar(cend, NULL, NULL);
- nclen = strlen(ncptr);
- p = zhalloc(lenalloc + nclen);
- memcpy(p, str3, strp);
- memcpy(p + strp, ncptr, nclen);
- strcpy(p + strp + nclen, str2 + 1);
-#else
- p = zhalloc(lenalloc + 1);
- memcpy(p, str3, strp);
- sprintf(p + strp, "%c", cend);
- strcat(p + strp, str2 + 1);
-#endif
- insertlinknode(list, last, p);
- if (rev) /* decreasing: add in reverse order. */
- last = nextnode(last);
- } while (cend-- > cstart);
- *np = nextnode(olast);
- return;
- }
-
- /* Get the first number of the range */
- rstart = zstrtol(str+1,&dots,10);
- rend = 0;
- wid1 = (dots - str) - 1;
- wid2 = (str2 - dots) - 2;
- wid3 = 0;
- strp = str - str3;
-
- if (dots == str + 1 || *dots != '.' || dots[1] != '.')
- err++;
- else {
- /* Get the last number of the range */
- rend = zstrtol(dots+2,&p,10);
- if (p == dots+2)
- err++;
- /* check for {num1..num2..incr} */
- if (p != str2) {
- wid2 = (p - dots) - 2;
- dots2 = p;
- if (dotdot == 2 && *p == '.' && p[1] == '.') {
- rincr = zstrtol(p+2, &p, 10);
- wid3 = p - dots2 - 2;
- if (p != str2 || !rincr)
- err++;
- } else
- err++;
- }
- }
- if (!err) {
- /* If either no. begins with a zero, pad the output with *
- * zeroes. Otherwise, set min width to 0 to suppress them.
- * str+1 is the first number in the range, dots+2 the last,
- * and dots2+2 is the increment if that's given. */
- /* TODO: sorry about this */
- int minw = (str[1] == '0' ||
- (IS_DASH(str[1]) && str[2] == '0'))
- ? wid1
- : (dots[2] == '0' ||
- (IS_DASH(dots[2]) && dots[3] == '0'))
- ? wid2
- : (dots2 && (dots2[2] == '0' ||
- (IS_DASH(dots2[2]) && dots2[3] == '0')))
- ? wid3
- : 0;
- if (rincr < 0) {
- /* Handle negative increment */
- rincr = -rincr;
- rev = !rev;
- }
- if (rstart > rend) {
- /* Handle decreasing ranges correctly. */
- zlong rt = rend;
- rend = rstart;
- rstart = rt;
- rev = !rev;
- } else if (rincr > 1) {
- /* when incr > 1, range is aligned to the highest number of str1,
- * compensate for this so that it is aligned to the first number */
- rend -= (rend - rstart) % rincr;
- }
- uremnode(list, node);
- for (; rend >= rstart; rend -= rincr) {
- /* Node added in at end, so do highest first */
- p = dupstring(str3);
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- sprintf(p + strp, "%0*lld", minw, rend);
-#else
- sprintf(p + strp, "%0*ld", minw, (long)rend);
-#endif
- strcat(p + strp, str2 + 1);
- insertlinknode(list, last, p);
- if (rev) /* decreasing: add in reverse order. */
- last = nextnode(last);
- }
- *np = nextnode(olast);
- return;
- }
- }
- if (!comma && isset(BRACECCL)) { /* {a-mnop} */
- /* Here we expand each character to a separate node, *
- * but also ranges of characters like a-m. ccl is a *
- * set of flags saying whether each character is present; *
- * the final list is in lexical order. */
- char ccl[256], *p;
- unsigned char c1, c2;
- unsigned int len, pl;
- int lastch = -1;
-
- uremnode(list, node);
- memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0]));
- for (p = str + 1; p < str2;) {
- if (itok(c1 = *p++))
- c1 = ztokens[c1 - STOUC(Pound)];
- if ((char) c1 == Meta)
- c1 = 32 ^ *p++;
- if (itok(c2 = *p))
- c2 = ztokens[c2 - STOUC(Pound)];
- if ((char) c2 == Meta)
- c2 = 32 ^ p[1];
- if (IS_DASH((char)c1) && lastch >= 0 &&
- p < str2 && lastch <= (int)c2) {
- while (lastch < (int)c2)
- ccl[lastch++] = 1;
- lastch = -1;
- } else
- ccl[lastch = c1] = 1;
- }
- pl = str - str3;
- len = pl + strlen(++str2) + 2;
- for (p = ccl + 256; p-- > ccl;)
- if (*p) {
- c1 = p - ccl;
- if (imeta(c1)) {
- str = hcalloc(len + 1);
- str[pl] = Meta;
- str[pl+1] = c1 ^ 32;
- strcpy(str + pl + 2, str2);
- } else {
- str = hcalloc(len);
- str[pl] = c1;
- strcpy(str + pl + 1, str2);
- }
- memcpy(str, str3, pl);
- insertlinknode(list, last, str);
- }
- *np = nextnode(last);
- return;
- }
- prev = str++ - str3;
- str2++;
- uremnode(list, node);
- node = last;
- /* Finally, normal comma expansion *
- * str1{foo,bar}str2 -> str1foostr2 str1barstr2. *
- * Any number of intervening commas is allowed. */
- for (;;) {
- char *zz, *str4;
- int cnt;
-
- for (str4 = str, cnt = 0; cnt || (*str != Comma && *str !=
- Outbrace); str++) {
- if (*str == Inbrace)
- cnt++;
- else if (*str == Outbrace)
- cnt--;
- DPUTS(!*str, "BUG: illegal brace expansion");
- }
- /* Concatenate the string before the braces (str3), the section *
- * just found (str4) and the text after the braces (str2) */
- zz = (char *) hcalloc(prev + (str - str4) + strlen(str2) + 1);
- ztrncpy(zz, str3, prev);
- strncat(zz, str4, str - str4);
- strcat(zz, str2);
- /* and add this text to the argument list. */
- insertlinknode(list, node, zz);
- incnode(node);
- if (*str != Outbrace)
- str++;
- else
- break;
- }
- *np = nextnode(last);
-}
-
-/* check to see if a matches b (b is not a filename pattern) */
-
-/**/
-int
-matchpat(char *a, char *b)
-{
- Patprog p;
- int ret;
-
- queue_signals(); /* Protect PAT_STATIC */
-
- if (!(p = patcompile(b, PAT_STATIC, NULL))) {
- zerr("bad pattern: %s", b);
- ret = 0;
- } else
- ret = pattry(p, a);
-
- unqueue_signals();
-
- return ret;
-}
-
-/* do the ${foo%%bar}, ${foo#bar} stuff */
-/* please do not laugh at this code. */
-
-/* Having found a match in getmatch, decide what part of string
- * to return. The matched part starts b characters into string imd->ustr
- * and finishes e characters in: 0 <= b <= e <= imd->ulen on input
- * (yes, empty matches should work).
- *
- * imd->flags is a set of the SUB_* matches defined in zsh.h from
- * SUB_MATCH onwards; the lower parts are ignored.
- *
- * imd->replstr is the replacement string for a substitution
- *
- * imd->replstr is metafied and the values put in imd->repllist are metafied.
- */
-
-/**/
-static char *
-get_match_ret(Imatchdata imd, int b, int e)
-{
- char buf[80], *r, *p, *rr, *replstr = imd->replstr;
- int ll = 0, bl = 0, t = 0, add = 0, fl = imd->flags, i;
-
- /* Account for b and e referring to unmetafied string */
- for (p = imd->ustr; p < imd->ustr + b; p++)
- if (imeta(*p))
- add++;
- b += add;
- for (; p < imd->ustr + e; p++)
- if (imeta(*p))
- add++;
- e += add;
-
- /* Everything now refers to metafied lengths. */
- if (replstr || (fl & SUB_LIST)) {
- if (fl & SUB_DOSUBST) {
- replstr = dupstring(replstr);
- singsub(&replstr);
- untokenize(replstr);
- }
- if ((fl & (SUB_GLOBAL|SUB_LIST)) && imd->repllist) {
- /* We are replacing the chunk, just add this to the list */
- Repldata rd = (Repldata)
- ((fl & SUB_LIST) ? zalloc(sizeof(*rd)) : zhalloc(sizeof(*rd)));
- rd->b = b;
- rd->e = e;
- rd->replstr = replstr;
- if (fl & SUB_LIST)
- zaddlinknode(imd->repllist, rd);
- else
- addlinknode(imd->repllist, rd);
- return imd->mstr;
- }
- ll += strlen(replstr);
- }
- if (fl & SUB_MATCH) /* matched portion */
- ll += 1 + (e - b);
- if (fl & SUB_REST) /* unmatched portion */
- ll += 1 + (imd->mlen - (e - b));
- if (fl & SUB_BIND) {
- /* position of start of matched portion */
- sprintf(buf, "%d ", MB_METASTRLEN2END(imd->mstr, 0, imd->mstr+b) + 1);
- ll += (bl = strlen(buf));
- }
- if (fl & SUB_EIND) {
- /* position of end of matched portion */
- sprintf(buf + bl, "%d ",
- MB_METASTRLEN2END(imd->mstr, 0, imd->mstr+e) + 1);
- ll += (bl = strlen(buf));
- }
- if (fl & SUB_LEN) {
- /* length of matched portion */
- sprintf(buf + bl, "%d ", MB_METASTRLEN2END(imd->mstr+b, 0,
- imd->mstr+e));
- ll += (bl = strlen(buf));
- }
- if (bl)
- buf[bl - 1] = '\0';
-
- rr = r = (char *) hcalloc(ll);
-
- if (fl & SUB_MATCH) {
- /* copy matched portion to new buffer */
- for (i = b, p = imd->mstr + b; i < e; i++)
- *rr++ = *p++;
- t = 1;
- }
- if (fl & SUB_REST) {
- /* Copy unmatched portion to buffer. If both portions *
- * requested, put a space in between (why?) */
- if (t)
- *rr++ = ' ';
- /* there may be unmatched bits at both beginning and end of string */
- for (i = 0, p = imd->mstr; i < b; i++)
- *rr++ = *p++;
- if (replstr)
- for (p = replstr; *p; )
- *rr++ = *p++;
- for (i = e, p = imd->mstr + e; i < imd->mlen; i++)
- *rr++ = *p++;
- t = 1;
- }
- *rr = '\0';
- if (bl) {
- /* if there was a buffer (with a numeric result), add it; *
- * if there was other stuff too, stick in a space first. */
- if (t)
- *rr++ = ' ';
- strcpy(rr, buf);
- }
- return r;
-}
-
-static Patprog
-compgetmatch(char *pat, int *flp, char **replstrp)
-{
- Patprog p;
- /*
- * Flags to pattern compiler: use static buffer since we only
- * have one pattern at a time; we will try the must-match test ourselves,
- * so tell the pattern compiler we are scanning.
- */
-
- /* int patflags = PAT_STATIC|PAT_SCAN|PAT_NOANCH;*/
-
- /* Unfortunately, PAT_STATIC doesn't work if we have a replstr with
- * something like ${x#...} in it which will be singsub()ed below because
- * that would overwrite the pattern buffer. */
-
- int patflags = PAT_SCAN|PAT_NOANCH | (*replstrp ? 0 : PAT_STATIC);
-
- /*
- * Search is anchored to the end of the string if we want to match
- * it all, or if we are matching at the end of the string and not
- * using substrings.
- */
- if ((*flp & SUB_ALL) || ((*flp & SUB_END) && !(*flp & SUB_SUBSTR)))
- patflags &= ~PAT_NOANCH;
- p = patcompile(pat, patflags, NULL);
- if (!p) {
- zerr("bad pattern: %s", pat);
- return NULL;
- }
- if (*replstrp) {
- if (p->patnpar || (p->globend & GF_MATCHREF)) {
- /*
- * Either backreferences or match references, so we
- * need to re-substitute replstr each time round.
- */
- *flp |= SUB_DOSUBST;
- } else {
- singsub(replstrp);
- untokenize(*replstrp);
- }
- }
-
- return p;
-}
-
-/*
- * This is called from paramsubst to get the match for ${foo#bar} etc.
- * fl is a set of the SUB_* flags defined in zsh.h
- * *sp points to the string we have to modify. The n'th match will be
- * returned in *sp. The heap is used to get memory for the result string.
- * replstr is the replacement string from a ${.../orig/repl}, in
- * which case pat is the original.
- *
- * n is now ignored unless we are looking for a substring, in
- * which case the n'th match from the start is counted such that
- * there is no more than one match from each position.
- */
-
-/**/
-int
-getmatch(char **sp, char *pat, int fl, int n, char *replstr)
-{
- Patprog p;
-
- if (!(p = compgetmatch(pat, &fl, &replstr)))
- return 1;
-
- return igetmatch(sp, p, fl, n, replstr, NULL);
-}
-
-/*
- * This is the corresponding function for array variables.
- * Matching is done with the same pattern on each element.
- */
-
-/**/
-void
-getmatcharr(char ***ap, char *pat, int fl, int n, char *replstr)
-{
- char **arr = *ap, **pp;
- Patprog p;
-
- if (!(p = compgetmatch(pat, &fl, &replstr)))
- return;
-
- *ap = pp = hcalloc(sizeof(char *) * (arrlen(arr) + 1));
- while ((*pp = *arr++))
- if (igetmatch(pp, p, fl, n, replstr, NULL))
- pp++;
-}
-
-/*
- * Match against str using pattern pp; return a list of
- * Repldata matches in the linked list *repllistp; this is
- * in permanent storage and to be freed by freematchlist()
- */
-
-/**/
-mod_export int
-getmatchlist(char *str, Patprog p, LinkList *repllistp)
-{
- char **sp = &str;
-
- /*
- * We don't care if we have longest or shortest match, but SUB_LONG
- * is cheaper since the pattern code does that by default.
- * We need SUB_GLOBAL to get all matches.
- * We need SUB_SUBSTR to scan through for substrings.
- * We need SUB_LIST to activate the special handling of the list
- * passed in.
- */
- return igetmatch(sp, p, SUB_LONG|SUB_GLOBAL|SUB_SUBSTR|SUB_LIST,
- 0, NULL, repllistp);
-}
-
-static void
-freerepldata(void *ptr)
-{
- zfree(ptr, sizeof(struct repldata));
-}
-
-/**/
-mod_export void
-freematchlist(LinkList repllist)
-{
- freelinklist(repllist, freerepldata);
-}
-
-/**/
-static void
-set_pat_start(Patprog p, int offs)
-{
- /*
- * If we are messing around with the test string by advancing up
- * it from the start, we need to tell the pattern matcher that
- * a start-of-string assertion, i.e. (#s), should fail. Hence
- * we test whether the offset of the real start of string from
- * the actual start, passed as offs, is zero.
- */
- if (offs)
- p->flags |= PAT_NOTSTART;
- else
- p->flags &= ~PAT_NOTSTART;
-}
-
-/**/
-static void
-set_pat_end(Patprog p, char null_me)
-{
- /*
- * If we are messing around with the string by shortening it at the
- * tail, we need to tell the pattern matcher that an end-of-string
- * assertion, i.e. (#e), should fail. Hence we test whether
- * the character null_me about to be zapped is or is not already a null.
- */
- if (null_me)
- p->flags |= PAT_NOTEND;
- else
- p->flags &= ~PAT_NOTEND;
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-
-/*
- * Increment *tp over character which may be multibyte.
- * Return number of bytes.
- * All unmetafied here.
- */
-
-/**/
-static int iincchar(char **tp, int left)
-{
- char *t = *tp;
- int mbclen = mb_charlenconv(t, left, NULL);
- *tp = t + mbclen;
-
- return mbclen;
-}
-
-/**/
-static int
-igetmatch(char **sp, Patprog p, int fl, int n, char *replstr,
- LinkList *repllistp)
-{
- char *s = *sp, *t, *tmatch, *send;
- /*
- * Note that ioff counts (possibly multibyte) characters in the
- * character set (Meta's are not included), while l counts characters in
- * the metafied string.
- *
- * umlen is a counter for (unmetafied) byte lengths---neither characters
- * nor raw byte indices; this is simply an optimisation for allocation.
- * umltot is the full length of the string in this scheme.
- *
- * l is the raw string length, used together with any pointers into
- * the string (typically t).
- */
- int ioff, l = strlen(*sp), matched = 1, umltot = ztrlen(*sp);
- int umlen, nmatches;
- struct patstralloc patstralloc;
- struct imatchdata imd;
-
- (void)patallocstr(p, s, l, umltot, 1, &patstralloc);
- s = patstralloc.alloced;
- DPUTS(!s, "forced patallocstr failed");
- send = s + umltot;
-
- imd.mstr = *sp;
- imd.mlen = l;
- imd.ustr = s;
- imd.ulen = umltot;
- imd.flags = fl;
- imd.replstr = replstr;
- imd.repllist = NULL;
-
- /* perform must-match test for complex closures */
- if (p->mustoff)
- {
- char *muststr = (char *)p + p->mustoff;
-
- matched = 0;
- if (p->patmlen <= umltot)
- {
- for (t = s; t <= send - p->patmlen; t++)
- {
- if (!memcmp(muststr, t, p->patmlen)) {
- matched = 1;
- break;
- }
- }
- }
- }
-
- /* in case we used the prog before... */
- p->flags &= ~(PAT_NOTSTART|PAT_NOTEND);
-
- if (fl & SUB_ALL) {
- int i = matched && pattrylen(p, s, umltot, 0, &patstralloc, 0);
- if (!i) {
- /* Perform under no-match conditions */
- umltot = 0;
- imd.replstr = NULL;
- }
- *sp = get_match_ret(&imd, 0, umltot);
- if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i)))
- return 0;
- return 1;
- }
- if (matched) {
- /*
- * The default behaviour is to match at the start; this
- * is modified by SUB_END and SUB_SUBSTR. SUB_END matches
- * at the end of the string instead of the start. SUB_SUBSTR
- * without SUB_END matches substrings searching from the start;
- * with SUB_END it matches substrings searching from the end.
- *
- * The possibilities are further modified by whether we want the
- * longest (SUB_LONG) or shortest possible match.
- *
- * SUB_START is only used in the case where we are also
- * forcing a match at the end (SUB_END with no SUB_SUBSTR,
- * with or without SUB_LONG), to indicate we should match
- * the entire string.
- */
- switch (fl & (SUB_END|SUB_LONG|SUB_SUBSTR)) {
- case 0:
- case SUB_LONG:
- /*
- * Largest/smallest possible match at head of string.
- * First get the longest match...
- */
- if (pattrylen(p, s, umltot, 0, &patstralloc, 0)) {
- /* patmatchlen returns unmetafied length in this case */
- int mlen = patmatchlen();
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- send = s + mlen;
- /*
- * ... now we know whether it's worth looking for the
- * shortest, which we do by brute force.
- */
- mb_charinit();
- for (t = s, umlen = 0; t < send; ) {
- set_pat_end(p, *t);
- if (pattrylen(p, s, umlen, 0, &patstralloc, 0)) {
- mlen = patmatchlen();
- break;
- }
- umlen += iincchar(&t, send - t);
- }
- }
- *sp = get_match_ret(&imd, 0, mlen);
- return 1;
- }
- break;
-
- case SUB_END:
- /*
- * Smallest possible match at tail of string.
- * As we can only be sure we've got wide characters right
- * when going forwards, we need to match at every point
- * until we fail and record the last successful match.
- *
- * It's important that we return the last successful match
- * so that match, mbegin, mend and MATCH, MBEGIN, MEND are
- * correct.
- */
- mb_charinit();
- tmatch = NULL;
- for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff))
- tmatch = t;
- if (fl & SUB_START)
- break;
- umlen -= iincchar(&t, send - t);
- }
- if (tmatch) {
- *sp = get_match_ret(&imd, tmatch - s, umltot);
- return 1;
- }
- if (!(fl & SUB_START) && pattrylen(p, s + umltot, 0, 0,
- &patstralloc, ioff)) {
- *sp = get_match_ret(&imd, umltot, umltot);
- return 1;
- }
- break;
-
- case (SUB_END|SUB_LONG):
- /* Largest possible match at tail of string: *
- * move forward along string until we get a match. *
- * Again there's no optimisation. */
- mb_charinit();
- for (ioff = 0, t = s, umlen = umltot; t <= send ; ioff++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) {
- *sp = get_match_ret(&imd, t-s, umltot);
- return 1;
- }
- if (fl & SUB_START)
- break;
- if (t == send)
- break;
- umlen -= iincchar(&t, send - t);
- }
- if (!(fl & SUB_START) && pattrylen(p, send, 0, 0,
- &patstralloc, ioff)) {
- *sp = get_match_ret(&imd, umltot, umltot);
- return 1;
- }
- break;
-
- case SUB_SUBSTR:
- /* Smallest at start, but matching substrings. */
- set_pat_start(p, l);
- if (!(fl & SUB_GLOBAL) &&
- pattrylen(p, send, 0, 0, &patstralloc, 0) &&
- !--n) {
- *sp = get_match_ret(&imd, 0, 0);
- return 1;
- } /* fall through */
- case (SUB_SUBSTR|SUB_LONG):
- /* longest or smallest at start with substrings */
- t = s;
- if (fl & SUB_GLOBAL) {
- imd.repllist = (fl & SUB_LIST) ? znewlinklist() : newlinklist();
- if (repllistp)
- *repllistp = imd.repllist;
- }
- ioff = 0; /* offset into string */
- umlen = umltot;
- mb_charinit();
- do {
- /* loop over all matches for global substitution */
- matched = 0;
- for (; t <= send; ioff++) {
- /* Find the longest match from this position. */
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) {
- char *mpos = t + patmatchlen();
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- char *ptr;
- int umlen2;
- /*
- * If searching for the shortest match,
- * start with a zero length and increase
- * it until we reach the longest possible
- * match, accepting the first successful
- * match.
- */
- for (ptr = t, umlen2 = 0; ptr < mpos;) {
- set_pat_end(p, *ptr);
- if (pattrylen(p, t, umlen2, 0,
- &patstralloc, ioff)) {
- mpos = t + patmatchlen();
- break;
- }
- umlen2 += iincchar(&ptr, mpos - ptr);
- }
- }
- if (!--n || (n <= 0 && (fl & SUB_GLOBAL))) {
- *sp = get_match_ret(&imd, t-s, mpos-s);
- if (mpos == t)
- mpos += mb_charlenconv(mpos, send - mpos, NULL);
- }
- if (!(fl & SUB_GLOBAL)) {
- if (n) {
- /*
- * Looking for a later match: in this case,
- * we can continue looking for matches from
- * the next character, even if it overlaps
- * with what we just found.
- */
- umlen -= iincchar(&t, send - t);
- continue;
- } else {
- return 1;
- }
- }
- /*
- * For a global match, we need to skip the stuff
- * which is already marked for replacement.
- */
- matched = 1;
- if (t == send)
- break;
- while (t < mpos) {
- ioff++;
- umlen -= iincchar(&t, send - t);
- }
- break;
- }
- if (t == send)
- break;
- umlen -= iincchar(&t, send - t);
- }
- } while (matched && t < send);
- /*
- * check if we can match a blank string, if so do it
- * at the start. Goodness knows if this is a good idea
- * with global substitution, so it doesn't happen.
- */
- set_pat_start(p, l);
- if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG &&
- pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) {
- *sp = get_match_ret(&imd, 0, 0);
- return 1;
- }
- break;
-
- case (SUB_END|SUB_SUBSTR):
- case (SUB_END|SUB_LONG|SUB_SUBSTR):
- /* Longest/shortest at end, matching substrings. */
- if (!(fl & SUB_LONG)) {
- set_pat_start(p, l);
- if (pattrylen(p, send, 0, 0, &patstralloc, umltot) &&
- !--n) {
- *sp = get_match_ret(&imd, umltot, umltot);
- return 1;
- }
- }
- /*
- * If multibyte characters are present we need to start from the
- * beginning. This is a bit unpleasant because we can't tell in
- * advance how many times it will match and from where, so if n is
- * greater then 1 we will need to count the number of times it
- * matched and then go through again until we reach the right
- * point. (Either that or record every single match in a list,
- * which isn't stupid; it involves more memory management at this
- * level but less use of the pattern matcher.)
- */
- nmatches = 0;
- tmatch = NULL;
- mb_charinit();
- for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) {
- nmatches++;
- tmatch = t;
- }
- umlen -= iincchar(&t, send - t);
- }
- if (nmatches) {
- char *mpos;
- if (n > 1) {
- /*
- * We need to find the n'th last match.
- */
- n = nmatches - n;
- mb_charinit();
- for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff) &&
- !n--) {
- tmatch = t;
- break;
- }
- umlen -= iincchar(&t, send - t);
- }
- }
- mpos = tmatch + patmatchlen();
- /* Look for the shortest match if necessary */
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- for (t = tmatch, umlen = 0; t < mpos; ) {
- set_pat_end(p, *t);
- if (pattrylen(p, tmatch, umlen, 0,
- &patstralloc, ioff)) {
- mpos = tmatch + patmatchlen();
- break;
- }
- umlen += iincchar(&t, mpos - t);
- }
- }
- *sp = get_match_ret(&imd, tmatch-s, mpos-s);
- return 1;
- }
- set_pat_start(p, l);
- if ((fl & SUB_LONG) && pattrylen(p, send, 0, 0,
- &patstralloc, umltot) &&
- !--n) {
- *sp = get_match_ret(&imd, umltot, umltot);
- return 1;
- }
- break;
- }
- }
-
- if (imd.repllist && nonempty(imd.repllist)) {
- /* Put all the bits of a global search and replace together. */
- LinkNode nd;
- Repldata rd;
- int lleft;
- char *ptr, *start;
- int i;
-
- /*
- * Use metafied string again.
- * Results from get_match_ret in repllist are all metafied.
- */
- s = *sp;
- if (!(fl & SUB_LIST)) {
- lleft = 0; /* size of returned string */
- i = 0; /* start of last chunk we got from *sp */
- for (nd = firstnode(imd.repllist); nd; incnode(nd)) {
- rd = (Repldata) getdata(nd);
- lleft += rd->b - i; /* previous chunk of *sp */
- lleft += strlen(rd->replstr); /* the replaced bit */
- i = rd->e; /* start of next chunk of *sp */
- }
- lleft += l - i; /* final chunk from *sp */
- start = t = zhalloc(lleft+1);
- i = 0;
- for (nd = firstnode(imd.repllist); nd; incnode(nd)) {
- rd = (Repldata) getdata(nd);
- memcpy(t, s + i, rd->b - i);
- t += rd->b - i;
- ptr = rd->replstr;
- while (*ptr)
- *t++ = *ptr++;
- i = rd->e;
- }
- memcpy(t, s + i, l - i);
- start[lleft] = '\0';
- *sp = (char *)start;
- }
- return 1;
- }
- if (fl & SUB_LIST) { /* safety: don't think this can happen */
- return 0;
- }
-
- /* munge the whole string: no match, so no replstr */
- imd.replstr = NULL;
- imd.repllist = NULL;
- *sp = get_match_ret(&imd, 0, 0);
- return (fl & SUB_RETFAIL) ? 0 : 1;
-}
-
-/**/
-#else
-
-/*
- * Increment pointer which may be on a Meta (x is a pointer variable),
- * returning the incremented value (i.e. like pre-increment).
- */
-#define METAINC(x) ((x) += (*(x) == Meta) ? 2 : 1)
-
-/**/
-static int
-igetmatch(char **sp, Patprog p, int fl, int n, char *replstr,
- LinkList *repllistp)
-{
- char *s = *sp, *t, *send;
- /*
- * Note that ioff and uml count characters in the character
- * set (Meta's are not included), while l counts characters in the
- * metafied string. umlen is a counter for (unmetafied) character
- * lengths.
- */
- int ioff, l = strlen(*sp), uml = ztrlen(*sp), matched = 1, umlen;
- struct patstralloc patstralloc;
- struct imatchdata imd;
-
- (void)patallocstr(p, s, l, uml, 1, &patstralloc);
- s = patstralloc.alloced;
- DPUTS(!s, "forced patallocstr failed");
- send = s + uml;
-
- imd.mstr = *sp;
- imd.mlen = l;
- imd.ustr = s;
- imd.ulen = uml;
- imd.flags = fl;
- imd.replstr = replstr;
- imd.repllist = NULL;
-
- /* perform must-match test for complex closures */
- if (p->mustoff)
- {
- char *muststr = (char *)p + p->mustoff;
-
- matched = 0;
- if (p->patmlen <= uml)
- {
- for (t = s; t <= send - p->patmlen; t++)
- {
- if (!memcmp(muststr, t, p->patmlen)) {
- matched = 1;
- break;
- }
- }
- }
- }
-
- /* in case we used the prog before... */
- p->flags &= ~(PAT_NOTSTART|PAT_NOTEND);
-
- if (fl & SUB_ALL) {
- int i = matched && pattrylen(p, s, uml, 0, &patstralloc, 0);
- if (!i)
- imd.replstr = NULL;
- *sp = get_match_ret(&imd, 0, i ? l : 0);
- if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i)))
- return 0;
- return 1;
- }
- if (matched) {
- switch (fl & (SUB_END|SUB_LONG|SUB_SUBSTR)) {
- case 0:
- case SUB_LONG:
- /*
- * Largest/smallest possible match at head of string.
- * First get the longest match...
- */
- if (pattrylen(p, s, uml, 0, &patstralloc, 0)) {
- /* patmatchlen returns metafied length, as we need */
- int mlen = patmatchlen();
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- send = s + mlen;
- /*
- * ... now we know whether it's worth looking for the
- * shortest, which we do by brute force.
- */
- for (t = s, umlen = 0; t < s + mlen; METAINC(t), umlen++) {
- set_pat_end(p, *t);
- if (pattrylen(p, s, umlen, 0, &patstralloc, 0)) {
- mlen = patmatchlen();
- break;
- }
- }
- }
- *sp = get_match_ret(&imd, 0, mlen);
- return 1;
- }
- break;
-
- case SUB_END:
- /* Smallest possible match at tail of string: *
- * move back down string until we get a match. *
- * There's no optimization here. */
- for (ioff = uml, t = send, umlen = 0; t >= s;
- t--, ioff--, umlen++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) {
- *sp = get_match_ret(&imd, t - s, uml);
- return 1;
- }
- }
- break;
-
- case (SUB_END|SUB_LONG):
- /* Largest possible match at tail of string: *
- * move forward along string until we get a match. *
- * Again there's no optimisation. */
- for (ioff = 0, t = s, umlen = uml; t < send;
- ioff++, t++, umlen--) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff)) {
- *sp = get_match_ret(&imd, t-s, uml);
- return 1;
- }
- }
- break;
-
- case SUB_SUBSTR:
- /* Smallest at start, but matching substrings. */
- set_pat_start(p, l);
- if (!(fl & SUB_GLOBAL) &&
- pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) {
- *sp = get_match_ret(&imd, 0, 0);
- return 1;
- } /* fall through */
- case (SUB_SUBSTR|SUB_LONG):
- /* longest or smallest at start with substrings */
- t = s;
- if (fl & SUB_GLOBAL) {
- imd.repllist = newlinklist();
- if (repllistp)
- *repllistp = imd.repllist;
- }
- ioff = 0; /* offset into string */
- umlen = uml;
- do {
- /* loop over all matches for global substitution */
- matched = 0;
- for (; t < send; t++, ioff++, umlen--) {
- /* Find the longest match from this position. */
- set_pat_start(p, t-s);
- if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff)) {
- char *mpos = t + patmatchlen();
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- char *ptr;
- int umlen2;
- for (ptr = t, umlen2 = 0; ptr < mpos;
- ptr++, umlen2++) {
- set_pat_end(p, *ptr);
- if (pattrylen(p, t, ptr - t, umlen2,
- &patstralloc, ioff)) {
- mpos = t + patmatchlen();
- break;
- }
- }
- }
- if (!--n || (n <= 0 && (fl & SUB_GLOBAL))) {
- *sp = get_match_ret(&imd, t-s, mpos-s);
- if (mpos == t)
- mpos++;
- }
- if (!(fl & SUB_GLOBAL)) {
- if (n) {
- /*
- * Looking for a later match: in this case,
- * we can continue looking for matches from
- * the next character, even if it overlaps
- * with what we just found.
- */
- continue;
- } else {
- return 1;
- }
- }
- /*
- * For a global match, we need to skip the stuff
- * which is already marked for replacement.
- */
- matched = 1;
- while (t < mpos) {
- ioff++;
- umlen--;
- t++;
- }
- break;
- }
- }
- } while (matched);
- /*
- * check if we can match a blank string, if so do it
- * at the start. Goodness knows if this is a good idea
- * with global substitution, so it doesn't happen.
- */
- set_pat_start(p, l);
- if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG &&
- pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) {
- *sp = get_match_ret(&imd, 0, 0);
- return 1;
- }
- break;
-
- case (SUB_END|SUB_SUBSTR):
- case (SUB_END|SUB_LONG|SUB_SUBSTR):
- /* Longest/shortest at end, matching substrings. */
- if (!(fl & SUB_LONG)) {
- set_pat_start(p, l);
- if (pattrylen(p, send, 0, 0, &patstralloc, uml) && !--n) {
- *sp = get_match_ret(&imd, uml, uml);
- return 1;
- }
- }
- for (ioff = uml - 1, t = send - 1, umlen = 1; t >= s;
- t--, ioff--, umlen++) {
- set_pat_start(p, t-s);
- if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff) &&
- !--n) {
- /* Found the longest match */
- char *mpos = t + patmatchlen();
- if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) {
- char *ptr;
- int umlen2;
- for (ptr = t, umlen2 = 0; ptr < mpos;
- ptr++, umlen2++) {
- set_pat_end(p, *ptr);
- if (pattrylen(p, t, umlen2, 0, &patstralloc,
- ioff)) {
- mpos = t + patmatchlen();
- break;
- }
- }
- }
- *sp = get_match_ret(&imd, t-s, mpos-s);
- return 1;
- }
- }
- set_pat_start(p, l);
- if ((fl & SUB_LONG) && pattrylen(p, send, 0, 0,
- &patstralloc, uml) &&
- !--n) {
- *sp = get_match_ret(&imd, uml, uml);
- return 1;
- }
- break;
- }
- }
-
- if (imd.repllist && nonempty(imd.repllist)) {
- /* Put all the bits of a global search and replace together. */
- LinkNode nd;
- Repldata rd;
- int lleft = 0; /* size of returned string */
- char *ptr, *start;
- int i;
-
- /*
- * Use metafied string again.
- * Results from get_match_ret in repllist are all metafied.
- */
- s = *sp;
- i = 0; /* start of last chunk we got from *sp */
- for (nd = firstnode(imd.repllist); nd; incnode(nd)) {
- rd = (Repldata) getdata(nd);
- lleft += rd->b - i; /* previous chunk of *sp */
- lleft += strlen(rd->replstr); /* the replaced bit */
- i = rd->e; /* start of next chunk of *sp */
- }
- lleft += l - i; /* final chunk from *sp */
- start = t = zhalloc(lleft+1);
- i = 0;
- for (nd = firstnode(imd.repllist); nd; incnode(nd)) {
- rd = (Repldata) getdata(nd);
- memcpy(t, s + i, rd->b - i);
- t += rd->b - i;
- ptr = rd->replstr;
- while (*ptr)
- *t++ = *ptr++;
- i = rd->e;
- }
- memcpy(t, s + i, l - i);
- start[lleft] = '\0';
- *sp = (char *)start;
- return 1;
- }
-
- /* munge the whole string: no match, so no replstr */
- imd.replstr = NULL;
- imd.repllist = NULL;
- *sp = get_match_ret(&imd, 0, 0);
- return 1;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/* blindly turn a string into a tokenised expression without lexing */
-
-/**/
-mod_export void
-tokenize(char *s)
-{
- zshtokenize(s, 0);
-}
-
-/*
- * shtokenize is used when we tokenize a string with GLOB_SUBST set.
- * In that case we need to retain backslashes when we turn the
- * pattern back into a string, so that the string is not
- * modified if it failed to match a pattern.
- *
- * It may be modified by the effect of SH_GLOB which turns off
- * various zsh-specific options.
- */
-
-/**/
-mod_export void
-shtokenize(char *s)
-{
- int flags = ZSHTOK_SUBST;
- if (isset(SHGLOB))
- flags |= ZSHTOK_SHGLOB;
- zshtokenize(s, flags);
-}
-
-/**/
-static void
-zshtokenize(char *s, int flags)
-{
- char *t;
- int bslash = 0;
-
- for (; *s; s++) {
- cont:
- switch (*s) {
- case Meta:
- /* skip both Meta and following character */
- s++;
- break;
- case Bnull:
- case Bnullkeep:
- case '\\':
- if (bslash) {
- s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull;
- break;
- }
- bslash = 1;
- continue;
- case '<':
- if (flags & ZSHTOK_SHGLOB)
- break;
- if (bslash) {
- s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull;
- break;
- }
- t = s;
- while (idigit(*++s));
- if (!IS_DASH(*s))
- goto cont;
- while (idigit(*++s));
- if (*s != '>')
- goto cont;
- *t = Inang;
- *s = Outang;
- break;
- case '(':
- case '|':
- case ')':
- if (flags & ZSHTOK_SHGLOB)
- break;
- /*FALLTHROUGH*/
- case '>':
- case '^':
- case '#':
- case '~':
- case '[':
- case ']':
- case '*':
- case '?':
- case '=':
- case '-':
- case '!':
- for (t = ztokens; *t; t++) {
- if (*t == *s) {
- if (bslash)
- s[-1] = (flags & ZSHTOK_SUBST) ? Bnullkeep : Bnull;
- else
- *s = (t - ztokens) + Pound;
- break;
- }
- }
- break;
- }
- bslash = 0;
- }
-}
-
-/* remove unnecessary Nulargs */
-
-/**/
-mod_export void
-remnulargs(char *s)
-{
- if (*s) {
- char *o = s, c;
-
- while ((c = *s++))
- if (c == Bnullkeep) {
- /*
- * An active backslash that needs to be turned back into
- * a real backslash for output. However, we don't
- * do that yet since we need to ignore it during
- * pattern matching.
- */
- continue;
- } else if (inull(c)) {
- char *t = s - 1;
-
- while ((c = *s++)) {
- if (c == Bnullkeep)
- *t++ = '\\';
- else if (!inull(c))
- *t++ = c;
- }
- *t = '\0';
- if (!*o) {
- o[0] = Nularg;
- o[1] = '\0';
- }
- break;
- }
- }
-}
-
-/* qualifier functions: mostly self-explanatory, see glob(). */
-
-/* device number */
-
-/**/
-static int
-qualdev(UNUSED(char *name), struct stat *buf, off_t dv, UNUSED(char *dummy))
-{
- return (off_t)buf->st_dev == dv;
-}
-
-/* number of hard links to file */
-
-/**/
-static int
-qualnlink(UNUSED(char *name), struct stat *buf, off_t ct, UNUSED(char *dummy))
-{
- return (g_range < 0 ? buf->st_nlink < ct :
- g_range > 0 ? buf->st_nlink > ct :
- buf->st_nlink == ct);
-}
-
-/* user ID */
-
-/**/
-static int
-qualuid(UNUSED(char *name), struct stat *buf, off_t uid, UNUSED(char *dummy))
-{
- return buf->st_uid == uid;
-}
-
-/* group ID */
-
-/**/
-static int
-qualgid(UNUSED(char *name), struct stat *buf, off_t gid, UNUSED(char *dummy))
-{
- return buf->st_gid == gid;
-}
-
-/* device special file? */
-
-/**/
-static int
-qualisdev(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISBLK(buf->st_mode) || S_ISCHR(buf->st_mode);
-}
-
-/* block special file? */
-
-/**/
-static int
-qualisblk(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISBLK(buf->st_mode);
-}
-
-/* character special file? */
-
-/**/
-static int
-qualischr(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISCHR(buf->st_mode);
-}
-
-/* directory? */
-
-/**/
-static int
-qualisdir(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISDIR(buf->st_mode);
-}
-
-/* FIFO? */
-
-/**/
-static int
-qualisfifo(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISFIFO(buf->st_mode);
-}
-
-/* symbolic link? */
-
-/**/
-static int
-qualislnk(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISLNK(buf->st_mode);
-}
-
-/* regular file? */
-
-/**/
-static int
-qualisreg(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISREG(buf->st_mode);
-}
-
-/* socket? */
-
-/**/
-static int
-qualissock(UNUSED(char *name), struct stat *buf, UNUSED(off_t junk), UNUSED(char *dummy))
-{
- return S_ISSOCK(buf->st_mode);
-}
-
-/* given flag is set in mode */
-
-/**/
-static int
-qualflags(UNUSED(char *name), struct stat *buf, off_t mod, UNUSED(char *dummy))
-{
- return mode_to_octal(buf->st_mode) & mod;
-}
-
-/* mode matches specification */
-
-/**/
-static int
-qualmodeflags(UNUSED(char *name), struct stat *buf, off_t mod, UNUSED(char *dummy))
-{
- long v = mode_to_octal(buf->st_mode), y = mod & 07777, n = mod >> 12;
-
- return ((v & y) == y && !(v & n));
-}
-
-/* regular executable file? */
-
-/**/
-static int
-qualiscom(UNUSED(char *name), struct stat *buf, UNUSED(off_t mod), UNUSED(char *dummy))
-{
- return S_ISREG(buf->st_mode) && (buf->st_mode & S_IXUGO);
-}
-
-/* size in required range? */
-
-/**/
-static int
-qualsize(UNUSED(char *name), struct stat *buf, off_t size, UNUSED(char *dummy))
-{
-#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
-# define QS_CAST_SIZE()
- zlong scaled = buf->st_size;
-#else
-# define QS_CAST_SIZE() (unsigned long)
- unsigned long scaled = (unsigned long)buf->st_size;
-#endif
-
- switch (g_units) {
- case TT_POSIX_BLOCKS:
- scaled += 511l;
- scaled /= 512l;
- break;
- case TT_KILOBYTES:
- scaled += 1023l;
- scaled /= 1024l;
- break;
- case TT_MEGABYTES:
- scaled += 1048575l;
- scaled /= 1048576l;
- break;
-#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
- case TT_GIGABYTES:
- scaled += ZLONG_CONST(1073741823);
- scaled /= ZLONG_CONST(1073741824);
- break;
- case TT_TERABYTES:
- scaled += ZLONG_CONST(1099511627775);
- scaled /= ZLONG_CONST(1099511627776);
- break;
-#endif
- }
-
- return (g_range < 0 ? scaled < QS_CAST_SIZE() size :
- g_range > 0 ? scaled > QS_CAST_SIZE() size :
- scaled == QS_CAST_SIZE() size);
-#undef QS_CAST_SIZE
-}
-
-/* time in required range? */
-
-/**/
-static int
-qualtime(UNUSED(char *name), struct stat *buf, off_t days, UNUSED(char *dummy))
-{
- time_t now, diff;
-
- time(&now);
- diff = now - (g_amc == 0 ? buf->st_atime : g_amc == 1 ? buf->st_mtime :
- buf->st_ctime);
- /* handle multipliers indicating units */
- switch (g_units) {
- case TT_DAYS:
- diff /= 86400l;
- break;
- case TT_HOURS:
- diff /= 3600l;
- break;
- case TT_MINS:
- diff /= 60l;
- break;
- case TT_WEEKS:
- diff /= 604800l;
- break;
- case TT_MONTHS:
- diff /= 2592000l;
- break;
- }
-
- return (g_range < 0 ? diff < days :
- g_range > 0 ? diff > days :
- diff == days);
-}
-
-/* evaluate a string */
-
-/**/
-static int
-qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str)
-{
- Eprog prog;
-
- if ((prog = parse_string(str, 0))) {
- int ef = errflag, lv = lastval, ret;
- int cshglob = badcshglob;
-
- unsetparam("reply");
- setsparam("REPLY", ztrdup(name));
- badcshglob = 0;
-
- execode(prog, 1, 0, "globqual");
-
- if ((ret = lastval))
- badcshglob |= cshglob;
- /* Retain any user interrupt error status */
- errflag = ef | (errflag & ERRFLAG_INT);
- lastval = lv;
-
- if (!(inserts = getaparam("reply")) &&
- !(inserts = gethparam("reply"))) {
- char *tmp;
-
- if ((tmp = getsparam("reply")) || (tmp = getsparam("REPLY"))) {
- static char *tmparr[2];
-
- tmparr[0] = tmp;
- tmparr[1] = NULL;
-
- inserts = tmparr;
- }
- }
-
- return !ret;
- }
- return 0;
-}
-
-/**/
-static int
-qualnonemptydir(char *name, struct stat *buf, UNUSED(off_t days), UNUSED(char *str))
-{
- DIR *dirh;
- struct dirent *de;
- int unamelen;
- char *uname = unmetafy(dupstring(name), &unamelen);
-
- if (!S_ISDIR(buf->st_mode))
- return 0;
-
- if (buf->st_nlink > 2)
- return 1;
-
- if (!(dirh = opendir(uname)))
- return 0;
-
- while ((de = readdir(dirh))) {
- if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {
- closedir(dirh);
- return 1;
- }
- }
-
- closedir(dirh);
- return 0;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.c
deleted file mode 100644
index b7baa314..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.c
+++ /dev/null
@@ -1,1617 +0,0 @@
-/*
- * hashtable.c - hash tables
- *
- * 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 "../config.h"
-
-#ifdef ZSH_HASH_DEBUG
-# define HASHTABLE_DEBUG_MEMBERS \
- /* Members of struct hashtable used for debugging hash tables */ \
- HashTable next, last; /* linked list of all hash tables */ \
- char *tablename; /* string containing name of the hash table */ \
- PrintTableStats printinfo; /* pointer to function to print table stats */
-#else /* !ZSH_HASH_DEBUG */
-# define HASHTABLE_DEBUG_MEMBERS
-#endif /* !ZSH_HASH_DEBUG */
-
-#define HASHTABLE_INTERNAL_MEMBERS \
- ScanStatus scan; /* status of a scan over this hashtable */ \
- HASHTABLE_DEBUG_MEMBERS
-
-typedef struct scanstatus *ScanStatus;
-
-#include "zsh.mdh"
-#include "hashtable.pro"
-
-/* Structure for recording status of a hashtable scan in progress. When a *
- * scan starts, the .scan member of the hashtable structure points to one *
- * of these. That member being non-NULL disables resizing of the *
- * hashtable (when adding elements). When elements are deleted, the *
- * contents of this structure is used to make sure the scan won't stumble *
- * into the deleted element. */
-
-struct scanstatus {
- int sorted;
- union {
- struct {
- HashNode *hashtab;
- int ct;
- } s;
- HashNode u;
- } u;
-};
-
-/********************************/
-/* Generic Hash Table functions */
-/********************************/
-
-#ifdef ZSH_HASH_DEBUG
-static HashTable firstht, lastht;
-#endif /* ZSH_HASH_DEBUG */
-
-/* Generic hash function */
-
-/**/
-mod_export unsigned
-hasher(const char *str)
-{
- unsigned hashval = 0, c;
-
- while ((c = *((unsigned char *) str++)))
- hashval += (hashval << 5) + c;
-
- return hashval;
-}
-
-/* Get a new hash table */
-
-/**/
-mod_export HashTable
-newhashtable(int size, UNUSED(char const *name), UNUSED(PrintTableStats printinfo))
-{
- HashTable ht;
-
- ht = (HashTable) zshcalloc(sizeof *ht);
-#ifdef ZSH_HASH_DEBUG
- ht->next = NULL;
- if(!firstht)
- firstht = ht;
- ht->last = lastht;
- if(lastht)
- lastht->next = ht;
- lastht = ht;
- ht->printinfo = printinfo ? printinfo : printhashtabinfo;
- ht->tablename = ztrdup(name);
-#endif /* ZSH_HASH_DEBUG */
- ht->nodes = (HashNode *) zshcalloc(size * sizeof(HashNode));
- ht->hsize = size;
- ht->ct = 0;
- ht->scan = NULL;
- ht->scantab = NULL;
- return ht;
-}
-
-/* Delete a hash table. After this function has been used, any *
- * existing pointers to the hash table are invalid. */
-
-/**/
-mod_export void
-deletehashtable(HashTable ht)
-{
- ht->emptytable(ht);
-#ifdef ZSH_HASH_DEBUG
- if(ht->next)
- ht->next->last = ht->last;
- else
- lastht = ht->last;
- if(ht->last)
- ht->last->next = ht->next;
- else
- firstht = ht->next;
- zsfree(ht->tablename);
-#endif /* ZSH_HASH_DEBUG */
- zfree(ht->nodes, ht->hsize * sizeof(HashNode));
- zfree(ht, sizeof(*ht));
-}
-
-/* Add a node to a hash table. *
- * nam is the key to use in hashing. nodeptr points *
- * to the node to add. If there is already a node in *
- * the table with the same key, it is first freed, and *
- * then the new node is added. If the number of nodes *
- * is now greater than twice the number of hash values, *
- * the table is then expanded. */
-
-/**/
-mod_export void
-addhashnode(HashTable ht, char *nam, void *nodeptr)
-{
- HashNode oldnode = addhashnode2(ht, nam, nodeptr);
- if (oldnode)
- ht->freenode(oldnode);
-}
-
-/* Add a node to a hash table, returning the old node on replacement. */
-
-/**/
-HashNode
-addhashnode2(HashTable ht, char *nam, void *nodeptr)
-{
- unsigned hashval;
- HashNode hn, hp, hq;
-
- hn = (HashNode) nodeptr;
- hn->nam = nam;
-
- hashval = ht->hash(hn->nam) % ht->hsize;
- hp = ht->nodes[hashval];
-
- /* check if this is the first node for this hash value */
- if (!hp) {
- hn->next = NULL;
- ht->nodes[hashval] = hn;
- if (++ht->ct >= ht->hsize * 2 && !ht->scan)
- expandhashtable(ht);
- return NULL;
- }
-
- /* else check if the first node contains the same key */
- if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
- ht->nodes[hashval] = hn;
- replacing:
- hn->next = hp->next;
- if(ht->scan) {
- if(ht->scan->sorted) {
- HashNode *hashtab = ht->scan->u.s.hashtab;
- int i;
- for(i = ht->scan->u.s.ct; i--; )
- if(hashtab[i] == hp)
- hashtab[i] = hn;
- } else if(ht->scan->u.u == hp)
- ht->scan->u.u = hn;
- }
- return hp;
- }
-
- /* else run through the list and check all the keys */
- hq = hp;
- hp = hp->next;
- for (; hp; hq = hp, hp = hp->next) {
- if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
- hq->next = hn;
- goto replacing;
- }
- }
-
- /* else just add it at the front of the list */
- hn->next = ht->nodes[hashval];
- ht->nodes[hashval] = hn;
- if (++ht->ct >= ht->hsize * 2 && !ht->scan)
- expandhashtable(ht);
- return NULL;
-}
-
-/* Get an enabled entry in a hash table. *
- * If successful, it returns a pointer to *
- * the hashnode. If the node is DISABLED *
- * or isn't found, it returns NULL */
-
-/**/
-mod_export HashNode
-gethashnode(HashTable ht, const char *nam)
-{
- unsigned hashval;
- HashNode hp;
-
- hashval = ht->hash(nam) % ht->hsize;
- for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
- if (ht->cmpnodes(hp->nam, nam) == 0) {
- if (hp->flags & DISABLED)
- return NULL;
- else
- return hp;
- }
- }
- return NULL;
-}
-
-/* Get an entry in a hash table. It will *
- * ignore the DISABLED flag and return a *
- * pointer to the hashnode if found, else *
- * it returns NULL. */
-
-/**/
-mod_export HashNode
-gethashnode2(HashTable ht, const char *nam)
-{
- unsigned hashval;
- HashNode hp;
-
- hashval = ht->hash(nam) % ht->hsize;
- for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
- if (ht->cmpnodes(hp->nam, nam) == 0)
- return hp;
- }
- return NULL;
-}
-
-/* Remove an entry from a hash table. *
- * If successful, it removes the node from the *
- * table and returns a pointer to it. If there *
- * is no such node, then it returns NULL */
-
-/**/
-mod_export HashNode
-removehashnode(HashTable ht, const char *nam)
-{
- unsigned hashval;
- HashNode hp, hq;
-
- hashval = ht->hash(nam) % ht->hsize;
- hp = ht->nodes[hashval];
-
- /* if no nodes at this hash value, return NULL */
- if (!hp)
- return NULL;
-
- /* else check if the key in the first one matches */
- if (ht->cmpnodes(hp->nam, nam) == 0) {
- ht->nodes[hashval] = hp->next;
- gotit:
- ht->ct--;
- if(ht->scan) {
- if(ht->scan->sorted) {
- HashNode *hashtab = ht->scan->u.s.hashtab;
- int i;
- for(i = ht->scan->u.s.ct; i--; )
- if(hashtab[i] == hp)
- hashtab[i] = NULL;
- } else if(ht->scan->u.u == hp)
- ht->scan->u.u = hp->next;
- }
- return hp;
- }
-
- /* else run through the list and check the rest of the keys */
- hq = hp;
- hp = hp->next;
- for (; hp; hq = hp, hp = hp->next) {
- if (ht->cmpnodes(hp->nam, nam) == 0) {
- hq->next = hp->next;
- goto gotit;
- }
- }
-
- /* else it is not in the list, so return NULL */
- return NULL;
-}
-
-/* Disable a node in a hash table */
-
-/**/
-void
-disablehashnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags |= DISABLED;
-}
-
-/* Enable a node in a hash table */
-
-/**/
-void
-enablehashnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags &= ~DISABLED;
-}
-
-/* Compare two hash table entries by name */
-
-/**/
-static int
-hnamcmp(const void *ap, const void *bp)
-{
- HashNode a = *(HashNode *)ap;
- HashNode b = *(HashNode *)bp;
- return ztrcmp(a->nam, b->nam);
-}
-
-/* Scan the nodes in a hash table and execute scanfunc on nodes based on
- * the flags that are set/unset. scanflags is passed unchanged to
- * scanfunc (if executed).
- *
- * If sorted != 0, then sort entries of hash table before scanning.
- * If flags1 > 0, then execute scanfunc on a node only if at least one of
- * these flags is set.
- * If flags2 > 0, then execute scanfunc on a node only if all of
- * these flags are NOT set.
- * The conditions above for flags1/flags2 must both be true.
- *
- * It is safe to add, remove or replace hash table elements from within
- * the scanfunc. Replaced elements will appear in the scan exactly once,
- * the new version if it was not scanned before the replacement was made.
- * Added elements might or might not appear in the scan.
- *
- * pprog, if non-NULL, is a pattern that must match the name
- * of the node.
- *
- * The function returns the number of matches, as reduced by pprog, flags1
- * and flags2.
- */
-
-/**/
-mod_export int
-scanmatchtable(HashTable ht, Patprog pprog, int sorted,
- int flags1, int flags2, ScanFunc scanfunc, int scanflags)
-{
- int match = 0;
- struct scanstatus st;
-
- /*
- * scantab is currently only used by modules to scan
- * tables where the contents are generated on the fly from
- * other objects. Note the fact that in this case pprog,
- * sorted, flags1 and flags2 are ignore.
- */
- if (!pprog && ht->scantab) {
- ht->scantab(ht, scanfunc, scanflags);
- return ht->ct;
- }
- if (sorted) {
- int i, ct = ht->ct;
- VARARR(HashNode, hnsorttab, ct);
- HashNode *htp, hn;
-
- /*
- * Because the structure might change under our feet,
- * we can't apply the flags and the pattern before sorting,
- * tempting though that is.
- */
- for (htp = hnsorttab, i = 0; i < ht->hsize; i++)
- for (hn = ht->nodes[i]; hn; hn = hn->next)
- *htp++ = hn;
- qsort((void *)hnsorttab, ct, sizeof(HashNode), hnamcmp);
-
- st.sorted = 1;
- st.u.s.hashtab = hnsorttab;
- st.u.s.ct = ct;
- ht->scan = &st;
-
- for (htp = hnsorttab, i = 0; i < ct; i++, htp++) {
- if ((!flags1 || ((*htp)->flags & flags1)) &&
- !((*htp)->flags & flags2) &&
- (!pprog || pattry(pprog, (*htp)->nam))) {
- match++;
- scanfunc(*htp, scanflags);
- }
- }
-
- ht->scan = NULL;
- } else {
- int i, hsize = ht->hsize;
- HashNode *nodes = ht->nodes;
-
- st.sorted = 0;
- ht->scan = &st;
-
- for (i = 0; i < hsize; i++)
- for (st.u.u = nodes[i]; st.u.u; ) {
- HashNode hn = st.u.u;
- st.u.u = st.u.u->next;
- if ((!flags1 || (hn->flags & flags1)) && !(hn->flags & flags2)
- && (!pprog || pattry(pprog, hn->nam))) {
- match++;
- scanfunc(hn, scanflags);
- }
- }
-
- ht->scan = NULL;
- }
-
- return match;
-}
-
-
-/**/
-mod_export int
-scanhashtable(HashTable ht, int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags)
-{
- return scanmatchtable(ht, NULL, sorted, flags1, flags2,
- scanfunc, scanflags);
-}
-
-/* Expand hash tables when they get too many entries. *
- * The new size is 4 times the previous size. */
-
-/**/
-static void
-expandhashtable(HashTable ht)
-{
- struct hashnode **onodes, **ha, *hn, *hp;
- int i, osize;
-
- osize = ht->hsize;
- onodes = ht->nodes;
-
- ht->hsize = osize * 4;
- ht->nodes = (HashNode *) zshcalloc(ht->hsize * sizeof(HashNode));
- ht->ct = 0;
-
- /* scan through the old list of nodes, and *
- * rehash them into the new list of nodes */
- for (i = 0, ha = onodes; i < osize; i++, ha++) {
- for (hn = *ha; hn;) {
- hp = hn->next;
- ht->addnode(ht, hn->nam, hn);
- hn = hp;
- }
- }
- zfree(onodes, osize * sizeof(HashNode));
-}
-
-/* Empty the hash table and resize it if necessary */
-
-/**/
-static void
-resizehashtable(HashTable ht, int newsize)
-{
- struct hashnode **ha, *hn, *hp;
- int i;
-
- /* free all the hash nodes */
- ha = ht->nodes;
- for (i = 0; i < ht->hsize; i++, ha++) {
- for (hn = *ha; hn;) {
- hp = hn->next;
- ht->freenode(hn);
- hn = hp;
- }
- }
-
- /* If new size desired is different from current size, *
- * we free it and allocate a new nodes array. */
- if (ht->hsize != newsize) {
- zfree(ht->nodes, ht->hsize * sizeof(HashNode));
- ht->nodes = (HashNode *) zshcalloc(newsize * sizeof(HashNode));
- ht->hsize = newsize;
- } else {
- /* else we just re-zero the current nodes array */
- memset(ht->nodes, 0, newsize * sizeof(HashNode));
- }
-
- ht->ct = 0;
-}
-
-/* Generic method to empty a hash table */
-
-/**/
-mod_export void
-emptyhashtable(HashTable ht)
-{
- resizehashtable(ht, ht->hsize);
-}
-
-/**/
-#ifdef ZSH_HASH_DEBUG
-
-/* Print info about hash table */
-
-#define MAXDEPTH 7
-
-/**/
-static void
-printhashtabinfo(HashTable ht)
-{
- HashNode hn;
- int chainlen[MAXDEPTH + 1];
- int i, tmpcount, total;
-
- printf("name of table : %s\n", ht->tablename);
- printf("size of nodes[] : %d\n", ht->hsize);
- printf("number of nodes : %d\n\n", ht->ct);
-
- memset(chainlen, 0, sizeof(chainlen));
-
- /* count the number of nodes just to be sure */
- total = 0;
- for (i = 0; i < ht->hsize; i++) {
- tmpcount = 0;
- for (hn = ht->nodes[i]; hn; hn = hn->next)
- tmpcount++;
- if (tmpcount >= MAXDEPTH)
- chainlen[MAXDEPTH]++;
- else
- chainlen[tmpcount]++;
- total += tmpcount;
- }
-
- for (i = 0; i < MAXDEPTH; i++)
- printf("number of hash values with chain of length %d : %4d\n", i, chainlen[i]);
- printf("number of hash values with chain of length %d+ : %4d\n", MAXDEPTH, chainlen[MAXDEPTH]);
- printf("total number of nodes : %4d\n", total);
-}
-
-/**/
-int
-bin_hashinfo(UNUSED(char *nam), UNUSED(char **args), UNUSED(Options ops), UNUSED(int func))
-{
- HashTable ht;
-
- printf("----------------------------------------------------\n");
- queue_signals();
- for(ht = firstht; ht; ht = ht->next) {
- ht->printinfo(ht);
- printf("----------------------------------------------------\n");
- }
- unqueue_signals();
- return 0;
-}
-
-/**/
-#endif /* ZSH_HASH_DEBUG */
-
-/********************************/
-/* Command Hash Table Functions */
-/********************************/
-
-/* hash table containing external commands */
-
-/**/
-mod_export HashTable cmdnamtab;
-
-/* how far we've hashed the PATH so far */
-
-/**/
-mod_export char **pathchecked;
-
-/* Create a new command hash table */
-
-/**/
-void
-createcmdnamtable(void)
-{
- cmdnamtab = newhashtable(201, "cmdnamtab", NULL);
-
- cmdnamtab->hash = hasher;
- cmdnamtab->emptytable = emptycmdnamtable;
- cmdnamtab->filltable = fillcmdnamtable;
- cmdnamtab->cmpnodes = strcmp;
- cmdnamtab->addnode = addhashnode;
- cmdnamtab->getnode = gethashnode2;
- cmdnamtab->getnode2 = gethashnode2;
- cmdnamtab->removenode = removehashnode;
- cmdnamtab->disablenode = NULL;
- cmdnamtab->enablenode = NULL;
- cmdnamtab->freenode = freecmdnamnode;
- cmdnamtab->printnode = printcmdnamnode;
-
- pathchecked = path;
-}
-
-/**/
-static void
-emptycmdnamtable(HashTable ht)
-{
- emptyhashtable(ht);
- pathchecked = path;
-}
-
-/* Add all commands in a given directory *
- * to the command hashtable. */
-
-/**/
-void
-hashdir(char **dirp)
-{
- Cmdnam cn;
- DIR *dir;
- char *fn, *unmetadir, *pathbuf, *pathptr;
- int dirlen;
-#if defined(_WIN32) || defined(__CYGWIN__)
- char *exe;
-#endif /* _WIN32 || _CYGWIN__ */
-
- if (isrelative(*dirp))
- return;
- unmetadir = unmeta(*dirp);
- if (!(dir = opendir(unmetadir)))
- return;
-
- dirlen = strlen(unmetadir);
- pathbuf = (char *)zalloc(dirlen + PATH_MAX + 2);
- sprintf(pathbuf, "%s/", unmetadir);
- pathptr = pathbuf + dirlen + 1;
-
- while ((fn = zreaddir(dir, 1))) {
- if (!cmdnamtab->getnode(cmdnamtab, fn)) {
- char *fname = ztrdup(fn);
- struct stat statbuf;
- int add = 0, dummylen;
-
- unmetafy(fn, &dummylen);
- if (strlen(fn) > PATH_MAX) {
- /* Too heavy to do all the allocation */
- add = 1;
- } else {
- strcpy(pathptr, fn);
- /*
- * This is the same test as for the glob qualifier for
- * executable plain files.
- */
- if (unset(HASHEXECUTABLESONLY) ||
- (access(pathbuf, X_OK) == 0 &&
- stat(pathbuf, &statbuf) == 0 &&
- S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO)))
- add = 1;
- }
- if (add) {
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = dirp;
- cmdnamtab->addnode(cmdnamtab, fname, cn);
- } else
- zsfree(fname);
- }
-#if defined(_WIN32) || defined(__CYGWIN__)
- /* Hash foo.exe as foo, since when no real foo exists, foo.exe
- will get executed by DOS automatically. This quiets
- spurious corrections when CORRECT or CORRECT_ALL is set. */
- if ((exe = strrchr(fn, '.')) &&
- (exe[1] == 'E' || exe[1] == 'e') &&
- (exe[2] == 'X' || exe[2] == 'x') &&
- (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) {
- *exe = 0;
- if (!cmdnamtab->getnode(cmdnamtab, fn)) {
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = dirp;
- cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
- }
- }
-#endif /* _WIN32 || __CYGWIN__ */
- }
- closedir(dir);
- zfree(pathbuf, dirlen + PATH_MAX + 2);
-}
-
-/* Go through user's PATH and add everything to *
- * the command hashtable. */
-
-/**/
-static void
-fillcmdnamtable(UNUSED(HashTable ht))
-{
- char **pq;
-
- for (pq = pathchecked; *pq; pq++)
- hashdir(pq);
-
- pathchecked = pq;
-}
-
-/**/
-static void
-freecmdnamnode(HashNode hn)
-{
- Cmdnam cn = (Cmdnam) hn;
-
- zsfree(cn->node.nam);
- if (cn->node.flags & HASHED)
- zsfree(cn->u.cmd);
-
- zfree(cn, sizeof(struct cmdnam));
-}
-
-/* Print an element of the cmdnamtab hash table (external command) */
-
-/**/
-static void
-printcmdnamnode(HashNode hn, int printflags)
-{
- Cmdnam cn = (Cmdnam) hn;
-
- if (printflags & PRINT_WHENCE_WORD) {
- printf("%s: %s\n", cn->node.nam, (cn->node.flags & HASHED) ?
- "hashed" : "command");
- return;
- }
-
- if ((printflags & PRINT_WHENCE_CSH) || (printflags & PRINT_WHENCE_SIMPLE)) {
- if (cn->node.flags & HASHED) {
- zputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- zputs(*(cn->u.name), stdout);
- putchar('/');
- zputs(cn->node.nam, stdout);
- putchar('\n');
- }
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- if (cn->node.flags & HASHED) {
- nicezputs(cn->node.nam, stdout);
- printf(" is hashed to ");
- nicezputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- nicezputs(cn->node.nam, stdout);
- printf(" is ");
- nicezputs(*(cn->u.name), stdout);
- putchar('/');
- nicezputs(cn->node.nam, stdout);
- putchar('\n');
- }
- return;
- }
-
- if (printflags & PRINT_LIST) {
- printf("hash ");
-
- if(cn->node.nam[0] == '-')
- printf("-- ");
- }
-
- if (cn->node.flags & HASHED) {
- quotedzputs(cn->node.nam, stdout);
- putchar('=');
- quotedzputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- quotedzputs(cn->node.nam, stdout);
- putchar('=');
- quotedzputs(*(cn->u.name), stdout);
- putchar('/');
- quotedzputs(cn->node.nam, stdout);
- putchar('\n');
- }
-}
-
-/***************************************/
-/* Shell Function Hash Table Functions */
-/***************************************/
-
-/* hash table containing the shell functions */
-
-/**/
-mod_export HashTable shfunctab;
-
-/**/
-void
-createshfunctable(void)
-{
- shfunctab = newhashtable(7, "shfunctab", NULL);
-
- shfunctab->hash = hasher;
- shfunctab->emptytable = NULL;
- shfunctab->filltable = NULL;
- shfunctab->cmpnodes = strcmp;
- shfunctab->addnode = addhashnode;
- shfunctab->getnode = gethashnode;
- shfunctab->getnode2 = gethashnode2;
- shfunctab->removenode = removeshfuncnode;
- shfunctab->disablenode = disableshfuncnode;
- shfunctab->enablenode = enableshfuncnode;
- shfunctab->freenode = freeshfuncnode;
- shfunctab->printnode = printshfuncnode;
-}
-
-/* Remove an entry from the shell function hash table. *
- * It checks if the function is a signal trap and if so, *
- * it will disable the trapping of that signal. */
-
-/**/
-static HashNode
-removeshfuncnode(UNUSED(HashTable ht), const char *nam)
-{
- HashNode hn;
- int signum;
-
- if (!strncmp(nam, "TRAP", 4) && (signum = getsignum(nam + 4)) != -1)
- hn = removetrap(signum);
- else
- hn = removehashnode(shfunctab, nam);
-
- return hn;
-}
-
-/* Disable an entry in the shell function hash table. *
- * It checks if the function is a signal trap and if so, *
- * it will disable the trapping of that signal. */
-
-/**/
-static void
-disableshfuncnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags |= DISABLED;
- if (!strncmp(hn->nam, "TRAP", 4)) {
- int signum = getsignum(hn->nam + 4);
- if (signum != -1) {
- sigtrapped[signum] &= ~ZSIG_FUNC;
- unsettrap(signum);
- }
- }
-}
-
-/* Re-enable an entry in the shell function hash table. *
- * It checks if the function is a signal trap and if so, *
- * it will re-enable the trapping of that signal. */
-
-/**/
-static void
-enableshfuncnode(HashNode hn, UNUSED(int flags))
-{
- Shfunc shf = (Shfunc) hn;
-
- shf->node.flags &= ~DISABLED;
- if (!strncmp(shf->node.nam, "TRAP", 4)) {
- int signum = getsignum(shf->node.nam + 4);
- if (signum != -1) {
- settrap(signum, NULL, ZSIG_FUNC);
- }
- }
-}
-
-/**/
-static void
-freeshfuncnode(HashNode hn)
-{
- Shfunc shf = (Shfunc) hn;
-
- zsfree(shf->node.nam);
- if (shf->funcdef)
- freeeprog(shf->funcdef);
- if (shf->redir)
- freeeprog(shf->redir);
- dircache_set(&shf->filename, NULL);
- if (shf->sticky) {
- if (shf->sticky->n_on_opts)
- zfree(shf->sticky->on_opts,
- shf->sticky->n_on_opts * sizeof(*shf->sticky->on_opts));
- if (shf->sticky->n_off_opts)
- zfree(shf->sticky->off_opts,
- shf->sticky->n_off_opts * sizeof(*shf->sticky->off_opts));
- zfree(shf->sticky, sizeof(*shf->sticky));
- }
- zfree(shf, sizeof(struct shfunc));
-}
-
-/* Print a shell function */
-
-/**/
-static void
-printshfuncnode(HashNode hn, int printflags)
-{
- Shfunc f = (Shfunc) hn;
- char *t = 0;
-
- if ((printflags & PRINT_NAMEONLY) ||
- ((printflags & PRINT_WHENCE_SIMPLE) &&
- !(printflags & PRINT_WHENCE_FUNCDEF))) {
- zputs(f->node.nam, stdout);
- putchar('\n');
- return;
- }
-
- if ((printflags & (PRINT_WHENCE_VERBOSE|PRINT_WHENCE_WORD)) &&
- !(printflags & PRINT_WHENCE_FUNCDEF)) {
- nicezputs(f->node.nam, stdout);
- printf((printflags & PRINT_WHENCE_WORD) ? ": function" :
- (f->node.flags & PM_UNDEFINED) ?
- " is an autoload shell function" :
- " is a shell function");
- if ((printflags & PRINT_WHENCE_VERBOSE) && f->filename) {
- printf(" from ");
- quotedzputs(f->filename, stdout);
- if (f->node.flags & PM_LOADDIR) {
- printf("/");
- quotedzputs(f->node.nam, stdout);
- }
- }
- putchar('\n');
- return;
- }
-
- quotedzputs(f->node.nam, stdout);
- if (f->funcdef || f->node.flags & PM_UNDEFINED) {
- printf(" () {\n");
- zoutputtab(stdout);
- if (f->node.flags & PM_UNDEFINED) {
- printf("%c undefined\n", hashchar);
- zoutputtab(stdout);
- } else
- t = getpermtext(f->funcdef, NULL, 1);
- if (f->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL)) {
- printf("%c traced\n", hashchar);
- zoutputtab(stdout);
- }
- if (!t) {
- char *fopt = "UtTkzc";
- int flgs[] = {
- PM_UNALIASED, PM_TAGGED, PM_TAGGED_LOCAL,
- PM_KSHSTORED, PM_ZSHSTORED, PM_CUR_FPATH, 0
- };
- int fl;;
-
- zputs("builtin autoload -X", stdout);
- for (fl=0;fopt[fl];fl++)
- if (f->node.flags & flgs[fl]) putchar(fopt[fl]);
- if (f->filename && (f->node.flags & PM_LOADDIR)) {
- putchar(' ');
- zputs(f->filename, stdout);
- }
- } else {
- zputs(t, stdout);
- zsfree(t);
- if (f->funcdef->flags & EF_RUN) {
- printf("\n");
- zoutputtab(stdout);
- quotedzputs(f->node.nam, stdout);
- printf(" \"$@\"");
- }
- }
- printf("\n}");
- } else {
- printf(" () { }");
- }
- if (f->redir) {
- t = getpermtext(f->redir, NULL, 1);
- if (t) {
- zputs(t, stdout);
- zsfree(t);
- }
- }
-
- putchar('\n');
-}
-
-/*
- * Wrap scanmatchtable for shell functions with optional
- * expansion of leading tabs.
- * expand = 0 is standard: use hard tabs.
- * expand > 0 uses that many spaces.
- * expand < 0 uses no identation.
- *
- * Note this function and the following two are called with
- * interrupts queued, so saving and restoring text_expand_tabs
- * is safe.
- */
-
-/**/
-mod_export int
-scanmatchshfunc(Patprog pprog, int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags, int expand)
-{
- int ret, save_expand;
-
- save_expand = text_expand_tabs;
- text_expand_tabs = expand;
- ret = scanmatchtable(shfunctab, pprog, sorted, flags1, flags2,
- scanfunc, scanflags);
- text_expand_tabs = save_expand;
-
- return ret;
-}
-
-/* Wrap scanhashtable to expand tabs for shell functions */
-
-/**/
-mod_export int
-scanshfunc(int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags, int expand)
-{
- return scanmatchshfunc(NULL, sorted, flags1, flags2,
- scanfunc, scanflags, expand);
-}
-
-/* Wrap shfunctab->printnode to expand tabs */
-
-/**/
-mod_export void
-printshfuncexpand(HashNode hn, int printflags, int expand)
-{
- int save_expand;
-
- save_expand = text_expand_tabs;
- text_expand_tabs = expand;
- shfunctab->printnode(hn, printflags);
- text_expand_tabs = save_expand;
-}
-
-/*
- * Get a heap-duplicated name of the shell function, for
- * use in tracing.
- */
-
-/**/
-mod_export char *
-getshfuncfile(Shfunc shf)
-{
- if (shf->node.flags & PM_LOADDIR) {
- return zhtricat(shf->filename, "/", shf->node.nam);
- } else if (shf->filename) {
- return dupstring(shf->filename);
- } else {
- return NULL;
- }
-}
-
-/**************************************/
-/* Reserved Word Hash Table Functions */
-/**************************************/
-
-/* Nodes for reserved word hash table */
-
-static struct reswd reswds[] = {
- {{NULL, "!", 0}, BANG},
- {{NULL, "[[", 0}, DINBRACK},
- {{NULL, "{", 0}, INBRACE},
- {{NULL, "}", 0}, OUTBRACE},
- {{NULL, "case", 0}, CASE},
- {{NULL, "coproc", 0}, COPROC},
- {{NULL, "declare", 0}, TYPESET},
- {{NULL, "do", 0}, DOLOOP},
- {{NULL, "done", 0}, DONE},
- {{NULL, "elif", 0}, ELIF},
- {{NULL, "else", 0}, ELSE},
- {{NULL, "end", 0}, ZEND},
- {{NULL, "esac", 0}, ESAC},
- {{NULL, "export", 0}, TYPESET},
- {{NULL, "fi", 0}, FI},
- {{NULL, "float", 0}, TYPESET},
- {{NULL, "for", 0}, FOR},
- {{NULL, "foreach", 0}, FOREACH},
- {{NULL, "function", 0}, FUNC},
- {{NULL, "if", 0}, IF},
- {{NULL, "integer", 0}, TYPESET},
- {{NULL, "local", 0}, TYPESET},
- {{NULL, "nocorrect", 0}, NOCORRECT},
- {{NULL, "readonly", 0}, TYPESET},
- {{NULL, "repeat", 0}, REPEAT},
- {{NULL, "select", 0}, SELECT},
- {{NULL, "then", 0}, THEN},
- {{NULL, "time", 0}, TIME},
- {{NULL, "typeset", 0}, TYPESET},
- {{NULL, "until", 0}, UNTIL},
- {{NULL, "while", 0}, WHILE},
- {{NULL, NULL, 0}, 0}
-};
-
-/* hash table containing the reserved words */
-
-/**/
-mod_export HashTable reswdtab;
-
-/* Build the hash table containing zsh's reserved words. */
-
-/**/
-void
-createreswdtable(void)
-{
- Reswd rw;
-
- reswdtab = newhashtable(23, "reswdtab", NULL);
-
- reswdtab->hash = hasher;
- reswdtab->emptytable = NULL;
- reswdtab->filltable = NULL;
- reswdtab->cmpnodes = strcmp;
- reswdtab->addnode = addhashnode;
- reswdtab->getnode = gethashnode;
- reswdtab->getnode2 = gethashnode2;
- reswdtab->removenode = NULL;
- reswdtab->disablenode = disablehashnode;
- reswdtab->enablenode = enablehashnode;
- reswdtab->freenode = NULL;
- reswdtab->printnode = printreswdnode;
-
- for (rw = reswds; rw->node.nam; rw++)
- reswdtab->addnode(reswdtab, rw->node.nam, rw);
-}
-
-/* Print a reserved word */
-
-/**/
-static void
-printreswdnode(HashNode hn, int printflags)
-{
- Reswd rw = (Reswd) hn;
-
- if (printflags & PRINT_WHENCE_WORD) {
- printf("%s: reserved\n", rw->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_CSH) {
- printf("%s: shell reserved word\n", rw->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- printf("%s is a reserved word\n", rw->node.nam);
- return;
- }
-
- /* default is name only */
- printf("%s\n", rw->node.nam);
-}
-
-/********************************/
-/* Aliases Hash Table Functions */
-/********************************/
-
-/* hash table containing the aliases */
-
-/**/
-mod_export HashTable aliastab;
-
-/* has table containing suffix aliases */
-
-/**/
-mod_export HashTable sufaliastab;
-
-/* Create new hash tables for aliases */
-
-/**/
-void
-createaliastable(HashTable ht)
-{
- ht->hash = hasher;
- ht->emptytable = NULL;
- ht->filltable = NULL;
- ht->cmpnodes = strcmp;
- ht->addnode = addhashnode;
- ht->getnode = gethashnode;
- ht->getnode2 = gethashnode2;
- ht->removenode = removehashnode;
- ht->disablenode = disablehashnode;
- ht->enablenode = enablehashnode;
- ht->freenode = freealiasnode;
- ht->printnode = printaliasnode;
-}
-
-/**/
-void
-createaliastables(void)
-{
- /* Table for regular and global aliases */
-
- aliastab = newhashtable(23, "aliastab", NULL);
-
- createaliastable(aliastab);
-
- /* add the default aliases */
- aliastab->addnode(aliastab, ztrdup("run-help"), createaliasnode(ztrdup("man"), 0));
- aliastab->addnode(aliastab, ztrdup("which-command"), createaliasnode(ztrdup("whence"), 0));
-
-
- /* Table for suffix aliases --- make this smaller */
-
- sufaliastab = newhashtable(11, "sufaliastab", NULL);
-
- createaliastable(sufaliastab);
-}
-
-/* Create a new alias node */
-
-/**/
-mod_export Alias
-createaliasnode(char *txt, int flags)
-{
- Alias al;
-
- al = (Alias) zshcalloc(sizeof *al);
- al->node.flags = flags;
- al->text = txt;
- al->inuse = 0;
- return al;
-}
-
-/**/
-static void
-freealiasnode(HashNode hn)
-{
- Alias al = (Alias) hn;
-
- zsfree(al->node.nam);
- zsfree(al->text);
- zfree(al, sizeof(struct alias));
-}
-
-/* Print an alias */
-
-/**/
-static void
-printaliasnode(HashNode hn, int printflags)
-{
- Alias a = (Alias) hn;
-
- if (printflags & PRINT_NAMEONLY) {
- zputs(a->node.nam, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_WORD) {
- if (a->node.flags & ALIAS_SUFFIX)
- printf("%s: suffix alias\n", a->node.nam);
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("%s: global alias\n", a->node.nam);
- else
- printf("%s: alias\n", a->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_SIMPLE) {
- zputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_CSH) {
- nicezputs(a->node.nam, stdout);
- printf(": ");
- if (a->node.flags & ALIAS_SUFFIX)
- printf("suffix ");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("globally ");
- printf ("aliased to ");
- nicezputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- nicezputs(a->node.nam, stdout);
- printf(" is a");
- if (a->node.flags & ALIAS_SUFFIX)
- printf(" suffix");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf(" global");
- else
- printf("n");
- printf(" alias for ");
- nicezputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_LIST) {
- /* Fast fail on unrepresentable values. */
- if (strchr(a->node.nam, '=')) {
- zwarn("invalid alias '%s' encountered while printing aliases",
- a->node.nam);
- /* ### TODO: Return an error status to the C caller */
- return;
- }
-
- /* Normal path. */
- printf("alias ");
- if (a->node.flags & ALIAS_SUFFIX)
- printf("-s ");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("-g ");
-
- /* If an alias begins with `-' or `+', then we must output `-- '
- * first, so that it is not interpreted as an option. */
- if(a->node.nam[0] == '-' || a->node.nam[0] == '+')
- printf("-- ");
- }
-
- quotedzputs(a->node.nam, stdout);
- putchar('=');
- quotedzputs(a->text, stdout);
-
- putchar('\n');
-}
-
-/*************************************/
-/* History Line Hash Table Functions */
-/*************************************/
-
-/**/
-void
-createhisttable(void)
-{
- histtab = newhashtable(599, "histtab", NULL);
-
- histtab->hash = histhasher;
- histtab->emptytable = emptyhisttable;
- histtab->filltable = NULL;
- histtab->cmpnodes = histstrcmp;
- histtab->addnode = addhistnode;
- histtab->getnode = gethashnode2;
- histtab->getnode2 = gethashnode2;
- histtab->removenode = removehashnode;
- histtab->disablenode = NULL;
- histtab->enablenode = NULL;
- histtab->freenode = freehistnode;
- histtab->printnode = NULL;
-}
-
-/**/
-unsigned
-histhasher(const char *str)
-{
- unsigned hashval = 0;
-
- while (inblank(*str)) str++;
-
- while (*str) {
- if (inblank(*str)) {
- do str++; while (inblank(*str));
- if (*str)
- hashval += (hashval << 5) + ' ';
- }
- else
- hashval += (hashval << 5) + *(unsigned char *)str++;
- }
- return hashval;
-}
-
-/**/
-void
-emptyhisttable(HashTable ht)
-{
- emptyhashtable(ht);
- if (hist_ring)
- histremovedups();
-}
-
-/* Compare two strings with normalized white-space */
-
-/**/
-int
-histstrcmp(const char *str1, const char *str2)
-{
- while (inblank(*str1)) str1++;
- while (inblank(*str2)) str2++;
- while (*str1 && *str2) {
- if (inblank(*str1)) {
- if (!inblank(*str2))
- break;
- do str1++; while (inblank(*str1));
- do str2++; while (inblank(*str2));
- }
- else {
- if (*str1 != *str2)
- break;
- str1++;
- str2++;
- }
- }
- return *str1 - *str2;
-}
-
-/**/
-void
-addhistnode(HashTable ht, char *nam, void *nodeptr)
-{
- HashNode oldnode = addhashnode2(ht, nam, nodeptr);
- Histent he = (Histent)nodeptr;
- if (oldnode && oldnode != (HashNode)nodeptr) {
- if (he->node.flags & HIST_MAKEUNIQUE
- || (he->node.flags & HIST_FOREIGN && (Histent)oldnode == he->up)) {
- (void) addhashnode2(ht, oldnode->nam, oldnode); /* restore hash */
- he->node.flags |= HIST_DUP;
- he->node.flags &= ~HIST_MAKEUNIQUE;
- }
- else {
- oldnode->flags |= HIST_DUP;
- if (hist_ignore_all_dups)
- freehistnode(oldnode); /* Remove the old dup */
- }
- }
- else
- he->node.flags &= ~HIST_MAKEUNIQUE;
-}
-
-/**/
-void
-freehistnode(HashNode nodeptr)
-{
- freehistdata((Histent)nodeptr, 1);
- zfree(nodeptr, sizeof (struct histent));
-}
-
-/**/
-void
-freehistdata(Histent he, int unlink)
-{
- if (!he)
- return;
-
- if (he == &curline)
- return;
-
- if (!(he->node.flags & (HIST_DUP | HIST_TMPSTORE)))
- removehashnode(histtab, he->node.nam);
-
- zsfree(he->node.nam);
- if (he->nwords)
- zfree(he->words, he->nwords*2*sizeof(short));
-
- if (unlink) {
- if (!--histlinect)
- hist_ring = NULL;
- else {
- if (he == hist_ring)
- hist_ring = hist_ring->up;
- he->up->down = he->down;
- he->down->up = he->up;
- }
- }
-}
-
-
-/***********************************************************************
- * Directory name cache mechanism
- *
- * The idea of this is that there are various shell structures,
- * notably functions, that record the directories with which they
- * are associated. Rather than store the full string each time,
- * we store a pointer to the same location and count the references.
- * This is optimised so that retrieval is quick at the expense of
- * searching the list when setting up the structure, which is a much
- * rarer operation.
- *
- * There is nothing special about the fact that the strings are
- * directories, except for the assumptions for efficiency that many
- * structures will point to the same one, and that there are not too
- * many different directories associated with the shell.
- **********************************************************************/
-
-struct dircache_entry
-{
- /* Name of directory in cache */
- char *name;
- /* Number of references to it */
- int refs;
-};
-
-/*
- * dircache is the cache, of length dircache_size.
- * dircache_lastentry is the last entry used, an optimisation
- * for multiple references to the same directory, e.g
- * "autoload /blah/blah/\*".
- */
-static struct dircache_entry *dircache, *dircache_lastentry;
-static int dircache_size;
-
-/*
- * Set *name to point to a cached version of value.
- * value is copied so may come from any source.
- *
- * If value is NULL, look for the existing value of *name (safe if this
- * too is NULL) and remove a reference to it from the cache. If it's
- * not found in the cache, it's assumed to be an allocated string and
- * freed --- this currently occurs for a shell function that's been
- * loaded as the filename is now a full path, not just a directory,
- * though we may one day optimise this to a cached directory plus a
- * name, too. Note --- the function does *not* otherwise check
- * if *name points to something already cached, so this is
- * necessary any time *name may already be in the cache.
- */
-
-/**/
-mod_export void
-dircache_set(char **name, char *value)
-{
- struct dircache_entry *dcptr, *dcnew;
-
- if (!value) {
- if (!*name)
- return;
- if (!dircache_size) {
- zsfree(*name);
- *name = NULL;
- return;
- }
-
- for (dcptr = dircache; dcptr < dircache + dircache_size; dcptr++)
- {
- /* Must be a pointer much, not a string match */
- if (*name == dcptr->name)
- {
- --dcptr->refs;
- if (!dcptr->refs) {
- ptrdiff_t ind = dcptr - dircache;
- zsfree(dcptr->name);
- --dircache_size;
-
- if (!dircache_size) {
- zfree(dircache, sizeof(*dircache));
- dircache = NULL;
- dircache_lastentry = NULL;
- *name = NULL;
- return;
- }
- dcnew = (struct dircache_entry *)
- zalloc(dircache_size * sizeof(*dcnew));
- if (ind)
- memcpy(dcnew, dircache, ind * sizeof(*dcnew));
- if (ind < dircache_size)
- memcpy(dcnew + ind, dcptr + 1,
- (dircache_size - ind) * sizeof(*dcnew));
- zfree(dircache, (dircache_size+1)*sizeof(*dcnew));
- dircache = dcnew;
- dircache_lastentry = NULL;
- }
- *name = NULL;
- return;
- }
- }
- zsfree(*name);
- *name = NULL;
- } else {
- /*
- * As the function path has been resolved to a particular
- * location, we'll store it as an absolute path.
- */
- if (*value != '/') {
- value = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP),
- "/", value);
- value = xsymlink(value, 1);
- }
- /*
- * We'll maintain the cache at exactly the right size rather
- * than overallocating. The rationale here is that typically
- * we'll get a lot of functions in a small number of directories
- * so the complexity overhead of maintaining a separate count
- * isn't really matched by the efficiency gain.
- */
- if (dircache_lastentry &&
- !strcmp(value, dircache_lastentry->name)) {
- *name = dircache_lastentry->name;
- ++dircache_lastentry->refs;
- return;
- } else if (!dircache_size) {
- dircache_size = 1;
- dcptr = dircache =
- (struct dircache_entry *)zalloc(sizeof(*dircache));
- } else {
- for (dcptr = dircache; dcptr < dircache + dircache_size; dcptr++)
- {
- if (!strcmp(value, dcptr->name)) {
- *name = dcptr->name;
- ++dcptr->refs;
- return;
- }
- }
- ++dircache_size;
- dircache = (struct dircache_entry *)
- zrealloc(dircache, sizeof(*dircache) * dircache_size);
- dcptr = dircache + dircache_size - 1;
- }
- dcptr->name = ztrdup(value);
- *name = dcptr->name;
- dcptr->refs = 1;
- dircache_lastentry = dcptr;
- }
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.h
deleted file mode 100644
index 21398e17..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/hashtable.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * hashtable.h - header file for hash table handling code
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-/* Builtin function numbers; used by handler functions that handle more *
- * than one builtin. Note that builtins such as compctl, that are not *
- * overloaded, don't get a number. */
-
-#define BIN_TYPESET 0
-#define BIN_BG 1
-#define BIN_FG 2
-#define BIN_JOBS 3
-#define BIN_WAIT 4
-#define BIN_DISOWN 5
-#define BIN_BREAK 6
-#define BIN_CONTINUE 7
-#define BIN_EXIT 8
-#define BIN_RETURN 9
-#define BIN_CD 10
-#define BIN_POPD 11
-#define BIN_PUSHD 12
-#define BIN_PRINT 13
-#define BIN_EVAL 14
-#define BIN_SCHED 15
-#define BIN_FC 16
-#define BIN_R 17
-#define BIN_PUSHLINE 18
-#define BIN_LOGOUT 19
-#define BIN_TEST 20
-#define BIN_BRACKET 21
-#define BIN_READONLY 22
-#define BIN_ECHO 23
-#define BIN_DISABLE 24
-#define BIN_ENABLE 25
-#define BIN_PRINTF 26
-#define BIN_COMMAND 27
-#define BIN_UNHASH 28
-#define BIN_UNALIAS 29
-#define BIN_UNFUNCTION 30
-#define BIN_UNSET 31
-
-/* These currently depend on being 0 and 1. */
-#define BIN_SETOPT 0
-#define BIN_UNSETOPT 1
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/init.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/init.c
deleted file mode 100644
index e9e6be9b..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/init.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-/*
- * init.c - main loop and initialization routines
- *
- * 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 "zshpaths.h"
-#include "zshxmods.h"
-
-#include "init.pro"
-
-#include "version.h"
-
-/**/
-int noexitct = 0;
-
-/* buffer for $_ and its length */
-
-/**/
-char *zunderscore;
-
-/**/
-int underscorelen, underscoreused;
-
-/* what level of sourcing we are at */
-
-/**/
-int sourcelevel;
-
-/* the shell tty fd */
-
-/**/
-mod_export int SHTTY;
-
-/* the FILE attached to the shell tty */
-
-/**/
-mod_export FILE *shout;
-
-/* termcap strings */
-
-/**/
-mod_export char *tcstr[TC_COUNT];
-
-/* lengths of each termcap string */
-
-/**/
-mod_export int tclen[TC_COUNT];
-
-/* Values of the li, co and am entries */
-
-/**/
-int tclines, tccolumns;
-/**/
-mod_export int hasam, hasbw, hasxn, hasye;
-
-/* Value of the Co (max_colors) entry: may not be set */
-
-/**/
-mod_export int tccolours;
-
-/* SIGCHLD mask */
-
-/**/
-mod_export sigset_t sigchld_mask;
-
-/**/
-mod_export struct hookdef zshhooks[] = {
- HOOKDEF("exit", NULL, HOOKF_ALL),
- HOOKDEF("before_trap", NULL, HOOKF_ALL),
- HOOKDEF("after_trap", NULL, HOOKF_ALL),
-};
-
-/* keep executing lists until EOF found */
-
-/**/
-enum loop_return
-loop(int toplevel, int justonce)
-{
- Eprog prog;
- int err, non_empty = 0;
-
- queue_signals();
- pushheap();
- if (!toplevel)
- zcontext_save();
- for (;;) {
- freeheap();
- if (stophist == 3) /* re-entry via preprompt() */
- hend(NULL);
- hbegin(1); /* init history mech */
- if (isset(SHINSTDIN)) {
- setblock_stdin();
- if (interact && toplevel) {
- int hstop = stophist;
- stophist = 3;
- /*
- * Reset all errors including the interrupt error status
- * immediately, so preprompt runs regardless of what
- * just happened. We'll reset again below as a
- * precaution to ensure we get back to the command line
- * no matter what.
- */
- errflag = 0;
- preprompt();
- if (stophist != 3)
- hbegin(1);
- else
- stophist = hstop;
- /*
- * Reset all errors, including user interupts.
- * This is what allows ^C in an interactive shell
- * to return us to the command line.
- */
- errflag = 0;
- }
- }
- use_exit_printed = 0;
- intr(); /* interrupts on */
- lexinit(); /* initialize lexical state */
- if (!(prog = parse_event(ENDINPUT))) {
- /* if we couldn't parse a list */
- hend(NULL);
- if ((tok == ENDINPUT && !errflag) ||
- (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
- justonce)
- break;
- if (exit_pending) {
- /*
- * Something down there (a ZLE function?) decided
- * to exit when there was stuff to clear up.
- * Handle that now.
- */
- stopmsg = 1;
- zexit(exit_pending >> 1, 0);
- }
- if (tok == LEXERR && !lastval)
- lastval = 1;
- continue;
- }
- if (hend(prog)) {
- enum lextok toksav = tok;
-
- non_empty = 1;
- if (toplevel &&
- (getshfunc("preexec") ||
- paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) {
- LinkList args;
- char *cmdstr;
-
- /*
- * As we're about to freeheap() or popheap()
- * anyway, there's no gain in using permanent
- * storage here.
- */
- args = newlinklist();
- addlinknode(args, "preexec");
- /* If curline got dumped from the history, we don't know
- * what the user typed. */
- if (hist_ring && curline.histnum == curhist)
- addlinknode(args, hist_ring->node.nam);
- else
- addlinknode(args, "");
- addlinknode(args, dupstring(getjobtext(prog, NULL)));
- addlinknode(args, cmdstr = getpermtext(prog, NULL, 0));
-
- callhookfunc("preexec", args, 1, NULL);
-
- /* The only permanent storage is from getpermtext() */
- zsfree(cmdstr);
- /*
- * Note this does *not* remove a user interrupt error
- * condition, even though we're at the top level loop:
- * that would be inconsistent with the case where
- * we didn't execute a preexec function. This is
- * an implementation detail that an interrupting user
- * does't care about.
- */
- errflag &= ~ERRFLAG_ERROR;
- }
- if (stopmsg) /* unset 'you have stopped jobs' flag */
- stopmsg--;
- execode(prog, 0, 0, toplevel ? "toplevel" : "file");
- tok = toksav;
- if (toplevel)
- noexitct = 0;
- }
- if (ferror(stderr)) {
- zerr("write error");
- clearerr(stderr);
- }
- if (subsh) /* how'd we get this far in a subshell? */
- exit(lastval);
- if (((!interact || sourcelevel) && errflag) || retflag)
- break;
- if (isset(SINGLECOMMAND) && toplevel) {
- dont_queue_signals();
- if (sigtrapped[SIGEXIT])
- dotrap(SIGEXIT);
- exit(lastval);
- }
- if (justonce)
- break;
- }
- err = errflag;
- if (!toplevel)
- zcontext_restore();
- popheap();
- unqueue_signals();
-
- if (err)
- return LOOP_ERROR;
- if (!non_empty)
- return LOOP_EMPTY;
- return LOOP_OK;
-}
-
-static int restricted;
-
-/**/
-static void
-parseargs(char *zsh_name, char **argv, char **runscript, char **cmdptr)
-{
- char **x;
- LinkList paramlist;
- int flags = PARSEARGS_TOPLEVEL;
- if (**argv == '-')
- flags |= PARSEARGS_LOGIN;
-
- argzero = posixzero = *argv++;
- SHIN = 0;
-
- /*
- * parseopts sets up some options after we deal with emulation in
- * order to be consistent --- the code in parseopts_setemulate() is
- * matched by code at the end of the present function.
- */
-
- if (parseopts(zsh_name, &argv, opts, cmdptr, NULL, flags))
- exit(1);
-
- /*
- * USEZLE remains set if the shell has access to a terminal and
- * is not reading from some other source as indicated by SHINSTDIN.
- * SHINSTDIN becomes set below if there is no command argument,
- * but it is the explicit setting (or not) that matters to USEZLE.
- * USEZLE may also become unset in init_io() if the shell is not
- * interactive or the terminal cannot be re-opened read/write.
- */
- if (opts[SHINSTDIN])
- opts[USEZLE] = (opts[USEZLE] && isatty(0));
-
- paramlist = znewlinklist();
- if (*argv) {
- if (unset(SHINSTDIN)) {
- posixzero = *argv;
- if (*cmdptr)
- argzero = *argv;
- else
- *runscript = *argv;
- opts[INTERACTIVE] &= 1;
- argv++;
- }
- while (*argv)
- zaddlinknode(paramlist, ztrdup(*argv++));
- } else if (!*cmdptr)
- opts[SHINSTDIN] = 1;
- if(isset(SINGLECOMMAND))
- opts[INTERACTIVE] &= 1;
- opts[INTERACTIVE] = !!opts[INTERACTIVE];
- if (opts[MONITOR] == 2)
- opts[MONITOR] = opts[INTERACTIVE];
- if (opts[HASHDIRS] == 2)
- opts[HASHDIRS] = opts[INTERACTIVE];
- pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
-
- while ((*x++ = (char *)getlinknode(paramlist)));
- free(paramlist);
- argzero = ztrdup(argzero);
- posixzero = ztrdup(posixzero);
-}
-
-/* Insert into list in order of pointer value */
-
-/**/
-static void
-parseopts_insert(LinkList optlist, char *base, int optno)
-{
- LinkNode node;
- void *ptr = base + (optno < 0 ? -optno : optno);
-
- for (node = firstnode(optlist); node; incnode(node)) {
- if (ptr < getdata(node)) {
- insertlinknode(optlist, prevnode(node), ptr);
- return;
- }
- }
-
- addlinknode(optlist, ptr);
-}
-
-/*
- * This sets the global emulation plus the options we traditionally
- * set immediately after that. This is just for historical consistency
- * --- I don't think those options actually need to be set here.
- */
-static void parseopts_setemulate(char *nam, int flags)
-{
- emulate(nam, 1, &emulation, opts); /* initialises most options */
- opts[LOGINSHELL] = ((flags & PARSEARGS_LOGIN) != 0);
- opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
-
- /* There's a bit of trickery with opts[INTERACTIVE] here. It starts *
- * at a value of 2 (instead of 1) or 0. If it is explicitly set on *
- * the command line, it goes to 1 or 0. If input is coming from *
- * somewhere that normally makes the shell non-interactive, we do *
- * "opts[INTERACTIVE] &= 1", so that only a *default* on state will *
- * be changed. At the end of the function, a value of 2 gets *
- * changed to 1. */
- opts[INTERACTIVE] = isatty(0) ? 2 : 0;
- /*
- * MONITOR is similar: we initialise it to 2, and if it's
- * still 2 at the end, we set it to the value of INTERACTIVE.
- */
- opts[MONITOR] = 2; /* may be unset in init_io() */
- opts[HASHDIRS] = 2; /* same relationship to INTERACTIVE */
- opts[USEZLE] = 1; /* see below, related to SHINSTDIN */
- opts[SHINSTDIN] = 0;
- opts[SINGLECOMMAND] = 0;
-}
-
-/*
- * Parse shell options.
- *
- * If (flags & PARSEARGS_TOPLEVEL):
- * - we are doing shell initilisation
- * - nam is the name under which the shell was started
- * - set up emulation and standard options based on that.
- * Otherwise:
- * - nam is a command name
- * - don't exit on failure.
- *
- * If optlist is not NULL, it used to form a list of pointers
- * into new_opts indicating which options have been changed.
- */
-
-/**/
-mod_export int
-parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp,
- LinkList optlist, int flags)
-{
- int optionbreak = 0;
- int action, optno;
- char **argv = *argvp;
- int toplevel = ((flags & PARSEARGS_TOPLEVEL) != 0u);
- int emulate_required = toplevel;
- char *top_emulation = nam;
-
- *cmdp = 0;
-#define WARN_OPTION(F, S) \
- do { \
- if (!toplevel) \
- zwarnnam(nam, F, S); \
- else \
- zerr(F, S); \
- } while (0)
-#define LAST_OPTION(N) \
- do { \
- if (!toplevel) { \
- if (*argv) \
- argv++; \
- goto doneargv; \
- } else exit(N); \
- } while(0)
-
- /* loop through command line options (begins with "-" or "+") */
- while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) {
- char *args = *argv;
- action = (**argv == '-');
- if (!argv[0][1])
- *argv = "--";
- while (*++*argv) {
- if (**argv == '-') {
- if (!argv[0][1]) {
- /* The pseudo-option `--' signifies the end of options. */
- argv++;
- goto doneoptions;
- }
- if (!toplevel || *argv != args+1 || **argv != '-')
- goto badoptionstring;
- /* GNU-style long options */
- ++*argv;
- if (!strcmp(*argv, "version")) {
- printf("zsh %s (%s-%s-%s)\n",
- ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE);
- LAST_OPTION(0);
- }
- if (!strcmp(*argv, "help")) {
- printhelp();
- LAST_OPTION(0);
- }
- if (!strcmp(*argv, "emulate")) {
- ++argv;
- if (!*argv) {
- zerr("--emulate: argument required");
- exit(1);
- }
- if (!emulate_required) {
- zerr("--emulate: must precede other options");
- exit(1);
- }
- top_emulation = *argv;
- break;
- }
- /* `-' characters are allowed in long options */
- for(args = *argv; *args; args++)
- if(*args == '-')
- *args = '_';
- goto longoptions;
- }
-
- if (unset(SHOPTIONLETTERS) && **argv == 'b') {
- if (emulate_required) {
- parseopts_setemulate(top_emulation, flags);
- emulate_required = 0;
- }
- /* -b ends options at the end of this argument */
- optionbreak = 1;
- } else if (**argv == 'c') {
- if (emulate_required) {
- parseopts_setemulate(top_emulation, flags);
- emulate_required = 0;
- }
- /* -c command */
- *cmdp = *argv;
- new_opts[INTERACTIVE] &= 1;
- if (toplevel)
- scriptname = scriptfilename = ztrdup("zsh");
- } else if (**argv == 'o') {
- if (!*++*argv)
- argv++;
- if (!*argv) {
- WARN_OPTION("string expected after -o", NULL);
- return 1;
- }
- longoptions:
- if (emulate_required) {
- parseopts_setemulate(top_emulation, flags);
- emulate_required = 0;
- }
- if (!(optno = optlookup(*argv))) {
- WARN_OPTION("no such option: %s", *argv);
- return 1;
- } else if (optno == RESTRICTED && toplevel) {
- restricted = action;
- } else if ((optno == EMACSMODE || optno == VIMODE) && !toplevel) {
- WARN_OPTION("can't change option: %s", *argv);
- } else {
- if (dosetopt(optno, action, toplevel, new_opts) &&
- !toplevel) {
- WARN_OPTION("can't change option: %s", *argv);
- } else if (optlist) {
- parseopts_insert(optlist, new_opts, optno);
- }
- }
- break;
- } else if (isspace(STOUC(**argv))) {
- /* zsh's typtab not yet set, have to use ctype */
- while (*++*argv)
- if (!isspace(STOUC(**argv))) {
- badoptionstring:
- WARN_OPTION("bad option string: '%s'", args);
- return 1;
- }
- break;
- } else {
- if (emulate_required) {
- parseopts_setemulate(top_emulation, flags);
- emulate_required = 0;
- }
- if (!(optno = optlookupc(**argv))) {
- WARN_OPTION("bad option: -%c", **argv);
- return 1;
- } else if (optno == RESTRICTED && toplevel) {
- restricted = action;
- } else if ((optno == EMACSMODE || optno == VIMODE) &&
- !toplevel) {
- WARN_OPTION("can't change option: %s", *argv);
- } else {
- if (dosetopt(optno, action, toplevel, new_opts) &&
- !toplevel) {
- WARN_OPTION("can't change option: -%c", **argv);
- } else if (optlist) {
- parseopts_insert(optlist, new_opts, optno);
- }
- }
- }
- }
- argv++;
- }
- doneoptions:
- if (*cmdp) {
- if (!*argv) {
- WARN_OPTION("string expected after -%s", *cmdp);
- return 1;
- }
- *cmdp = *argv++;
- }
- doneargv:
- *argvp = argv;
- if (emulate_required) {
- parseopts_setemulate(top_emulation, flags);
- emulate_required = 0;
- }
- return 0;
-}
-
-/**/
-static void
-printhelp(void)
-{
- printf("Usage: %s [] [ ...]\n", argzero);
- printf("\nSpecial options:\n");
- printf(" --help show this message, then exit\n");
- printf(" --version show zsh version number, then exit\n");
- if(unset(SHOPTIONLETTERS))
- printf(" -b end option processing, like --\n");
- printf(" -c take first argument as a command to execute\n");
- printf(" -o OPTION set an option by name (see below)\n");
- printf("\nNormal options are named. An option may be turned on by\n");
- printf("`-o OPTION', `--OPTION', `+o no_OPTION' or `+-no-OPTION'. An\n");
- printf("option may be turned off by `-o no_OPTION', `--no-OPTION',\n");
- printf("`+o OPTION' or `+-OPTION'. Options are listed below only in\n");
- printf("`--OPTION' or `--no-OPTION' form.\n");
- printoptionlist();
-}
-
-/**/
-mod_export void
-init_io(char *cmd)
-{
- static char outbuf[BUFSIZ], errbuf[BUFSIZ];
-
-#ifdef RSH_BUG_WORKAROUND
- int i;
-#endif
-
-/* stdout, stderr fully buffered */
-#ifdef _IOFBF
- setvbuf(stdout, outbuf, _IOFBF, BUFSIZ);
- setvbuf(stderr, errbuf, _IOFBF, BUFSIZ);
-#else
- setbuffer(stdout, outbuf, BUFSIZ);
- setbuffer(stderr, errbuf, BUFSIZ);
-#endif
-
-/* This works around a bug in some versions of in.rshd. *
- * Currently this is not defined by default. */
-#ifdef RSH_BUG_WORKAROUND
- if (cmd) {
- for (i = 3; i < 10; i++)
- close(i);
- }
-#else
- (void)cmd;
-#endif
-
- if (shout) {
- /*
- * Check if shout was set to stderr, if so don't close it.
- * We do this if we are interactive but don't have a
- * terminal.
- */
- if (shout != stderr)
- fclose(shout);
- shout = 0;
- }
- if (SHTTY != -1) {
- zclose(SHTTY);
- SHTTY = -1;
- }
-
- /* Send xtrace output to stderr -- see execcmd() */
- xtrerr = stderr;
-
- /* Make sure the tty is opened read/write. */
- if (isatty(0)) {
- zsfree(ttystrname);
- if ((ttystrname = ztrdup(ttyname(0)))) {
- SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
-#ifdef TIOCNXCL
- /*
- * See if the terminal claims to be busy. If so, and fd 0
- * is a terminal, try and set non-exclusive use for that.
- * This is something to do with Solaris over-cleverness.
- */
- if (SHTTY == -1 && errno == EBUSY)
- ioctl(0, TIOCNXCL, 0);
-#endif
- }
- /*
- * xterm, rxvt and probably all terminal emulators except
- * dtterm on Solaris 2.6 & 7 have a bug. Applications are
- * unable to open /dev/tty or /dev/pts/
- * because something in Sun's STREAMS modules doesn't like
- * it. The open() call fails with EBUSY which is not even
- * listed as a possibility in the open(2) man page. So we'll
- * try to outsmart The Company. --
- *
- * Presumably there's no harm trying this on any OS, given that
- * isatty(0) worked but opening the tty didn't. Possibly we won't
- * get the tty read/write, but it's the best we can do -- pws
- *
- * Try both stdin and stdout before trying /dev/tty. -- Bart
- */
-#if defined(HAVE_FCNTL_H) && defined(F_GETFL)
-#define rdwrtty(fd) ((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR)
-#else
-#define rdwrtty(fd) 1
-#endif
- if (SHTTY == -1 && rdwrtty(0)) {
- SHTTY = movefd(dup(0));
- }
- }
- if (SHTTY == -1 && isatty(1) && rdwrtty(1) &&
- (SHTTY = movefd(dup(1))) != -1) {
- zsfree(ttystrname);
- ttystrname = ztrdup(ttyname(1));
- }
- if (SHTTY == -1 &&
- (SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) {
- zsfree(ttystrname);
- ttystrname = ztrdup(ttyname(SHTTY));
- }
- if (SHTTY == -1) {
- zsfree(ttystrname);
- ttystrname = ztrdup("");
- } else {
-#ifdef FD_CLOEXEC
- long fdflags = fcntl(SHTTY, F_GETFD, 0);
- if (fdflags != (long)-1) {
- fdflags |= FD_CLOEXEC;
- fcntl(SHTTY, F_SETFD, fdflags);
- }
-#endif
- if (!ttystrname)
- ttystrname = ztrdup("/dev/tty");
- }
-
- /* We will only use zle if shell is interactive, *
- * SHTTY != -1, and shout != 0 */
- if (interact) {
- init_shout();
- if(!SHTTY || !shout)
- opts[USEZLE] = 0;
- } else
- opts[USEZLE] = 0;
-
-#ifdef JOB_CONTROL
- /* If interactive, make sure the shell is in the foreground and is the
- * process group leader.
- */
- mypid = (zlong)getpid();
- if (opts[MONITOR] && (SHTTY != -1)) {
- origpgrp = GETPGRP();
- acquire_pgrp(); /* might also clear opts[MONITOR] */
- } else
- opts[MONITOR] = 0;
-#else
- opts[MONITOR] = 0;
-#endif
-}
-
-/**/
-mod_export void
-init_shout(void)
-{
- static char shoutbuf[BUFSIZ];
-#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC)
- int ldisc;
-#endif
-
- if (SHTTY == -1)
- {
- /* Since we're interactive, it's nice to have somewhere to write. */
- shout = stderr;
- return;
- }
-
-#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC)
- ldisc = NTTYDISC;
- ioctl(SHTTY, TIOCSETD, (char *)&ldisc);
-#endif
-
- /* Associate terminal file descriptor with a FILE pointer */
- shout = fdopen(SHTTY, "w");
-#ifdef _IOFBF
- if (shout)
- setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ);
-#endif
-
- gettyinfo(&shttyinfo); /* get tty state */
-#if defined(__sgi)
- if (shttyinfo.tio.c_cc[VSWTCH] <= 0) /* hack for irises */
- shttyinfo.tio.c_cc[VSWTCH] = CSWTCH;
-#endif
-}
-
-/* names of the termcap strings we want */
-
-static char *tccapnams[TC_COUNT] = {
- "cl", "le", "LE", "nd", "RI", "up", "UP", "do",
- "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
- "md", "so", "us", "me", "se", "ue", "ch",
- "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB"
-};
-
-/**/
-mod_export char *
-tccap_get_name(int cap)
-{
- if (cap >= TC_COUNT) {
-#ifdef DEBUG
- dputs("name of invalid capability %d requested", cap);
-#endif
- return "";
- }
- return tccapnams[cap];
-}
-
-/* Initialise termcap */
-
-/**/
-mod_export int
-init_term(void)
-{
-#ifndef TGETENT_ACCEPTS_NULL
- static char termbuf[2048]; /* the termcap buffer */
-#endif
-
- if (!*term) {
- termflags |= TERM_UNKNOWN;
- return 0;
- }
-
- /* unset zle if using zsh under emacs */
- if (!strcmp(term, "emacs"))
- opts[USEZLE] = 0;
-
-#ifdef TGETENT_ACCEPTS_NULL
- /* If possible, we let tgetent allocate its own termcap buffer */
- if (tgetent(NULL, term) != TGETENT_SUCCESS)
-#else
- if (tgetent(termbuf, term) != TGETENT_SUCCESS)
-#endif
- {
- if (interact)
- zerr("can't find terminal definition for %s", term);
- errflag &= ~ERRFLAG_ERROR;
- termflags |= TERM_BAD;
- return 0;
- } else {
- char tbuf[1024], *pp;
- int t0;
-
- termflags &= ~TERM_BAD;
- termflags &= ~TERM_UNKNOWN;
- for (t0 = 0; t0 != TC_COUNT; t0++) {
- pp = tbuf;
- zsfree(tcstr[t0]);
- /* AIX tgetstr() ignores second argument */
- if (!(pp = tgetstr(tccapnams[t0], &pp)))
- tcstr[t0] = NULL, tclen[t0] = 0;
- else {
- tclen[t0] = strlen(pp);
- tcstr[t0] = (char *) zalloc(tclen[t0] + 1);
- memcpy(tcstr[t0], pp, tclen[t0] + 1);
- }
- }
-
- /* check whether terminal has automargin (wraparound) capability */
- hasam = tgetflag("am");
- hasbw = tgetflag("bw");
- hasxn = tgetflag("xn"); /* also check for newline wraparound glitch */
- hasye = tgetflag("YE"); /* print in last column does carriage return */
-
- tclines = tgetnum("li");
- tccolumns = tgetnum("co");
- tccolours = tgetnum("Co");
-
- /* if there's no termcap entry for cursor up, use single line mode: *
- * this is flagged by termflags which is examined in zle_refresh.c *
- */
- if (tccan(TCUP))
- termflags &= ~TERM_NOUP;
- else {
- zsfree(tcstr[TCUP]);
- tcstr[TCUP] = NULL;
- termflags |= TERM_NOUP;
- }
-
- /* most termcaps don't define "bc" because they use \b. */
- if (!tccan(TCBACKSPACE)) {
- zsfree(tcstr[TCBACKSPACE]);
- tcstr[TCBACKSPACE] = ztrdup("\b");
- tclen[TCBACKSPACE] = 1;
- }
-
- /* if there's no termcap entry for cursor left, use backspace. */
- if (!tccan(TCLEFT)) {
- zsfree(tcstr[TCLEFT]);
- tcstr[TCLEFT] = ztrdup(tcstr[TCBACKSPACE]);
- tclen[TCLEFT] = tclen[TCBACKSPACE];
- }
-
- if (tccan(TCSAVECURSOR) && !tccan(TCRESTRCURSOR)) {
- tclen[TCSAVECURSOR] = 0;
- zsfree(tcstr[TCSAVECURSOR]);
- tcstr[TCSAVECURSOR] = NULL;
- }
-
- /* if the termcap entry for down is \n, don't use it. */
- if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') {
- tclen[TCDOWN] = 0;
- zsfree(tcstr[TCDOWN]);
- tcstr[TCDOWN] = NULL;
- }
-
- /* if there's no termcap entry for clear, use ^L. */
- if (!tccan(TCCLEARSCREEN)) {
- zsfree(tcstr[TCCLEARSCREEN]);
- tcstr[TCCLEARSCREEN] = ztrdup("\14");
- tclen[TCCLEARSCREEN] = 1;
- }
- rprompt_indent = 1; /* If you change this, update rprompt_indent_unsetfn() */
- /* The following is an attempt at a heuristic,
- * but it fails in some cases */
- /* rprompt_indent = ((hasam && !hasbw) || hasye || !tccan(TCLEFT)); */
- }
- return 1;
-}
-
-/* Initialize lots of global variables and hash tables */
-
-/**/
-void
-setupvals(char *cmd, char *runscript, char *zsh_name)
-{
-#ifdef USE_GETPWUID
- struct passwd *pswd;
-#endif
- struct timezone dummy_tz;
- char *ptr;
- int i, j;
-#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) || defined(FIXED_FPATH_DIR)
-#define FPATH_NEEDS_INIT 1
- char **fpathptr;
-# if defined(FPATH_DIR) && defined(FPATH_SUBDIRS)
- char *fpath_subdirs[] = FPATH_SUBDIRS;
-# endif
-# if defined(ADDITIONAL_FPATH)
- char *more_fndirs[] = ADDITIONAL_FPATH;
- int more_fndirs_len;
-# endif
-# ifdef FIXED_FPATH_DIR
-# define FIXED_FPATH_LEN 1
-# else
-# define FIXED_FPATH_LEN 0
-# endif
-# ifdef SITEFPATH_DIR
-# define SITE_FPATH_LEN 1
-# else
-# define SITE_FPATH_LEN 0
-# endif
- int fpathlen = FIXED_FPATH_LEN + SITE_FPATH_LEN;
-#endif
- int close_fds[10], tmppipe[2];
-
- /*
- * Workaround a problem with NIS (in one guise or another) which
- * grabs file descriptors and keeps them for future reference.
- * We don't want these to be in the range where the user can
- * open fd's, i.e. 0 to 9 inclusive. So we make sure all
- * fd's in that range are in use.
- */
- memset(close_fds, 0, 10*sizeof(int));
- if (pipe(tmppipe) == 0) {
- /*
- * Strategy: Make sure we have at least fd 0 open (hence
- * the pipe). From then on, keep dup'ing until we are
- * up to 9. If we go over the top, close immediately, else
- * mark for later closure.
- */
- i = -1; /* max fd we have checked */
- while (i < 9) {
- /* j is current fd */
- if (i < tmppipe[0])
- j = tmppipe[0];
- else if (i < tmppipe[1])
- j = tmppipe[1];
- else {
- j = dup(0);
- if (j == -1)
- break;
- }
- if (j < 10)
- close_fds[j] = 1;
- else
- close(j);
- if (i < j)
- i = j;
- }
- if (i < tmppipe[0])
- close(tmppipe[0]);
- if (i < tmppipe[1])
- close(tmppipe[1]);
- }
-
- (void)addhookdefs(NULL, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks));
-
- init_eprog();
-
- zero_mnumber.type = MN_INTEGER;
- zero_mnumber.u.l = 0;
-
- noeval = 0;
- curhist = 0;
- histsiz = DEFAULT_HISTSIZE;
- inithist();
-
- cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
- cmdsp = 0;
-
- bangchar = '!';
- hashchar = '#';
- hatchar = '^';
- termflags = TERM_UNKNOWN;
- curjob = prevjob = coprocin = coprocout = -1;
- gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */
- srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */
-
- /* Set default path */
- path = (char **) zalloc(sizeof(*path) * 5);
- path[0] = ztrdup("/bin");
- path[1] = ztrdup("/usr/bin");
- path[2] = ztrdup("/usr/ucb");
- path[3] = ztrdup("/usr/local/bin");
- path[4] = NULL;
-
- cdpath = mkarray(NULL);
- manpath = mkarray(NULL);
- fignore = mkarray(NULL);
-
-#ifdef FPATH_NEEDS_INIT
-# ifdef FPATH_DIR
-# ifdef FPATH_SUBDIRS
- fpathlen += sizeof(fpath_subdirs)/sizeof(char *);
-# else /* FPATH_SUBDIRS */
- fpathlen++;
-# endif /* FPATH_SUBDIRS */
-# endif /* FPATH_DIR */
-# if defined(ADDITIONAL_FPATH)
- more_fndirs_len = sizeof(more_fndirs)/sizeof(char *);
- fpathlen += more_fndirs_len;
-# endif /* ADDITONAL_FPATH */
- fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *));
-# ifdef FIXED_FPATH_DIR
- *fpathptr++ = ztrdup(FIXED_FPATH_DIR);
- fpathlen--;
-# endif
-# ifdef SITEFPATH_DIR
- *fpathptr++ = ztrdup(SITEFPATH_DIR);
- fpathlen--;
-# endif /* SITEFPATH_DIR */
-# if defined(ADDITIONAL_FPATH)
- for (j = 0; j < more_fndirs_len; j++)
- *fpathptr++ = ztrdup(more_fndirs[j]);
-# endif
-# ifdef FPATH_DIR
-# ifdef FPATH_SUBDIRS
-# ifdef ADDITIONAL_FPATH
- for (j = more_fndirs_len; j < fpathlen; j++)
- *fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j - more_fndirs_len]);
-# else
- for (j = 0; j < fpathlen; j++)
- *fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j]);
-#endif
-# else
- *fpathptr++ = ztrdup(FPATH_DIR);
-# endif
-# endif
- *fpathptr = NULL;
-#else /* FPATH_NEEDS_INIT */
- fpath = mkarray(NULL);
-#endif /* FPATH_NEEDS_INIT */
-
- mailpath = mkarray(NULL);
- watch = mkarray(NULL);
- psvar = mkarray(NULL);
- module_path = mkarray(ztrdup(MODULE_DIR));
- modulestab = newmoduletable(17, "modules");
- linkedmodules = znewlinklist();
-
- /* Set default prompts */
- if(unset(INTERACTIVE)) {
- prompt = ztrdup("");
- prompt2 = ztrdup("");
- } else if (EMULATION(EMULATE_KSH|EMULATE_SH)) {
- prompt = ztrdup(privasserted() ? "# " : "$ ");
- prompt2 = ztrdup("> ");
- } else {
- prompt = ztrdup("%m%# ");
- prompt2 = ztrdup("%_> ");
- }
- prompt3 = ztrdup("?# ");
- prompt4 = EMULATION(EMULATE_KSH|EMULATE_SH)
- ? ztrdup("+ ") : ztrdup("+%N:%i> ");
- sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? ");
-
- ifs = EMULATION(EMULATE_KSH|EMULATE_SH) ?
- ztrdup(DEFAULT_IFS_SH) : ztrdup(DEFAULT_IFS);
- wordchars = ztrdup(DEFAULT_WORDCHARS);
- postedit = ztrdup("");
- zunderscore = (char *) zalloc(underscorelen = 32);
- underscoreused = 1;
- *zunderscore = '\0';
-
- zoptarg = ztrdup("");
- zoptind = 1;
-
- ppid = (zlong) getppid();
- mypid = (zlong) getpid();
- term = ztrdup("");
-
- nullcmd = ztrdup("cat");
- readnullcmd = ztrdup(DEFAULT_READNULLCMD);
-
- /* We cache the uid so we know when to *
- * recheck the info for `USERNAME' */
- cached_uid = getuid();
-
- /* Get password entry and set info for `USERNAME' */
-#ifdef USE_GETPWUID
- if ((pswd = getpwuid(cached_uid))) {
- if (EMULATION(EMULATE_ZSH))
- home = metafy(pswd->pw_dir, -1, META_DUP);
- cached_username = ztrdup(pswd->pw_name);
- }
- else
-#endif /* USE_GETPWUID */
- {
- if (EMULATION(EMULATE_ZSH))
- home = ztrdup("/");
- cached_username = ztrdup("");
- }
-
- /*
- * Try a cheap test to see if we can initialize `PWD' from `HOME'.
- * In non-native emulations HOME must come from the environment;
- * we're not allowed to set it locally.
- */
- if (EMULATION(EMULATE_ZSH))
- ptr = home;
- else
- ptr = zgetenv("HOME");
- if (ptr && ispwd(ptr))
- pwd = ztrdup(ptr);
- else if ((ptr = zgetenv("PWD")) && (strlen(ptr) < PATH_MAX) &&
- (ptr = metafy(ptr, -1, META_STATIC), ispwd(ptr)))
- pwd = ztrdup(ptr);
- else {
- pwd = NULL;
- pwd = metafy(zgetcwd(), -1, META_DUP);
- }
-
- oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */
-
- inittyptab(); /* initialize the ztypes table */
- initlextabs(); /* initialize lexing tables */
-
- createreswdtable(); /* create hash table for reserved words */
- createaliastables(); /* create hash tables for aliases */
- createcmdnamtable(); /* create hash table for external commands */
- createshfunctable(); /* create hash table for shell functions */
- createbuiltintable(); /* create hash table for builtin commands */
- createnameddirtable(); /* create hash table for named directories */
- createparamtable(); /* create parameter hash table */
-
- condtab = NULL;
- wrappers = NULL;
-
-#ifdef TIOCGWINSZ
- adjustwinsize(0);
-#else
- /* columns and lines are normally zero, unless something different *
- * was inhereted from the environment. If either of them are zero *
- * the setiparam calls below set them to the defaults from termcap */
- setiparam("COLUMNS", zterm_columns);
- setiparam("LINES", zterm_lines);
-#endif
-
-#ifdef HAVE_GETRLIMIT
- for (i = 0; i != RLIM_NLIMITS; i++) {
- getrlimit(i, current_limits + i);
- limits[i] = current_limits[i];
- }
-#endif
-
- breaks = loops = 0;
- lastmailcheck = time(NULL);
- locallevel = sourcelevel = 0;
- sfcontext = SFC_NONE;
- trap_return = 0;
- trap_state = TRAP_STATE_INACTIVE;
- noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL;
- nohistsave = 1;
- dirstack = znewlinklist();
- bufstack = znewlinklist();
- hsubl = hsubr = NULL;
- lastpid = 0;
-
- get_usage();
-
- /* Close the file descriptors we opened to block off 0 to 9 */
- for (i = 0; i < 10; i++)
- if (close_fds[i])
- close(i);
-
- /* Colour sequences for outputting colours in prompts and zle */
- set_default_colour_sequences();
-
- if (cmd)
- setsparam("ZSH_EXECUTION_STRING", ztrdup(cmd));
- if (runscript)
- setsparam("ZSH_SCRIPT", ztrdup(runscript));
- setsparam("ZSH_NAME", ztrdup(zsh_name)); /* NOTE: already metafied early in zsh_main() */
-}
-
-/*
- * Setup shell input, opening any script file (runscript, may be NULL).
- * This is deferred until we have a path to search, in case
- * PATHSCRIPT is set for sh-compatible behaviour.
- */
-static void
-setupshin(char *runscript)
-{
- if (runscript) {
- char *funmeta, *sfname = NULL;
- struct stat st;
-
- funmeta = unmeta(runscript);
- /*
- * Always search the current directory first.
- */
- if (access(funmeta, F_OK) == 0 &&
- stat(funmeta, &st) >= 0 &&
- !S_ISDIR(st.st_mode))
- sfname = runscript;
- else if (isset(PATHSCRIPT) && !strchr(runscript, '/')) {
- /*
- * With the PATHSCRIPT option, search the path if no
- * path was given in the script name.
- */
- funmeta = pathprog(runscript, &sfname);
- }
- if (!sfname ||
- (SHIN = movefd(open(funmeta, O_RDONLY | O_NOCTTY)))
- == -1) {
- zerr("can't open input file: %s", runscript);
- exit(127);
- }
- scriptfilename = sfname;
- sfname = argzero; /* copy to avoid race condition */
- argzero = ztrdup(runscript);
- zsfree(sfname); /* argzero ztrdup'd in parseargs */
- }
- /*
- * We only initialise line numbering once there is a script to
- * read commands from.
- */
- lineno = 1;
- /*
- * Finish setting up SHIN and its relatives.
- */
- bshin = SHIN ? fdopen(SHIN, "r") : stdin;
- if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) {
-#ifdef _IONBF
- setvbuf(stdin, NULL, _IONBF, 0);
-#else
- setlinebuf(stdin);
-#endif
- }
-}
-
-/* Initialize signal handling */
-
-/**/
-void
-init_signals(void)
-{
- if (interact) {
- int i;
- signal_setmask(signal_mask(0));
- for (i=0; i= 10)
- fclose(bshin);
- SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY));
- bshin = fdopen(SHIN, "r");
- execstring(cmd, 0, 1, "cmdarg");
- stopmsg = 1;
- zexit(lastval, 0);
- }
-
- if (interact && isset(RCS))
- readhistfile(NULL, 0, HFILE_USE_OPTIONS);
-}
-
-/*
- * source a file
- * Returns one of the SOURCE_* enum values.
- */
-
-/**/
-mod_export enum source_return
-source(char *s)
-{
- Eprog prog;
- int tempfd = -1, fd, cj;
- zlong oldlineno;
- int oldshst, osubsh, oloops;
- FILE *obshin;
- char *old_scriptname = scriptname, *us;
- char *old_scriptfilename = scriptfilename;
- unsigned char *ocs;
- int ocsp;
- int otrap_return = trap_return, otrap_state = trap_state;
- struct funcstack fstack;
- enum source_return ret = SOURCE_OK;
-
- if (!s ||
- (!(prog = try_source_file((us = unmeta(s)))) &&
- (tempfd = movefd(open(us, O_RDONLY | O_NOCTTY))) == -1)) {
- return SOURCE_NOT_FOUND;
- }
-
- /* save the current shell state */
- fd = SHIN; /* store the shell input fd */
- obshin = bshin; /* store file handle for buffered shell input */
- osubsh = subsh; /* store whether we are in a subshell */
- cj = thisjob; /* store our current job number */
- oldlineno = lineno; /* store our current lineno */
- oloops = loops; /* stored the # of nested loops we are in */
- oldshst = opts[SHINSTDIN]; /* store current value of this option */
- ocs = cmdstack;
- ocsp = cmdsp;
- cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
- cmdsp = 0;
-
- if (!prog) {
- SHIN = tempfd;
- bshin = fdopen(SHIN, "r");
- }
- subsh = 0;
- lineno = 1;
- loops = 0;
- dosetopt(SHINSTDIN, 0, 1, opts);
- scriptname = s;
- scriptfilename = s;
-
- if (isset(SOURCETRACE)) {
- printprompt4();
- fprintf(xtrerr ? xtrerr : stderr, "\n");
- }
-
- /*
- * The special return behaviour of traps shouldn't
- * trigger in files sourced from traps; the return
- * is just a return from the file.
- */
- trap_state = TRAP_STATE_INACTIVE;
-
- sourcelevel++;
-
- fstack.name = scriptfilename;
- fstack.caller = funcstack ? funcstack->name :
- dupstring(old_scriptfilename ? old_scriptfilename : "zsh");
- fstack.flineno = 0;
- fstack.lineno = oldlineno;
- fstack.filename = scriptfilename;
- fstack.prev = funcstack;
- fstack.tp = FS_SOURCE;
- funcstack = &fstack;
-
- if (prog) {
- pushheap();
- errflag &= ~ERRFLAG_ERROR;
- execode(prog, 1, 0, "filecode");
- popheap();
- if (errflag)
- ret = SOURCE_ERROR;
- } else {
- /* loop through the file to be sourced */
- switch (loop(0, 0))
- {
- case LOOP_OK:
- /* nothing to do but compilers like a complete enum */
- break;
-
- case LOOP_EMPTY:
- /* Empty code resets status */
- lastval = 0;
- break;
-
- case LOOP_ERROR:
- ret = SOURCE_ERROR;
- break;
- }
- }
- funcstack = funcstack->prev;
- sourcelevel--;
-
- trap_state = otrap_state;
- trap_return = otrap_return;
-
- /* restore the current shell state */
- if (prog)
- freeeprog(prog);
- else {
- fclose(bshin);
- fdtable[SHIN] = FDT_UNUSED;
- SHIN = fd; /* the shell input fd */
- bshin = obshin; /* file handle for buffered shell input */
- }
- subsh = osubsh; /* whether we are in a subshell */
- thisjob = cj; /* current job number */
- lineno = oldlineno; /* our current lineno */
- loops = oloops; /* the # of nested loops we are in */
- dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */
- errflag &= ~ERRFLAG_ERROR;
- if (!exit_pending)
- retflag = 0;
- scriptname = old_scriptname;
- scriptfilename = old_scriptfilename;
- zfree(cmdstack, CMDSTACKSZ);
- cmdstack = ocs;
- cmdsp = ocsp;
-
- return ret;
-}
-
-/* Try to source a file in the home directory */
-
-/**/
-void
-sourcehome(char *s)
-{
- char *h;
-
- queue_signals();
- if (EMULATION(EMULATE_SH|EMULATE_KSH) || !(h = getsparam_u("ZDOTDIR"))) {
- h = home;
- if (!h) {
- unqueue_signals();
- return;
- }
- }
-
- {
- /* Let source() complain if path is too long */
- VARARR(char, buf, strlen(h) + strlen(s) + 2);
- sprintf(buf, "%s/%s", h, s);
- unqueue_signals();
- source(buf);
- }
-}
-
-/**/
-void
-init_bltinmods(void)
-{
-
-#include "bltinmods.list"
-
- (void)load_module("zsh/main", NULL, 0);
-}
-
-/**/
-mod_export void
-noop_function(void)
-{
- /* do nothing */
-}
-
-/**/
-mod_export void
-noop_function_int(UNUSED(int nothing))
-{
- /* do nothing */
-}
-
-/*
- * ZLE entry point pointer.
- * No other source file needs to know which modules are linked in.
- */
-/**/
-mod_export ZleEntryPoint zle_entry_ptr;
-
-/*
- * State of loading of zle.
- * 0 = Not loaded, not attempted.
- * 1 = Loaded successfully
- * 2 = Failed to load.
- */
-/**/
-mod_export int zle_load_state;
-
-/**/
-mod_export char *
-zleentry(VA_ALIST1(int cmd))
-VA_DCL
-{
- char *ret = NULL;
- va_list ap;
- VA_DEF_ARG(int cmd);
-
- VA_START(ap, cmd);
- VA_GET_ARG(ap, cmd, int);
-
-#if defined(LINKED_XMOD_zshQszle) || defined(UNLINKED_XMOD_zshQszle)
- /* autoload */
- switch (zle_load_state) {
- case 0:
- /*
- * Some commands don't require us to load ZLE.
- * These also have no fallback.
- */
- if (cmd != ZLE_CMD_TRASH && cmd != ZLE_CMD_RESET_PROMPT &&
- cmd != ZLE_CMD_REFRESH)
- {
- if (load_module("zsh/zle", NULL, 0) != 1) {
- (void)load_module("zsh/compctl", NULL, 0);
- ret = zle_entry_ptr(cmd, ap);
- /* Don't execute fallback code */
- cmd = -1;
- } else {
- zle_load_state = 2;
- /* Execute fallback code below */
- }
- }
- break;
-
- case 1:
- ret = zle_entry_ptr(cmd, ap);
- /* Don't execute fallback code */
- cmd = -1;
- break;
-
- case 2:
- /* Execute fallback code */
- break;
- }
-#endif
-
- switch (cmd) {
- /*
- * Only the read command really needs a fallback if zle
- * is not available. ZLE_CMD_GET_LINE has traditionally
- * had local code in bufferwords() to do this, but that'
- * probably only because bufferwords() is part of completion
- * and so everything to do with it is horribly complicated.
- */
- case ZLE_CMD_READ:
- {
- char *pptbuf, **lp;
- int pptlen;
-
- lp = va_arg(ap, char **);
-
- pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL,
- NULL),
- &pptlen);
- write_loop(2, pptbuf, pptlen);
- free(pptbuf);
-
- ret = shingetline();
- break;
- }
-
- case ZLE_CMD_GET_LINE:
- {
- int *ll, *cs;
-
- ll = va_arg(ap, int *);
- cs = va_arg(ap, int *);
- *ll = *cs = 0;
- ret = ztrdup("");
- break;
- }
- }
-
- va_end(ap);
- return ret;
-}
-
-/* compctl entry point pointers. Similar to the ZLE ones. */
-
-/**/
-mod_export CompctlReadFn compctlreadptr = fallback_compctlread;
-
-/**/
-mod_export int
-fallback_compctlread(char *name, UNUSED(char **args), UNUSED(Options ops), UNUSED(char *reply))
-{
- zwarnnam(name, "no loaded module provides read for completion context");
- return 1;
-}
-
-/*
- * Used by zle to indicate it has already printed a "use 'exit' to exit"
- * message.
- */
-/**/
-mod_export int use_exit_printed;
-
-/*
- * This is real main entry point. This has to be mod_export'ed
- * so zsh.exe can found it on Cygwin
- */
-
-/**/
-mod_export int
-zsh_main(UNUSED(int argc), char **argv)
-{
- char **t, *runscript = NULL, *zsh_name;
- char *cmd; /* argument to -c */
- int t0;
-#ifdef USE_LOCALE
- setlocale(LC_ALL, "");
-#endif
-
- init_jobs(argv, environ);
-
- /*
- * Provisionally set up the type table to allow metafication.
- * This will be done properly when we have decided if we are
- * interactive
- */
- typtab['\0'] |= IMETA;
- typtab[STOUC(Meta) ] |= IMETA;
- typtab[STOUC(Marker)] |= IMETA;
- for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
- typtab[t0] |= ITOK | IMETA;
-
- for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
-
- zsh_name = argv[0];
- do {
- char *arg0 = zsh_name;
- if (!(zsh_name = strrchr(arg0, '/')))
- zsh_name = arg0;
- else
- zsh_name++;
- if (*zsh_name == '-')
- zsh_name++;
- if (strcmp(zsh_name, "su") == 0) {
- char *sh = zgetenv("SHELL");
- if (sh && *sh && arg0 != sh)
- zsh_name = sh;
- else
- break;
- } else
- break;
- } while (zsh_name);
-
- fdtable_size = zopenmax();
- fdtable = zshcalloc(fdtable_size*sizeof(*fdtable));
- fdtable[0] = fdtable[1] = fdtable[2] = FDT_EXTERNAL;
-
- createoptiontable();
- /* sets emulation, LOGINSHELL, PRIVILEGED, ZLE, INTERACTIVE,
- * SHINSTDIN and SINGLECOMMAND */
- parseargs(zsh_name, argv, &runscript, &cmd);
-
- SHTTY = -1;
- init_io(cmd);
- setupvals(cmd, runscript, zsh_name);
-
- init_signals();
- init_bltinmods();
- init_builtins();
- run_init_scripts();
- setupshin(runscript);
- init_misc(cmd, zsh_name);
-
- for (;;) {
- /*
- * See if we can free up some of jobtab.
- * We only do this at top level, because if we are
- * executing stuff we may refer to them by job pointer.
- */
- int errexit = 0;
- maybeshrinkjobtab();
-
- do {
- /* Reset return from top level which gets us back here */
- retflag = 0;
- loop(1,0);
- if (errflag && !interact && !isset(CONTINUEONERROR)) {
- errexit = 1;
- break;
- }
- } while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN)));
- if (tok == LEXERR || errexit) {
- /* Make sure a fatal error exits with non-zero status */
- if (!lastval)
- lastval = 1;
- stopmsg = 1;
- zexit(lastval, 0);
- }
- if (!(isset(IGNOREEOF) && interact)) {
-#if 0
- if (interact)
- fputs(islogin ? "logout\n" : "exit\n", shout);
-#endif
- zexit(lastval, 0);
- continue;
- }
- noexitct++;
- if (noexitct >= 10) {
- stopmsg = 1;
- zexit(lastval, 0);
- }
- /*
- * Don't print the message if it was already handled by
- * zle, since that makes special arrangements to keep
- * the display tidy.
- */
- if (!use_exit_printed)
- zerrnam("zsh", (!islogin) ? "use 'exit' to exit."
- : "use 'logout' to logout.");
- }
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/input.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/input.c
deleted file mode 100644
index 9787dedf..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/input.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- * input.c - read and store lines of input
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-
-/*
- * This file deals with input buffering, supplying characters to the
- * history expansion code a character at a time. Input is stored on a
- * stack, which allows insertion of strings into the input, possibly with
- * flags marking the end of alias expansion, with minimal copying of
- * strings. The same stack is used to record the fact that the input
- * is a history or alias expansion and to store the alias while it is in use.
- *
- * Input is taken either from zle, if appropriate, or read directly from
- * the input file, or may be supplied by some other part of the shell (such
- * as `eval' or $(...) substitution). In the last case, it should be
- * supplied by pushing a new level onto the stack, via inpush(input_string,
- * flag, alias); if the current input really needs to be altered, use
- * inputsetline(input_string, flag). `Flag' can include or's of INP_FREE
- * (if the input string is to be freed when used), INP_CONT (if the input
- * is to continue onto what's already in the input queue), INP_ALIAS
- * (push supplied alias onto stack) or INP_HIST (ditto, but used to
- * mark history expansion). `alias' is ignored unless INP_ALIAS or
- * INP_HIST is supplied. INP_ALIAS is always set if INP_HIST is.
- *
- * Note that the input string is itself used as the input buffer: it is not
- * copied, nor is it every written back to, so using a constant string
- * should work. Consequently, when passing areas of memory from the heap
- * it is necessary that that heap last as long as the operation of reading
- * the string. After the string is read, the stack should be popped with
- * inpop(), which effectively flushes any unread input as well as restoring
- * the previous input state.
- *
- * The internal flags INP_ALCONT and INP_HISTCONT show that the stack
- * element was pushed by an alias or history expansion; they should not
- * be needed elsewhere.
- *
- * The global variable inalmore is set to indicate aliases should
- * continue to be expanded because the last alias expansion ended
- * in a space. It is only reset after a complete word was read
- * without expanding a new alias, in exalias().
- *
- * PWS 1996/12/10
- */
-
-#ifdef HAVE_STDIO_H
-#include
-#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;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/jobs.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/jobs.c
deleted file mode 100644
index 38b3d896..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/jobs.c
+++ /dev/null
@@ -1,2894 +0,0 @@
-/*
- * jobs.c - job control
- *
- * 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 "jobs.pro"
-
-/* the process group of the shell at startup (equal to mypgprp, except
- when we started without being process group leader */
-
-/**/
-mod_export pid_t origpgrp;
-
-/* the process group of the shell */
-
-/**/
-mod_export pid_t mypgrp;
-
-/* the job we are working on */
-
-/**/
-mod_export int thisjob;
-
-/* the current job (+) */
-
-/**/
-mod_export int curjob;
-
-/* the previous job (-) */
-
-/**/
-mod_export int prevjob;
-
-/* the job table */
-
-/**/
-mod_export struct job *jobtab;
-
-/* Size of the job table. */
-
-/**/
-mod_export int jobtabsize;
-
-/* The highest numbered job in the jobtable */
-
-/**/
-mod_export int maxjob;
-
-/* If we have entered a subshell, the original shell's job table. */
-static struct job *oldjobtab;
-
-/* The size of that. */
-static int oldmaxjob;
-
-/* shell timings */
-
-/**/
-#ifdef HAVE_GETRUSAGE
-/**/
-static struct rusage child_usage;
-/**/
-#else
-/**/
-static struct tms shtms;
-/**/
-#endif
-
-/* 1 if ttyctl -f has been executed */
-
-/**/
-mod_export int ttyfrozen;
-
-/* Previous values of errflag and breaks if the signal handler had to
- * change them. And a flag saying if it did that. */
-
-/**/
-int prev_errflag, prev_breaks, errbrk_saved;
-
-/**/
-int numpipestats, pipestats[MAX_PIPESTATS];
-
-/* Diff two timevals for elapsed-time computations */
-
-/**/
-static struct timeval *
-dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2)
-{
- dt->tv_sec = t2->tv_sec - t1->tv_sec;
- dt->tv_usec = t2->tv_usec - t1->tv_usec;
- if (dt->tv_usec < 0) {
- dt->tv_usec += 1000000.0;
- dt->tv_sec -= 1.0;
- }
- return dt;
-}
-
-/* change job table entry from stopped to running */
-
-/**/
-void
-makerunning(Job jn)
-{
- Process pn;
-
- jn->stat &= ~STAT_STOPPED;
- for (pn = jn->procs; pn; pn = pn->next) {
-#if 0
- if (WIFSTOPPED(pn->status) &&
- (!(jn->stat & STAT_SUPERJOB) || pn->next))
- pn->status = SP_RUNNING;
-#endif
- if (WIFSTOPPED(pn->status))
- pn->status = SP_RUNNING;
- }
-
- if (jn->stat & STAT_SUPERJOB)
- makerunning(jobtab + jn->other);
-}
-
-/* Find process and job associated with pid. *
- * Return 1 if search was successful, else return 0. */
-
-/**/
-int
-findproc(pid_t pid, Job *jptr, Process *pptr, int aux)
-{
- Process pn;
- int i;
-
- *jptr = NULL;
- *pptr = NULL;
- for (i = 1; i <= maxjob; i++)
- {
- /*
- * We are only interested in jobs with processes still
- * marked as live. Careful in case there's an identical
- * process number in a job we haven't quite got around
- * to deleting.
- */
- if (jobtab[i].stat & STAT_DONE)
- continue;
-
- for (pn = aux ? jobtab[i].auxprocs : jobtab[i].procs;
- pn; pn = pn->next)
- {
- /*
- * Make sure we match a process that's still running.
- *
- * When a job contains two pids, one terminated pid and one
- * running pid, then the condition (jobtab[i].stat &
- * STAT_DONE) will not stop these pids from being candidates
- * for the findproc result (which is supposed to be a
- * RUNNING pid), and if the terminated pid is an identical
- * process number for the pid identifying the running
- * process we are trying to find (after pid number
- * wrapping), then we need to avoid returning the terminated
- * pid, otherwise the shell would block and wait forever for
- * the termination of the process which pid we were supposed
- * to return in a different job.
- */
- if (pn->pid == pid) {
- *pptr = pn;
- *jptr = jobtab + i;
- if (pn->status == SP_RUNNING)
- return 1;
- }
- }
- }
-
- return (*pptr && *jptr);
-}
-
-/* Does the given job number have any processes? */
-
-/**/
-int
-hasprocs(int job)
-{
- Job jn;
-
- if (job < 0) {
- DPUTS(1, "job number invalid in hasprocs");
- return 0;
- }
- jn = jobtab + job;
-
- return jn->procs || jn->auxprocs;
-}
-
-/* Find the super-job of a sub-job. */
-
-/**/
-static int
-super_job(int sub)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if ((jobtab[i].stat & STAT_SUPERJOB) &&
- jobtab[i].other == sub &&
- jobtab[i].gleader)
- return i;
- return 0;
-}
-
-/**/
-static int
-handle_sub(int job, int fg)
-{
- /* job: superjob; sj: subjob. */
- Job jn = jobtab + job, sj = jobtab + jn->other;
-
- if ((sj->stat & STAT_DONE) || (!sj->procs && !sj->auxprocs)) {
- struct process *p;
-
- for (p = sj->procs; p; p = p->next) {
- if (WIFSIGNALED(p->status)) {
- if (jn->gleader != mypgrp && jn->procs->next)
- killpg(jn->gleader, WTERMSIG(p->status));
- else
- kill(jn->procs->pid, WTERMSIG(p->status));
- kill(sj->other, SIGCONT);
- kill(sj->other, WTERMSIG(p->status));
- break;
- }
- }
- if (!p) {
- int cp;
-
- jn->stat &= ~STAT_SUPERJOB;
- jn->stat |= STAT_WASSUPER;
-
- if ((cp = ((WIFEXITED(jn->procs->status) ||
- WIFSIGNALED(jn->procs->status)) &&
- killpg(jn->gleader, 0) == -1))) {
- Process p;
- for (p = jn->procs; p->next; p = p->next);
- jn->gleader = p->pid;
- }
- /* This deleted the job too early if the parent
- shell waited for a command in a list that will
- be executed by the sub-shell (e.g.: if we have
- `ls|if true;then sleep 20;cat;fi' and ^Z the
- sleep, the rest will be executed by a sub-shell,
- but the parent shell gets notified for the
- sleep.
- deletejob(sj, 0); */
- /* If this super-job contains only the sub-shell,
- we have to attach the tty to its process group
- now. */
- if ((fg || thisjob == job) &&
- (!jn->procs->next || cp || jn->procs->pid != jn->gleader))
- attachtty(jn->gleader);
- kill(sj->other, SIGCONT);
- if (jn->stat & STAT_DISOWN)
- {
- deletejob(jn, 1);
- }
- }
- curjob = jn - jobtab;
- } else if (sj->stat & STAT_STOPPED) {
- struct process *p;
-
- jn->stat |= STAT_STOPPED;
- for (p = jn->procs; p; p = p->next)
- if (p->status == SP_RUNNING ||
- (!WIFEXITED(p->status) && !WIFSIGNALED(p->status)))
- p->status = sj->procs->status;
- curjob = jn - jobtab;
- printjob(jn, !!isset(LONGLISTJOBS), 1);
- return 1;
- }
- return 0;
-}
-
-
-/* Get the latest usage information */
-
-/**/
-void
-get_usage(void)
-{
-#ifdef HAVE_GETRUSAGE
- getrusage(RUSAGE_CHILDREN, &child_usage);
-#else
- times(&shtms);
-#endif
-}
-
-
-#if !defined HAVE_WAIT3 || !defined HAVE_GETRUSAGE
-/* Update status of process that we have just WAIT'ed for */
-
-/**/
-void
-update_process(Process pn, int status)
-{
- struct timezone dummy_tz;
-#ifdef HAVE_GETRUSAGE
- struct timeval childs = child_usage.ru_stime;
- struct timeval childu = child_usage.ru_utime;
-#else
- long childs = shtms.tms_cstime;
- long childu = shtms.tms_cutime;
-#endif
-
- /* get time-accounting info */
- get_usage();
- gettimeofday(&pn->endtime, &dummy_tz); /* record time process exited */
-
- pn->status = status; /* save the status returned by WAIT */
-#ifdef HAVE_GETRUSAGE
- dtime(&pn->ti.ru_stime, &childs, &child_usage.ru_stime);
- dtime(&pn->ti.ru_utime, &childu, &child_usage.ru_utime);
-#else
- pn->ti.st = shtms.tms_cstime - childs; /* compute process system space time */
- pn->ti.ut = shtms.tms_cutime - childu; /* compute process user space time */
-#endif
-}
-#endif
-
-/*
- * Called when the current shell is behaving as if it received
- * a interactively generated signal (sig).
- *
- * As we got the signal or are pretending we did, we need to pretend
- * anything attached to a CURSH process got it, too.
- */
-/**/
-void
-check_cursh_sig(int sig)
-{
- int i, j;
-
- if (!errflag)
- return;
- for (i = 1; i <= maxjob; i++) {
- if ((jobtab[i].stat & (STAT_CURSH|STAT_DONE)) ==
- STAT_CURSH) {
- for (j = 0; j < 2; j++) {
- Process pn = j ? jobtab[i].auxprocs : jobtab[i].procs;
- for (; pn; pn = pn->next) {
- if (pn->status == SP_RUNNING) {
- kill(pn->pid, sig);
- }
- }
- }
- }
- }
-}
-
-/**/
-void
-storepipestats(Job jn, int inforeground, int fixlastval)
-{
- int i, pipefail = 0, jpipestats[MAX_PIPESTATS];
- Process p;
-
- for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) {
- jpipestats[i] = (WIFSIGNALED(p->status) ?
- 0200 | WTERMSIG(p->status) :
- (WIFSTOPPED(p->status) ?
- 0200 | WEXITSTATUS(p->status) :
- WEXITSTATUS(p->status)));
- if (jpipestats[i])
- pipefail = jpipestats[i];
- }
- if (inforeground) {
- memcpy(pipestats, jpipestats, sizeof(int)*i);
- if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS)
- pipestats[i++] = lastval;
- numpipestats = i;
- }
-
- if (fixlastval) {
- if (jn->stat & STAT_CURSH) {
- if (!lastval && isset(PIPEFAIL))
- lastval = pipefail;
- } else if (isset(PIPEFAIL))
- lastval = pipefail;
- }
-}
-
-/* Update status of job, possibly printing it */
-
-/**/
-void
-update_job(Job jn)
-{
- Process pn;
- int job;
- int val = 0, status = 0;
- int somestopped = 0, inforeground = 0;
-
- for (pn = jn->auxprocs; pn; pn = pn->next) {
-#ifdef WIFCONTINUED
- if (WIFCONTINUED(pn->status))
- pn->status = SP_RUNNING;
-#endif
- if (pn->status == SP_RUNNING)
- return;
- }
-
- for (pn = jn->procs; pn; pn = pn->next) {
-#ifdef WIFCONTINUED
- if (WIFCONTINUED(pn->status)) {
- jn->stat &= ~STAT_STOPPED;
- pn->status = SP_RUNNING;
- }
-#endif
- if (pn->status == SP_RUNNING) /* some processes in this job are running */
- return; /* so no need to update job table entry */
- if (WIFSTOPPED(pn->status)) /* some processes are stopped */
- somestopped = 1; /* so job is not done, but entry needs updating */
- if (!pn->next) /* last job in pipeline determines exit status */
- val = (WIFSIGNALED(pn->status) ?
- 0200 | WTERMSIG(pn->status) :
- (WIFSTOPPED(pn->status) ?
- 0200 | WEXITSTATUS(pn->status) :
- WEXITSTATUS(pn->status)));
- if (pn->pid == jn->gleader) /* if this process is process group leader */
- status = pn->status;
- }
-
- job = jn - jobtab; /* compute job number */
-
- if (somestopped) {
- if (jn->stty_in_env && !jn->ty) {
- jn->ty = (struct ttyinfo *) zalloc(sizeof(struct ttyinfo));
- gettyinfo(jn->ty);
- }
- if (jn->stat & STAT_STOPPED) {
- if (jn->stat & STAT_SUBJOB) {
- /* If we have `cat foo|while read a; grep $a bar;done'
- * and have hit ^Z, the sub-job is stopped, but the
- * super-job may still be running, waiting to be stopped
- * or to exit. So we have to send it a SIGTSTP. */
- int i;
-
- if ((i = super_job(job)))
- killpg(jobtab[i].gleader, SIGTSTP);
- }
- return;
- }
- }
- { /* job is done or stopped, remember return value */
- lastval2 = val;
- /* If last process was run in the current shell, keep old status
- * and let it handle its own traps, but always allow the test
- * for the pgrp.
- */
- if (jn->stat & STAT_CURSH)
- inforeground = 1;
- else if (job == thisjob) {
- lastval = val;
- inforeground = 2;
- }
- }
-
- if (shout && shout != stderr && !ttyfrozen && !jn->stty_in_env &&
- !zleactive && job == thisjob && !somestopped &&
- !(jn->stat & STAT_NOSTTY))
- gettyinfo(&shttyinfo);
-
- if (isset(MONITOR)) {
- pid_t pgrp = gettygrp(); /* get process group of tty */
-
- /* is this job in the foreground of an interactive shell? */
- if (mypgrp != pgrp && inforeground &&
- (jn->gleader == pgrp || (pgrp > 1 && kill(-pgrp, 0) == -1))) {
- if (list_pipe) {
- if (somestopped || (pgrp > 1 && kill(-pgrp, 0) == -1)) {
- attachtty(mypgrp);
- /* check window size and adjust if necessary */
- adjustwinsize(0);
- } else {
- /*
- * Oh, dear, we're right in the middle of some confusion
- * of shell jobs on the righthand side of a pipeline, so
- * it's death to call attachtty() just yet. Mark the
- * fact in the job, so that the attachtty() will be called
- * when the job is finally deleted.
- */
- jn->stat |= STAT_ATTACH;
- }
- /* If we have `foo|while true; (( x++ )); done', and hit
- * ^C, we have to stop the loop, too. */
- if ((val & 0200) && inforeground == 1 &&
- ((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) {
- if (!errbrk_saved) {
- errbrk_saved = 1;
- prev_breaks = breaks;
- prev_errflag = errflag;
- }
- breaks = loops;
- errflag |= ERRFLAG_INT;
- inerrflush();
- }
- } else {
- attachtty(mypgrp);
- /* check window size and adjust if necessary */
- adjustwinsize(0);
- }
- }
- } else if (list_pipe && (val & 0200) && inforeground == 1 &&
- ((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) {
- if (!errbrk_saved) {
- errbrk_saved = 1;
- prev_breaks = breaks;
- prev_errflag = errflag;
- }
- breaks = loops;
- errflag |= ERRFLAG_INT;
- inerrflush();
- }
- if (somestopped && jn->stat & STAT_SUPERJOB)
- return;
- jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
- STAT_CHANGED | STAT_DONE;
- if (jn->stat & (STAT_DONE|STAT_STOPPED)) {
- /* This may be redundant with printjob() but note that inforeground
- * is true here for STAT_CURSH jobs even when job != thisjob, most
- * likely because thisjob = -1 from exec.c:execsimple() trickery.
- * However, if we reset lastval here we break it for printjob().
- */
- storepipestats(jn, inforeground, 0);
- }
- if (!inforeground &&
- (jn->stat & (STAT_SUBJOB | STAT_DONE)) == (STAT_SUBJOB | STAT_DONE)) {
- int su;
-
- if ((su = super_job(jn - jobtab)))
- handle_sub(su, 0);
- }
- if ((jn->stat & (STAT_DONE | STAT_STOPPED)) == STAT_STOPPED) {
- prevjob = curjob;
- curjob = job;
- }
- if ((isset(NOTIFY) || job == thisjob) && (jn->stat & STAT_LOCKED)) {
- if (printjob(jn, !!isset(LONGLISTJOBS), 0) &&
- zleactive)
- zleentry(ZLE_CMD_REFRESH);
- }
- if (sigtrapped[SIGCHLD] && job != thisjob)
- dotrap(SIGCHLD);
-
- /* When MONITOR is set, the foreground process runs in a different *
- * process group from the shell, so the shell will not receive *
- * terminal signals, therefore we pretend that the shell got *
- * the signal too. */
- if (inforeground == 2 && isset(MONITOR) && WIFSIGNALED(status)) {
- int sig = WTERMSIG(status);
-
- if (sig == SIGINT || sig == SIGQUIT) {
- if (sigtrapped[sig]) {
- dotrap(sig);
- /* We keep the errflag as set or not by dotrap.
- * This is to fulfil the promise to carry on
- * with the jobs if trap returns zero.
- * Setting breaks = loops ensures a consistent return
- * status if inside a loop. Maybe the code in loops
- * should be changed.
- */
- if (errflag)
- breaks = loops;
- } else {
- breaks = loops;
- errflag |= ERRFLAG_INT;
- }
- check_cursh_sig(sig);
- }
- }
-}
-
-/* set the previous job to something reasonable */
-
-/**/
-static void
-setprevjob(void)
-{
- int i;
-
- for (i = maxjob; i; i--)
- if ((jobtab[i].stat & STAT_INUSE) && (jobtab[i].stat & STAT_STOPPED) &&
- !(jobtab[i].stat & STAT_SUBJOB) && i != curjob && i != thisjob) {
- prevjob = i;
- return;
- }
-
- for (i = maxjob; i; i--)
- if ((jobtab[i].stat & STAT_INUSE) && !(jobtab[i].stat & STAT_SUBJOB) &&
- i != curjob && i != thisjob) {
- prevjob = i;
- return;
- }
-
- prevjob = -1;
-}
-
-/**/
-long
-get_clktck(void)
-{
- static long clktck;
-
-#ifdef _SC_CLK_TCK
- if (!clktck)
- /* fetch clock ticks per second from *
- * sysconf only the first time */
- clktck = sysconf(_SC_CLK_TCK);
-#else
-# ifdef __NeXT__
- /* NeXTStep 3.3 defines CLK_TCK wrongly */
- clktck = 60;
-# else
-# ifdef CLK_TCK
- clktck = CLK_TCK;
-# else
-# ifdef HZ
- clktck = HZ;
-# else
- clktck = 60;
-# endif
-# endif
-# endif
-#endif
-
- return clktck;
-}
-
-/**/
-static void
-printhhmmss(double secs)
-{
- int mins = (int) secs / 60;
- int hours = mins / 60;
-
- secs -= 60 * mins;
- mins -= 60 * hours;
- if (hours)
- fprintf(stderr, "%d:%02d:%05.2f", hours, mins, secs);
- else if (mins)
- fprintf(stderr, "%d:%05.2f", mins, secs);
- else
- fprintf(stderr, "%.3f", secs);
-}
-
-static void
-printtime(struct timeval *real, child_times_t *ti, char *desc)
-{
- char *s;
- double elapsed_time, user_time, system_time;
-#ifdef HAVE_GETRUSAGE
- double total_time;
-#endif
- int percent, desclen;
-
- if (!desc)
- {
- desc = "";
- desclen = 0;
- }
- else
- {
- desc = dupstring(desc);
- unmetafy(desc, &desclen);
- }
-
- /* go ahead and compute these, since almost every TIMEFMT will have them */
- elapsed_time = real->tv_sec + real->tv_usec / 1000000.0;
-
-#ifdef HAVE_GETRUSAGE
- user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0;
- system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0;
- total_time = user_time + system_time;
- percent = 100.0 * total_time
- / (real->tv_sec + real->tv_usec / 1000000.0);
-#else
- {
- long clktck = get_clktck();
- user_time = ti->ut / (double) clktck;
- system_time = ti->st / (double) clktck;
- percent = 100.0 * (ti->ut + ti->st)
- / (clktck * real->tv_sec + clktck * real->tv_usec / 1000000.0);
- }
-#endif
-
- queue_signals();
- if (!(s = getsparam("TIMEFMT")))
- s = DEFAULT_TIMEFMT;
- else
- s = unmetafy(s, NULL);
-
- for (; *s; s++)
- if (*s == '%')
- switch (*++s) {
- case 'E':
- fprintf(stderr, "%4.2fs", elapsed_time);
- break;
- case 'U':
- fprintf(stderr, "%4.2fs", user_time);
- break;
- case 'S':
- fprintf(stderr, "%4.2fs", system_time);
- break;
- case 'm':
- switch (*++s) {
- case 'E':
- fprintf(stderr, "%0.fms", elapsed_time * 1000.0);
- break;
- case 'U':
- fprintf(stderr, "%0.fms", user_time * 1000.0);
- break;
- case 'S':
- fprintf(stderr, "%0.fms", system_time * 1000.0);
- break;
- default:
- fprintf(stderr, "%%m");
- s--;
- break;
- }
- break;
- case 'u':
- switch (*++s) {
- case 'E':
- fprintf(stderr, "%0.fus", elapsed_time * 1000000.0);
- break;
- case 'U':
- fprintf(stderr, "%0.fus", user_time * 1000000.0);
- break;
- case 'S':
- fprintf(stderr, "%0.fus", system_time * 1000000.0);
- break;
- default:
- fprintf(stderr, "%%u");
- s--;
- break;
- }
- break;
- case '*':
- switch (*++s) {
- case 'E':
- printhhmmss(elapsed_time);
- break;
- case 'U':
- printhhmmss(user_time);
- break;
- case 'S':
- printhhmmss(system_time);
- break;
- default:
- fprintf(stderr, "%%*");
- s--;
- break;
- }
- break;
- case 'P':
- fprintf(stderr, "%d%%", percent);
- break;
-#ifdef HAVE_STRUCT_RUSAGE_RU_NSWAP
- case 'W':
- fprintf(stderr, "%ld", ti->ru_nswap);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
- case 'X':
- fprintf(stderr, "%ld",
- total_time ?
- (long)(ti->ru_ixrss / total_time) :
- (long)0);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
- case 'D':
- fprintf(stderr, "%ld",
- total_time ?
- (long) ((ti->ru_idrss
-#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
- + ti->ru_isrss
-#endif
- ) / total_time) :
- (long)0);
- break;
-#endif
-#if defined(HAVE_STRUCT_RUSAGE_RU_IDRSS) || \
- defined(HAVE_STRUCT_RUSAGE_RU_ISRSS) || \
- defined(HAVE_STRUCT_RUSAGE_RU_IXRSS)
- case 'K':
- /* treat as D if X not available */
- fprintf(stderr, "%ld",
- total_time ?
- (long) ((
-#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
- ti->ru_ixrss
-#else
- 0
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
- + ti->ru_idrss
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
- + ti->ru_isrss
-#endif
- ) / total_time) :
- (long)0);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS
- case 'M':
- fprintf(stderr, "%ld", ti->ru_maxrss / 1024);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_MAJFLT
- case 'F':
- fprintf(stderr, "%ld", ti->ru_majflt);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_MINFLT
- case 'R':
- fprintf(stderr, "%ld", ti->ru_minflt);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_INBLOCK
- case 'I':
- fprintf(stderr, "%ld", ti->ru_inblock);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_OUBLOCK
- case 'O':
- fprintf(stderr, "%ld", ti->ru_oublock);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_MSGRCV
- case 'r':
- fprintf(stderr, "%ld", ti->ru_msgrcv);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_MSGSND
- case 's':
- fprintf(stderr, "%ld", ti->ru_msgsnd);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_NSIGNALS
- case 'k':
- fprintf(stderr, "%ld", ti->ru_nsignals);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_NVCSW
- case 'w':
- fprintf(stderr, "%ld", ti->ru_nvcsw);
- break;
-#endif
-#ifdef HAVE_STRUCT_RUSAGE_RU_NIVCSW
- case 'c':
- fprintf(stderr, "%ld", ti->ru_nivcsw);
- break;
-#endif
- case 'J':
- fwrite(desc, sizeof(char), desclen, stderr);
- break;
- case '%':
- putc('%', stderr);
- break;
- case '\0':
- s--;
- break;
- default:
- fprintf(stderr, "%%%c", *s);
- break;
- } else
- putc(*s, stderr);
- unqueue_signals();
- putc('\n', stderr);
- fflush(stderr);
-}
-
-/**/
-static void
-dumptime(Job jn)
-{
- Process pn;
- struct timeval dtimeval;
-
- if (!jn->procs)
- return;
- for (pn = jn->procs; pn; pn = pn->next)
- printtime(dtime(&dtimeval, &pn->bgtime, &pn->endtime), &pn->ti,
- pn->text);
-}
-
-/* Check whether shell should report the amount of time consumed *
- * by job. This will be the case if we have preceded the command *
- * with the keyword time, or if REPORTTIME is non-negative and the *
- * amount of time consumed by the job is greater than REPORTTIME */
-
-/**/
-static int
-should_report_time(Job j)
-{
- struct value vbuf;
- Value v;
- char *s = "REPORTTIME";
- int save_errflag = errflag;
- zlong reporttime = -1;
-#ifdef HAVE_GETRUSAGE
- char *sm = "REPORTMEMORY";
- zlong reportmemory = -1;
-#endif
-
- /* if the time keyword was used */
- if (j->stat & STAT_TIMED)
- return 1;
-
- queue_signals();
- errflag = 0;
- if ((v = getvalue(&vbuf, &s, 0)))
- reporttime = getintvalue(v);
-#ifdef HAVE_GETRUSAGE
- if ((v = getvalue(&vbuf, &sm, 0)))
- reportmemory = getintvalue(v);
-#endif
- errflag = save_errflag;
- unqueue_signals();
- if (reporttime < 0
-#ifdef HAVE_GETRUSAGE
- && reportmemory < 0
-#endif
- )
- return 0;
- /* can this ever happen? */
- if (!j->procs)
- return 0;
- if (zleactive)
- return 0;
-
- if (reporttime >= 0)
- {
-#ifdef HAVE_GETRUSAGE
- reporttime -= j->procs->ti.ru_utime.tv_sec +
- j->procs->ti.ru_stime.tv_sec;
- if (j->procs->ti.ru_utime.tv_usec +
- j->procs->ti.ru_stime.tv_usec >= 1000000)
- reporttime--;
- if (reporttime <= 0)
- return 1;
-#else
- {
- clktck = get_clktck();
- if ((j->procs->ti.ut + j->procs->ti.st) / clktck >= reporttime)
- return 1;
- }
-#endif
- }
-
-#ifdef HAVE_GETRUSAGE
- if (reportmemory >= 0 &&
- j->procs->ti.ru_maxrss / 1024 > reportmemory)
- return 1;
-#endif
-
- return 0;
-}
-
-/* !(lng & 3) means jobs *
- * (lng & 1) means jobs -l *
- * (lng & 2) means jobs -p
- * (lng & 4) means jobs -d
- *
- * synch = 0 means asynchronous
- * synch = 1 means synchronous
- * synch = 2 means called synchronously from jobs
- * synch = 3 means called synchronously from bg or fg
- *
- * Returns 1 if some output was done.
- *
- * The function also deletes the job if it was done, even it
- * is not printed.
- */
-
-/**/
-int
-printjob(Job jn, int lng, int synch)
-{
- Process pn;
- int job, len = 9, sig, sflag = 0, llen;
- int conted = 0, lineleng = zterm_columns, skip = 0, doputnl = 0;
- int doneprint = 0, skip_print = 0;
- FILE *fout = (synch == 2 || !shout) ? stdout : shout;
-
- if (synch > 1 && oldjobtab != NULL)
- job = jn - oldjobtab;
- else
- job = jn - jobtab;
- DPUTS3(job < 0 || job > (oldjobtab && synch > 1 ? oldmaxjob : maxjob),
- "bogus job number, jn = %L, jobtab = %L, oldjobtab = %L",
- (long)jn, (long)jobtab, (long)oldjobtab);
-
- if (jn->stat & STAT_NOPRINT) {
- skip_print = 1;
- }
-
- if (lng < 0) {
- conted = 1;
- lng = !!isset(LONGLISTJOBS);
- }
-
-/* find length of longest signame, check to see */
-/* if we really need to print this job */
-
- for (pn = jn->procs; pn; pn = pn->next) {
- if (jn->stat & STAT_SUPERJOB &&
- jn->procs->status == SP_RUNNING && !pn->next)
- pn->status = SP_RUNNING;
- if (pn->status != SP_RUNNING) {
- if (WIFSIGNALED(pn->status)) {
- sig = WTERMSIG(pn->status);
- llen = strlen(sigmsg(sig));
- if (WCOREDUMP(pn->status))
- llen += 14;
- if (llen > len)
- len = llen;
- if (sig != SIGINT && sig != SIGPIPE)
- sflag = 1;
- if (job == thisjob && sig == SIGINT)
- doputnl = 1;
- if (isset(PRINTEXITVALUE) && isset(SHINSTDIN)) {
- sflag = 1;
- skip_print = 0;
- }
- } else if (WIFSTOPPED(pn->status)) {
- sig = WSTOPSIG(pn->status);
- if ((int)strlen(sigmsg(sig)) > len)
- len = strlen(sigmsg(sig));
- if (job == thisjob && sig == SIGTSTP)
- doputnl = 1;
- } else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
- WEXITSTATUS(pn->status)) {
- sflag = 1;
- skip_print = 0;
- }
- }
- }
-
- if (skip_print) {
- if (jn->stat & STAT_DONE) {
- /* This looks silly, but see update_job() */
- if (synch <= 1)
- storepipestats(jn, job == thisjob, job == thisjob);
- if (should_report_time(jn))
- dumptime(jn);
- deletejob(jn, 0);
- if (job == curjob) {
- curjob = prevjob;
- prevjob = job;
- }
- if (job == prevjob)
- setprevjob();
- }
- return 0;
- }
-
- /*
- * - Always print if called from jobs
- * - Otherwise, require MONITOR option ("jobbing") and some
- * change of state
- * - also either the shell is interactive or this is synchronous.
- */
- if (synch == 2 ||
- ((interact || synch) && jobbing &&
- ((jn->stat & STAT_STOPPED) || sflag || job != thisjob))) {
- int len2, fline = 1;
- /* POSIX requires just the job text for bg and fg */
- int plainfmt = (synch == 3) && isset(POSIXJOBS);
- /* use special format for current job, except in `jobs' */
- int thisfmt = job == thisjob && synch != 2;
- Process qn;
-
- if (!synch)
- zleentry(ZLE_CMD_TRASH);
- if (doputnl && !synch) {
- doneprint = 1;
- putc('\n', fout);
- }
- for (pn = jn->procs; pn;) {
- len2 = (thisfmt ? 5 : 10) + len; /* 2 spaces */
- if (lng & 3)
- qn = pn->next;
- else
- for (qn = pn->next; qn; qn = qn->next) {
- if (qn->status != pn->status)
- break;
- if ((int)strlen(qn->text) + len2 + ((qn->next) ? 3 : 0)
- > lineleng)
- break;
- len2 += strlen(qn->text) + 2;
- }
- doneprint = 1;
- if (!plainfmt) {
- if (!thisfmt || lng) {
- if (fline)
- fprintf(fout, "[%ld] %c ",
- (long)job,
- (job == curjob) ? '+'
- : (job == prevjob) ? '-' : ' ');
- else
- fprintf(fout, (job > 9) ? " " : " ");
- } else
- fprintf(fout, "zsh: ");
- if (lng & 1)
- fprintf(fout, "%ld ", (long) pn->pid);
- else if (lng & 2) {
- pid_t x = jn->gleader;
-
- fprintf(fout, "%ld ", (long) x);
- do
- skip++;
- while ((x /= 10));
- skip++;
- lng &= ~3;
- } else
- fprintf(fout, "%*s", skip, "");
- if (pn->status == SP_RUNNING) {
- if (!conted)
- fprintf(fout, "running%*s", len - 7 + 2, "");
- else
- fprintf(fout, "continued%*s", len - 9 + 2, "");
- }
- else if (WIFEXITED(pn->status)) {
- if (WEXITSTATUS(pn->status))
- fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status),
- len - 9 + 2, "");
- else
- fprintf(fout, "done%*s", len - 4 + 2, "");
- } else if (WIFSTOPPED(pn->status))
- fprintf(fout, "%-*s", len + 2,
- sigmsg(WSTOPSIG(pn->status)));
- else if (WCOREDUMP(pn->status))
- fprintf(fout, "%s (core dumped)%*s",
- sigmsg(WTERMSIG(pn->status)),
- (int)(len - 14 + 2 -
- strlen(sigmsg(WTERMSIG(pn->status)))), "");
- else
- fprintf(fout, "%-*s", len + 2,
- sigmsg(WTERMSIG(pn->status)));
- }
- for (; pn != qn; pn = pn->next) {
- char *txt = dupstring(pn->text);
- int txtlen;
- unmetafy(txt, &txtlen);
- fwrite(txt, sizeof(char), txtlen, fout);
- if (pn->next)
- fputs(" | ", fout);
- }
- putc('\n', fout);
- fline = 0;
- }
- fflush(fout);
- } else if (doputnl && interact && !synch) {
- doneprint = 1;
- putc('\n', fout);
- fflush(fout);
- }
-
- /* print "(pwd now: foo)" messages: with (lng & 4) we are printing
- * the directory where the job is running, otherwise the current directory
- */
-
- if ((lng & 4) || (interact && job == thisjob &&
- jn->pwd && strcmp(jn->pwd, pwd))) {
- doneprint = 1;
- fprintf(fout, "(pwd %s: ", (lng & 4) ? "" : "now");
- fprintdir(((lng & 4) && jn->pwd) ? jn->pwd : pwd, fout);
- fprintf(fout, ")\n");
- fflush(fout);
- }
-
- /* delete job if done */
-
- if (jn->stat & STAT_DONE) {
- /* This looks silly, but see update_job() */
- if (synch <= 1)
- storepipestats(jn, job == thisjob, job == thisjob);
- if (should_report_time(jn))
- dumptime(jn);
- deletejob(jn, 0);
- if (job == curjob) {
- curjob = prevjob;
- prevjob = job;
- }
- if (job == prevjob)
- setprevjob();
- } else
- jn->stat &= ~STAT_CHANGED;
-
- return doneprint;
-}
-
-/* Add a file to be deleted or fd to be closed to the current job */
-
-/**/
-void
-addfilelist(const char *name, int fd)
-{
- Jobfile jf = (Jobfile)zalloc(sizeof(struct jobfile));
- LinkList ll = jobtab[thisjob].filelist;
-
- if (!ll)
- ll = jobtab[thisjob].filelist = znewlinklist();
- if (name)
- {
- jf->u.name = ztrdup(name);
- jf->is_fd = 0;
- }
- else
- {
- jf->u.fd = fd;
- jf->is_fd = 1;
- }
- zaddlinknode(ll, jf);
-}
-
-/* Clean up pipes no longer needed associated with a job */
-
-/**/
-void
-pipecleanfilelist(LinkList filelist, int proc_subst_only)
-{
- LinkNode node;
-
- if (!filelist)
- return;
- node = firstnode(filelist);
- while (node) {
- Jobfile jf = (Jobfile)getdata(node);
- if (jf->is_fd &&
- (!proc_subst_only || fdtable[jf->u.fd] == FDT_PROC_SUBST)) {
- LinkNode next = nextnode(node);
- zclose(jf->u.fd);
- (void)remnode(filelist, node);
- zfree(jf, sizeof(*jf));
- node = next;
- } else
- incnode(node);
- }
-}
-
-/* Finished with list of files for a job */
-
-/**/
-void
-deletefilelist(LinkList file_list, int disowning)
-{
- Jobfile jf;
- if (file_list) {
- while ((jf = (Jobfile)getlinknode(file_list))) {
- if (jf->is_fd) {
- if (!disowning)
- zclose(jf->u.fd);
- } else {
- if (!disowning)
- unlink(jf->u.name);
- zsfree(jf->u.name);
- }
- zfree(jf, sizeof(*jf));
- }
- zfree(file_list, sizeof(struct linklist));
- }
-}
-
-/**/
-void
-freejob(Job jn, int deleting)
-{
- struct process *pn, *nx;
-
- pn = jn->procs;
- jn->procs = NULL;
- for (; pn; pn = nx) {
- nx = pn->next;
- zfree(pn, sizeof(struct process));
- }
-
- pn = jn->auxprocs;
- jn->auxprocs = NULL;
- for (; pn; pn = nx) {
- nx = pn->next;
- zfree(pn, sizeof(struct process));
- }
-
- if (jn->ty)
- zfree(jn->ty, sizeof(struct ttyinfo));
- if (jn->pwd)
- zsfree(jn->pwd);
- jn->pwd = NULL;
- if (jn->stat & STAT_WASSUPER) {
- /* careful in case we shrink and move the job table */
- int job = jn - jobtab;
- if (deleting)
- deletejob(jobtab + jn->other, 0);
- else
- freejob(jobtab + jn->other, 0);
- jn = jobtab + job;
- }
- jn->gleader = jn->other = 0;
- jn->stat = jn->stty_in_env = 0;
- jn->filelist = NULL;
- jn->ty = NULL;
-
- /* Find the new highest job number. */
- if (maxjob == jn - jobtab) {
- while (maxjob && !(jobtab[maxjob].stat & STAT_INUSE))
- maxjob--;
- }
-}
-
-/*
- * We are actually finished with this job, rather
- * than freeing it to make space.
- *
- * If "disowning" is set, files associated with the job are not
- * actually deleted --- and won't be as there is nothing left
- * to clear up.
- */
-
-/**/
-void
-deletejob(Job jn, int disowning)
-{
- deletefilelist(jn->filelist, disowning);
- if (jn->stat & STAT_ATTACH) {
- attachtty(mypgrp);
- adjustwinsize(0);
- }
- if (jn->stat & STAT_SUPERJOB) {
- Job jno = jobtab + jn->other;
- if (jno->stat & STAT_SUBJOB)
- jno->stat |= STAT_SUBJOB_ORPHANED;
- }
-
- freejob(jn, 1);
-}
-
-/*
- * Add a process to the current job.
- * The third argument is 1 if we are adding a process which is not
- * part of the main pipeline but an auxiliary process used for
- * handling MULTIOS or process substitution. We will wait for it
- * but not display job information about it.
- */
-
-/**/
-void
-addproc(pid_t pid, char *text, int aux, struct timeval *bgtime)
-{
- Process pn, *pnlist;
-
- DPUTS(thisjob == -1, "No valid job in addproc.");
- pn = (Process) zshcalloc(sizeof *pn);
- pn->pid = pid;
- if (text)
- strcpy(pn->text, text);
- else
- *pn->text = '\0';
- pn->status = SP_RUNNING;
- pn->next = NULL;
-
- if (!aux)
- {
- pn->bgtime = *bgtime;
- /* if this is the first process we are adding to *
- * the job, then it's the group leader. */
- if (!jobtab[thisjob].gleader)
- jobtab[thisjob].gleader = pid;
- /* attach this process to end of process list of current job */
- pnlist = &jobtab[thisjob].procs;
- }
- else
- pnlist = &jobtab[thisjob].auxprocs;
-
- if (*pnlist) {
- Process n;
-
- for (n = *pnlist; n->next; n = n->next);
- n->next = pn;
- } else {
- /* first process for this job */
- *pnlist = pn;
- }
- /* If the first process in the job finished before any others were *
- * added, maybe STAT_DONE got set incorrectly. This can happen if *
- * a $(...) was waited for and the last existing job in the *
- * pipeline was already finished. We need to be very careful that *
- * there was no call to printjob() between then and now, else *
- * the job will already have been deleted from the table. */
- jobtab[thisjob].stat &= ~STAT_DONE;
-}
-
-/* Check if we have files to delete. We need to check this to see *
- * if it's all right to exec a command without forking in the last *
- * component of subshells or after the `-c' option. */
-
-/**/
-int
-havefiles(void)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if (jobtab[i].stat && jobtab[i].filelist)
- return 1;
- return 0;
-
-}
-
-/*
- * Wait for a particular process.
- * wait_cmd indicates this is from the interactive wait command,
- * in which case the behaviour is a little different: the command
- * itself can be interrupted by a trapped signal.
- */
-
-/**/
-int
-waitforpid(pid_t pid, int wait_cmd)
-{
- int first = 1, q = queue_signal_level();
-
- /* child_block() around this loop in case #ifndef WNOHANG */
- dont_queue_signals();
- child_block(); /* unblocked in signal_suspend() */
- queue_traps(wait_cmd);
-
- /* This function should never be called with a pid that is not a
- * child of the current shell. Consequently, if kill(0, pid)
- * fails here with ESRCH, the child has already been reaped. In
- * the loop body, we expect this to happen in signal_suspend()
- * via zhandler(), after which this test terminates the loop.
- */
- while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
- if (first)
- first = 0;
- else if (!wait_cmd)
- kill(pid, SIGCONT);
-
- last_signal = -1;
- signal_suspend(SIGCHLD, wait_cmd);
- if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 &&
- (sigtrapped[last_signal] & ZSIG_TRAPPED)) {
- /* wait command interrupted, but no error: return */
- restore_queue_signals(q);
- return 128 + last_signal;
- }
- child_block();
- }
- unqueue_traps();
- child_unblock();
- restore_queue_signals(q);
-
- return 0;
-}
-
-/*
- * Wait for a job to finish.
- * wait_cmd indicates this is from the wait builtin; see
- * wait_cmd in waitforpid().
- */
-
-/**/
-static int
-zwaitjob(int job, int wait_cmd)
-{
- int q = queue_signal_level();
- Job jn = jobtab + job;
-
- child_block(); /* unblocked during signal_suspend() */
- queue_traps(wait_cmd);
- dont_queue_signals();
- if (jn->procs || jn->auxprocs) { /* if any forks were done */
- jn->stat |= STAT_LOCKED;
- if (jn->stat & STAT_CHANGED)
- printjob(jn, !!isset(LONGLISTJOBS), 1);
- if (jn->filelist) {
- /*
- * The main shell is finished with any file descriptors used
- * for process substitution associated with this job: close
- * them to indicate to listeners there's no more input.
- *
- * Note we can't safely delete temporary files yet as these
- * are directly visible to other processes. However,
- * we can't deadlock on the fact that those still exist, so
- * that's not a problem.
- */
- pipecleanfilelist(jn->filelist, 0);
- }
- while (!(errflag & ERRFLAG_ERROR) && jn->stat &&
- !(jn->stat & STAT_DONE) &&
- !(interact && (jn->stat & STAT_STOPPED))) {
- signal_suspend(SIGCHLD, wait_cmd);
- if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 &&
- (sigtrapped[last_signal] & ZSIG_TRAPPED))
- {
- /* builtin wait interrupted by trapped signal */
- restore_queue_signals(q);
- return 128 + last_signal;
- }
- /* Commenting this out makes ^C-ing a job started by a function
- stop the whole function again. But I guess it will stop
- something else from working properly, we have to find out
- what this might be. --oberon
-
- When attempting to separate errors and interrupts, we
- assumed because of the previous comment it would be OK
- to remove ERRFLAG_ERROR and leave ERRFLAG_INT set, since
- that's the one related to ^C. But that doesn't work.
- There's something more here we don't understand. --pws
-
- The change above to ignore ERRFLAG_INT in the loop test
- solves a problem wherein child processes that ignore the
- INT signal were never waited-for. Clearing the flag here
- still seems the wrong thing, but perhaps ERRFLAG_INT
- should be saved and restored around signal_suspend() to
- prevent it being lost within a signal trap? --Bart
-
- errflag = 0; */
-
- if (subsh) {
- killjb(jn, SIGCONT);
- jn->stat &= ~STAT_STOPPED;
- }
- if (jn->stat & STAT_SUPERJOB)
- if (handle_sub(jn - jobtab, 1))
- break;
- child_block();
- }
- } else {
- deletejob(jn, 0);
- pipestats[0] = lastval;
- numpipestats = 1;
- }
- restore_queue_signals(q);
- unqueue_traps();
- child_unblock();
-
- return 0;
-}
-
-/* wait for running job to finish */
-
-/**/
-void
-waitjobs(void)
-{
- Job jn = jobtab + thisjob;
- DPUTS(thisjob == -1, "No valid job in waitjobs.");
-
- if (jn->procs || jn->auxprocs)
- zwaitjob(thisjob, 0);
- else {
- deletejob(jn, 0);
- pipestats[0] = lastval;
- numpipestats = 1;
- }
- thisjob = -1;
-}
-
-/* clear job table when entering subshells */
-
-/**/
-mod_export void
-clearjobtab(int monitor)
-{
- int i;
-
- if (isset(POSIXJOBS))
- oldmaxjob = 0;
- for (i = 1; i <= maxjob; i++) {
- /*
- * See if there is a jobtable worth saving.
- * We never free the saved version; it only happens
- * once for each subshell of a shell with job control,
- * so doesn't create a leak.
- */
- if (monitor && !isset(POSIXJOBS) && jobtab[i].stat)
- oldmaxjob = i+1;
- else if (jobtab[i].stat & STAT_INUSE)
- freejob(jobtab + i, 0);
- }
-
- if (monitor && oldmaxjob) {
- int sz = oldmaxjob * sizeof(struct job);
- if (oldjobtab)
- free(oldjobtab);
- oldjobtab = (struct job *)zalloc(sz);
- memcpy(oldjobtab, jobtab, sz);
-
- /* Don't report any job we're part of */
- if (thisjob != -1 && thisjob < oldmaxjob)
- memset(oldjobtab+thisjob, 0, sizeof(struct job));
- }
-
- memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */
- maxjob = 0;
-
- /*
- * Although we don't have job control in subshells, we
- * sometimes needs control structures for other purposes such
- * as multios. Grab a job for this purpose; any will do
- * since we've freed them all up (so there's no question
- * of problems with the job table size here).
- */
- thisjob = initjob();
-}
-
-static int initnewjob(int i)
-{
- jobtab[i].stat = STAT_INUSE;
- if (jobtab[i].pwd) {
- zsfree(jobtab[i].pwd);
- jobtab[i].pwd = NULL;
- }
- jobtab[i].gleader = 0;
-
- if (i > maxjob)
- maxjob = i;
-
- return i;
-}
-
-/* Get a free entry in the job table and initialize it. */
-
-/**/
-int
-initjob(void)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if (!jobtab[i].stat)
- return initnewjob(i);
- if (maxjob + 1 < jobtabsize)
- return initnewjob(maxjob+1);
-
- if (expandjobtab())
- return initnewjob(i);
-
- zerr("job table full or recursion limit exceeded");
- return -1;
-}
-
-/**/
-void
-setjobpwd(void)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if (jobtab[i].stat && !jobtab[i].pwd)
- jobtab[i].pwd = ztrdup(pwd);
-}
-
-/* print pids for & */
-
-/**/
-void
-spawnjob(void)
-{
- Process pn;
-
- DPUTS(thisjob == -1, "No valid job in spawnjob.");
- /* if we are not in a subshell */
- if (!subsh) {
- if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED)) {
- curjob = thisjob;
- setprevjob();
- } else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
- prevjob = thisjob;
- if (jobbing && jobtab[thisjob].procs) {
- FILE *fout = shout ? shout : stdout;
- fprintf(fout, "[%d]", thisjob);
- for (pn = jobtab[thisjob].procs; pn; pn = pn->next)
- fprintf(fout, " %ld", (long) pn->pid);
- fprintf(fout, "\n");
- fflush(fout);
- }
- }
- if (!hasprocs(thisjob))
- deletejob(jobtab + thisjob, 0);
- else {
- jobtab[thisjob].stat |= STAT_LOCKED;
- pipecleanfilelist(jobtab[thisjob].filelist, 0);
- }
- thisjob = -1;
-}
-
-/**/
-void
-shelltime(void)
-{
- struct timezone dummy_tz;
- struct timeval dtimeval, now;
- child_times_t ti;
-#ifndef HAVE_GETRUSAGE
- struct tms buf;
-#endif
-
- gettimeofday(&now, &dummy_tz);
-
-#ifdef HAVE_GETRUSAGE
- getrusage(RUSAGE_SELF, &ti);
-#else
- times(&buf);
-
- ti.ut = buf.tms_utime;
- ti.st = buf.tms_stime;
-#endif
- printtime(dtime(&dtimeval, &shtimer, &now), &ti, "shell");
-
-#ifdef HAVE_GETRUSAGE
- getrusage(RUSAGE_CHILDREN, &ti);
-#else
- ti.ut = buf.tms_cutime;
- ti.st = buf.tms_cstime;
-#endif
- printtime(&dtimeval, &ti, "children");
-
-}
-
-/* see if jobs need printing */
-
-/**/
-void
-scanjobs(void)
-{
- int i;
-
- for (i = 1; i <= maxjob; i++)
- if (jobtab[i].stat & STAT_CHANGED)
- printjob(jobtab + i, !!isset(LONGLISTJOBS), 1);
-}
-
-/**** job control builtins ****/
-
-/* This simple function indicates whether or not s may represent *
- * a number. It returns true iff s consists purely of digits and *
- * minuses. Note that minus may appear more than once, and the empty *
- * string will produce a `true' response. */
-
-/**/
-static int
-isanum(char *s)
-{
- while (*s == '-' || idigit(*s))
- s++;
- return *s == '\0';
-}
-
-/* Make sure we have a suitable current and previous job set. */
-
-/**/
-static void
-setcurjob(void)
-{
- if (curjob == thisjob ||
- (curjob != -1 && !(jobtab[curjob].stat & STAT_INUSE))) {
- curjob = prevjob;
- setprevjob();
- if (curjob == thisjob ||
- (curjob != -1 && !((jobtab[curjob].stat & STAT_INUSE) &&
- curjob != thisjob))) {
- curjob = prevjob;
- setprevjob();
- }
- }
-}
-
-/* Convert a job specifier ("%%", "%1", "%foo", "%?bar?", etc.) *
- * to a job number. */
-
-/**/
-mod_export int
-getjob(const char *s, const char *prog)
-{
- int jobnum, returnval, mymaxjob;
- Job myjobtab;
-
- if (oldjobtab) {
- myjobtab = oldjobtab;
- mymaxjob = oldmaxjob;
- } else {
- myjobtab= jobtab;
- mymaxjob = maxjob;
- }
-
- /* if there is no %, treat as a name */
- if (*s != '%')
- goto jump;
- s++;
- /* "%%", "%+" and "%" all represent the current job */
- if (*s == '%' || *s == '+' || !*s) {
- if (curjob == -1) {
- if (prog)
- zwarnnam(prog, "no current job");
- returnval = -1;
- goto done;
- }
- returnval = curjob;
- goto done;
- }
- /* "%-" represents the previous job */
- if (*s == '-') {
- if (prevjob == -1) {
- if (prog)
- zwarnnam(prog, "no previous job");
- returnval = -1;
- goto done;
- }
- returnval = prevjob;
- goto done;
- }
- /* a digit here means we have a job number */
- if (idigit(*s)) {
- jobnum = atoi(s);
- if (jobnum && jobnum <= mymaxjob && myjobtab[jobnum].stat &&
- !(myjobtab[jobnum].stat & STAT_SUBJOB) &&
- /*
- * If running jobs in a subshell, we are allowed to
- * refer to the "current" job (it's not really the
- * current job in the subshell). It's possible we
- * should reset thisjob to -1 on entering the subshell.
- */
- (myjobtab == oldjobtab || jobnum != thisjob)) {
- returnval = jobnum;
- goto done;
- }
- if (prog)
- zwarnnam(prog, "%%%s: no such job", s);
- returnval = -1;
- goto done;
- }
- /* "%?" introduces a search string */
- if (*s == '?') {
- struct process *pn;
-
- for (jobnum = mymaxjob; jobnum >= 0; jobnum--)
- if (myjobtab[jobnum].stat &&
- !(myjobtab[jobnum].stat & STAT_SUBJOB) &&
- jobnum != thisjob)
- for (pn = myjobtab[jobnum].procs; pn; pn = pn->next)
- if (strstr(pn->text, s + 1)) {
- returnval = jobnum;
- goto done;
- }
- if (prog)
- zwarnnam(prog, "job not found: %s", s);
- returnval = -1;
- goto done;
- }
- jump:
- /* anything else is a job name, specified as a string that begins the
- job's command */
- if ((jobnum = findjobnam(s)) != -1) {
- returnval = jobnum;
- goto done;
- }
- /* if we get here, it is because none of the above succeeded and went
- to done */
- zwarnnam(prog, "job not found: %s", s);
- returnval = -1;
- done:
- return returnval;
-}
-
-#ifndef HAVE_SETPROCTITLE
-/* For jobs -Z (which modifies the shell's name as seen in ps listings). *
- * hackzero is the start of the safely writable space, and hackspace is *
- * its length, excluding a final NUL terminator that will always be left. */
-
-static char *hackzero;
-static int hackspace;
-#endif
-
-
-/* Initialise job handling. */
-
-/**/
-void
-init_jobs(char **argv, char **envp)
-{
-#ifndef HAVE_SETPROCTITLE
- char *p, *q;
-#endif
- size_t init_bytes = MAXJOBS_ALLOC*sizeof(struct job);
-
- /*
- * Initialise the job table. If this fails, we're in trouble.
- */
- jobtab = (struct job *)zalloc(init_bytes);
- if (!jobtab) {
- zerr("failed to allocate job table, aborting.");
- exit(1);
- }
- jobtabsize = MAXJOBS_ALLOC;
- memset(jobtab, 0, init_bytes);
-
-#ifndef HAVE_SETPROCTITLE
- /*
- * Initialise the jobs -Z system. The technique is borrowed from
- * perl: check through the argument and environment space, to see
- * how many of the strings are in contiguous space. This determines
- * the value of hackspace.
- */
- hackzero = *argv;
- p = strchr(hackzero, 0);
- while(*++argv) {
- q = *argv;
- if(q != p+1)
- goto done;
- p = strchr(q, 0);
- }
-#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
- for(; *envp; envp++) {
- q = *envp;
- if(q != p+1)
- goto done;
- p = strchr(q, 0);
- }
-#endif
- done:
- hackspace = p - hackzero;
-#endif
-}
-
-
-/*
- * We have run out of space in the job table.
- * Expand it by an additional MAXJOBS_ALLOC slots.
- */
-
-/*
- * An arbitrary limit on the absolute maximum size of the job table.
- * This prevents us taking over the entire universe.
- * Ought to be a multiple of MAXJOBS_ALLOC, but doesn't need to be.
- */
-#define MAX_MAXJOBS 1000
-
-/**/
-int
-expandjobtab(void)
-{
- int newsize = jobtabsize + MAXJOBS_ALLOC;
- struct job *newjobtab;
-
- if (newsize > MAX_MAXJOBS)
- return 0;
-
- newjobtab = (struct job *)zrealloc(jobtab, newsize * sizeof(struct job));
- if (!newjobtab)
- return 0;
-
- /*
- * Clear the new section of the table; this is necessary for
- * the jobs to appear unused.
- */
- memset(newjobtab + jobtabsize, 0, MAXJOBS_ALLOC * sizeof(struct job));
-
- jobtab = newjobtab;
- jobtabsize = newsize;
-
- return 1;
-}
-
-
-/*
- * See if we can reduce the job table. We can if we go over
- * a MAXJOBS_ALLOC boundary. However, we leave a boundary,
- * currently 20 jobs, so that we have a place for immediate
- * expansion and don't play ping pong with the job table size.
- */
-
-/**/
-void
-maybeshrinkjobtab(void)
-{
- int jobbound;
-
- queue_signals();
- jobbound = maxjob + MAXJOBS_ALLOC - (maxjob % MAXJOBS_ALLOC);
- if (jobbound < jobtabsize && jobbound > maxjob + 20) {
- struct job *newjobtab;
-
- /* Hope this can't fail, but anyway... */
- newjobtab = (struct job *)zrealloc(jobtab,
- jobbound*sizeof(struct job));
-
- if (newjobtab) {
- jobtab = newjobtab;
- jobtabsize = jobbound;
- }
- }
- unqueue_signals();
-}
-
-/*
- * Definitions for the background process stuff recorded below.
- * This would be more efficient as a hash, but
- * - that's quite heavyweight for something not needed very often
- * - we need some kind of ordering as POSIX allows us to limit
- * the size of the list to the value of _SC_CHILD_MAX and clearly
- * we want to clear the oldest first
- * - cases with a long list of background jobs where the user doesn't
- * wait for a large number, and then does wait for one (the only
- * inefficient case) are rare
- * - in the context of waiting for an external process, looping
- * over a list isn't so very inefficient.
- * Enough excuses already.
- */
-
-/* Data in the link list, a key (process ID) / value (exit status) pair. */
-struct bgstatus {
- pid_t pid;
- int status;
-};
-typedef struct bgstatus *Bgstatus;
-/* The list of those entries */
-static LinkList bgstatus_list;
-/* Count of entries. Reaches value of _SC_CHILD_MAX and stops. */
-static long bgstatus_count;
-
-/*
- * Remove and free a bgstatus entry.
- */
-static void rembgstatus(LinkNode node)
-{
- zfree(remnode(bgstatus_list, node), sizeof(struct bgstatus));
- bgstatus_count--;
-}
-
-/*
- * Record the status of a background process that exited so we
- * can execute the builtin wait for it.
- *
- * We can't execute the wait builtin for something that exited in the
- * foreground as it's not visible to the user, so don't bother recording.
- */
-
-/**/
-void
-addbgstatus(pid_t pid, int status)
-{
- static long child_max;
- Bgstatus bgstatus_entry;
-
- if (!child_max) {
-#ifdef _SC_CHILD_MAX
- child_max = sysconf(_SC_CHILD_MAX);
- if (!child_max) /* paranoia */
-#endif
- {
- /* Be inventive */
- child_max = 1024L;
- }
- }
-
- if (!bgstatus_list) {
- bgstatus_list = znewlinklist();
- /*
- * We're not always robust about memory failures, but
- * this is pretty deep in the shell basics to be failing owing
- * to memory, and a failure to wait is reported loudly, so test
- * and fail silently here.
- */
- if (!bgstatus_list)
- return;
- }
- if (bgstatus_count == child_max) {
- /* Overflow. List is in order, remove first */
- rembgstatus(firstnode(bgstatus_list));
- }
- bgstatus_entry = (Bgstatus)zalloc(sizeof(*bgstatus_entry));
- if (!bgstatus_entry) {
- /* See note above */
- return;
- }
- bgstatus_entry->pid = pid;
- bgstatus_entry->status = status;
- if (!zaddlinknode(bgstatus_list, bgstatus_entry)) {
- zfree(bgstatus_entry, sizeof(*bgstatus_entry));
- return;
- }
- bgstatus_count++;
-}
-
-/*
- * See if pid has a recorded exit status.
- * Note we make no guarantee that the PIDs haven't wrapped, so this
- * may not be the right process.
- *
- * This is only used by wait, which must only work on each
- * pid once, so we need to remove the entry if we find it.
- */
-
-static int getbgstatus(pid_t pid)
-{
- LinkNode node;
- Bgstatus bgstatus_entry;
-
- if (!bgstatus_list)
- return -1;
- for (node = firstnode(bgstatus_list); node; incnode(node)) {
- bgstatus_entry = (Bgstatus)getdata(node);
- if (bgstatus_entry->pid == pid) {
- int status = bgstatus_entry->status;
- rembgstatus(node);
- return status;
- }
- }
- return -1;
-}
-
-/* bg, disown, fg, jobs, wait: most of the job control commands are *
- * here. They all take the same type of argument. Exception: wait can *
- * take a pid or a job specifier, whereas the others only work on jobs. */
-
-/**/
-int
-bin_fg(char *name, char **argv, Options ops, int func)
-{
- int job, lng, firstjob = -1, retval = 0, ofunc = func;
-
- if (OPT_ISSET(ops,'Z')) {
- int len;
-
- if(isset(RESTRICTED)) {
- zwarnnam(name, "-Z is restricted");
- return 1;
- }
- if(!argv[0] || argv[1]) {
- zwarnnam(name, "-Z requires one argument");
- return 1;
- }
- queue_signals();
- unmetafy(*argv, &len);
-#ifdef HAVE_SETPROCTITLE
- setproctitle("%s", *argv);
-#else
- if(len > hackspace)
- len = hackspace;
- memcpy(hackzero, *argv, len);
- memset(hackzero + len, 0, hackspace - len);
-#endif
- unqueue_signals();
- return 0;
- }
-
- if (func == BIN_JOBS) {
- lng = (OPT_ISSET(ops,'l')) ? 1 : (OPT_ISSET(ops,'p')) ? 2 : 0;
- if (OPT_ISSET(ops,'d'))
- lng |= 4;
- } else {
- lng = !!isset(LONGLISTJOBS);
- }
-
- if ((func == BIN_FG || func == BIN_BG) && !jobbing) {
- /* oops... maybe bg and fg should have been disabled? */
- zwarnnam(name, "no job control in this shell.");
- return 1;
- }
-
- queue_signals();
- /*
- * In case any processes changed state recently, wait for them.
- * This updates stopped processes (but we should have been
- * signalled about those, up to inevitable races), and also
- * continued processes if that feature is available.
- */
- wait_for_processes();
-
- /* If necessary, update job table. */
- if (unset(NOTIFY))
- scanjobs();
-
- if (func != BIN_JOBS || isset(MONITOR) || !oldmaxjob)
- setcurjob();
-
- if (func == BIN_JOBS)
- /* If you immediately type "exit" after "jobs", this *
- * will prevent zexit from complaining about stopped jobs */
- stopmsg = 2;
- if (!*argv) {
- /* This block handles all of the default cases (no arguments). bg,
- fg and disown act on the current job, and jobs and wait act on all the
- jobs. */
- if (func == BIN_FG || func == BIN_BG || func == BIN_DISOWN) {
- /* W.r.t. the above comment, we'd better have a current job at this
- point or else. */
- if (curjob == -1 || (jobtab[curjob].stat & STAT_NOPRINT)) {
- zwarnnam(name, "no current job");
- unqueue_signals();
- return 1;
- }
- firstjob = curjob;
- } else if (func == BIN_JOBS) {
- /* List jobs. */
- struct job *jobptr;
- int curmaxjob, ignorejob;
- if (unset(MONITOR) && oldmaxjob) {
- jobptr = oldjobtab;
- curmaxjob = oldmaxjob ? oldmaxjob - 1 : 0;
- ignorejob = 0;
- } else {
- jobptr = jobtab;
- curmaxjob = maxjob;
- ignorejob = thisjob;
- }
- for (job = 0; job <= curmaxjob; job++, jobptr++)
- if (job != ignorejob && jobptr->stat) {
- if ((!OPT_ISSET(ops,'r') && !OPT_ISSET(ops,'s')) ||
- (OPT_ISSET(ops,'r') && OPT_ISSET(ops,'s')) ||
- (OPT_ISSET(ops,'r') &&
- !(jobptr->stat & STAT_STOPPED)) ||
- (OPT_ISSET(ops,'s') && jobptr->stat & STAT_STOPPED))
- printjob(jobptr, lng, 2);
- }
- unqueue_signals();
- return 0;
- } else { /* Must be BIN_WAIT, so wait for all jobs */
- for (job = 0; job <= maxjob; job++)
- if (job != thisjob && jobtab[job].stat &&
- !(jobtab[job].stat & STAT_NOPRINT))
- retval = zwaitjob(job, 1);
- unqueue_signals();
- return retval;
- }
- }
-
- /* Defaults have been handled. We now have an argument or two, or three...
- In the default case for bg, fg and disown, the argument will be provided by
- the above routine. We now loop over the arguments. */
- for (; (firstjob != -1) || *argv; (void)(*argv && argv++)) {
- int stopped, ocj = thisjob, jstat;
-
- func = ofunc;
-
- if (func == BIN_WAIT && isanum(*argv)) {
- /* wait can take a pid; the others can't. */
- pid_t pid = (long)atoi(*argv);
- Job j;
- Process p;
-
- if (findproc(pid, &j, &p, 0)) {
- if (j->stat & STAT_STOPPED) {
- retval = (killjb(j, SIGCONT) != 0);
- if (retval == 0)
- makerunning(j);
- }
- if (retval == 0) {
- /*
- * returns 0 for normal exit, else signal+128
- * in which case we should return that status.
- */
- retval = waitforpid(pid, 1);
- }
- if (retval == 0) {
- if ((retval = getbgstatus(pid)) < 0) {
- retval = lastval2;
- }
- }
- } else if ((retval = getbgstatus(pid)) < 0) {
- zwarnnam(name, "pid %d is not a child of this shell", pid);
- /* presumably lastval2 doesn't tell us a heck of a lot? */
- retval = 1;
- }
- thisjob = ocj;
- continue;
- }
- if (func != BIN_JOBS && oldjobtab != NULL) {
- zwarnnam(name, "can't manipulate jobs in subshell");
- unqueue_signals();
- return 1;
- }
- /* The only type of argument allowed now is a job spec. Check it. */
- job = (*argv) ? getjob(*argv, name) : firstjob;
- firstjob = -1;
- if (job == -1) {
- retval = 1;
- break;
- }
- jstat = oldjobtab ? oldjobtab[job].stat : jobtab[job].stat;
- if (!(jstat & STAT_INUSE) ||
- (jstat & STAT_NOPRINT)) {
- zwarnnam(name, "%s: no such job", *argv);
- unqueue_signals();
- return 1;
- }
- /* If AUTO_CONTINUE is set (automatically make stopped jobs running
- * on disown), we actually do a bg and then delete the job table entry. */
-
- if (isset(AUTOCONTINUE) && func == BIN_DISOWN &&
- jstat & STAT_STOPPED)
- func = BIN_BG;
-
- /* We have a job number. Now decide what to do with it. */
- switch (func) {
- case BIN_FG:
- case BIN_BG:
- case BIN_WAIT:
- if (func == BIN_BG) {
- jobtab[job].stat |= STAT_NOSTTY;
- jobtab[job].stat &= ~STAT_CURSH;
- }
- if ((stopped = (jobtab[job].stat & STAT_STOPPED))) {
- makerunning(jobtab + job);
- if (func == BIN_BG) {
- /* Set $! to indicate this was backgrounded */
- Process pn = jobtab[job].procs;
- for (;;) {
- Process next = pn->next;
- if (!next) {
- lastpid = (zlong) pn->pid;
- break;
- }
- pn = next;
- }
- }
- } else if (func == BIN_BG) {
- /* Silly to bg a job already running. */
- zwarnnam(name, "job already in background");
- thisjob = ocj;
- unqueue_signals();
- return 1;
- }
- /* It's time to shuffle the jobs around! Reset the current job,
- and pick a sensible secondary job. */
- if (curjob == job) {
- curjob = prevjob;
- prevjob = (func == BIN_BG) ? -1 : job;
- }
- if (prevjob == job || prevjob == -1)
- setprevjob();
- if (curjob == -1) {
- curjob = prevjob;
- setprevjob();
- }
- if (func != BIN_WAIT)
- /* for bg and fg -- show the job we are operating on */
- printjob(jobtab + job, (stopped) ? -1 : lng, 3);
- if (func != BIN_BG) { /* fg or wait */
- if (jobtab[job].pwd && strcmp(jobtab[job].pwd, pwd)) {
- FILE *fout = (func == BIN_JOBS || !shout) ? stdout : shout;
- fprintf(fout, "(pwd : ");
- fprintdir(jobtab[job].pwd, fout);
- fprintf(fout, ")\n");
- fflush(fout);
- }
- if (func != BIN_WAIT) { /* fg */
- thisjob = job;
- if ((jobtab[job].stat & STAT_SUPERJOB) &&
- ((!jobtab[job].procs->next ||
- (jobtab[job].stat & STAT_SUBLEADER) ||
- killpg(jobtab[job].gleader, 0) == -1)) &&
- jobtab[jobtab[job].other].gleader)
- attachtty(jobtab[jobtab[job].other].gleader);
- else
- attachtty(jobtab[job].gleader);
- }
- }
- if (stopped) {
- if (func != BIN_BG && jobtab[job].ty)
- settyinfo(jobtab[job].ty);
- killjb(jobtab + job, SIGCONT);
- }
- if (func == BIN_WAIT)
- {
- retval = zwaitjob(job, 1);
- if (!retval)
- retval = lastval2;
- }
- else if (func != BIN_BG) {
- /*
- * HERE: there used not to be an "else" above. How
- * could it be right to wait for the foreground job
- * when we've just been told to wait for another
- * job (and done it)?
- */
- waitjobs();
- retval = lastval2;
- } else if (ofunc == BIN_DISOWN)
- deletejob(jobtab + job, 1);
- break;
- case BIN_JOBS:
- printjob(job + (oldjobtab ? oldjobtab : jobtab), lng, 2);
- break;
- case BIN_DISOWN:
- if (jobtab[job].stat & STAT_SUPERJOB) {
- jobtab[job].stat |= STAT_DISOWN;
- continue;
- }
- if (jobtab[job].stat & STAT_STOPPED) {
- char buf[20], *pids = "";
-
- if (jobtab[job].stat & STAT_SUPERJOB) {
- Process pn;
-
- for (pn = jobtab[jobtab[job].other].procs; pn; pn = pn->next) {
- sprintf(buf, " -%d", pn->pid);
- pids = dyncat(pids, buf);
- }
- for (pn = jobtab[job].procs; pn->next; pn = pn->next) {
- sprintf(buf, " %d", pn->pid);
- pids = dyncat(pids, buf);
- }
- if (!jobtab[jobtab[job].other].procs && pn) {
- sprintf(buf, " %d", pn->pid);
- pids = dyncat(pids, buf);
- }
- } else {
- sprintf(buf, " -%d", jobtab[job].gleader);
- pids = buf;
- }
- zwarnnam(name,
-#ifdef USE_SUSPENDED
- "warning: job is suspended, use `kill -CONT%s' to resume",
-#else
- "warning: job is stopped, use `kill -CONT%s' to resume",
-#endif
- pids);
- }
- deletejob(jobtab + job, 1);
- break;
- }
- thisjob = ocj;
- }
- unqueue_signals();
- return retval;
-}
-
-static const struct {
- const char *name;
- int num;
-} alt_sigs[] = {
-#if defined(SIGCHLD) && defined(SIGCLD)
-#if SIGCHLD == SIGCLD
- { "CLD", SIGCLD },
-#endif
-#endif
-#if defined(SIGPOLL) && defined(SIGIO)
-#if SIGPOLL == SIGIO
- { "IO", SIGIO },
-#endif
-#endif
-#if !defined(SIGERR)
- /*
- * If SIGERR is not defined by the operating system, use it
- * as an alias for SIGZERR.
- */
- { "ERR", SIGZERR },
-#endif
- { NULL, 0 }
-};
-
-/* kill: send a signal to a process. The process(es) may be specified *
- * by job specifier (see above) or pid. A signal, defaulting to *
- * SIGTERM, may be specified by name or number, preceded by a dash. */
-
-/**/
-int
-bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
-{
- int sig = SIGTERM;
- int returnval = 0;
-
- /* check for, and interpret, a signal specifier */
- if (*argv && **argv == '-') {
- if (idigit((*argv)[1])) {
- char *endp;
- /* signal specified by number */
- sig = zstrtol(*argv + 1, &endp, 10);
- if (*endp) {
- zwarnnam(nam, "invalid signal number: %s", *argv);
- return 1;
- }
- } else if ((*argv)[1] != '-' || (*argv)[2]) {
- char *signame;
-
- /* with argument "-l" display the list of signal names */
- if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
- if (argv[1]) {
- while (*++argv) {
- sig = zstrtol(*argv, &signame, 10);
- if (signame == *argv) {
- if (!strncmp(signame, "SIG", 3))
- signame += 3;
- for (sig = 1; sig <= SIGCOUNT; sig++)
- if (!strcasecmp(sigs[sig], signame))
- break;
- if (sig > SIGCOUNT) {
- int i;
-
- for (i = 0; alt_sigs[i].name; i++)
- if (!strcasecmp(alt_sigs[i].name, signame))
- {
- sig = alt_sigs[i].num;
- break;
- }
- }
- if (sig > SIGCOUNT) {
- zwarnnam(nam, "unknown signal: SIG%s",
- signame);
- returnval++;
- } else
- printf("%d\n", sig);
- } else {
- if (*signame) {
- zwarnnam(nam, "unknown signal: SIG%s",
- signame);
- returnval++;
- } else {
- if (WIFSIGNALED(sig))
- sig = WTERMSIG(sig);
- else if (WIFSTOPPED(sig))
- sig = WSTOPSIG(sig);
- if (1 <= sig && sig <= SIGCOUNT)
- printf("%s\n", sigs[sig]);
- else
- printf("%d\n", sig);
- }
- }
- }
- return returnval;
- }
- printf("%s", sigs[1]);
- for (sig = 2; sig <= SIGCOUNT; sig++)
- printf(" %s", sigs[sig]);
- putchar('\n');
- return 0;
- }
-
- if ((*argv)[1] == 'n' && (*argv)[2] == '\0') {
- char *endp;
-
- if (!*++argv) {
- zwarnnam(nam, "-n: argument expected");
- return 1;
- }
- sig = zstrtol(*argv, &endp, 10);
- if (*endp) {
- zwarnnam(nam, "invalid signal number: %s", *argv);
- return 1;
- }
- } else {
- if (!((*argv)[1] == 's' && (*argv)[2] == '\0'))
- signame = *argv + 1;
- else if (!(*++argv)) {
- zwarnnam(nam, "-s: argument expected");
- return 1;
- } else
- signame = *argv;
- if (!*signame) {
- zwarnnam(nam, "-: signal name expected");
- return 1;
- }
- signame = casemodify(signame, CASMOD_UPPER);
- if (!strncmp(signame, "SIG", 3))
- signame+=3;
-
- /* check for signal matching specified name */
- for (sig = 1; sig <= SIGCOUNT; sig++)
- if (!strcmp(*(sigs + sig), signame))
- break;
- if (*signame == '0' && !signame[1])
- sig = 0;
- if (sig > SIGCOUNT) {
- int i;
-
- for (i = 0; alt_sigs[i].name; i++)
- if (!strcmp(alt_sigs[i].name, signame))
- {
- sig = alt_sigs[i].num;
- break;
- }
- }
- if (sig > SIGCOUNT) {
- zwarnnam(nam, "unknown signal: SIG%s", signame);
- zwarnnam(nam, "type kill -l for a list of signals");
- return 1;
- }
- }
- }
- argv++;
- }
-
- /* Discard the standard "-" and "--" option breaks */
- if (*argv && (*argv)[0] == '-' && (!(*argv)[1] || (*argv)[1] == '-'))
- argv++;
-
- if (!*argv) {
- zwarnnam(nam, "not enough arguments");
- return 1;
- }
-
- queue_signals();
- setcurjob();
-
- /* Remaining arguments specify processes. Loop over them, and send the
- signal (number sig) to each process. */
- for (; *argv; argv++) {
- if (**argv == '%') {
- /* job specifier introduced by '%' */
- int p;
-
- if ((p = getjob(*argv, nam)) == -1) {
- returnval++;
- continue;
- }
- if (killjb(jobtab + p, sig) == -1) {
- zwarnnam("kill", "kill %s failed: %e", *argv, errno);
- returnval++;
- continue;
- }
- /* automatically update the job table if sending a SIGCONT to a
- job, and send the job a SIGCONT if sending it a non-stopping
- signal. */
- if (jobtab[p].stat & STAT_STOPPED) {
-#ifndef WIFCONTINUED
- /* With WIFCONTINUED we find this out properly */
- if (sig == SIGCONT)
- makerunning(jobtab + p);
-#endif
- if (sig != SIGKILL && sig != SIGCONT && sig != SIGTSTP
- && sig != SIGTTOU && sig != SIGTTIN && sig != SIGSTOP)
- killjb(jobtab + p, SIGCONT);
- }
- } else if (!isanum(*argv)) {
- zwarnnam("kill", "illegal pid: %s", *argv);
- returnval++;
- } else {
- int pid = atoi(*argv);
- if (kill(pid, sig) == -1) {
- zwarnnam("kill", "kill %s failed: %e", *argv, errno);
- returnval++;
- }
-#ifndef WIFCONTINUED
- else if (sig == SIGCONT) {
- Job jn;
- Process pn;
- /* With WIFCONTINUED we find this out properly */
- if (findproc(pid, &jn, &pn, 0)) {
- if (WIFSTOPPED(pn->status))
- pn->status = SP_RUNNING;
- }
- }
-#endif
- }
- }
- unqueue_signals();
-
- return returnval < 126 ? returnval : 1;
-}
-/* Get a signal number from a string */
-
-/**/
-mod_export int
-getsignum(const char *s)
-{
- int x, i;
-
- /* check for a signal specified by number */
- x = atoi(s);
- if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
- return x;
-
- /* search for signal by name */
- if (!strncmp(s, "SIG", 3))
- s += 3;
-
- for (i = 0; i < VSIGCOUNT; i++)
- if (!strcmp(s, sigs[i]))
- return i;
-
- for (i = 0; alt_sigs[i].name; i++)
- {
- if (!strcmp(s, alt_sigs[i].name))
- return alt_sigs[i].num;
- }
-
- /* no matching signal */
- return -1;
-}
-
-/* Get the name for a signal. */
-
-/**/
-mod_export const char *
-getsigname(int sig)
-{
- if (sigtrapped[sig] & ZSIG_ALIAS)
- {
- int i;
- for (i = 0; alt_sigs[i].name; i++)
- if (sig == alt_sigs[i].num)
- return alt_sigs[i].name;
- }
- else
- return sigs[sig];
-
- /* shouldn't reach here */
-#ifdef DEBUG
- dputs("Bad alias flag for signal");
-#endif
- return "";
-}
-
-
-/* Get the function node for a trap, taking care about alternative names */
-/**/
-HashNode
-gettrapnode(int sig, int ignoredisable)
-{
- char fname[20];
- HashNode hn;
- HashNode (*getptr)(HashTable ht, const char *name);
- int i;
- if (ignoredisable)
- getptr = shfunctab->getnode2;
- else
- getptr = shfunctab->getnode;
-
- sprintf(fname, "TRAP%s", sigs[sig]);
- if ((hn = getptr(shfunctab, fname)))
- return hn;
-
- for (i = 0; alt_sigs[i].name; i++) {
- if (alt_sigs[i].num == sig) {
- sprintf(fname, "TRAP%s", alt_sigs[i].name);
- if ((hn = getptr(shfunctab, fname)))
- return hn;
- }
- }
-
- return NULL;
-}
-
-/* Remove a TRAP function under any name for the signal */
-
-/**/
-void
-removetrapnode(int sig)
-{
- HashNode hn = gettrapnode(sig, 1);
- if (hn) {
- shfunctab->removenode(shfunctab, hn->nam);
- shfunctab->freenode(hn);
- }
-}
-
-/* Suspend this shell */
-
-/**/
-int
-bin_suspend(char *name, UNUSED(char **argv), Options ops, UNUSED(int func))
-{
- /* won't suspend a login shell, unless forced */
- if (islogin && !OPT_ISSET(ops,'f')) {
- zwarnnam(name, "can't suspend login shell");
- return 1;
- }
- if (jobbing) {
- /* stop ignoring signals */
- signal_default(SIGTTIN);
- signal_default(SIGTSTP);
- signal_default(SIGTTOU);
-
- /* Move ourselves back to the process group we came from */
- release_pgrp();
- }
-
- /* suspend ourselves with a SIGTSTP */
- killpg(origpgrp, SIGTSTP);
-
- if (jobbing) {
- acquire_pgrp();
- /* restore signal handling */
- signal_ignore(SIGTTOU);
- signal_ignore(SIGTSTP);
- signal_ignore(SIGTTIN);
- }
- return 0;
-}
-
-/* find a job named s */
-
-/**/
-int
-findjobnam(const char *s)
-{
- int jobnum;
-
- for (jobnum = maxjob; jobnum >= 0; jobnum--)
- if (!(jobtab[jobnum].stat & (STAT_SUBJOB | STAT_NOPRINT)) &&
- jobtab[jobnum].stat && jobtab[jobnum].procs && jobnum != thisjob &&
- jobtab[jobnum].procs->text[0] && strpfx(s, jobtab[jobnum].procs->text))
- return jobnum;
- return -1;
-}
-
-
-/* make sure we are a process group leader by creating a new process
- group if necessary */
-
-/**/
-void
-acquire_pgrp(void)
-{
- long ttpgrp;
- sigset_t blockset, oldset;
-
- if ((mypgrp = GETPGRP()) >= 0) {
- long lastpgrp = mypgrp;
- sigemptyset(&blockset);
- sigaddset(&blockset, SIGTTIN);
- sigaddset(&blockset, SIGTTOU);
- sigaddset(&blockset, SIGTSTP);
- oldset = signal_block(blockset);
- while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) {
- mypgrp = GETPGRP();
- if (mypgrp == mypid) {
- if (!interact)
- break; /* attachtty() will be a no-op, give up */
- signal_setmask(oldset);
- attachtty(mypgrp); /* Might generate SIGT* */
- signal_block(blockset);
- }
- if (mypgrp == gettygrp())
- break;
- signal_setmask(oldset);
- if (read(0, NULL, 0) != 0) {} /* Might generate SIGT* */
- signal_block(blockset);
- mypgrp = GETPGRP();
- if (mypgrp == lastpgrp && !interact)
- break; /* Unlikely that pgrp will ever change */
- lastpgrp = mypgrp;
- }
- if (mypgrp != mypid) {
- if (setpgrp(0, 0) == 0) {
- mypgrp = mypid;
- attachtty(mypgrp);
- } else
- opts[MONITOR] = 0;
- }
- signal_setmask(oldset);
- } else
- opts[MONITOR] = 0;
-}
-
-/* revert back to the process group we came from (before acquire_pgrp) */
-
-/**/
-void
-release_pgrp(void)
-{
- if (origpgrp != mypgrp) {
- /* in linux pid namespaces, origpgrp may never have been set */
- if (origpgrp) {
- attachtty(origpgrp);
- setpgrp(0, origpgrp);
- }
- mypgrp = origpgrp;
- }
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/lex.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/lex.c
deleted file mode 100644
index 44ad8804..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/lex.c
+++ /dev/null
@@ -1,2203 +0,0 @@
-/*
- * lex.c - lexical analysis
- *
- * 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 "lex.pro"
-
-#define LEX_HEAP_SIZE (32)
-
-/* tokens */
-
-/**/
-mod_export char ztokens[] = "#$^*(())$=|{}[]`<>>?~`,-!'\"\\\\";
-
-/* parts of the current token */
-
-/**/
-char *zshlextext;
-/**/
-mod_export char *tokstr;
-/**/
-mod_export enum lextok tok;
-/**/
-mod_export int tokfd;
-
-/*
- * Line number at which the first character of a token was found.
- * We always set this in gettok(), which is always called from
- * zshlex() unless we have reached an error. So it is always
- * valid when parsing. It is not useful during execution
- * of the parsed structure.
- */
-
-/**/
-zlong toklineno;
-
-/* lexical analyzer error flag */
-
-/**/
-mod_export int lexstop;
-
-/* if != 0, this is the first line of the command */
-
-/**/
-mod_export int isfirstln;
-
-/* if != 0, this is the first char of the command (not including white space) */
-
-/**/
-int isfirstch;
-
-/* flag that an alias should be expanded after expansion ending in space */
-
-/**/
-int inalmore;
-
-/*
- * Don't do spelling correction.
- * Bit 1 is only valid for the current word. It's
- * set when we detect a lookahead that stops the word from
- * needing correction.
- */
-
-/**/
-int nocorrect;
-
-/*
- * TBD: the following exported variables are part of the non-interface
- * with ZLE for completion. They are poorly named and the whole
- * scheme is incredibly brittle. One piece of robustness is applied:
- * the variables are only set if LEXFLAGS_ZLE is set. Improvements
- * should therefore concentrate on areas with this flag set.
- *
- * Cursor position and line length in zle when the line is
- * metafied for access from the main shell.
- */
-
-/**/
-mod_export int zlemetacs, zlemetall;
-
-/* inwhat says what exactly we are in *
- * (its value is one of the IN_* things). */
-
-/**/
-mod_export int inwhat;
-
-/* 1 if x added to complete in a blank between words */
-
-/**/
-mod_export int addedx;
-
-/* wb and we hold the beginning/end position of the word we are completing. */
-
-/**/
-mod_export int wb, we;
-
-/**/
-mod_export int wordbeg;
-
-/**/
-mod_export int parbegin;
-
-/**/
-mod_export int parend;
-
-
-/* 1 if aliases should not be expanded */
-
-/**/
-mod_export int noaliases;
-
-/*
- * If non-zero, we are parsing a line sent to use by the editor, or some
- * other string that's not part of standard command input (e.g. eval is
- * part of normal command input).
- *
- * Set of bits from LEXFLAGS_*.
- *
- * Note that although it is passed into the lexer as an input, the
- * lexer can set it to zero after finding the word it's searching for.
- * This only happens if the line being parsed actually does come from
- * ZLE, and hence the bit LEXFLAGS_ZLE is set.
- */
-
-/**/
-mod_export int lexflags;
-
-/* don't recognize comments */
-
-/**/
-mod_export int nocomments;
-
-/* add raw input characters while parsing command substitution */
-
-/**/
-int lex_add_raw;
-
-/* variables associated with the above */
-
-static char *tokstr_raw;
-static struct lexbufstate lexbuf_raw;
-
-/* text of punctuation tokens */
-
-/**/
-mod_export char *tokstrings[WHILE + 1] = {
- NULL, /* NULLTOK 0 */
- ";", /* SEPER */
- "\\n", /* NEWLIN */
- ";", /* SEMI */
- ";;", /* DSEMI */
- "&", /* AMPER 5 */
- "(", /* INPAR */
- ")", /* OUTPAR */
- "||", /* DBAR */
- "&&", /* DAMPER */
- ">", /* OUTANG 10 */
- ">|", /* OUTANGBANG */
- ">>", /* DOUTANG */
- ">>|", /* DOUTANGBANG */
- "<", /* INANG */
- "<>", /* INOUTANG 15 */
- "<<", /* DINANG */
- "<<-", /* DINANGDASH */
- "<&", /* INANGAMP */
- ">&", /* OUTANGAMP */
- "&>", /* AMPOUTANG 20 */
- "&>|", /* OUTANGAMPBANG */
- ">>&", /* DOUTANGAMP */
- ">>&|", /* DOUTANGAMPBANG */
- "<<<", /* TRINANG */
- "|", /* BAR 25 */
- "|&", /* BARAMP */
- "()", /* INOUTPAR */
- "((", /* DINPAR */
- "))", /* DOUTPAR */
- "&|", /* AMPERBANG 30 */
- ";&", /* SEMIAMP */
- ";|", /* SEMIBAR */
-};
-
-/* lexical state */
-
-static int dbparens;
-static struct lexbufstate lexbuf = { NULL, 256, 0 };
-
-/* save lexical context */
-
-/**/
-void
-lex_context_save(struct lex_stack *ls, int toplevel)
-{
- (void)toplevel;
-
- ls->dbparens = dbparens;
- ls->isfirstln = isfirstln;
- ls->isfirstch = isfirstch;
- ls->lexflags = lexflags;
-
- ls->tok = tok;
- ls->tokstr = tokstr;
- ls->zshlextext = zshlextext;
- ls->lexbuf = lexbuf;
- ls->lex_add_raw = lex_add_raw;
- ls->tokstr_raw = tokstr_raw;
- ls->lexbuf_raw = lexbuf_raw;
- ls->lexstop = lexstop;
- ls->toklineno = toklineno;
-
- tokstr = zshlextext = lexbuf.ptr = NULL;
- lexbuf.siz = 256;
- tokstr_raw = lexbuf_raw.ptr = NULL;
- lexbuf_raw.siz = lexbuf_raw.len = lex_add_raw = 0;
-}
-
-/* restore lexical context */
-
-/**/
-mod_export void
-lex_context_restore(const struct lex_stack *ls, int toplevel)
-{
- (void)toplevel;
-
- dbparens = ls->dbparens;
- isfirstln = ls->isfirstln;
- isfirstch = ls->isfirstch;
- lexflags = ls->lexflags;
- tok = ls->tok;
- tokstr = ls->tokstr;
- zshlextext = ls->zshlextext;
- lexbuf = ls->lexbuf;
- lex_add_raw = ls->lex_add_raw;
- tokstr_raw = ls->tokstr_raw;
- lexbuf_raw = ls->lexbuf_raw;
- lexstop = ls->lexstop;
- toklineno = ls->toklineno;
-}
-
-/**/
-void
-zshlex(void)
-{
- if (tok == LEXERR)
- return;
- do {
- if (inrepeat_)
- ++inrepeat_;
- if (inrepeat_ == 3 && isset(SHORTLOOPS))
- incmdpos = 1;
- tok = gettok();
- } while (tok != ENDINPUT && exalias());
- nocorrect &= 1;
- if (tok == NEWLIN || tok == ENDINPUT) {
- while (hdocs) {
- struct heredocs *next = hdocs->next;
- char *doc, *munged_term;
-
- hwbegin(0);
- cmdpush(hdocs->type == REDIR_HEREDOC ? CS_HEREDOC : CS_HEREDOCD);
- munged_term = dupstring(hdocs->str);
- STOPHIST
- doc = gethere(&munged_term, hdocs->type);
- ALLOWHIST
- cmdpop();
- hwend();
- if (!doc) {
- zerr("here document too large");
- while (hdocs) {
- next = hdocs->next;
- zfree(hdocs, sizeof(struct heredocs));
- hdocs = next;
- }
- tok = LEXERR;
- break;
- }
- setheredoc(hdocs->pc, REDIR_HERESTR, doc, hdocs->str,
- munged_term);
- zfree(hdocs, sizeof(struct heredocs));
- hdocs = next;
- }
- }
- if (tok != NEWLIN)
- isnewlin = 0;
- else
- isnewlin = (inbufct) ? -1 : 1;
- if (tok == SEMI || (tok == NEWLIN && !(lexflags & LEXFLAGS_NEWLINE)))
- tok = SEPER;
-}
-
-/**/
-mod_export void
-ctxtlex(void)
-{
- static int oldpos;
-
- zshlex();
- switch (tok) {
- case SEPER:
- case NEWLIN:
- case SEMI:
- case DSEMI:
- case SEMIAMP:
- case SEMIBAR:
- case AMPER:
- case AMPERBANG:
- case INPAR:
- case INBRACE:
- case DBAR:
- case DAMPER:
- case BAR:
- case BARAMP:
- case INOUTPAR:
- case DOLOOP:
- case THEN:
- case ELIF:
- case ELSE:
- case DOUTBRACK:
- incmdpos = 1;
- break;
- case STRING:
- case TYPESET:
- /* case ENVSTRING: */
- case ENVARRAY:
- case OUTPAR:
- case CASE:
- case DINBRACK:
- incmdpos = 0;
- break;
-
- default:
- /* nothing to do, keep compiler happy */
- break;
- }
- if (tok != DINPAR)
- infor = tok == FOR ? 2 : 0;
- if (IS_REDIROP(tok) || tok == FOR || tok == FOREACH || tok == SELECT) {
- inredir = 1;
- oldpos = incmdpos;
- incmdpos = 0;
- } else if (inredir) {
- incmdpos = oldpos;
- inredir = 0;
- }
-}
-
-#define LX1_BKSLASH 0
-#define LX1_COMMENT 1
-#define LX1_NEWLIN 2
-#define LX1_SEMI 3
-#define LX1_AMPER 5
-#define LX1_BAR 6
-#define LX1_INPAR 7
-#define LX1_OUTPAR 8
-#define LX1_INANG 13
-#define LX1_OUTANG 14
-#define LX1_OTHER 15
-
-#define LX2_BREAK 0
-#define LX2_OUTPAR 1
-#define LX2_BAR 2
-#define LX2_STRING 3
-#define LX2_INBRACK 4
-#define LX2_OUTBRACK 5
-#define LX2_TILDE 6
-#define LX2_INPAR 7
-#define LX2_INBRACE 8
-#define LX2_OUTBRACE 9
-#define LX2_OUTANG 10
-#define LX2_INANG 11
-#define LX2_EQUALS 12
-#define LX2_BKSLASH 13
-#define LX2_QUOTE 14
-#define LX2_DQUOTE 15
-#define LX2_BQUOTE 16
-#define LX2_COMMA 17
-#define LX2_DASH 18
-#define LX2_BANG 19
-#define LX2_OTHER 20
-#define LX2_META 21
-
-static unsigned char lexact1[256], lexact2[256], lextok2[256];
-
-/**/
-void
-initlextabs(void)
-{
- int t0;
- static char *lx1 = "\\q\n;!&|(){}[]<>";
- static char *lx2 = ";)|$[]~({}><=\\\'\"`,-!";
-
- for (t0 = 0; t0 != 256; t0++) {
- lexact1[t0] = LX1_OTHER;
- lexact2[t0] = LX2_OTHER;
- lextok2[t0] = t0;
- }
- for (t0 = 0; lx1[t0]; t0++)
- lexact1[(int)lx1[t0]] = t0;
- for (t0 = 0; lx2[t0]; t0++)
- lexact2[(int)lx2[t0]] = t0;
- lexact2['&'] = LX2_BREAK;
- lexact2[STOUC(Meta)] = LX2_META;
- lextok2['*'] = Star;
- lextok2['?'] = Quest;
- lextok2['{'] = Inbrace;
- lextok2['['] = Inbrack;
- lextok2['$'] = String;
- lextok2['~'] = Tilde;
- lextok2['#'] = Pound;
- lextok2['^'] = Hat;
-}
-
-/* initialize lexical state */
-
-/**/
-void
-lexinit(void)
-{
- nocorrect = dbparens = lexstop = 0;
- tok = ENDINPUT;
-}
-
-/* add a char to the string buffer */
-
-/**/
-void
-add(int c)
-{
- *lexbuf.ptr++ = c;
- if (lexbuf.siz == ++lexbuf.len) {
- int newbsiz = lexbuf.siz * 2;
-
- if (newbsiz > inbufct && inbufct > lexbuf.siz)
- newbsiz = inbufct;
-
- tokstr = (char *)hrealloc(tokstr, lexbuf.siz, newbsiz);
- lexbuf.ptr = tokstr + lexbuf.len;
- /* len == bsiz, so bptr is at the start of newly allocated memory */
- memset(lexbuf.ptr, 0, newbsiz - lexbuf.siz);
- lexbuf.siz = newbsiz;
- }
-}
-
-#define SETPARBEGIN { \
- if ((lexflags & LEXFLAGS_ZLE) && !(inbufflags & INP_ALIAS) && \
- zlemetacs >= zlemetall+1-inbufct) \
- parbegin = inbufct; \
- }
-#define SETPAREND { \
- if ((lexflags & LEXFLAGS_ZLE) && !(inbufflags & INP_ALIAS) && \
- parbegin != -1 && parend == -1) { \
- if (zlemetacs >= zlemetall + 1 - inbufct) \
- parbegin = -1; \
- else \
- parend = inbufct; \
- } \
- }
-
-enum {
- CMD_OR_MATH_CMD,
- CMD_OR_MATH_MATH,
- CMD_OR_MATH_ERR
-};
-
-/*
- * Return one of the above. If it couldn't be
- * parsed as math, but there was no gross error, it's a command.
- */
-
-static int
-cmd_or_math(int cs_type)
-{
- int oldlen = lexbuf.len;
- int c;
- int oinflags = inbufflags;
-
- cmdpush(cs_type);
- inbufflags |= INP_APPEND;
- c = dquote_parse(')', 0);
- if (!(oinflags & INP_APPEND))
- inbufflags &= ~INP_APPEND;
- cmdpop();
- *lexbuf.ptr = '\0';
- if (!c) {
- /* Successfully parsed, see if it was math */
- c = hgetc();
- if (c == ')')
- return CMD_OR_MATH_MATH; /* yes */
- hungetc(c);
- lexstop = 0;
- c = ')';
- } else if (lexstop) {
- /* we haven't got anything to unget */
- return CMD_OR_MATH_ERR;
- }
- /* else unsuccessful: unget the whole thing */
- hungetc(c);
- lexstop = 0;
- while (lexbuf.len > oldlen && !(errflag & ERRFLAG_ERROR)) {
- lexbuf.len--;
- hungetc(itok(*--lexbuf.ptr) ?
- ztokens[*lexbuf.ptr - Pound] : *lexbuf.ptr);
- }
- if (errflag)
- return CMD_OR_MATH_ERR;
- hungetc('(');
- return errflag ? CMD_OR_MATH_ERR : CMD_OR_MATH_CMD;
-}
-
-
-/*
- * Parse either a $(( ... )) or a $(...)
- * Return the same as cmd_or_math().
- */
-static int
-cmd_or_math_sub(void)
-{
- int c = hgetc(), ret;
-
- if (c == '(') {
- int lexpos = (int)(lexbuf.ptr - tokstr);
- add(Inpar);
- add('(');
- if ((ret = cmd_or_math(CS_MATHSUBST)) == CMD_OR_MATH_MATH) {
- tokstr[lexpos] = Inparmath;
- add(')');
- return CMD_OR_MATH_MATH;
- }
- if (ret == CMD_OR_MATH_ERR)
- return CMD_OR_MATH_ERR;
- lexbuf.ptr -= 2;
- lexbuf.len -= 2;
- } else {
- hungetc(c);
- lexstop = 0;
- }
- return skipcomm() ? CMD_OR_MATH_ERR : CMD_OR_MATH_CMD;
-}
-
-/* Check whether we're looking at valid numeric globbing syntax *
- * (/\<[0-9]*-[0-9]*\>/). Call pointing just after the opening "<". *
- * Leaves the input in the same place, returning 0 or 1. */
-
-/**/
-static int
-isnumglob(void)
-{
- int c, ec = '-', ret = 0;
- int tbs = 256, n = 0;
- char *tbuf = (char *)zalloc(tbs);
-
- while(1) {
- c = hgetc();
- if(lexstop) {
- lexstop = 0;
- break;
- }
- tbuf[n++] = c;
- if(!idigit(c)) {
- if(c != ec)
- break;
- if(ec == '>') {
- ret = 1;
- break;
- }
- ec = '>';
- }
- if(n == tbs)
- tbuf = (char *)realloc(tbuf, tbs *= 2);
- }
- while(n--)
- hungetc(tbuf[n]);
- zfree(tbuf, tbs);
- return ret;
-}
-
-/**/
-static enum lextok
-gettok(void)
-{
- int c, d;
- int peekfd = -1;
- enum lextok peek;
-
- beginning:
- tokstr = NULL;
- while (iblank(c = hgetc()) && !lexstop);
- toklineno = lineno;
- if (lexstop)
- return (errflag) ? LEXERR : ENDINPUT;
- isfirstln = 0;
- if ((lexflags & LEXFLAGS_ZLE) && !(inbufflags & INP_ALIAS))
- wordbeg = inbufct - (qbang && c == bangchar);
- hwbegin(-1-(qbang && c == bangchar));
- /* word includes the last character read and possibly \ before ! */
- if (dbparens) {
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = (char *) hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
- hungetc(c);
- cmdpush(CS_MATH);
- c = dquote_parse(infor ? ';' : ')', 0);
- cmdpop();
- *lexbuf.ptr = '\0';
- if (!c && infor) {
- infor--;
- return DINPAR;
- }
- if (c || (c = hgetc()) != ')') {
- hungetc(c);
- return LEXERR;
- }
- dbparens = 0;
- return DOUTPAR;
- } else if (idigit(c)) { /* handle 1< foo */
- d = hgetc();
- if(d == '&') {
- d = hgetc();
- if(d == '>') {
- peekfd = c - '0';
- hungetc('>');
- c = '&';
- } else {
- hungetc(d);
- lexstop = 0;
- hungetc('&');
- }
- } else if (d == '>' || d == '<') {
- peekfd = c - '0';
- c = d;
- } else {
- hungetc(d);
- lexstop = 0;
- }
- }
-
- /* chars in initial position in word */
-
- /*
- * Handle comments. There are some special cases when this
- * is not normal command input: lexflags implies we are examining
- * a line lexically without it being used for normal command input.
- */
- if (c == hashchar && !nocomments &&
- (isset(INTERACTIVECOMMENTS) ||
- ((!lexflags || (lexflags & LEXFLAGS_COMMENTS)) && !expanding &&
- (!interact || unset(SHINSTDIN) || strin)))) {
- /* History is handled here to prevent extra *
- * newlines being inserted into the history. */
-
- if (lexflags & LEXFLAGS_COMMENTS_KEEP) {
- lexbuf.len = 0;
- lexbuf.ptr = tokstr =
- (char *)hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
- add(c);
- }
- hwabort();
- while ((c = ingetc()) != '\n' && !lexstop) {
- hwaddc(c);
- addtoline(c);
- if (lexflags & LEXFLAGS_COMMENTS_KEEP)
- add(c);
- }
-
- if (errflag)
- peek = LEXERR;
- else {
- if (lexflags & LEXFLAGS_COMMENTS_KEEP) {
- *lexbuf.ptr = '\0';
- if (!lexstop)
- hungetc(c);
- peek = STRING;
- } else {
- hwend();
- hwbegin(0);
- hwaddc('\n');
- addtoline('\n');
- /*
- * If splitting a line and removing comments,
- * we don't want a newline token since it's
- * treated specially.
- */
- if ((lexflags & LEXFLAGS_COMMENTS_STRIP) && lexstop)
- peek = ENDINPUT;
- else
- peek = NEWLIN;
- }
- }
- return peek;
- }
- switch (lexact1[STOUC(c)]) {
- case LX1_BKSLASH:
- d = hgetc();
- if (d == '\n')
- goto beginning;
- hungetc(d);
- lexstop = 0;
- break;
- case LX1_NEWLIN:
- return NEWLIN;
- case LX1_SEMI:
- d = hgetc();
- if(d == ';')
- return DSEMI;
- else if(d == '&')
- return SEMIAMP;
- else if (d == '|')
- return SEMIBAR;
- hungetc(d);
- lexstop = 0;
- return SEMI;
- case LX1_AMPER:
- d = hgetc();
- if (d == '&')
- return DAMPER;
- else if (d == '!' || d == '|')
- return AMPERBANG;
- else if (d == '>') {
- tokfd = peekfd;
- d = hgetc();
- if (d == '!' || d == '|')
- return OUTANGAMPBANG;
- else if (d == '>') {
- d = hgetc();
- if (d == '!' || d == '|')
- return DOUTANGAMPBANG;
- hungetc(d);
- lexstop = 0;
- return DOUTANGAMP;
- }
- hungetc(d);
- lexstop = 0;
- return AMPOUTANG;
- }
- hungetc(d);
- lexstop = 0;
- return AMPER;
- case LX1_BAR:
- d = hgetc();
- if (d == '|' && !incasepat)
- return DBAR;
- else if (d == '&')
- return BARAMP;
- hungetc(d);
- lexstop = 0;
- return BAR;
- case LX1_INPAR:
- d = hgetc();
- if (d == '(') {
- if (infor) {
- dbparens = 1;
- return DINPAR;
- }
- if (incmdpos || (isset(SHGLOB) && !isset(KSHGLOB))) {
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = (char *)
- hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
- switch (cmd_or_math(CS_MATH)) {
- case CMD_OR_MATH_MATH:
- return DINPAR;
-
- case CMD_OR_MATH_CMD:
- /*
- * Not math, so we don't return the contents
- * as a string in this case.
- */
- tokstr = NULL;
- return INPAR;
-
- case CMD_OR_MATH_ERR:
- /*
- * LEXFLAGS_ACTIVE means we came from bufferwords(),
- * so we treat as an incomplete math expression
- */
- if (lexflags & LEXFLAGS_ACTIVE)
- tokstr = dyncat("((", tokstr ? tokstr : "");
- /* fall through */
-
- default:
- return LEXERR;
- }
- }
- } else if (d == ')')
- return INOUTPAR;
- hungetc(d);
- lexstop = 0;
- if (!(isset(SHGLOB) || incond == 1 || incmdpos))
- break;
- return INPAR;
- case LX1_OUTPAR:
- return OUTPAR;
- case LX1_INANG:
- d = hgetc();
- if (d == '(') {
- hungetc(d);
- lexstop = 0;
- unpeekfd:
- if(peekfd != -1) {
- hungetc(c);
- c = '0' + peekfd;
- }
- break;
- }
- if (d == '>') {
- peek = INOUTANG;
- } else if (d == '<') {
- int e = hgetc();
-
- if (e == '(') {
- hungetc(e);
- hungetc(d);
- peek = INANG;
- } else if (e == '<')
- peek = TRINANG;
- else if (e == '-')
- peek = DINANGDASH;
- else {
- hungetc(e);
- lexstop = 0;
- peek = DINANG;
- }
- } else if (d == '&') {
- peek = INANGAMP;
- } else {
- hungetc(d);
- if(isnumglob())
- goto unpeekfd;
- peek = INANG;
- }
- tokfd = peekfd;
- return peek;
- case LX1_OUTANG:
- d = hgetc();
- if (d == '(') {
- hungetc(d);
- goto unpeekfd;
- } else if (d == '&') {
- d = hgetc();
- if (d == '!' || d == '|')
- peek = OUTANGAMPBANG;
- else {
- hungetc(d);
- lexstop = 0;
- peek = OUTANGAMP;
- }
- } else if (d == '!' || d == '|')
- peek = OUTANGBANG;
- else if (d == '>') {
- d = hgetc();
- if (d == '&') {
- d = hgetc();
- if (d == '!' || d == '|')
- peek = DOUTANGAMPBANG;
- else {
- hungetc(d);
- lexstop = 0;
- peek = DOUTANGAMP;
- }
- } else if (d == '!' || d == '|')
- peek = DOUTANGBANG;
- else if (d == '(') {
- hungetc(d);
- hungetc('>');
- peek = OUTANG;
- } else {
- hungetc(d);
- lexstop = 0;
- peek = DOUTANG;
- if (isset(HISTALLOWCLOBBER))
- hwaddc('|');
- }
- } else {
- hungetc(d);
- lexstop = 0;
- peek = OUTANG;
- if (!incond && isset(HISTALLOWCLOBBER))
- hwaddc('|');
- }
- tokfd = peekfd;
- return peek;
- }
-
- /* we've started a string, now get the *
- * rest of it, performing tokenization */
- return gettokstr(c, 0);
-}
-
-/*
- * Get the remains of a token string. This has two uses.
- * When called from gettok(), with sub = 0, we have already identified
- * any interesting initial character and want to get the rest of
- * what we now know is a string. However, the string may still include
- * metacharacters and potentially substitutions.
- *
- * When called from parse_subst_string() with sub = 1, we are not
- * fully parsing a command line, merely tokenizing a string.
- * In this case we always add characters to the parsed string
- * unless there is a parse error.
- */
-
-/**/
-static enum lextok
-gettokstr(int c, int sub)
-{
- int bct = 0, pct = 0, brct = 0, seen_brct = 0, fdpar = 0;
- int intpos = 1, in_brace_param = 0;
- int inquote, unmatched = 0;
- enum lextok peek;
-#ifdef DEBUG
- int ocmdsp = cmdsp;
-#endif
-
- peek = STRING;
- if (!sub) {
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = (char *) hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
- }
- for (;;) {
- int act;
- int e;
- int inbl = inblank(c);
-
- if (fdpar && !inbl && c != ')')
- fdpar = 0;
-
- if (inbl && !in_brace_param && !pct)
- act = LX2_BREAK;
- else {
- act = lexact2[STOUC(c)];
- c = lextok2[STOUC(c)];
- }
- switch (act) {
- case LX2_BREAK:
- if (!in_brace_param && !sub)
- goto brk;
- break;
- case LX2_META:
- c = hgetc();
-#ifdef DEBUG
- if (lexstop) {
- fputs("BUG: input terminated by Meta\n", stderr);
- fflush(stderr);
- goto brk;
- }
-#endif
- add(Meta);
- break;
- case LX2_OUTPAR:
- if (fdpar) {
- /* this is a single word `( )', treat as INOUTPAR */
- add(c);
- *lexbuf.ptr = '\0';
- return INOUTPAR;
- }
- if ((sub || in_brace_param) && isset(SHGLOB))
- break;
- if (!in_brace_param && !pct--) {
- if (sub) {
- pct = 0;
- break;
- } else
- goto brk;
- }
- c = Outpar;
- break;
- case LX2_BAR:
- if (!pct && !in_brace_param) {
- if (sub)
- break;
- else
- goto brk;
- }
- if (unset(SHGLOB) || (!sub && !in_brace_param))
- c = Bar;
- break;
- case LX2_STRING:
- e = hgetc();
- if (e == '[') {
- cmdpush(CS_MATHSUBST);
- add(String);
- add(Inbrack);
- c = dquote_parse(']', sub);
- cmdpop();
- if (c) {
- peek = LEXERR;
- goto brk;
- }
- c = Outbrack;
- } else if (e == '(') {
- add(String);
- switch (cmd_or_math_sub()) {
- case CMD_OR_MATH_CMD:
- c = Outpar;
- break;
-
- case CMD_OR_MATH_MATH:
- c = Outparmath;
- break;
-
- default:
- peek = LEXERR;
- goto brk;
- }
- } else {
- if (e == '{') {
- add(c);
- c = Inbrace;
- ++bct;
- cmdpush(CS_BRACEPAR);
- if (!in_brace_param) {
- if ((in_brace_param = bct))
- seen_brct = 0;
- }
- } else {
- hungetc(e);
- lexstop = 0;
- }
- }
- break;
- case LX2_INBRACK:
- if (!in_brace_param) {
- brct++;
- seen_brct = 1;
- }
- c = Inbrack;
- break;
- case LX2_OUTBRACK:
- if (!in_brace_param)
- brct--;
- if (brct < 0)
- brct = 0;
- c = Outbrack;
- break;
- case LX2_INPAR:
- if (isset(SHGLOB)) {
- if (sub || in_brace_param)
- break;
- if (incasepat > 0 && !lexbuf.len)
- return INPAR;
- if (!isset(KSHGLOB) && lexbuf.len)
- goto brk;
- }
- if (!in_brace_param) {
- if (!sub) {
- e = hgetc();
- hungetc(e);
- lexstop = 0;
- /* For command words, parentheses are only
- * special at the start. But now we're tokenising
- * the remaining string. So I don't see what
- * the old incmdpos test here is for.
- * pws 1999/6/8
- *
- * Oh, no.
- * func1( )
- * is a valid function definition in [k]sh. The best
- * thing we can do, without really nasty lookahead tricks,
- * is break if we find a blank after a parenthesis. At
- * least this can't happen inside braces or brackets. We
- * only allow this with SHGLOB (set for both sh and ksh).
- *
- * Things like `print @( |foo)' should still
- * work, because [k]sh don't allow multiple words
- * in a function definition, so we only do this
- * in command position.
- * pws 1999/6/14
- */
- if (e == ')' || (isset(SHGLOB) && inblank(e) && !bct &&
- !brct && !intpos && incmdpos)) {
- /*
- * Either a () token, or a command word with
- * something suspiciously like a ksh function
- * definition.
- * The current word isn't spellcheckable.
- */
- nocorrect |= 2;
- goto brk;
- }
- }
- /*
- * This also handles the [k]sh `foo( )' function definition.
- * Maintain a variable fdpar, set as long as a single set of
- * parentheses contains only space. Then if we get to the
- * closing parenthesis and it is still set, we can assume we
- * have a function definition. Only do this at the start of
- * the word, since the (...) must be a separate token.
- */
- if (!pct++ && isset(SHGLOB) && intpos && !bct && !brct)
- fdpar = 1;
- }
- c = Inpar;
- break;
- case LX2_INBRACE:
- if (isset(IGNOREBRACES) || sub)
- c = '{';
- else {
- if (!lexbuf.len && incmdpos) {
- add('{');
- *lexbuf.ptr = '\0';
- return STRING;
- }
- if (in_brace_param) {
- cmdpush(CS_BRACE);
- }
- bct++;
- }
- break;
- case LX2_OUTBRACE:
- if ((isset(IGNOREBRACES) || sub) && !in_brace_param)
- break;
- if (!bct)
- break;
- if (in_brace_param) {
- cmdpop();
- }
- if (bct-- == in_brace_param)
- in_brace_param = 0;
- c = Outbrace;
- break;
- case LX2_COMMA:
- if (unset(IGNOREBRACES) && !sub && bct > in_brace_param)
- c = Comma;
- break;
- case LX2_OUTANG:
- if (in_brace_param || sub)
- break;
- e = hgetc();
- if (e != '(') {
- hungetc(e);
- lexstop = 0;
- goto brk;
- }
- add(OutangProc);
- if (skipcomm()) {
- peek = LEXERR;
- goto brk;
- }
- c = Outpar;
- break;
- case LX2_INANG:
- if (isset(SHGLOB) && sub)
- break;
- e = hgetc();
- if (!(in_brace_param || sub) && e == '(') {
- add(Inang);
- if (skipcomm()) {
- peek = LEXERR;
- goto brk;
- }
- c = Outpar;
- break;
- }
- hungetc(e);
- if(isnumglob()) {
- add(Inang);
- while ((c = hgetc()) != '>')
- add(c);
- c = Outang;
- break;
- }
- lexstop = 0;
- if (in_brace_param || sub)
- break;
- goto brk;
- case LX2_EQUALS:
- if (!sub) {
- if (intpos) {
- e = hgetc();
- if (e != '(') {
- hungetc(e);
- lexstop = 0;
- c = Equals;
- } else {
- add(Equals);
- if (skipcomm()) {
- peek = LEXERR;
- goto brk;
- }
- c = Outpar;
- }
- } else if (peek != ENVSTRING &&
- (incmdpos || intypeset) && !bct && !brct) {
- char *t = tokstr;
- if (idigit(*t))
- while (++t < lexbuf.ptr && idigit(*t));
- else {
- int sav = *lexbuf.ptr;
- *lexbuf.ptr = '\0';
- t = itype_end(t, IIDENT, 0);
- if (t < lexbuf.ptr) {
- skipparens(Inbrack, Outbrack, &t);
- } else {
- *lexbuf.ptr = sav;
- }
- }
- if (*t == '+')
- t++;
- if (t == lexbuf.ptr) {
- e = hgetc();
- if (e == '(') {
- *lexbuf.ptr = '\0';
- return ENVARRAY;
- }
- hungetc(e);
- lexstop = 0;
- peek = ENVSTRING;
- intpos = 2;
- } else
- c = Equals;
- } else
- c = Equals;
- }
- break;
- case LX2_BKSLASH:
- c = hgetc();
- if (c == '\n') {
- c = hgetc();
- if (!lexstop)
- continue;
- } else {
- add(Bnull);
- if (c == STOUC(Meta)) {
- c = hgetc();
-#ifdef DEBUG
- if (lexstop) {
- fputs("BUG: input terminated by Meta\n", stderr);
- fflush(stderr);
- goto brk;
- }
-#endif
- add(Meta);
- }
- }
- if (lexstop)
- goto brk;
- break;
- case LX2_QUOTE: {
- int strquote = (lexbuf.len && lexbuf.ptr[-1] == String);
-
- add(Snull);
- cmdpush(CS_QUOTE);
- for (;;) {
- STOPHIST
- while ((c = hgetc()) != '\'' && !lexstop) {
- if (strquote && c == '\\') {
- c = hgetc();
- if (lexstop)
- break;
- /*
- * Mostly we don't need to do anything special
- * with escape backslashes or closing quotes
- * inside $'...'; however in completion we
- * need to be able to strip multiple backslashes
- * neatly.
- */
- if (c == '\\' || c == '\'')
- add(Bnull);
- else
- add('\\');
- } else if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') {
- if (lexbuf.ptr[-1] == '\\')
- lexbuf.ptr--, lexbuf.len--;
- else
- break;
- }
- add(c);
- }
- ALLOWHIST
- if (c != '\'') {
- unmatched = '\'';
- /* Not an error when called from bufferwords() */
- if (!(lexflags & LEXFLAGS_ACTIVE))
- peek = LEXERR;
- cmdpop();
- goto brk;
- }
- e = hgetc();
- if (e != '\'' || unset(RCQUOTES) || strquote)
- break;
- add(c);
- }
- cmdpop();
- hungetc(e);
- lexstop = 0;
- c = Snull;
- break;
- }
- case LX2_DQUOTE:
- add(Dnull);
- cmdpush(CS_DQUOTE);
- c = dquote_parse('"', sub);
- cmdpop();
- if (c) {
- unmatched = '"';
- /* Not an error when called from bufferwords() */
- if (!(lexflags & LEXFLAGS_ACTIVE))
- peek = LEXERR;
- goto brk;
- }
- c = Dnull;
- break;
- case LX2_BQUOTE:
- add(Tick);
- cmdpush(CS_BQUOTE);
- SETPARBEGIN
- inquote = 0;
- while ((c = hgetc()) != '`' && !lexstop) {
- if (c == '\\') {
- c = hgetc();
- if (c != '\n') {
- add(c == '`' || c == '\\' || c == '$' ? Bnull : '\\');
- add(c);
- }
- else if (!sub && isset(CSHJUNKIEQUOTES))
- add(c);
- } else {
- if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') {
- break;
- }
- add(c);
- if (c == '\'') {
- if ((inquote = !inquote))
- STOPHIST
- else
- ALLOWHIST
- }
- }
- }
- if (inquote)
- ALLOWHIST
- cmdpop();
- if (c != '`') {
- unmatched = '`';
- /* Not an error when called from bufferwords() */
- if (!(lexflags & LEXFLAGS_ACTIVE))
- peek = LEXERR;
- goto brk;
- }
- c = Tick;
- SETPAREND
- break;
- case LX2_DASH:
- /*
- * - shouldn't be treated as a special character unless
- * we're in a pattern. Unfortunately, working out for
- * sure in complicated expressions whether we're in a
- * pattern is tricky. So we'll make it special and
- * turn it back any time we don't need it special.
- * This is not ideal as it's a lot of work.
- */
- c = Dash;
- break;
- case LX2_BANG:
- /*
- * Same logic as Dash, for ! to perform negation in range.
- */
- if (seen_brct)
- c = Bang;
- else
- c = '!';
- }
- add(c);
- c = hgetc();
- if (intpos)
- intpos--;
- if (lexstop)
- break;
- }
- brk:
- if (errflag) {
- if (in_brace_param) {
- while(bct-- >= in_brace_param)
- cmdpop();
- }
- return LEXERR;
- }
- hungetc(c);
- if (unmatched && !(lexflags & LEXFLAGS_ACTIVE))
- zerr("unmatched %c", unmatched);
- if (in_brace_param) {
- while(bct-- >= in_brace_param)
- cmdpop();
- zerr("closing brace expected");
- } else if (unset(IGNOREBRACES) && !sub && lexbuf.len > 1 &&
- peek == STRING && lexbuf.ptr[-1] == '}' &&
- lexbuf.ptr[-2] != Bnull) {
- /* hack to get {foo} command syntax work */
- lexbuf.ptr--;
- lexbuf.len--;
- lexstop = 0;
- hungetc('}');
- }
- *lexbuf.ptr = '\0';
- DPUTS(cmdsp != ocmdsp, "BUG: gettok: cmdstack changed.");
- return peek;
-}
-
-
-/*
- * Parse input as if in double quotes.
- * endchar is the end character to expect.
- * sub has got something to do with whether we are doing quoted substitution.
- * Return non-zero for error (character to unget), else zero
- */
-
-/**/
-static int
-dquote_parse(char endchar, int sub)
-{
- int pct = 0, brct = 0, bct = 0, intick = 0, err = 0;
- int c;
- int math = endchar == ')' || endchar == ']' || infor;
- int zlemath = math && zlemetacs > zlemetall + addedx - inbufct;
-
- while (((c = hgetc()) != endchar || bct ||
- (math && ((pct > 0) || (brct > 0))) ||
- intick) && !lexstop) {
- cont:
- switch (c) {
- case '\\':
- c = hgetc();
- if (c != '\n') {
- if (c == '$' || c == '\\' || (c == '}' && !intick && bct) ||
- c == endchar || c == '`' ||
- (endchar == ']' && (c == '[' || c == ']' ||
- c == '(' || c == ')' ||
- c == '{' || c == '}' ||
- (c == '"' && sub))))
- add(Bnull);
- else {
- /* lexstop is implicitly handled here */
- add('\\');
- goto cont;
- }
- } else if (sub || unset(CSHJUNKIEQUOTES) || endchar != '"')
- continue;
- break;
- case '\n':
- err = !sub && isset(CSHJUNKIEQUOTES) && endchar == '"';
- break;
- case '$':
- if (intick)
- break;
- c = hgetc();
- if (c == '(') {
- add(Qstring);
- switch (cmd_or_math_sub()) {
- case CMD_OR_MATH_CMD:
- c = Outpar;
- break;
-
- case CMD_OR_MATH_MATH:
- c = Outparmath;
- break;
-
- default:
- err = 1;
- break;
- }
- } else if (c == '[') {
- add(String);
- add(Inbrack);
- cmdpush(CS_MATHSUBST);
- err = dquote_parse(']', sub);
- cmdpop();
- c = Outbrack;
- } else if (c == '{') {
- add(Qstring);
- c = Inbrace;
- cmdpush(CS_BRACEPAR);
- bct++;
- } else if (c == '$')
- add(Qstring);
- else {
- hungetc(c);
- lexstop = 0;
- c = Qstring;
- }
- break;
- case '}':
- if (intick || !bct)
- break;
- c = Outbrace;
- bct--;
- cmdpop();
- break;
- case '`':
- c = Qtick;
- if (intick == 2)
- ALLOWHIST
- if ((intick = !intick)) {
- SETPARBEGIN
- cmdpush(CS_BQUOTE);
- } else {
- SETPAREND
- cmdpop();
- }
- break;
- case '\'':
- if (!intick)
- break;
- if (intick == 1)
- intick = 2, STOPHIST
- else
- intick = 1, ALLOWHIST
- break;
- case '(':
- if (!math || !bct)
- pct++;
- break;
- case ')':
- if (!math || !bct)
- err = (!pct-- && math);
- break;
- case '[':
- if (!math || !bct)
- brct++;
- break;
- case ']':
- if (!math || !bct)
- err = (!brct-- && math);
- break;
- case '"':
- if (intick || (endchar != '"' && !bct))
- break;
- if (bct) {
- add(Dnull);
- cmdpush(CS_DQUOTE);
- err = dquote_parse('"', sub);
- cmdpop();
- c = Dnull;
- } else
- err = 1;
- break;
- }
- if (err || lexstop)
- break;
- add(c);
- }
- if (intick == 2)
- ALLOWHIST
- if (intick) {
- cmdpop();
- }
- while (bct--)
- cmdpop();
- if (lexstop)
- err = intick || endchar || err;
- else if (err == 1) {
- /*
- * TODO: as far as I can see, this hack is used in gettokstr()
- * to hungetc() a character on an error. However, I don't
- * understand what that actually gets us, and we can't guarantee
- * it's a character anyway, because of the previous test.
- *
- * We use the same feature in cmd_or_math where we actually do
- * need to unget if we decide it's really a command substitution.
- * We try to handle the other case by testing for lexstop.
- */
- err = c;
- }
- if (zlemath && zlemetacs <= zlemetall + 1 - inbufct)
- inwhat = IN_MATH;
- return err;
-}
-
-/*
- * Tokenize a string given in s. Parsing is done as in double
- * quotes. This is usually called before singsub().
- *
- * parsestr() is noisier, reporting an error if the parse failed.
- *
- * On entry, *s must point to a string allocated from the stack of
- * exactly the right length, i.e. strlen(*s) + 1, as the string
- * is used as the lexical token string whose memory management
- * demands this. Usually the input string will therefore be
- * the result of an immediately preceding dupstring().
- */
-
-/**/
-mod_export int
-parsestr(char **s)
-{
- int err;
-
- if ((err = parsestrnoerr(s))) {
- untokenize(*s);
- if (!(errflag & ERRFLAG_INT)) {
- if (err > 32 && err < 127)
- zerr("parse error near `%c'", err);
- else
- zerr("parse error");
- }
- }
- return err;
-}
-
-/**/
-mod_export int
-parsestrnoerr(char **s)
-{
- int l = strlen(*s), err;
-
- zcontext_save();
- untokenize(*s);
- inpush(dupstring(*s), 0, NULL);
- strinbeg(0);
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = *s;
- lexbuf.siz = l + 1;
- err = dquote_parse('\0', 1);
- if (tokstr)
- *s = tokstr;
- *lexbuf.ptr = '\0';
- strinend();
- inpop();
- DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty.");
- zcontext_restore();
- return err;
-}
-
-/*
- * Parse a subscript in string s.
- * sub is passed down to dquote_parse().
- * endchar is the final character.
- * Return the next character, or NULL.
- */
-/**/
-mod_export char *
-parse_subscript(char *s, int sub, int endchar)
-{
- int l = strlen(s), err, toklen;
- char *t;
-
- if (!*s || *s == endchar)
- return 0;
- zcontext_save();
- untokenize(t = dupstring(s));
- inpush(t, 0, NULL);
- strinbeg(0);
- /*
- * Warning to Future Generations:
- *
- * This way of passing the subscript through the lexer is brittle.
- * Code above this for several layers assumes that when we tokenise
- * the input it goes into the same place as the original string.
- * However, the lexer may overwrite later bits of the string or
- * reallocate it, in particular when expanding aliaes. To get
- * around this, we copy the string and then copy it back. This is a
- * bit more robust but still relies on the underlying assumption of
- * length preservation.
- */
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = dupstring(s);
- lexbuf.siz = l + 1;
- err = dquote_parse(endchar, sub);
- toklen = (int)(lexbuf.ptr - tokstr);
- DPUTS(toklen > l, "Bad length for parsed subscript");
- memcpy(s, tokstr, toklen);
- if (err) {
- char *strend = s + toklen;
- err = *strend;
- *strend = '\0';
- untokenize(s);
- *strend = err;
- s = NULL;
- } else {
- s += toklen;
- }
- strinend();
- inpop();
- DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty.");
- zcontext_restore();
- return s;
-}
-
-/* Tokenize a string given in s. Parsing is done as if s were a normal *
- * command-line argument but it may contain separators. This is used *
- * to parse the right-hand side of ${...%...} substitutions. */
-
-/**/
-mod_export int
-parse_subst_string(char *s)
-{
- int c, l = strlen(s), err;
- char *ptr;
- enum lextok ctok;
-
- if (!*s || !strcmp(s, nulstring))
- return 0;
- zcontext_save();
- untokenize(s);
- inpush(dupstring(s), 0, NULL);
- strinbeg(0);
- lexbuf.len = 0;
- lexbuf.ptr = tokstr = s;
- lexbuf.siz = l + 1;
- c = hgetc();
- ctok = gettokstr(c, 1);
- err = errflag;
- strinend();
- inpop();
- DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty.");
- zcontext_restore();
- /* Keep any interrupt error status */
- errflag = err | (errflag & ERRFLAG_INT);
- if (ctok == LEXERR) {
- untokenize(s);
- return 1;
- }
-#ifdef DEBUG
- /*
- * Historical note: we used to check here for olen (the value of lexbuf.len
- * before zcontext_restore()) == l, but that's not necessarily the case if
- * we stripped an RCQUOTE.
- */
- if (ctok != STRING || (errflag && !noerrs)) {
- fprintf(stderr, "Oops. Bug in parse_subst_string: %s\n",
- errflag ? "errflag" : "ctok != STRING");
- fflush(stderr);
- untokenize(s);
- return 1;
- }
-#endif
- /* Check for $'...' quoting. This needs special handling. */
- for (ptr = s; *ptr; )
- {
- if (*ptr == String && ptr[1] == Snull)
- {
- char *t;
- int len, tlen, diff;
- t = getkeystring(ptr + 2, &len, GETKEYS_DOLLARS_QUOTE, NULL);
- len += 2;
- tlen = strlen(t);
- diff = len - tlen;
- /*
- * Yuk.
- * parse_subst_string() currently handles strings in-place.
- * That's not so easy to fix without knowing whether
- * additional memory should come off the heap or
- * otherwise. So we cheat by copying the unquoted string
- * into place, unless it's too long. That's not the
- * normal case, but I'm worried there are pathological
- * cases with converting metafied multibyte strings.
- * If someone can prove there aren't I will be very happy.
- */
- if (diff < 0) {
- DPUTS(1, "$'...' subst too long: fix get_parse_string()");
- return 1;
- }
- memcpy(ptr, t, tlen);
- ptr += tlen;
- if (diff > 0) {
- char *dptr = ptr;
- char *sptr = ptr + diff;
- while ((*dptr++ = *sptr++))
- ;
- }
- } else
- ptr++;
- }
- return 0;
-}
-
-/* Called below to report word positions. */
-
-/**/
-static void
-gotword(void)
-{
- int nwe = zlemetall + 1 - inbufct + (addedx == 2 ? 1 : 0);
- if (zlemetacs <= nwe) {
- int nwb = zlemetall - wordbeg + addedx;
- if (zlemetacs >= nwb) {
- wb = nwb;
- we = nwe;
- } else {
- wb = zlemetacs + addedx;
- if (we < wb)
- we = wb;
- }
- lexflags = 0;
- }
-}
-
-/* Check if current lex text matches an alias: 1 if so, else 0 */
-
-static int
-checkalias(void)
-{
- Alias an;
-
- if (!zshlextext)
- return 0;
-
- if (!noaliases && isset(ALIASESOPT) &&
- (!isset(POSIXALIASES) ||
- (tok == STRING && !reswdtab->getnode(reswdtab, zshlextext)))) {
- char *suf;
-
- an = (Alias) aliastab->getnode(aliastab, zshlextext);
- if (an && !an->inuse &&
- ((an->node.flags & ALIAS_GLOBAL) ||
- (incmdpos && tok == STRING) || inalmore)) {
- if (!lexstop) {
- /*
- * Tokens that don't require a space after, get one,
- * because they are treated as if preceded by one.
- */
- int c = hgetc();
- hungetc(c);
- if (!iblank(c))
- inpush(" ", INP_ALIAS, 0);
- }
- inpush(an->text, INP_ALIAS, an);
- if (an->text[0] == ' ' && !(an->node.flags & ALIAS_GLOBAL))
- aliasspaceflag = 1;
- lexstop = 0;
- return 1;
- }
- if ((suf = strrchr(zshlextext, '.')) && suf[1] &&
- suf > zshlextext && suf[-1] != Meta &&
- (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) &&
- !an->inuse && incmdpos) {
- inpush(dupstring(zshlextext), INP_ALIAS, an);
- inpush(" ", INP_ALIAS, NULL);
- inpush(an->text, INP_ALIAS, NULL);
- lexstop = 0;
- return 1;
- }
- }
-
- return 0;
-}
-
-/* expand aliases and reserved words */
-
-/**/
-int
-exalias(void)
-{
- Reswd rw;
-
- hwend();
- if (interact && isset(SHINSTDIN) && !strin && incasepat <= 0 &&
- tok == STRING && !nocorrect && !(inbufflags & INP_ALIAS) &&
- (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)))
- spckword(&tokstr, 1, incmdpos, 1);
-
- if (!tokstr) {
- zshlextext = tokstrings[tok];
-
- if (tok == NEWLIN)
- return 0;
- return checkalias();
- } else {
- VARARR(char, copy, (strlen(tokstr) + 1));
-
- if (has_token(tokstr)) {
- char *p, *t;
-
- zshlextext = p = copy;
- for (t = tokstr;
- (*p++ = itok(*t) ? ztokens[*t++ - Pound] : *t++););
- } else
- zshlextext = tokstr;
-
- if ((lexflags & LEXFLAGS_ZLE) && !(inbufflags & INP_ALIAS)) {
- int zp = lexflags;
-
- gotword();
- if ((zp & LEXFLAGS_ZLE) && !lexflags) {
- if (zshlextext == copy)
- zshlextext = tokstr;
- return 0;
- }
- }
-
- if (tok == STRING) {
- /* Check for an alias */
- if ((zshlextext != copy || !isset(POSIXALIASES)) && checkalias()) {
- if (zshlextext == copy)
- zshlextext = tokstr;
- return 1;
- }
-
- /* Then check for a reserved word */
- if ((incmdpos ||
- (unset(IGNOREBRACES) && unset(IGNORECLOSEBRACES) &&
- zshlextext[0] == '}' && !zshlextext[1])) &&
- (rw = (Reswd) reswdtab->getnode(reswdtab, zshlextext))) {
- tok = rw->token;
- inrepeat_ = (tok == REPEAT);
- if (tok == DINBRACK)
- incond = 1;
- } else if (incond && !strcmp(zshlextext, "]]")) {
- tok = DOUTBRACK;
- incond = 0;
- } else if (incond == 1 && zshlextext[0] == '!' && !zshlextext[1])
- tok = BANG;
- }
- inalmore = 0;
- if (zshlextext == copy)
- zshlextext = tokstr;
- }
- return 0;
-}
-
-/**/
-void
-zshlex_raw_add(int c)
-{
- if (!lex_add_raw)
- return;
-
- *lexbuf_raw.ptr++ = c;
- if (lexbuf_raw.siz == ++lexbuf_raw.len) {
- int newbsiz = lexbuf_raw.siz * 2;
-
- tokstr_raw = (char *)hrealloc(tokstr_raw, lexbuf_raw.siz, newbsiz);
- lexbuf_raw.ptr = tokstr_raw + lexbuf_raw.len;
- memset(lexbuf_raw.ptr, 0, newbsiz - lexbuf_raw.siz);
- lexbuf_raw.siz = newbsiz;
- }
-}
-
-/**/
-void
-zshlex_raw_back(void)
-{
- if (!lex_add_raw)
- return;
- lexbuf_raw.ptr--;
- lexbuf_raw.len--;
-}
-
-/**/
-int
-zshlex_raw_mark(int offset)
-{
- if (!lex_add_raw)
- return 0;
- return lexbuf_raw.len + offset;
-}
-
-/**/
-void
-zshlex_raw_back_to_mark(int mark)
-{
- if (!lex_add_raw)
- return;
- lexbuf_raw.ptr = tokstr_raw + mark;
- lexbuf_raw.len = mark;
-}
-
-/*
- * Skip (...) for command-style substitutions: $(...), <(...), >(...)
- *
- * In order to ensure we don't stop at closing parentheses with
- * some other syntactic significance, we'll parse the input until
- * we find an unmatched closing parenthesis. However, we'll throw
- * away the result of the parsing and just keep the string we've built
- * up on the way.
- */
-
-/**/
-static int
-skipcomm(void)
-{
-#ifdef ZSH_OLD_SKIPCOMM
- int pct = 1, c, start = 1;
-
- cmdpush(CS_CMDSUBST);
- SETPARBEGIN
- c = Inpar;
- do {
- int iswhite;
- add(c);
- c = hgetc();
- if (itok(c) || lexstop)
- break;
- iswhite = inblank(c);
- switch (c) {
- case '(':
- pct++;
- break;
- case ')':
- pct--;
- break;
- case '\\':
- add(c);
- c = hgetc();
- break;
- case '\'': {
- int strquote = lexbuf.ptr[-1] == '$';
- add(c);
- STOPHIST
- while ((c = hgetc()) != '\'' && !lexstop) {
- if (c == '\\' && strquote) {
- add(c);
- c = hgetc();
- }
- add(c);
- }
- ALLOWHIST
- break;
- }
- case '\"':
- add(c);
- while ((c = hgetc()) != '\"' && !lexstop)
- if (c == '\\') {
- add(c);
- add(hgetc());
- } else
- add(c);
- break;
- case '`':
- add(c);
- while ((c = hgetc()) != '`' && !lexstop)
- if (c == '\\')
- add(c), add(hgetc());
- else
- add(c);
- break;
- case '#':
- if (start) {
- add(c);
- while ((c = hgetc()) != '\n' && !lexstop)
- add(c);
- iswhite = 1;
- }
- break;
- }
- start = iswhite;
- }
- while (pct);
- if (!lexstop)
- SETPAREND
- cmdpop();
- return lexstop;
-#else
- char *new_tokstr;
- int new_lexstop, new_lex_add_raw;
- int save_infor = infor;
- struct lexbufstate new_lexbuf;
-
- infor = 0;
- cmdpush(CS_CMDSUBST);
- SETPARBEGIN
- add(Inpar);
-
- new_lex_add_raw = lex_add_raw + 1;
- if (!lex_add_raw) {
- /*
- * We'll combine the string so far with the input
- * read in for the command substitution. To do this
- * we'll just propagate the current tokstr etc. as the
- * variables used for adding raw input, and
- * ensure we swap those for the real tokstr etc. at the end.
- *
- * However, we need to save and restore the rest of the
- * lexical and parse state as we're effectively parsing
- * an internal string. Because we're still parsing it from
- * the original input source (we have to --- we don't know
- * when to stop inputting it otherwise and can't rely on
- * the input being recoverable until we've read it) we need
- * to keep the same history context.
- */
- new_tokstr = tokstr;
- new_lexbuf = lexbuf;
-
- /*
- * If we're expanding an alias at this point, we need the whole
- * remaining text as part of the string for the command in
- * parentheses, so don't backtrack. This is different from the
- * usual case where the alias is fully within the command, where
- * we want the unexpanded text so that it will be expanded
- * again when the command in the parentheses is executed.
- *
- * I never wanted to be a software engineer, you know.
- */
- if (inbufflags & INP_ALIAS)
- inbufflags |= INP_RAW_KEEP;
- zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
- hist_in_word(1);
- } else {
- /*
- * Set up for nested command subsitution, however
- * we don't actually need the string until we get
- * back to the top level and recover the lot.
- * The $() body just appears empty.
- *
- * We do need to propagate the raw variables which would
- * otherwise by cleared, though.
- */
- new_tokstr = tokstr_raw;
- new_lexbuf = lexbuf_raw;
-
- zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
- }
- tokstr_raw = new_tokstr;
- lexbuf_raw = new_lexbuf;
- lex_add_raw = new_lex_add_raw;
- /*
- * Don't do any ZLE specials down here: they're only needed
- * when we return the string from the recursive parse.
- * (TBD: this probably means we should be initialising lexflags
- * more consistently.)
- *
- * Note that in that case we're still using the ZLE line reading
- * function at the history layer --- this is consistent with the
- * intention of maintaining the history and input layers across
- * the recursive parsing.
- *
- * Also turn off LEXFLAGS_NEWLINE because this is already skipping
- * across the entire construct, and parse_event() needs embedded
- * newlines to be "real" when looking for the OUTPAR token.
- */
- lexflags &= ~(LEXFLAGS_ZLE|LEXFLAGS_NEWLINE);
- dbparens = 0; /* restored by zcontext_restore_partial() */
-
- if (!parse_event(OUTPAR) || tok != OUTPAR) {
- if (strin) {
- /*
- * Get the rest of the string raw since we don't
- * know where this token ends.
- */
- while (!lexstop)
- (void)ingetc();
- } else
- lexstop = 1;
- }
- /* Outpar lexical token gets added in caller if present */
-
- /*
- * We're going to keep the full raw input string
- * as the current token string after popping the stack.
- */
- new_tokstr = tokstr_raw;
- new_lexbuf = lexbuf_raw;
- /*
- * We're also going to propagate the lexical state:
- * if we couldn't parse the command substitution we
- * can't continue.
- */
- new_lexstop = lexstop;
-
- zcontext_restore_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
-
- if (lex_add_raw) {
- /*
- * Keep going, so retain the raw variables.
- */
- tokstr_raw = new_tokstr;
- lexbuf_raw = new_lexbuf;
- } else {
- if (!new_lexstop) {
- /* Ignore the ')' added on input */
- new_lexbuf.len--;
- *--new_lexbuf.ptr = '\0';
- }
-
- /*
- * Convince the rest of lex.c we were examining a string
- * all along.
- */
- tokstr = new_tokstr;
- lexbuf = new_lexbuf;
- lexstop = new_lexstop;
- hist_in_word(0);
- }
-
- if (!lexstop)
- SETPAREND
- cmdpop();
- infor = save_infor;
-
- return lexstop;
-#endif
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/loop.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/loop.c
deleted file mode 100644
index 1013aeb5..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/loop.c
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * loop.c - loop execution
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zsh.mdh"
-#include "loop.pro"
-
-/* # of nested loops we are in */
-
-/**/
-int loops;
-
-/* # of continue levels */
-
-/**/
-mod_export int contflag;
-
-/* # of break levels */
-
-/**/
-mod_export int breaks;
-
-/**/
-int
-execfor(Estate state, int do_exec)
-{
- Wordcode end, loop;
- wordcode code = state->pc[-1];
- int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
- int last = 0;
- char *name, *str, *cond = NULL, *advance = NULL;
- zlong val = 0;
- LinkList vars = NULL, args = NULL;
- int old_simple_pline = simple_pline;
-
- /* See comments in execwhile() */
- simple_pline = 1;
-
- end = state->pc + WC_FOR_SKIP(code);
-
- if (iscond) {
- str = dupstring(ecgetstr(state, EC_NODUP, NULL));
- singsub(&str);
- if (isset(XTRACE)) {
- char *str2 = dupstring(str);
- untokenize(str2);
- printprompt4();
- fprintf(xtrerr, "%s\n", str2);
- fflush(xtrerr);
- }
- if (!errflag) {
- matheval(str);
- }
- if (errflag) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 1;
- }
- cond = ecgetstr(state, EC_NODUP, &ctok);
- advance = ecgetstr(state, EC_NODUP, &atok);
- } else {
- vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL);
-
- if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
- int htok = 0;
-
- if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 0;
- }
- if (htok) {
- execsubst(args);
- if (errflag) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 1;
- }
- }
- } else {
- char **x;
-
- args = newlinklist();
- for (x = pparams; *x; x++)
- addlinknode(args, dupstring(*x));
- }
- }
-
- if (!args || empty(args))
- lastval = 0;
-
- loops++;
- pushheap();
- cmdpush(CS_FOR);
- loop = state->pc;
- while (!last) {
- if (iscond) {
- if (ctok) {
- str = dupstring(cond);
- singsub(&str);
- } else
- str = cond;
- if (!errflag) {
- while (iblank(*str))
- str++;
- if (*str) {
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "%s\n", str);
- fflush(xtrerr);
- }
- val = mathevali(str);
- } else
- val = 1;
- }
- if (errflag) {
- if (breaks)
- breaks--;
- lastval = 1;
- break;
- }
- if (!val)
- break;
- } else {
- LinkNode node;
- int count = 0;
- for (node = firstnode(vars); node; incnode(node))
- {
- name = (char *)getdata(node);
- if (!args || !(str = (char *) ugetnode(args)))
- {
- if (count) {
- str = "";
- last = 1;
- } else
- break;
- }
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "%s=%s\n", name, str);
- fflush(xtrerr);
- }
- setsparam(name, ztrdup(str));
- count++;
- }
- if (!count)
- break;
- }
- state->pc = loop;
- execlist(state, 1, do_exec && args && empty(args));
- if (breaks) {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (retflag)
- break;
- if (iscond && !errflag) {
- if (atok) {
- str = dupstring(advance);
- singsub(&str);
- } else
- str = advance;
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "%s\n", str);
- fflush(xtrerr);
- }
- if (!errflag)
- matheval(str);
- }
- if (errflag) {
- if (breaks)
- breaks--;
- lastval = 1;
- break;
- }
- freeheap();
- }
- popheap();
- cmdpop();
- loops--;
- simple_pline = old_simple_pline;
- state->pc = end;
- this_noerrexit = 1;
- return lastval;
-}
-
-/**/
-int
-execselect(Estate state, UNUSED(int do_exec))
-{
- Wordcode end, loop;
- wordcode code = state->pc[-1];
- char *str, *s, *name;
- LinkNode n;
- int i, usezle;
- FILE *inp;
- size_t more;
- LinkList args;
- int old_simple_pline = simple_pline;
-
- /* See comments in execwhile() */
- simple_pline = 1;
-
- end = state->pc + WC_FOR_SKIP(code);
- name = ecgetstr(state, EC_NODUP, NULL);
-
- if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
- char **x;
-
- args = newlinklist();
- for (x = pparams; *x; x++)
- addlinknode(args, dupstring(*x));
- } else {
- int htok = 0;
-
- if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 0;
- }
- if (htok) {
- execsubst(args);
- if (errflag) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 1;
- }
- }
- }
- if (!args || empty(args)) {
- state->pc = end;
- simple_pline = old_simple_pline;
- return 0;
- }
- loops++;
-
- pushheap();
- cmdpush(CS_SELECT);
- usezle = interact && SHTTY != -1 && isset(USEZLE);
- inp = fdopen(dup(usezle ? SHTTY : 0), "r");
- more = selectlist(args, 0);
- loop = state->pc;
- for (;;) {
- for (;;) {
- if (empty(bufstack)) {
- if (usezle) {
- int oef = errflag;
-
- isfirstln = 1;
- str = zleentry(ZLE_CMD_READ, &prompt3, NULL,
- 0, ZLCON_SELECT);
- if (errflag)
- str = NULL;
- /* Keep any user interrupt error status */
- errflag = oef | (errflag & ERRFLAG_INT);
- } else {
- str = promptexpand(prompt3, 0, NULL, NULL, NULL);
- zputs(str, stderr);
- free(str);
- fflush(stderr);
- str = fgets(zhalloc(256), 256, inp);
- }
- } else
- str = (char *)getlinknode(bufstack);
- if (!str && !errflag)
- setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
- if (!str || errflag) {
- if (breaks)
- breaks--;
- fprintf(stderr, "\n");
- fflush(stderr);
- goto done;
- }
- if ((s = strchr(str, '\n')))
- *s = '\0';
- if (*str)
- break;
- more = selectlist(args, more);
- }
- setsparam("REPLY", ztrdup(str));
- i = atoi(str);
- if (!i)
- str = "";
- else {
- for (i--, n = firstnode(args); n && i; incnode(n), i--);
- if (n)
- str = (char *) getdata(n);
- else
- str = "";
- }
- setsparam(name, ztrdup(str));
- state->pc = loop;
- execlist(state, 1, 0);
- freeheap();
- if (breaks) {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (retflag || errflag)
- break;
- }
- done:
- cmdpop();
- popheap();
- fclose(inp);
- loops--;
- simple_pline = old_simple_pline;
- state->pc = end;
- this_noerrexit = 1;
- return lastval;
-}
-
-/* And this is used to print select lists. */
-
-/**/
-size_t
-selectlist(LinkList l, size_t start)
-{
- size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
- char **arr, **ap;
-
- zleentry(ZLE_CMD_TRASH);
- arr = hlinklist2array(l, 0);
- for (ap = arr; *ap; ap++)
- if (strlen(*ap) > longest)
- longest = strlen(*ap);
- t0 = ct = ap - arr;
- longest++;
- while (t0)
- t0 /= 10, longest++;
- /* to compensate for added ')' */
- fct = (zterm_columns - 1) / (longest + 3);
- if (fct == 0)
- fct = 1;
- else
- fw = (zterm_columns - 1) / fct;
- colsz = (ct + fct - 1) / fct;
- for (t1 = start; t1 != colsz && t1 - start < zterm_lines - 2; t1++) {
- ap = arr + t1;
- do {
- size_t t2 = strlen(*ap) + 2;
- int t3;
-
- fprintf(stderr, "%d) %s", t3 = ap - arr + 1, *ap);
- while (t3)
- t2++, t3 /= 10;
- for (; t2 < fw; t2++)
- fputc(' ', stderr);
- for (t0 = colsz; t0 && *ap; t0--, ap++);
- }
- while (*ap);
- fputc('\n', stderr);
- }
-
- /* Below is a simple attempt at doing it the Korn Way..
- ap = arr;
- t0 = 0;
- do {
- t0++;
- fprintf(stderr,"%d) %s\n",t0,*ap);
- ap++;
- }
- while (*ap);*/
- fflush(stderr);
-
- return t1 < colsz ? t1 : 0;
-}
-
-/**/
-int
-execwhile(Estate state, UNUSED(int do_exec))
-{
- Wordcode end, loop;
- wordcode code = state->pc[-1];
- int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
- int old_simple_pline = simple_pline;
-
- end = state->pc + WC_WHILE_SKIP(code);
- olderrexit = noerrexit;
- oldval = 0;
- pushheap();
- cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
- loops++;
- loop = state->pc;
-
- if (loop[0] == WC_END && loop[1] == WC_END) {
-
- /* This is an empty loop. Make sure the signal handler sets the
- * flags and then just wait for someone hitting ^C. */
-
- simple_pline = 1;
-
- while (!breaks)
- ;
- breaks--;
-
- simple_pline = old_simple_pline;
- } else
- for (;;) {
- state->pc = loop;
- noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
-
- /* In case the test condition is a functional no-op,
- * make sure signal handlers recognize ^C to end the loop. */
- simple_pline = 1;
-
- execlist(state, 1, 0);
-
- simple_pline = old_simple_pline;
- noerrexit = olderrexit;
- if (!((lastval == 0) ^ isuntil)) {
- if (breaks)
- breaks--;
- if (!retflag)
- lastval = oldval;
- break;
- }
- if (retflag)
- break;
-
- /* In case the loop body is also a functional no-op,
- * make sure signal handlers recognize ^C as above. */
- simple_pline = 1;
-
- execlist(state, 1, 0);
-
- simple_pline = old_simple_pline;
- if (breaks) {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (errflag) {
- lastval = 1;
- break;
- }
- if (retflag)
- break;
- freeheap();
- oldval = lastval;
- }
- cmdpop();
- popheap();
- loops--;
- state->pc = end;
- this_noerrexit = 1;
- return lastval;
-}
-
-/**/
-int
-execrepeat(Estate state, UNUSED(int do_exec))
-{
- Wordcode end, loop;
- wordcode code = state->pc[-1];
- int count, htok = 0;
- char *tmp;
- int old_simple_pline = simple_pline;
-
- /* See comments in execwhile() */
- simple_pline = 1;
-
- end = state->pc + WC_REPEAT_SKIP(code);
-
- lastval = 0;
- tmp = ecgetstr(state, EC_DUPTOK, &htok);
- if (htok)
- singsub(&tmp);
- count = mathevali(tmp);
- if (errflag)
- return 1;
- pushheap();
- cmdpush(CS_REPEAT);
- loops++;
- loop = state->pc;
- while (count-- > 0) {
- state->pc = loop;
- execlist(state, 1, 0);
- freeheap();
- if (breaks) {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (errflag) {
- lastval = 1;
- break;
- }
- if (retflag)
- break;
- }
- cmdpop();
- popheap();
- loops--;
- simple_pline = old_simple_pline;
- state->pc = end;
- this_noerrexit = 1;
- return lastval;
-}
-
-/**/
-int
-execif(Estate state, int do_exec)
-{
- Wordcode end, next;
- wordcode code = state->pc[-1];
- int olderrexit, s = 0, run = 0;
-
- olderrexit = noerrexit;
- end = state->pc + WC_IF_SKIP(code);
-
- noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN;
- while (state->pc < end) {
- code = *state->pc++;
- if (wc_code(code) != WC_IF ||
- (run = (WC_IF_TYPE(code) == WC_IF_ELSE))) {
- if (run)
- run = 2;
- break;
- }
- next = state->pc + WC_IF_SKIP(code);
- cmdpush(s ? CS_ELIF : CS_IF);
- execlist(state, 1, 0);
- cmdpop();
- if (!lastval) {
- run = 1;
- break;
- }
- if (retflag)
- break;
- s = 1;
- state->pc = next;
- }
-
- if (run) {
- /* we need to ignore lastval until we reach execcmd() */
- if (olderrexit)
- noerrexit = olderrexit;
- else if (lastval)
- noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC;
- else
- noerrexit &= ~ (NOERREXIT_EXIT | NOERREXIT_RETURN);
- cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
- execlist(state, 1, do_exec);
- cmdpop();
- } else {
- noerrexit = olderrexit;
- if (!retflag)
- lastval = 0;
- }
- state->pc = end;
- this_noerrexit = 1;
-
- return lastval;
-}
-
-/**/
-int
-execcase(Estate state, int do_exec)
-{
- Wordcode end, next;
- wordcode code = state->pc[-1];
- char *word, *pat;
- int npat, save, nalts, ialt, patok, anypatok;
- Patprog *spprog, pprog;
-
- end = state->pc + WC_CASE_SKIP(code);
-
- word = ecgetstr(state, EC_DUP, NULL);
- singsub(&word);
- untokenize(word);
- anypatok = 0;
-
- cmdpush(CS_CASE);
- while (state->pc < end) {
- code = *state->pc++;
- if (wc_code(code) != WC_CASE)
- break;
-
- save = 0;
- next = state->pc + WC_CASE_SKIP(code);
- nalts = *state->pc++;
- ialt = patok = 0;
-
- if (isset(XTRACE)) {
- printprompt4();
- fprintf(xtrerr, "case %s (", word);
- }
-
- while (!patok && nalts) {
- npat = state->pc[1];
- spprog = state->prog->pats + npat;
- pprog = NULL;
- pat = NULL;
-
- queue_signals();
-
- if (isset(XTRACE)) {
- int htok = 0;
- pat = dupstring(ecrawstr(state->prog, state->pc, &htok));
- if (htok)
- singsub(&pat);
-
- if (ialt++)
- fprintf(stderr, " | ");
- quote_tokenized_output(pat, xtrerr);
- }
-
- if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
- pprog = *spprog;
-
- if (!pprog) {
- if (!pat) {
- char *opat;
- int htok = 0;
-
- pat = dupstring(opat = ecrawstr(state->prog,
- state->pc, &htok));
- if (htok)
- singsub(&pat);
- save = (!(state->prog->flags & EF_HEAP) &&
- !strcmp(pat, opat) && *spprog != dummy_patprog2);
- }
- if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
- NULL)))
- zerr("bad pattern: %s", pat);
- else if (save)
- *spprog = pprog;
- }
- if (pprog && pattry(pprog, word))
- patok = anypatok = 1;
- state->pc += 2;
- nalts--;
-
- unqueue_signals();
- }
- state->pc += 2 * nalts;
- if (isset(XTRACE)) {
- fprintf(xtrerr, ")\n");
- fflush(xtrerr);
- }
- if (patok) {
- execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
- do_exec));
- while (!retflag && wc_code(code) == WC_CASE &&
- WC_CASE_TYPE(code) == WC_CASE_AND && state->pc < end) {
- state->pc = next;
- code = *state->pc++;
- next = state->pc + WC_CASE_SKIP(code);
- nalts = *state->pc++;
- state->pc += 2 * nalts;
- execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
- do_exec));
- }
- if (WC_CASE_TYPE(code) != WC_CASE_TESTAND)
- break;
- }
- state->pc = next;
- }
- cmdpop();
-
- state->pc = end;
-
- if (!anypatok)
- lastval = 0;
- this_noerrexit = 1;
-
- return lastval;
-}
-
-/*
- * Errflag from `try' block, may be reset in `always' block.
- * Accessible from an integer parameter, so needs to be a zlong.
- */
-
-/**/
-zlong
-try_errflag = -1;
-
-/**
- * Corresponding interrupt error status form `try' block.
- */
-
-/**/
-zlong
-try_interrupt = -1;
-
-/**/
-zlong
-try_tryflag = 0;
-
-/**/
-int
-exectry(Estate state, int do_exec)
-{
- Wordcode end, always;
- int endval;
- int save_retflag, save_breaks, save_contflag;
- zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
-
- end = state->pc + WC_TRY_SKIP(state->pc[-1]);
- always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
- state->pc++;
- pushheap();
- cmdpush(CS_CURSH);
-
- /* The :try clause */
- save_try_tryflag = try_tryflag;
- try_tryflag = 1;
-
- execlist(state, 1, do_exec);
-
- try_tryflag = save_try_tryflag;
-
- /* Don't record errflag here, may be reset. However, */
- /* endval should show failure when there is an error. */
- endval = lastval ? lastval : errflag;
-
- freeheap();
-
- cmdpop();
- cmdpush(CS_ALWAYS);
-
- /* The always clause. */
- save_try_errflag = try_errflag;
- save_try_interrupt = try_interrupt;
- try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
- try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0);
- /* We need to reset all errors to allow the block to execute */
- errflag = 0;
- save_retflag = retflag;
- retflag = 0;
- save_breaks = breaks;
- breaks = 0;
- save_contflag = contflag;
- contflag = 0;
-
- state->pc = always;
- execlist(state, 1, do_exec);
-
- if (try_errflag)
- errflag |= ERRFLAG_ERROR;
- else
- errflag &= ~ERRFLAG_ERROR;
- if (try_interrupt)
- errflag |= ERRFLAG_INT;
- else
- errflag &= ~ERRFLAG_INT;
- try_errflag = save_try_errflag;
- try_interrupt = save_try_interrupt;
- if (!retflag)
- retflag = save_retflag;
- if (!breaks)
- breaks = save_breaks;
- if (!contflag)
- contflag = save_contflag;
-
- cmdpop();
- popheap();
- state->pc = end;
-
- return endval;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/makepro.awk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/makepro.awk
deleted file mode 100644
index 0498c154..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/makepro.awk
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# makepro.awk - generate prototype lists
-#
-
-BEGIN {
- aborting = 0
-
- # arg 1 is the name of the file to process
- # arg 2 is the name of the subdirectory it is in
- if(ARGC != 3) {
- aborting = 1
- exit 1
- }
- name = ARGV[1]
- gsub(/^.*\//, "", name)
- gsub(/\.c$/, "", name)
- name = ARGV[2] "_" name
- gsub(/\//, "_", name)
- ARGC--
-
- printf "E#ifndef have_%s_globals\n", name
- printf "E#define have_%s_globals\n", name
- printf "E\n"
-}
-
-# all relevant declarations are preceded by "/**/" on a line by itself
-
-/^\/\*\*\/$/ {
- # The declaration is on following lines. The interesting part might
- # be terminated by a `{' (`int foo(void) { }' or `int bar[] = {')
- # or `;' (`int x;').
- line = ""
- isfunc = 0
- while(1) {
- if(getline <= 0) {
- aborting = 1
- exit 1
- }
- if (line == "" && $0 ~ /^[ \t]*#/) {
- # Directly after the /**/ was a preprocessor line.
- # Spit it out and re-start the outer loop.
- printf "E%s\n", $0
- printf "L%s\n", $0
- next
- }
- gsub(/\t/, " ")
- line = line " " $0
- gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line)
- if(line ~ /\/\*/)
- continue
- # If it is a function definition, note so.
- if(line ~ /\) *(VA_DCL )*[{].*$/) #}
- isfunc = 1
- if(sub(/ *[{;].*$/, "", line)) #}
- break
- }
- if (!match(line, /VA_ALIST/)) {
- # Put spaces around each identifier.
- while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) ||
- match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/))
- line = substr(line, 1, RSTART) " " substr(line, RSTART+1)
- }
- # Separate declarations into a type and a list of declarators.
- # In each declarator, "@{" and "@}" are used in place of parens to
- # mark function parameter lists, and "@!" is used in place of commas
- # in parameter lists. "@<" and "@>" are used in place of
- # non-parameter list parens.
- gsub(/ _ +/, " _ ", line)
- while(1) {
- if(isfunc && match(line, /\([^()]*\)$/))
- line = substr(line, 1, RSTART-1) " _ (" substr(line, RSTART) ")"
- else if(match(line, / _ \(\([^,()]*,/))
- line = substr(line, 1, RSTART+RLENGTH-2) "@!" substr(line, RSTART+RLENGTH)
- else if(match(line, / _ \(\([^,()]*\)\)/))
- line = substr(line, 1, RSTART-1) "@{" substr(line, RSTART+5, RLENGTH-7) "@}" substr(line, RSTART+RLENGTH)
- else if(match(line, /\([^,()]*\)/))
- line = substr(line, 1, RSTART-1) "@<" substr(line, RSTART+1, RLENGTH-2) "@>" substr(line, RSTART+RLENGTH)
- else
- break
- }
- sub(/^ */, "", line)
- match(line, /^((const|enum|mod_export|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/)
- dtype = substr(line, 1, RLENGTH)
- sub(/ *$/, "", dtype)
- if(" " dtype " " ~ / static /)
- locality = "L"
- else
- locality = "E"
- exported = " " dtype " " ~ / mod_export /
- line = substr(line, RLENGTH+1) ","
- # Handle each declarator.
- if (match(line, /VA_ALIST/)) {
- # Already has VARARGS handling.
-
- # Put parens etc. back
- gsub(/@[{]/, "((", line)
- gsub(/@}/, "))", line)
- gsub(/@, "(", line)
- gsub(/@>/, ")", line)
- gsub(/@!/, ",", line)
- sub(/,$/, ";", line)
- gsub(/mod_export/, "mod_import_function", dtype)
- gsub(/VA_ALIST/, "VA_ALIST_PROTO", line)
- sub(/ VA_DCL/, "", line)
-
- if(locality ~ /E/)
- dtype = "extern " dtype
-
- if (match(line, /[_0-9A-Za-z]+\(VA_ALIST/))
- dnam = substr(line, RSTART, RLENGTH-9)
-
- # If this is exported, add it to the exported symbol list.
- if (exported)
- printf "X%s\n", dnam
-
- printf "%s%s %s\n", locality, dtype, line
- } else {
- while(match(line, /^[^,]*,/)) {
- # Separate out the name from the declarator. Use "@+" and "@-"
- # to bracket the name within the declarator. Strip off any
- # initialiser.
- dcltor = substr(line, 1, RLENGTH-1)
- line = substr(line, RLENGTH+1)
- sub(/\=.*$/, "", dcltor)
- match(dcltor, /^([^_0-9A-Za-z]| const )*/)
- dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1)
- match(dcltor, /^.*@\+[_0-9A-Za-z]+/)
- dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1)
- dnam = dcltor
- sub(/^.*@\+/, "", dnam)
- sub(/@-.*$/, "", dnam)
-
- # Put parens etc. back
- gsub(/@[{]/, " _((", dcltor)
- gsub(/@}/, "))", dcltor)
- gsub(/@, "(", dcltor)
- gsub(/@>/, ")", dcltor)
- gsub(/@!/, ",", dcltor)
-
- # If this is exported, add it to the exported symbol list.
- if(exported)
- printf "X%s\n", dnam
-
- # Format the declaration for output
- dcl = dtype " " dcltor ";"
- if(locality ~ /E/)
- dcl = "extern " dcl
- if(isfunc)
- gsub(/ mod_export /, " mod_import_function ", dcl)
- else
- gsub(/ mod_export /, " mod_import_variable ", dcl)
- gsub(/@[+-]/, "", dcl)
- gsub(/ +/, " ", dcl)
- while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
- dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
- printf "%s%s\n", locality, dcl
- }
- }
-}
-
-END {
- if(aborting)
- exit 1
- printf "E\n"
- printf "E#endif /* !have_%s_globals */\n", name
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mem.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mem.c
deleted file mode 100644
index 77e4375f..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mem.c
+++ /dev/null
@@ -1,1899 +0,0 @@
-/*
- * mem.c - memory management
- *
- * 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 "mem.pro"
-
-/*
- There are two ways to allocate memory in zsh. The first way is
- to call zalloc/zshcalloc, which call malloc/calloc directly. It
- is legal to call realloc() or free() on memory allocated this way.
- The second way is to call zhalloc/hcalloc, which allocates memory
- from one of the memory pools on the heap stack. Such memory pools
- will automatically created when the heap allocation routines are
- called. To be sure that they are freed at appropriate times
- one should call pushheap() before one starts using heaps and
- popheap() after that (when the memory allocated on the heaps since
- the last pushheap() isn't needed anymore).
- pushheap() saves the states of all currently allocated heaps and
- popheap() resets them to the last state saved and destroys the
- information about that state. If you called pushheap() and
- allocated some memory on the heaps and then come to a place where
- you don't need the allocated memory anymore but you still want
- to allocate memory on the heap, you should call freeheap(). This
- works like popheap(), only that it doesn't free the information
- about the heap states (i.e. the heaps are like after the call to
- pushheap() and you have to call popheap some time later).
-
- Memory allocated in this way does not have to be freed explicitly;
- it will all be freed when the pool is destroyed. In fact,
- attempting to free this memory may result in a core dump.
-
- If possible, the heaps are allocated using mmap() so that the
- (*real*) heap isn't filled up with empty zsh heaps. If mmap()
- is not available and zsh's own allocator is used, we use a simple trick
- to avoid that: we allocate a large block of memory before allocating
- a heap pool, this memory is freed again immediately after the pool
- is allocated. If there are only small blocks on the free list this
- guarantees that the memory for the pool is at the end of the memory
- which means that we can give it back to the system when the pool is
- freed.
-
- hrealloc(char *p, size_t old, size_t new) is an optimisation
- with a similar interface to realloc(). Typically the new size
- will be larger than the old one, since there is no gain in
- shrinking the allocation (indeed, that will confused hrealloc()
- since it will forget that the unused space once belonged to this
- pointer). However, new == 0 is a special case; then if we
- had to allocate a special heap for this memory it is freed at
- that point.
-*/
-
-#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
-
-#include
-
-/*
- * This definition is designed to enable use of memory mapping on MacOS.
- * However, performance tests indicate that MacOS mapped regions are
- * somewhat slower to allocate than memory from malloc(), so whether
- * using this improves performance depends on details of zhalloc().
- */
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-#if defined(MAP_ANONYMOUS) && defined(MAP_PRIVATE)
-
-#define USE_MMAP 1
-#define MMAP_FLAGS (MAP_ANONYMOUS | MAP_PRIVATE)
-
-#endif
-#endif
-
-#ifdef ZSH_MEM_WARNING
-# ifndef DEBUG
-# define DEBUG 1
-# endif
-#endif
-
-#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
-
-static int h_m[1025], h_push, h_pop, h_free;
-
-#endif
-
-/* Make sure we align to the longest fundamental type. */
-union mem_align {
- zlong l;
- double d;
-};
-
-#define H_ISIZE sizeof(union mem_align)
-#define HEAPSIZE (16384 - H_ISIZE)
-/* Memory available for user data in default arena size */
-#define HEAP_ARENA_SIZE (HEAPSIZE - sizeof(struct heap))
-#define HEAPFREE (16384 - H_ISIZE)
-
-/* Memory available for user data in heap h */
-#define ARENA_SIZEOF(h) ((h)->size - sizeof(struct heap))
-
-/* list of zsh heaps */
-
-static Heap heaps;
-
-/* a heap with free space, not always correct (it will be the last heap
- * if that was newly allocated but it may also be another one) */
-
-static Heap fheap;
-
-/**/
-#ifdef ZSH_HEAP_DEBUG
-/*
- * The heap ID we'll allocate next.
- *
- * We'll avoid using 0 as that means zero-initialised memory
- * containing a heap ID is (correctly) marked as invalid.
- */
-static Heapid next_heap_id = (Heapid)1;
-
-/*
- * The ID of the heap from which we last allocated heap memory.
- * In theory, since we carefully avoid allocating heap memory during
- * interrupts, after any call to zhalloc() or wrappers this should
- * be the ID of the heap containing the memory just returned.
- */
-/**/
-mod_export Heapid last_heap_id;
-
-/*
- * Stack of heaps saved by new_heaps().
- * Assumes old_heaps() will come along and restore it later
- * (outputs an error if old_heaps() is called out of sequence).
- */
-static LinkList heaps_saved;
-
-/*
- * Debugging verbosity. This must be set from a debugger.
- * An 'or' of bits from the enum heap_debug_verbosity.
- */
-static volatile int heap_debug_verbosity;
-
-/*
- * Generate a heap identifier that's unique up to unsigned integer wrap.
- *
- * For the purposes of debugging we won't bother trying to make a
- * heap_id globally unique, which would require checking all existing
- * heaps every time we create an ID and still wouldn't do what we
- * ideally want, which is to make sure the IDs of valid heaps are
- * different from the IDs of no-longer-valid heaps. Given that,
- * we'll just assume that if we haven't tracked the problem when the
- * ID wraps we're out of luck. We could change the type to a long long
- * if we wanted more room
- */
-
-static Heapid
-new_heap_id(void)
-{
- return next_heap_id++;
-}
-
-/**/
-#endif
-
-/* Use new heaps from now on. This returns the old heap-list. */
-
-/**/
-mod_export Heap
-new_heaps(void)
-{
- Heap h;
-
- queue_signals();
- h = heaps;
-
- fheap = heaps = NULL;
- unqueue_signals();
-
-#ifdef ZSH_HEAP_DEBUG
- if (heap_debug_verbosity & HDV_NEW) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT
- " saved, new heaps created.\n", h->heap_id);
- }
- if (!heaps_saved)
- heaps_saved = znewlinklist();
- zpushnode(heaps_saved, h);
-#endif
- return h;
-}
-
-/* Re-install the old heaps again, freeing the new ones. */
-
-/**/
-mod_export void
-old_heaps(Heap old)
-{
- Heap h, n;
-
- queue_signals();
- for (h = heaps; h; h = n) {
- n = h->next;
- DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
-#ifdef ZSH_HEAP_DEBUG
- if (heap_debug_verbosity & HDV_FREE) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT
- "freed in old_heaps().\n", h->heap_id);
- }
-#endif
-#ifdef USE_MMAP
- munmap((void *) h, h->size);
-#else
- zfree(h, HEAPSIZE);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_DESTROY_MEMPOOL((char *)h);
-#endif
- }
- heaps = old;
-#ifdef ZSH_HEAP_DEBUG
- if (heap_debug_verbosity & HDV_OLD) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT
- "restored.\n", heaps->heap_id);
- }
- {
- Heap myold = heaps_saved ? getlinknode(heaps_saved) : NULL;
- if (old != myold)
- {
- fprintf(stderr, "HEAP DEBUG: invalid old heap " HEAPID_FMT
- ", expecting " HEAPID_FMT ".\n", old->heap_id,
- myold->heap_id);
- }
- }
-#endif
- fheap = NULL;
- unqueue_signals();
-}
-
-/* Temporarily switch to other heaps (or back again). */
-
-/**/
-mod_export Heap
-switch_heaps(Heap new)
-{
- Heap h;
-
- queue_signals();
- h = heaps;
-
-#ifdef ZSH_HEAP_DEBUG
- if (heap_debug_verbosity & HDV_SWITCH) {
- fprintf(stderr, "HEAP DEBUG: heap temporarily switched from "
- HEAPID_FMT " to " HEAPID_FMT ".\n", h->heap_id, new->heap_id);
- }
-#endif
- heaps = new;
- fheap = NULL;
- unqueue_signals();
-
- return h;
-}
-
-/* save states of zsh heaps */
-
-/**/
-mod_export void
-pushheap(void)
-{
- Heap h;
- Heapstack hs;
-
- queue_signals();
-
-#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
- h_push++;
-#endif
-
- for (h = heaps; h; h = h->next) {
- DPUTS(!h->used && h->next, "BUG: empty heap");
- hs = (Heapstack) zalloc(sizeof(*hs));
- hs->next = h->sp;
- h->sp = hs;
- hs->used = h->used;
-#ifdef ZSH_HEAP_DEBUG
- hs->heap_id = h->heap_id;
- h->heap_id = new_heap_id();
- if (heap_debug_verbosity & HDV_PUSH) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT " pushed, new id is "
- HEAPID_FMT ".\n",
- hs->heap_id, h->heap_id);
- }
-#endif
- }
- unqueue_signals();
-}
-
-/* reset heaps to previous state */
-
-/**/
-mod_export void
-freeheap(void)
-{
- Heap h, hn, hl = NULL;
-
- queue_signals();
-
-#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
- h_free++;
-#endif
-
- /*
- * When pushheap() is called, it sweeps over the entire heaps list of
- * arenas and marks every one of them with the amount of free space in
- * that arena at that moment. zhalloc() is then allowed to grab bits
- * out of any of those arenas that have free space.
- *
- * Whenever fheap is NULL here, the loop below sweeps back over the
- * entire heap list again, resetting the free space in every arena to
- * the amount stashed by pushheap() and finding the arena with the most
- * free space to optimize zhalloc()'s next search. When there's a lot
- * of stuff already on the heap, this is an enormous amount of work,
- * and performance goes to hell.
- *
- * Therefore, we defer freeing the most recently allocated arena until
- * we reach popheap().
- *
- * However, if the arena to which fheap points is unused, we want to
- * reclaim space in earlier arenas, so we have no choice but to do the
- * sweep for a new fheap.
- */
- if (fheap && !fheap->sp)
- fheap = NULL; /* We used to do this unconditionally */
- /*
- * In other cases, either fheap is already correct, or it has never
- * been set and this loop will do it, or it'll be reset from scratch
- * on the next popheap(). So all that's needed here is to pick up
- * the scan wherever the last pass [or the last popheap()] left off.
- */
- for (h = (fheap ? fheap : heaps); h; h = hn) {
- hn = h->next;
- if (h->sp) {
-#ifdef ZSH_MEM_DEBUG
-#ifdef ZSH_VALGRIND
- VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + h->sp->used,
- h->used - h->sp->used);
-#endif
- memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used);
-#endif
- h->used = h->sp->used;
- if (!fheap) {
- if (h->used < ARENA_SIZEOF(h))
- fheap = h;
- } else if (ARENA_SIZEOF(h) - h->used >
- ARENA_SIZEOF(fheap) - fheap->used)
- fheap = h;
- hl = h;
-#ifdef ZSH_HEAP_DEBUG
- /*
- * As the free makes the heap invalid, give it a new
- * identifier. We're not popping it, so don't use
- * the one in the heap stack.
- */
- {
- Heapid new_id = new_heap_id();
- if (heap_debug_verbosity & HDV_FREE) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT
- " freed, new id is " HEAPID_FMT ".\n",
- h->heap_id, new_id);
- }
- h->heap_id = new_id;
- }
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
-#endif
- } else {
- if (fheap == h)
- fheap = NULL;
- if (h->next) {
- /* We want to cut this out of the arena list if we can */
- if (h == heaps)
- hl = heaps = h->next;
- else if (hl && hl->next == h)
- hl->next = h->next;
- else {
- DPUTS(hl, "hl->next != h when freeing");
- hl = h;
- continue;
- }
- h->next = NULL;
- } else {
- /* Leave an empty arena at the end until popped */
- h->used = 0;
- fheap = hl = h;
- break;
- }
-#ifdef USE_MMAP
- munmap((void *) h, h->size);
-#else
- zfree(h, HEAPSIZE);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_DESTROY_MEMPOOL((char *)h);
-#endif
- }
- }
- if (hl)
- hl->next = NULL;
- else
- heaps = fheap = NULL;
-
- unqueue_signals();
-}
-
-/* reset heap to previous state and destroy state information */
-
-/**/
-mod_export void
-popheap(void)
-{
- Heap h, hn, hl = NULL;
- Heapstack hs;
-
- queue_signals();
-
-#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
- h_pop++;
-#endif
-
- fheap = NULL;
- for (h = heaps; h; h = hn) {
- hn = h->next;
- if ((hs = h->sp)) {
- h->sp = hs->next;
-#ifdef ZSH_MEM_DEBUG
-#ifdef ZSH_VALGRIND
- VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + hs->used,
- h->used - hs->used);
-#endif
- memset(arena(h) + hs->used, 0xff, h->used - hs->used);
-#endif
- h->used = hs->used;
-#ifdef ZSH_HEAP_DEBUG
- if (heap_debug_verbosity & HDV_POP) {
- fprintf(stderr, "HEAP DEBUG: heap " HEAPID_FMT
- " popped, old heap was " HEAPID_FMT ".\n",
- h->heap_id, hs->heap_id);
- }
- h->heap_id = hs->heap_id;
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
-#endif
- if (!fheap) {
- if (h->used < ARENA_SIZEOF(h))
- fheap = h;
- } else if (ARENA_SIZEOF(h) - h->used >
- ARENA_SIZEOF(fheap) - fheap->used)
- fheap = h;
- zfree(hs, sizeof(*hs));
-
- hl = h;
- } else {
- if (h->next) {
- /* We want to cut this out of the arena list if we can */
- if (h == heaps)
- hl = heaps = h->next;
- else if (hl && hl->next == h)
- hl->next = h->next;
- else {
- DPUTS(hl, "hl->next != h when popping");
- hl = h;
- continue;
- }
- h->next = NULL;
- } else if (hl == h) /* This is the last arena of all */
- hl = NULL;
-#ifdef USE_MMAP
- munmap((void *) h, h->size);
-#else
- zfree(h, HEAPSIZE);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_DESTROY_MEMPOOL((char *)h);
-#endif
- }
- }
- if (hl)
- hl->next = NULL;
- else
- heaps = NULL;
-
- unqueue_signals();
-}
-
-#ifdef USE_MMAP
-/*
- * Utility function to allocate a heap area of at least *n bytes.
- * *n will be rounded up to the next page boundary.
- */
-static Heap
-mmap_heap_alloc(size_t *n)
-{
- Heap h;
- static size_t pgsz = 0;
-
- if (!pgsz) {
-
-#ifdef _SC_PAGESIZE
- pgsz = sysconf(_SC_PAGESIZE); /* SVR4 */
-#else
-# ifdef _SC_PAGE_SIZE
- pgsz = sysconf(_SC_PAGE_SIZE); /* HPUX */
-# else
- pgsz = getpagesize();
-# endif
-#endif
-
- pgsz--;
- }
- *n = (*n + pgsz) & ~pgsz;
- h = (Heap) mmap(NULL, *n, PROT_READ | PROT_WRITE,
- MMAP_FLAGS, -1, 0);
- if (h == ((Heap) -1)) {
- zerr("fatal error: out of heap memory");
- exit(1);
- }
-
- return h;
-}
-#endif
-
-/* check whether a pointer is within a memory pool */
-
-/**/
-mod_export void *
-zheapptr(void *p)
-{
- Heap h;
- queue_signals();
- for (h = heaps; h; h = h->next)
- if ((char *)p >= arena(h) &&
- (char *)p + H_ISIZE < arena(h) + ARENA_SIZEOF(h))
- break;
- unqueue_signals();
- return (h ? p : 0);
-}
-
-/* allocate memory from the current memory pool */
-
-/**/
-mod_export void *
-zhalloc(size_t size)
-{
- Heap h, hp = NULL;
- size_t n;
-#ifdef ZSH_VALGRIND
- size_t req_size = size;
-
- if (size == 0)
- return NULL;
-#endif
-
- size = (size + H_ISIZE - 1) & ~(H_ISIZE - 1);
-
- queue_signals();
-
-#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
- h_m[size < (1024 * H_ISIZE) ? (size / H_ISIZE) : 1024]++;
-#endif
-
- /* find a heap with enough free space */
-
- /*
- * This previously assigned:
- * h = ((fheap && ARENA_SIZEOF(fheap) >= (size + fheap->used))
- * ? fheap : heaps);
- * but we think that nothing upstream of fheap has more free space,
- * so why start over at heaps just because fheap has too little?
- */
- for (h = (fheap ? fheap : heaps); h; h = h->next) {
- hp = h;
- if (ARENA_SIZEOF(h) >= (n = size + h->used)) {
- void *ret;
-
- h->used = n;
- ret = arena(h) + n - size;
- unqueue_signals();
-#ifdef ZSH_HEAP_DEBUG
- last_heap_id = h->heap_id;
- if (heap_debug_verbosity & HDV_ALLOC) {
- fprintf(stderr, "HEAP DEBUG: allocated memory from heap "
- HEAPID_FMT ".\n", h->heap_id);
- }
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)ret, req_size);
-#endif
- return ret;
- }
- }
- {
- /* not found, allocate new heap */
-#if defined(ZSH_MEM) && !defined(USE_MMAP)
- static int called = 0;
- void *foo = called ? (void *)malloc(HEAPFREE) : NULL;
- /* tricky, see above */
-#endif
-
- n = HEAP_ARENA_SIZE > size ? HEAPSIZE : size + sizeof(*h);
-
-#ifdef USE_MMAP
- h = mmap_heap_alloc(&n);
-#else
- h = (Heap) zalloc(n);
-#endif
-
-#if defined(ZSH_MEM) && !defined(USE_MMAP)
- if (called)
- zfree(foo, HEAPFREE);
- called = 1;
-#endif
-
- h->size = n;
- h->used = size;
- h->next = NULL;
- h->sp = NULL;
-#ifdef ZSH_HEAP_DEBUG
- h->heap_id = new_heap_id();
- if (heap_debug_verbosity & HDV_CREATE) {
- fprintf(stderr, "HEAP DEBUG: create new heap " HEAPID_FMT ".\n",
- h->heap_id);
- }
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_CREATE_MEMPOOL((char *)h, 0, 0);
- VALGRIND_MAKE_MEM_NOACCESS((char *)arena(h),
- n - ((char *)arena(h)-(char *)h));
- VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)arena(h), req_size);
-#endif
-
- DPUTS(hp && hp->next, "failed to find end of chain in zhalloc");
- if (hp)
- hp->next = h;
- else
- heaps = h;
- fheap = h;
-
- unqueue_signals();
-#ifdef ZSH_HEAP_DEBUG
- last_heap_id = h->heap_id;
- if (heap_debug_verbosity & HDV_ALLOC) {
- fprintf(stderr, "HEAP DEBUG: allocated memory from heap "
- HEAPID_FMT ".\n", h->heap_id);
- }
-#endif
- return arena(h);
- }
-}
-
-/**/
-mod_export void *
-hrealloc(char *p, size_t old, size_t new)
-{
- Heap h, ph;
-
-#ifdef ZSH_VALGRIND
- size_t new_req = new;
-#endif
-
- old = (old + H_ISIZE - 1) & ~(H_ISIZE - 1);
- new = (new + H_ISIZE - 1) & ~(H_ISIZE - 1);
-
- if (old == new)
- return p;
- if (!old && !p)
-#ifdef ZSH_VALGRIND
- return zhalloc(new_req);
-#else
- return zhalloc(new);
-#endif
-
- /* find the heap with p */
-
- queue_signals();
- for (h = heaps, ph = NULL; h; ph = h, h = h->next)
- if (p >= arena(h) && p < arena(h) + ARENA_SIZEOF(h))
- break;
-
- DPUTS(!h, "BUG: hrealloc() called for non-heap memory.");
- DPUTS(h->sp && arena(h) + h->sp->used > p,
- "BUG: hrealloc() wants to realloc pushed memory");
-
- /*
- * If the end of the old chunk is before the used pointer,
- * more memory has been zhalloc'ed afterwards.
- * We can't tell if that's still in use, obviously, since
- * that's the whole point of heap memory.
- * We have no choice other than to grab some more memory
- * somewhere else and copy in the old stuff.
- */
- if (p + old < arena(h) + h->used) {
- if (new > old) {
-#ifdef ZSH_VALGRIND
- char *ptr = (char *) zhalloc(new_req);
-#else
- char *ptr = (char *) zhalloc(new);
-#endif
- memcpy(ptr, p, old);
-#ifdef ZSH_MEM_DEBUG
- memset(p, 0xff, old);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
- /*
- * zhalloc() marked h,ptr,new as an allocation so we don't
- * need to do that here.
- */
-#endif
- unqueue_signals();
- return ptr;
- } else {
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
- if (p) {
- VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p,
- new_req);
- VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
- }
-#endif
- unqueue_signals();
- return new ? p : NULL;
- }
- }
-
- DPUTS(p + old != arena(h) + h->used, "BUG: hrealloc more than allocated");
-
- /*
- * We now know there's nothing afterwards in the heap, now see if
- * there's nothing before. Then we can reallocate the whole thing.
- * Otherwise, we need to keep the stuff at the start of the heap,
- * then allocate a new one too; this is handled below. (This will
- * guarantee we occupy a full heap next time round, provided we
- * don't use the heap for anything else.)
- */
- if (p == arena(h)) {
-#ifdef ZSH_HEAP_DEBUG
- Heapid heap_id = h->heap_id;
-#endif
- /*
- * Zero new seems to be a special case saying we've finished
- * with the specially reallocated memory, see scanner() in glob.c.
- */
- if (!new) {
- if (ph)
- ph->next = h->next;
- else
- heaps = h->next;
- fheap = NULL;
-#ifdef USE_MMAP
- munmap((void *) h, h->size);
-#else
- zfree(h, HEAPSIZE);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_DESTROY_MEMPOOL((char *)h);
-#endif
- unqueue_signals();
- return NULL;
- }
- if (new > ARENA_SIZEOF(h)) {
- Heap hnew;
- /*
- * Not enough memory in this heap. Allocate a new
- * one of sufficient size.
- *
- * To avoid this happening too often, allocate
- * chunks in multiples of HEAPSIZE.
- * (Historical note: there didn't used to be any
- * point in this since we didn't consistently record
- * the allocated size of the heap, but now we do.)
- */
- size_t n = (new + sizeof(*h) + HEAPSIZE);
- n -= n % HEAPSIZE;
- fheap = NULL;
-
-#ifdef USE_MMAP
- {
- /*
- * I don't know any easy portable way of requesting
- * a mmap'd segment be extended, so simply allocate
- * a new one and copy.
- */
- hnew = mmap_heap_alloc(&n);
- /* Copy the entire heap, header (with next pointer) included */
- memcpy(hnew, h, h->size);
- munmap((void *)h, h->size);
- }
-#else
- hnew = (Heap) realloc(h, n);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_FREE((char *)h, p);
- VALGRIND_DESTROY_MEMPOOL((char *)h);
- VALGRIND_CREATE_MEMPOOL((char *)hnew, 0, 0);
- VALGRIND_MEMPOOL_ALLOC((char *)hnew, (char *)arena(hnew),
- new_req);
- VALGRIND_MAKE_MEM_DEFINED((char *)hnew, (char *)arena(hnew));
-#endif
- h = hnew;
-
- h->size = n;
- if (ph)
- ph->next = h;
- else
- heaps = h;
- }
-#ifdef ZSH_VALGRIND
- else {
- VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
- VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
- VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
- }
-#endif
- h->used = new;
-#ifdef ZSH_HEAP_DEBUG
- h->heap_id = heap_id;
-#endif
- unqueue_signals();
- return arena(h);
- }
-#ifndef USE_MMAP
- DPUTS(h->used > ARENA_SIZEOF(h), "BUG: hrealloc at invalid address");
-#endif
- if (h->used + (new - old) <= ARENA_SIZEOF(h)) {
- h->used += new - old;
- unqueue_signals();
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
- VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
- VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
-#endif
- return p;
- } else {
- char *t = zhalloc(new);
- memcpy(t, p, old > new ? new : old);
- h->used -= old;
-#ifdef ZSH_MEM_DEBUG
- memset(p, 0xff, old);
-#endif
-#ifdef ZSH_VALGRIND
- VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
- /* t already marked as allocated by zhalloc() */
-#endif
- unqueue_signals();
- return t;
- }
-}
-
-/**/
-#ifdef ZSH_HEAP_DEBUG
-/*
- * Check if heap_id is the identifier of a currently valid heap,
- * including any heap buried on the stack, or of permanent memory.
- * Return 0 if so, else 1.
- *
- * This gets confused by use of switch_heaps(). That's because so do I.
- */
-
-/**/
-mod_export int
-memory_validate(Heapid heap_id)
-{
- Heap h;
- Heapstack hs;
- LinkNode node;
-
- if (heap_id == HEAPID_PERMANENT)
- return 0;
-
- queue_signals();
- for (h = heaps; h; h = h->next) {
- if (h->heap_id == heap_id) {
- unqueue_signals();
- return 0;
- }
- for (hs = heaps->sp; hs; hs = hs->next) {
- if (hs->heap_id == heap_id) {
- unqueue_signals();
- return 0;
- }
- }
- }
-
- if (heaps_saved) {
- for (node = firstnode(heaps_saved); node; incnode(node)) {
- for (h = (Heap)getdata(node); h; h = h->next) {
- if (h->heap_id == heap_id) {
- unqueue_signals();
- return 0;
- }
- for (hs = heaps->sp; hs; hs = hs->next) {
- if (hs->heap_id == heap_id) {
- unqueue_signals();
- return 0;
- }
- }
- }
- }
- }
-
- unqueue_signals();
- return 1;
-}
-/**/
-#endif
-
-/* allocate memory from the current memory pool and clear it */
-
-/**/
-mod_export void *
-hcalloc(size_t size)
-{
- void *ptr;
-
- ptr = zhalloc(size);
- memset(ptr, 0, size);
- return ptr;
-}
-
-/* allocate permanent memory */
-
-/**/
-mod_export void *
-zalloc(size_t size)
-{
- void *ptr;
-
- if (!size)
- size = 1;
- queue_signals();
- if (!(ptr = (void *) malloc(size))) {
- zerr("fatal error: out of memory");
- exit(1);
- }
- unqueue_signals();
-
- return ptr;
-}
-
-/**/
-mod_export void *
-zshcalloc(size_t size)
-{
- void *ptr = zalloc(size);
- if (!size)
- size = 1;
- memset(ptr, 0, size);
- return ptr;
-}
-
-/* This front-end to realloc is used to make sure we have a realloc *
- * that conforms to POSIX realloc. Older realloc's can fail if *
- * passed a NULL pointer, but POSIX realloc should handle this. A *
- * better solution would be for configure to check if realloc is *
- * POSIX compliant, but I'm not sure how to do that. */
-
-/**/
-mod_export void *
-zrealloc(void *ptr, size_t size)
-{
- queue_signals();
- if (ptr) {
- if (size) {
- /* Do normal realloc */
- if (!(ptr = (void *) realloc(ptr, size))) {
- zerr("fatal error: out of memory");
- exit(1);
- }
- unqueue_signals();
- return ptr;
- }
- else
- /* If ptr is not NULL, but size is zero, *
- * then object pointed to is freed. */
- free(ptr);
-
- ptr = NULL;
- } else {
- /* If ptr is NULL, then behave like malloc */
- if (!(ptr = (void *) malloc(size))) {
- zerr("fatal error: out of memory");
- exit(1);
- }
- }
- unqueue_signals();
-
- return ptr;
-}
-
-/**/
-#ifdef ZSH_MEM
-
-/*
- Below is a simple segment oriented memory allocator for systems on
- which it is better than the system's one. Memory is given in blocks
- aligned to an integer multiple of sizeof(union mem_align), which will
- probably be 64-bit as it is the longer of zlong or double. Each block is
- preceded by a header which contains the length of the data part (in
- bytes). In allocated blocks only this field of the structure m_hdr is
- senseful. In free blocks the second field (next) is a pointer to the next
- free segment on the free list.
-
- On top of this simple allocator there is a second allocator for small
- chunks of data. It should be both faster and less space-consuming than
- using the normal segment mechanism for such blocks.
- For the first M_NSMALL-1 possible sizes memory is allocated in arrays
- that can hold M_SNUM blocks. Each array is stored in one segment of the
- main allocator. In these segments the third field of the header structure
- (free) contains a pointer to the first free block in the array. The
- last field (used) gives the number of already used blocks in the array.
-
- If the macro name ZSH_MEM_DEBUG is defined, some information about the memory
- usage is stored. This information can than be viewed by calling the
- builtin `mem' (which is only available if ZSH_MEM_DEBUG is set).
-
- If ZSH_MEM_WARNING is defined, error messages are printed in case of errors.
-
- If ZSH_SECURE_FREE is defined, free() checks if the given address is really
- one that was returned by malloc(), it ignores it if it wasn't (printing
- an error message if ZSH_MEM_WARNING is also defined).
-*/
-#if !defined(__hpux) && !defined(DGUX) && !defined(__osf__)
-# if defined(_BSD)
-# ifndef HAVE_BRK_PROTO
- extern int brk _((caddr_t));
-# endif
-# ifndef HAVE_SBRK_PROTO
- extern caddr_t sbrk _((int));
-# endif
-# else
-# ifndef HAVE_BRK_PROTO
- extern int brk _((void *));
-# endif
-# ifndef HAVE_SBRK_PROTO
- extern void *sbrk _((int));
-# endif
-# endif
-#endif
-
-#if defined(_BSD) && !defined(STDC_HEADERS)
-# define FREE_RET_T int
-# define FREE_ARG_T char *
-# define FREE_DO_RET
-# define MALLOC_RET_T char *
-# define MALLOC_ARG_T size_t
-#else
-# define FREE_RET_T void
-# define FREE_ARG_T void *
-# define MALLOC_RET_T void *
-# define MALLOC_ARG_T size_t
-#endif
-
-/* structure for building free list in blocks holding small blocks */
-
-struct m_shdr {
- struct m_shdr *next; /* next one on free list */
-#ifdef PAD_64_BIT
- /* dummy to make this 64-bit aligned */
- struct m_shdr *dummy;
-#endif
-};
-
-struct m_hdr {
- zlong len; /* length of memory block */
-#if defined(PAD_64_BIT) && !defined(ZSH_64_BIT_TYPE)
- /* either 1 or 2 zlong's, whichever makes up 64 bits. */
- zlong dummy1;
-#endif
- struct m_hdr *next; /* if free: next on free list
- if block of small blocks: next one with
- small blocks of same size*/
- struct m_shdr *free; /* if block of small blocks: free list */
- zlong used; /* if block of small blocks: number of used
- blocks */
-#if defined(PAD_64_BIT) && !defined(ZSH_64_BIT_TYPE)
- zlong dummy2;
-#endif
-};
-
-
-/* alignment for memory blocks */
-
-#define M_ALIGN (sizeof(union mem_align))
-
-/* length of memory header, length of first field of memory header and
- minimal size of a block left free (if we allocate memory and take a
- block from the free list that is larger than needed, it must have at
- least M_MIN extra bytes to be splitted; if it has, the rest is put on
- the free list) */
-
-#define M_HSIZE (sizeof(struct m_hdr))
-#if defined(PAD_64_BIT) && !defined(ZSH_64_BIT_TYPE)
-# define M_ISIZE (2*sizeof(zlong))
-#else
-# define M_ISIZE (sizeof(zlong))
-#endif
-#define M_MIN (2 * M_ISIZE)
-
-/* M_FREE is the number of bytes that have to be free before memory is
- * given back to the system
- * M_KEEP is the number of bytes that will be kept when memory is given
- * back; note that this has to be less than M_FREE
- * M_ALLOC is the number of extra bytes to request from the system */
-
-#define M_FREE 32768
-#define M_KEEP 16384
-#define M_ALLOC M_KEEP
-
-/* a pointer to the last free block, a pointer to the free list (the blocks
- on this list are kept in order - lowest address first) */
-
-static struct m_hdr *m_lfree, *m_free;
-
-/* system's pagesize */
-
-static long m_pgsz = 0;
-
-/* the highest and the lowest valid memory addresses, kept for fast validity
- checks in free() and to find out if and when we can give memory back to
- the system */
-
-static char *m_high, *m_low;
-
-/* Management of blocks for small blocks:
- Such blocks are kept in lists (one list for each of the sizes that are
- allocated in such blocks). The lists are stored in the m_small array.
- M_SIDX() calculates the index into this array for a given size. M_SNUM
- is the size (in small blocks) of such blocks. M_SLEN() calculates the
- size of the small blocks held in a memory block, given a pointer to the
- header of it. M_SBLEN() gives the size of a memory block that can hold
- an array of small blocks, given the size of these small blocks. M_BSLEN()
- calculates the size of the small blocks held in a memory block, given the
- length of that block (including the header of the memory block. M_NSMALL
- is the number of possible block sizes that small blocks should be used
- for. */
-
-
-#define M_SIDX(S) ((S) / M_ISIZE)
-#define M_SNUM 128
-#define M_SLEN(M) ((M)->len / M_SNUM)
-#if defined(PAD_64_BIT) && !defined(ZSH_64_BIT_TYPE)
-/* Include the dummy in the alignment */
-#define M_SBLEN(S) ((S) * M_SNUM + sizeof(struct m_shdr *) + \
- 2*sizeof(zlong) + sizeof(struct m_hdr *))
-#define M_BSLEN(S) (((S) - sizeof(struct m_shdr *) - \
- 2*sizeof(zlong) - sizeof(struct m_hdr *)) / M_SNUM)
-#else
-#define M_SBLEN(S) ((S) * M_SNUM + sizeof(struct m_shdr *) + \
- sizeof(zlong) + sizeof(struct m_hdr *))
-#define M_BSLEN(S) (((S) - sizeof(struct m_shdr *) - \
- sizeof(zlong) - sizeof(struct m_hdr *)) / M_SNUM)
-#endif
-#define M_NSMALL 8
-
-static struct m_hdr *m_small[M_NSMALL];
-
-#ifdef ZSH_MEM_DEBUG
-
-static int m_s = 0, m_b = 0;
-static int m_m[1025], m_f[1025];
-
-static struct m_hdr *m_l;
-
-#endif /* ZSH_MEM_DEBUG */
-
-MALLOC_RET_T
-malloc(MALLOC_ARG_T size)
-{
- struct m_hdr *m, *mp, *mt;
- long n, s, os = 0;
-#ifndef USE_MMAP
- struct heap *h, *hp, *hf = NULL, *hfp = NULL;
-#endif
-
- /* some systems want malloc to return the highest valid address plus one
- if it is called with an argument of zero.
-
- TODO: really? Suppose we allocate more memory, so
- that this is now in bounds, then a more rational application
- that thinks it can free() anything it malloc'ed, even
- of zero length, calls free for it? Aren't we in big
- trouble? Wouldn't it be safer just to allocate some
- memory anyway?
-
- If the above comment is really correct, then at least
- we need to check in free() if we're freeing memory
- at m_high.
- */
-
- if (!size)
-#if 1
- size = 1;
-#else
- return (MALLOC_RET_T) m_high;
-#endif
-
- queue_signals(); /* just queue signals rather than handling them */
-
- /* first call, get page size */
-
- if (!m_pgsz) {
-
-#ifdef _SC_PAGESIZE
- m_pgsz = sysconf(_SC_PAGESIZE); /* SVR4 */
-#else
-# ifdef _SC_PAGE_SIZE
- m_pgsz = sysconf(_SC_PAGE_SIZE); /* HPUX */
-# else
- m_pgsz = getpagesize();
-# endif
-#endif
-
- m_free = m_lfree = NULL;
- }
- size = (size + M_ALIGN - 1) & ~(M_ALIGN - 1);
-
- /* Do we need a small block? */
-
- if ((s = M_SIDX(size)) && s < M_NSMALL) {
- /* yep, find a memory block with free small blocks of the
- appropriate size (if we find it in this list, this means that
- it has room for at least one more small block) */
- for (mp = NULL, m = m_small[s]; m && !m->free; mp = m, m = m->next);
-
- if (m) {
- /* we found one */
- struct m_shdr *sh = m->free;
-
- m->free = sh->next;
- m->used++;
-
- /* if all small blocks in this block are allocated, the block is
- put at the end of the list blocks with small blocks of this
- size (i.e., we try to keep blocks with free blocks at the
- beginning of the list, to make the search faster) */
-
- if (m->used == M_SNUM && m->next) {
- for (mt = m; mt->next; mt = mt->next);
-
- mt->next = m;
- if (mp)
- mp->next = m->next;
- else
- m_small[s] = m->next;
- m->next = NULL;
- }
-#ifdef ZSH_MEM_DEBUG
- m_m[size / M_ISIZE]++;
-#endif
-
- unqueue_signals();
- return (MALLOC_RET_T) sh;
- }
- /* we still want a small block but there were no block with a free
- small block of the requested size; so we use the real allocation
- routine to allocate a block for small blocks of this size */
- os = size;
- size = M_SBLEN(size);
- } else
- s = 0;
-
- /* search the free list for an block of at least the requested size */
- for (mp = NULL, m = m_free; m && m->len < size; mp = m, m = m->next);
-
-#ifndef USE_MMAP
-
- /* if there is an empty zsh heap at a lower address we steal it and take
- the memory from it, putting the rest on the free list (remember
- that the blocks on the free list are ordered) */
-
- for (hp = NULL, h = heaps; h; hp = h, h = h->next)
- if (!h->used &&
- (!hf || h < hf) &&
- (!m || ((char *)m) > ((char *)h)))
- hf = h, hfp = hp;
-
- if (hf) {
- /* we found such a heap */
- Heapstack hso, hsn;
-
- /* delete structures on the list holding the heap states */
- for (hso = hf->sp; hso; hso = hsn) {
- hsn = hso->next;
- zfree(hso, sizeof(*hso));
- }
- /* take it from the list of heaps */
- if (hfp)
- hfp->next = hf->next;
- else
- heaps = hf->next;
- /* now we simply free it and than search the free list again */
- zfree(hf, HEAPSIZE);
-
- for (mp = NULL, m = m_free; m && m->len < size; mp = m, m = m->next);
- }
-#endif
- if (!m) {
- long nal;
- /* no matching free block was found, we have to request new
- memory from the system */
- n = (size + M_HSIZE + M_ALLOC + m_pgsz - 1) & ~(m_pgsz - 1);
-
- if (((char *)(m = (struct m_hdr *)sbrk(n))) == ((char *)-1)) {
- DPUTS1(1, "MEM: allocation error at sbrk, size %L.", n);
- unqueue_signals();
- return NULL;
- }
- if ((nal = ((long)(char *)m) & (M_ALIGN-1))) {
- if ((char *)sbrk(M_ALIGN - nal) == (char *)-1) {
- DPUTS(1, "MEM: allocation error at sbrk.");
- unqueue_signals();
- return NULL;
- }
- m = (struct m_hdr *) ((char *)m + (M_ALIGN - nal));
- }
- /* set m_low, for the check in free() */
- if (!m_low)
- m_low = (char *)m;
-
-#ifdef ZSH_MEM_DEBUG
- m_s += n;
-
- if (!m_l)
- m_l = m;
-#endif
-
- /* save new highest address */
- m_high = ((char *)m) + n;
-
- /* initialize header */
- m->len = n - M_ISIZE;
- m->next = NULL;
-
- /* put it on the free list and set m_lfree pointing to it */
- if ((mp = m_lfree))
- m_lfree->next = m;
- m_lfree = m;
- }
- if ((n = m->len - size) > M_MIN) {
- /* the block we want to use has more than M_MIN bytes plus the
- number of bytes that were requested; we split it in two and
- leave the rest on the free list */
- struct m_hdr *mtt = (struct m_hdr *)(((char *)m) + M_ISIZE + size);
-
- mtt->len = n - M_ISIZE;
- mtt->next = m->next;
-
- m->len = size;
-
- /* put the rest on the list */
- if (m_lfree == m)
- m_lfree = mtt;
-
- if (mp)
- mp->next = mtt;
- else
- m_free = mtt;
- } else if (mp) {
- /* the block we found wasn't the first one on the free list */
- if (m == m_lfree)
- m_lfree = mp;
- mp->next = m->next;
- } else {
- /* it was the first one */
- m_free = m->next;
- if (m == m_lfree)
- m_lfree = m_free;
- }
-
- if (s) {
- /* we are allocating a block that should hold small blocks */
- struct m_shdr *sh, *shn;
-
- /* build the free list in this block and set `used' filed */
- m->free = sh = (struct m_shdr *)(((char *)m) +
- sizeof(struct m_hdr) + os);
-
- for (n = M_SNUM - 2; n--; sh = shn)
- shn = sh->next = sh + s;
- sh->next = NULL;
-
- m->used = 1;
-
- /* put the block on the list of blocks holding small blocks if
- this size */
- m->next = m_small[s];
- m_small[s] = m;
-
-#ifdef ZSH_MEM_DEBUG
- m_m[os / M_ISIZE]++;
-#endif
-
- unqueue_signals();
- return (MALLOC_RET_T) (((char *)m) + sizeof(struct m_hdr));
- }
-#ifdef ZSH_MEM_DEBUG
- m_m[m->len < (1024 * M_ISIZE) ? (m->len / M_ISIZE) : 1024]++;
-#endif
-
- unqueue_signals();
- return (MALLOC_RET_T) & m->next;
-}
-
-/* this is an internal free(); the second argument may, but need not hold
- the size of the block the first argument is pointing to; if it is the
- right size of this block, freeing it will be faster, though; the value
- 0 for this parameter means: `don't know' */
-
-/**/
-mod_export void
-zfree(void *p, int sz)
-{
- struct m_hdr *m = (struct m_hdr *)(((char *)p) - M_ISIZE), *mp, *mt = NULL;
- int i;
-# ifdef DEBUG
- int osz = sz;
-# endif
-
-#ifdef ZSH_SECURE_FREE
- sz = 0;
-#else
- sz = (sz + M_ALIGN - 1) & ~(M_ALIGN - 1);
-#endif
-
- if (!p)
- return;
-
- /* first a simple check if the given address is valid */
- if (((char *)p) < m_low || ((char *)p) > m_high ||
- ((long)p) & (M_ALIGN - 1)) {
- DPUTS(1, "BUG: attempt to free storage at invalid address");
- return;
- }
-
- queue_signals();
-
- fr_rec:
-
- if ((i = sz / M_ISIZE) < M_NSMALL || !sz)
- /* if the given sizes says that it is a small block, find the
- memory block holding it; we search all blocks with blocks
- of at least the given size; if the size parameter is zero,
- this means, that all blocks are searched */
- for (; i < M_NSMALL; i++) {
- for (mp = NULL, mt = m_small[i];
- mt && (((char *)mt) > ((char *)p) ||
- (((char *)mt) + mt->len) < ((char *)p));
- mp = mt, mt = mt->next);
-
- if (mt) {
- /* we found the block holding the small block */
- struct m_shdr *sh = (struct m_shdr *)p;
-
-#ifdef ZSH_SECURE_FREE
- struct m_shdr *sh2;
-
- /* check if the given address is equal to the address of
- the first small block plus an integer multiple of the
- block size */
- if ((((char *)p) - (((char *)mt) + sizeof(struct m_hdr))) %
- M_BSLEN(mt->len)) {
-
- DPUTS(1, "BUG: attempt to free storage at invalid address");
- unqueue_signals();
- return;
- }
- /* check, if the address is on the (block-intern) free list */
- for (sh2 = mt->free; sh2; sh2 = sh2->next)
- if (((char *)p) == ((char *)sh2)) {
-
- DPUTS(1, "BUG: attempt to free already free storage");
- unqueue_signals();
- return;
- }
-#endif
- DPUTS(M_BSLEN(mt->len) < osz,
- "BUG: attempt to free more than allocated.");
-
-#ifdef ZSH_MEM_DEBUG
- m_f[M_BSLEN(mt->len) / M_ISIZE]++;
- memset(sh, 0xff, M_BSLEN(mt->len));
-#endif
-
- /* put the block onto the free list */
- sh->next = mt->free;
- mt->free = sh;
-
- if (--mt->used) {
- /* if there are still used blocks in this block, we
- put it at the beginning of the list with blocks
- holding small blocks of the same size (since we
- know that there is at least one free block in it,
- this will make allocation of small blocks faster;
- it also guarantees that long living memory blocks
- are preferred over younger ones */
- if (mp) {
- mp->next = mt->next;
- mt->next = m_small[i];
- m_small[i] = mt;
- }
- unqueue_signals();
- return;
- }
- /* if there are no more used small blocks in this
- block, we free the whole block */
- if (mp)
- mp->next = mt->next;
- else
- m_small[i] = mt->next;
-
- m = mt;
- p = (void *) & m->next;
-
- break;
- } else if (sz) {
- /* if we didn't find a block and a size was given, try it
- again as if no size were given */
- sz = 0;
- goto fr_rec;
- }
- }
-#ifdef ZSH_MEM_DEBUG
- if (!mt)
- m_f[m->len < (1024 * M_ISIZE) ? (m->len / M_ISIZE) : 1024]++;
-#endif
-
-#ifdef ZSH_SECURE_FREE
- /* search all memory blocks, if one of them is at the given address */
- for (mt = (struct m_hdr *)m_low;
- ((char *)mt) < m_high;
- mt = (struct m_hdr *)(((char *)mt) + M_ISIZE + mt->len))
- if (((char *)p) == ((char *)&mt->next))
- break;
-
- /* no block was found at the given address */
- if (((char *)mt) >= m_high) {
- DPUTS(1, "BUG: attempt to free storage at invalid address");
- unqueue_signals();
- return;
- }
-#endif
-
- /* see if the block is on the free list */
- for (mp = NULL, mt = m_free; mt && mt < m; mp = mt, mt = mt->next);
-
- if (m == mt) {
- /* it is, ouch! */
- DPUTS(1, "BUG: attempt to free already free storage");
- unqueue_signals();
- return;
- }
- DPUTS(m->len < osz, "BUG: attempt to free more than allocated");
-#ifdef ZSH_MEM_DEBUG
- memset(p, 0xff, m->len);
-#endif
- if (mt && ((char *)mt) == (((char *)m) + M_ISIZE + m->len)) {
- /* the block after the one we are freeing is free, we put them
- together */
- m->len += mt->len + M_ISIZE;
- m->next = mt->next;
-
- if (mt == m_lfree)
- m_lfree = m;
- } else
- m->next = mt;
-
- if (mp && ((char *)m) == (((char *)mp) + M_ISIZE + mp->len)) {
- /* the block before the one we are freeing is free, we put them
- together */
- mp->len += m->len + M_ISIZE;
- mp->next = m->next;
-
- if (m == m_lfree)
- m_lfree = mp;
- } else if (mp)
- /* otherwise, we just put it on the free list */
- mp->next = m;
- else {
- m_free = m;
- if (!m_lfree)
- m_lfree = m_free;
- }
-
- /* if the block we have just freed was at the end of the process heap
- and now there is more than one page size of memory, we can give
- it back to the system (and we do it ;-) */
- if ((((char *)m_lfree) + M_ISIZE + m_lfree->len) == m_high &&
- m_lfree->len >= m_pgsz + M_MIN + M_FREE) {
- long n = (m_lfree->len - M_MIN - M_KEEP) & ~(m_pgsz - 1);
-
- m_lfree->len -= n;
-#ifdef HAVE_BRK
- if (brk(m_high -= n) == -1) {
-#else
- m_high -= n;
- if (sbrk(-n) == (void *)-1) {
-#endif /* HAVE_BRK */
- DPUTS(1, "MEM: allocation error at brk.");
- }
-
-#ifdef ZSH_MEM_DEBUG
- m_b += n;
-#endif
- }
- unqueue_signals();
-}
-
-FREE_RET_T
-free(FREE_ARG_T p)
-{
- zfree(p, 0); /* 0 means: size is unknown */
-
-#ifdef FREE_DO_RET
- return 0;
-#endif
-}
-
-/* this one is for strings (and only strings, real strings, real C strings,
- those that have a zero byte at the end) */
-
-/**/
-mod_export void
-zsfree(char *p)
-{
- if (p)
- zfree(p, strlen(p) + 1);
-}
-
-MALLOC_RET_T
-realloc(MALLOC_RET_T p, MALLOC_ARG_T size)
-{
- struct m_hdr *m = (struct m_hdr *)(((char *)p) - M_ISIZE), *mt;
- char *r;
- int i, l = 0;
-
- /* some system..., see above */
- if (!p && size) {
- queue_signals();
- r = malloc(size);
- unqueue_signals();
- return (MALLOC_RET_T) r;
- }
-
- /* and some systems even do this... */
- if (!p || !size)
- return (MALLOC_RET_T) p;
-
- queue_signals(); /* just queue signals caught rather than handling them */
-
- /* check if we are reallocating a small block, if we do, we have
- to compute the size of the block from the sort of block it is in */
- for (i = 0; i < M_NSMALL; i++) {
- for (mt = m_small[i];
- mt && (((char *)mt) > ((char *)p) ||
- (((char *)mt) + mt->len) < ((char *)p));
- mt = mt->next);
-
- if (mt) {
- l = M_BSLEN(mt->len);
- break;
- }
- }
- if (!l)
- /* otherwise the size of the block is in the memory just before
- the given address */
- l = m->len;
-
- /* now allocate the new block, copy the old contents, and free the
- old block */
- r = malloc(size);
- memcpy(r, (char *)p, (size > l) ? l : size);
- free(p);
-
- unqueue_signals();
- return (MALLOC_RET_T) r;
-}
-
-MALLOC_RET_T
-calloc(MALLOC_ARG_T n, MALLOC_ARG_T size)
-{
- long l;
- char *r;
-
- if (!(l = n * size))
- return (MALLOC_RET_T) m_high;
-
- /*
- * use realloc() (with a NULL `p` argument it behaves exactly the same
- * as malloc() does) to prevent an infinite loop caused by sibling-call
- * optimizations (the malloc() call would otherwise be replaced by an
- * unconditional branch back to line 1719 ad infinitum).
- */
- r = realloc(NULL, l);
-
- memset(r, 0, l);
-
- return (MALLOC_RET_T) r;
-}
-
-#ifdef ZSH_MEM_DEBUG
-
-/**/
-int
-bin_mem(char *name, char **argv, Options ops, int func)
-{
- int i, ii, fi, ui, j;
- struct m_hdr *m, *mf, *ms;
- char *b, *c, buf[40];
- long u = 0, f = 0, to, cu;
-
- queue_signals();
- if (OPT_ISSET(ops,'v')) {
- printf("The lower and the upper addresses of the heap. Diff gives\n");
- printf("the difference between them, i.e. the size of the heap.\n\n");
- }
- printf("low mem %ld\t high mem %ld\t diff %ld\n",
- (long)m_l, (long)m_high, (long)(m_high - ((char *)m_l)));
-
- if (OPT_ISSET(ops,'v')) {
- printf("\nThe number of bytes that were allocated using sbrk() and\n");
- printf("the number of bytes that were given back to the system\n");
- printf("via brk().\n");
- }
- printf("\nsbrk %d\tbrk %d\n", m_s, m_b);
-
- if (OPT_ISSET(ops,'v')) {
- printf("\nInformation about the sizes that were allocated or freed.\n");
- printf("For each size that were used the number of mallocs and\n");
- printf("frees is shown. Diff gives the difference between these\n");
- printf("values, i.e. the number of blocks of that size that is\n");
- printf("currently allocated. Total is the product of size and diff,\n");
- printf("i.e. the number of bytes that are allocated for blocks of\n");
- printf("this size. The last field gives the accumulated number of\n");
- printf("bytes for all sizes.\n");
- }
- printf("\nsize\tmalloc\tfree\tdiff\ttotal\tcum\n");
- for (i = 0, cu = 0; i < 1024; i++)
- if (m_m[i] || m_f[i]) {
- to = (long) i * M_ISIZE * (m_m[i] - m_f[i]);
- printf("%ld\t%d\t%d\t%d\t%ld\t%ld\n",
- (long)i * M_ISIZE, m_m[i], m_f[i], m_m[i] - m_f[i],
- to, (cu += to));
- }
-
- if (m_m[i] || m_f[i])
- printf("big\t%d\t%d\t%d\n", m_m[i], m_f[i], m_m[i] - m_f[i]);
-
- if (OPT_ISSET(ops,'v')) {
- printf("\nThe list of memory blocks. For each block the following\n");
- printf("information is shown:\n\n");
- printf("num\tthe number of this block\n");
- printf("tnum\tlike num but counted separately for used and free\n");
- printf("\tblocks\n");
- printf("addr\tthe address of this block\n");
- printf("len\tthe length of the block\n");
- printf("state\tthe state of this block, this can be:\n");
- printf("\t used\tthis block is used for one big block\n");
- printf("\t free\tthis block is free\n");
- printf("\t small\tthis block is used for an array of small blocks\n");
- printf("cum\tthe accumulated sizes of the blocks, counted\n");
- printf("\tseparately for used and free blocks\n");
- printf("\nFor blocks holding small blocks the number of free\n");
- printf("blocks, the number of used blocks and the size of the\n");
- printf("blocks is shown. For otherwise used blocks the first few\n");
- printf("bytes are shown as an ASCII dump.\n");
- }
- printf("\nblock list:\nnum\ttnum\taddr\t\tlen\tstate\tcum\n");
- for (m = m_l, mf = m_free, ii = fi = ui = 1; ((char *)m) < m_high;
- m = (struct m_hdr *)(((char *)m) + M_ISIZE + m->len), ii++) {
- for (j = 0, ms = NULL; j < M_NSMALL && !ms; j++)
- for (ms = m_small[j]; ms; ms = ms->next)
- if (ms == m)
- break;
-
- if (m == mf)
- buf[0] = '\0';
- else if (m == ms)
- sprintf(buf, "%ld %ld %ld", (long)(M_SNUM - ms->used),
- (long)ms->used,
- (long)(m->len - sizeof(struct m_hdr)) / M_SNUM + 1);
-
- else {
- for (i = 0, b = buf, c = (char *)&m->next; i < 20 && i < m->len;
- i++, c++)
- *b++ = (*c >= ' ' && *c < 127) ? *c : '.';
- *b = '\0';
- }
-
- printf("%d\t%d\t%ld\t%ld\t%s\t%ld\t%s\n", ii,
- (m == mf) ? fi++ : ui++,
- (long)m, (long)m->len,
- (m == mf) ? "free" : ((m == ms) ? "small" : "used"),
- (m == mf) ? (f += m->len) : (u += m->len),
- buf);
-
- if (m == mf)
- mf = mf->next;
- }
-
- if (OPT_ISSET(ops,'v')) {
- printf("\nHere is some information about the small blocks used.\n");
- printf("For each size the arrays with the number of free and the\n");
- printf("number of used blocks are shown.\n");
- }
- printf("\nsmall blocks:\nsize\tblocks (free/used)\n");
-
- for (i = 0; i < M_NSMALL; i++)
- if (m_small[i]) {
- printf("%ld\t", (long)i * M_ISIZE);
-
- for (ii = 0, m = m_small[i]; m; m = m->next) {
- printf("(%ld/%ld) ", (long)(M_SNUM - m->used),
- (long)m->used);
- if (!((++ii) & 7))
- printf("\n\t");
- }
- putchar('\n');
- }
- if (OPT_ISSET(ops,'v')) {
- printf("\n\nBelow is some information about the allocation\n");
- printf("behaviour of the zsh heaps. First the number of times\n");
- printf("pushheap(), popheap(), and freeheap() were called.\n");
- }
- printf("\nzsh heaps:\n\n");
-
- printf("push %d\tpop %d\tfree %d\n\n", h_push, h_pop, h_free);
-
- if (OPT_ISSET(ops,'v')) {
- printf("\nThe next list shows for several sizes the number of times\n");
- printf("memory of this size were taken from heaps.\n\n");
- }
- printf("size\tmalloc\ttotal\n");
- for (i = 0; i < 1024; i++)
- if (h_m[i])
- printf("%ld\t%d\t%ld\n", (long)i * H_ISIZE, h_m[i],
- (long)i * H_ISIZE * h_m[i]);
- if (h_m[1024])
- printf("big\t%d\n", h_m[1024]);
-
- unqueue_signals();
- return 0;
-}
-
-#endif
-
-/**/
-#else /* not ZSH_MEM */
-
-/**/
-mod_export void
-zfree(void *p, UNUSED(int sz))
-{
- free(p);
-}
-
-/**/
-mod_export void
-zsfree(char *p)
-{
- free(p);
-}
-
-/**/
-#endif
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkbltnmlst.sh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkbltnmlst.sh
deleted file mode 100644
index c4611d8b..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkbltnmlst.sh
+++ /dev/null
@@ -1,116 +0,0 @@
-#! /bin/sh
-#
-# mkbltnmlst.sh: generate boot code for linked-in modules
-#
-# Written by Andrew Main
-#
-
-srcdir=${srcdir-`echo $0|sed 's%/[^/][^/]*$%%'`}
-test "x$srcdir" = "x$0" && srcdir=.
-test "x$srcdir" = "x" && srcdir=.
-CFMOD=${CFMOD-$srcdir/../config.modules}
-
-bin_mods="`grep ' link=static' $CFMOD | sed -e '/^#/d' \
--e 's/ .*/ /' -e 's/^name=/ /'`"
-
-x_mods="`grep ' load=yes' $CFMOD | sed -e '/^#/d' -e '/ link=no/d' \
--e 's/ .*/ /' -e 's/^name=/ /'`"
-
-trap "rm -f $1; exit 1" 1 2 15
-
-exec > $1
-
-for x_mod in $x_mods; do
- modfile="`grep '^name='$x_mod' ' $CFMOD | sed -e 's/^.* modfile=//' \
- -e 's/ .*//'`"
- if test "x$modfile" = x; then
- echo >&2 "WARNING: no name for \`$x_mod' in $CFMOD (ignored)"
- continue
- fi
- case "$bin_mods" in
- *" $x_mod "*)
- echo "/* linked-in known module \`$x_mod' */"
- linked=yes
- ;;
- *)
- echo "#ifdef DYNAMIC"
- echo "/* non-linked-in known module \`$x_mod' */"
- linked=no
- esac
- unset moddeps autofeatures autofeatures_emu
- . $srcdir/../$modfile
- if test "x$autofeatures" != x; then
- if test "x$autofeatures_emu" != x; then
- echo " {"
- echo " char *zsh_features[] = { "
- for feature in $autofeatures; do
- echo " \"$feature\","
- done
- echo " NULL"
- echo " }; "
- echo " char *emu_features[] = { "
- for feature in $autofeatures_emu; do
- echo " \"$feature\","
- done
- echo " NULL"
- echo " }; "
- echo " autofeatures(\"zsh\", \"$x_mod\","
- echo " EMULATION(EMULATE_ZSH) ? zsh_features : emu_features,"
- echo " 0, 1);"
- echo " }"
- else
- echo " if (EMULATION(EMULATE_ZSH)) {"
- echo " char *features[] = { "
- for feature in $autofeatures; do
- echo " \"$feature\","
- done
- echo " NULL"
- echo " }; "
- echo " autofeatures(\"zsh\", \"$x_mod\", features, 0, 1);"
- echo " }"
- fi
- fi
- for dep in $moddeps; do
- echo " add_dep(\"$x_mod\", \"$dep\");"
- done
- test "x$linked" = xno && echo "#endif"
-done
-
-echo
-done_mods=" "
-for bin_mod in $bin_mods; do
- q_bin_mod=`echo $bin_mod | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
- modfile="`grep '^name='$bin_mod' ' $CFMOD | sed -e 's/^.* modfile=//' \
- -e 's/ .*//'`"
- echo "/* linked-in module \`$bin_mod' */"
- unset moddeps
- . $srcdir/../$modfile
- for dep in $moddeps; do
- # This assumes there are no circular dependencies in the builtin
- # modules. Better ordering of config.modules would be necessary
- # to enforce stricter dependency checking.
- case $bin_mods in
- *" $dep "*)
- echo " /* depends on \`$dep' */" ;;
- *) echo >&2 "ERROR: linked-in module \`$bin_mod' depends on \`$dep'"
- rm -f $1
- exit 1 ;;
- esac
- done
- echo " {"
- echo " extern int setup_${q_bin_mod} _((Module));"
- echo " extern int boot_${q_bin_mod} _((Module));"
- echo " extern int features_${q_bin_mod} _((Module,char***));"
- echo " extern int enables_${q_bin_mod} _((Module,int**));"
- echo " extern int cleanup_${q_bin_mod} _((Module));"
- echo " extern int finish_${q_bin_mod} _((Module));"
- echo
- echo " register_module(\"$bin_mod\","
- echo " setup_${q_bin_mod},"
- echo " features_${q_bin_mod},"
- echo " enables_${q_bin_mod},"
- echo " boot_${q_bin_mod},"
- echo " cleanup_${q_bin_mod}, finish_${q_bin_mod});"
- echo " }"
- done_mods="$done_mods$bin_mod "
-done
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkmakemod.sh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkmakemod.sh
deleted file mode 100644
index 140bf706..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/mkmakemod.sh
+++ /dev/null
@@ -1,468 +0,0 @@
-#!/bin/sh
-#
-# mkmakemod.sh: generate Makefile.in files for module building
-#
-# Options:
-# -m = file is already generated; only build the second stage
-# -i = do not build second stage
-#
-# Args:
-# $1 = subdirectory to look in, relative to $top_srcdir
-# $2 = final output filename, within the $1 directory
-#
-# This script must be run from the top-level build directory, and $top_srcdir
-# must be set correctly in the environment.
-#
-# This looks in $1, and uses all the *.mdd files there. Each .mdd file
-# defines one module. The .mdd file is actually a shell script, which will
-# be sourced. It may define the following shell variables:
-#
-# name name of this module
-# moddeps modules on which this module depends (default none)
-# nozshdep non-empty indicates no dependence on the `zsh/main' pseudo-module
-# alwayslink if non-empty, always link the module into the executable
-# autofeatures features defined by the module, for autoloading
-# autofeatures_emu As autofeatures, but for non-zsh emulation modes
-# objects .o files making up this module (*must* be defined)
-# proto .syms files for this module (default generated from $objects)
-# headers extra headers for this module (default none)
-# hdrdeps extra headers on which the .mdh depends (default none)
-# otherincs extra headers that are included indirectly (default none)
-#
-# The .mdd file may also include a Makefile.in fragment between lines
-# `:<<\Make' and `Make' -- this will be copied into Makemod.in.
-#
-# The resulting Makemod.in knows how to build each module that is defined.
-# For each module it also knows how to build a .mdh file. Each source file
-# should #include the .mdh file for the module it is a part of. The .mdh
-# file #includes the .mdh files for any module dependencies, then each of
-# $headers, and then each .epro (for global declarations). It will
-# be recreated if any of the dependency .mdh files changes, or if any of
-# $headers or $hdrdeps changes. When anything depends on it, all the .epros
-# and $otherincs will be made up to date, but the .mdh file won't actually
-# be rebuilt if those files change.
-#
-# The order of sections of the output file is thus:
-# simple generated macros
-# macros generated from *.mdd
-# included Makemod.in.in
-# rules generated from *.mdd
-# The order dependencies are basically that the generated macros are required
-# in Makemod.in.in, but some of the macros that it creates are needed in the
-# later rules.
-#
-
-# sed script to normalise a pathname
-sed_normalise='
- s,^,/,
- s,$,/,
- :1
- s,/\./,/,
- t1
- :2
- s,/[^/.][^/]*/\.\./,/,
- s,/\.[^/.][^/]*/\.\./,/,
- s,/\.\.[^/][^/]*/\.\./,/,
- t2
- s,^/$,.,
- s,^/,,
- s,\(.\)/$,\1,
-'
-
-# decide which stages to process
-first_stage=true
-second_stage=true
-if test ."$1" = .-m; then
- shift
- first_stage=false
-elif test ."$1" = .-i; then
- shift
- second_stage=false
-fi
-
-top_srcdir=`echo $top_srcdir | sed "$sed_normalise"`
-the_subdir=$1
-the_makefile=$2
-
-if $first_stage; then
-
- dir_top=`echo $the_subdir | sed 's,[^/][^/]*,..,g'`
-
- trap "rm -f $the_subdir/${the_makefile}.in; exit 1" 1 2 15
- echo "creating $the_subdir/${the_makefile}.in"
- exec 3>&1 >$the_subdir/${the_makefile}.in
- echo "##### ${the_makefile}.in generated automatically by mkmakemod.sh"
- echo "##### DO NOT EDIT!"
- echo
- echo "##### ===== DEFINITIONS ===== #####"
- echo
- echo "makefile = ${the_makefile}"
- echo "dir_top = ${dir_top}"
- echo "subdir = ${the_subdir}"
- echo
-
- bin_mods=`grep link=static ./config.modules | \
- sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`
- dyn_mods="`grep link=dynamic ./config.modules | \
- sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`"
- module_list="${bin_mods}${dyn_mods}"
-
- if grep '^#define DYNAMIC ' config.h >/dev/null; then
- is_dynamic=true
- else
- is_dynamic=false
- fi
-
- here_mddnames=
- all_subdirs=
- all_modobjs=
- all_modules=
- all_mdds=
- all_mdhs=
- all_proto=
- lastsub=//
- for module in $module_list; do
- modfile="`grep '^name='$module' ' ./config.modules | \
- sed -e 's/^.* modfile=//' -e 's/ .*//'`"
- case $modfile in
- $the_subdir/$lastsub/*) ;;
- $the_subdir/*/*)
- lastsub=`echo $modfile | sed 's,^'$the_subdir'/,,;s,/[^/]*$,,'`
- case "$all_subdirs " in
- *" $lastsub "* ) ;;
- * )
- all_subdirs="$all_subdirs $lastsub"
- ;;
- esac
- ;;
- $the_subdir/*)
- mddname=`echo $modfile | sed 's,^.*/,,;s,\.mdd$,,'`
- here_mddnames="$here_mddnames $mddname"
- build=$is_dynamic
- case $is_dynamic@$bin_mods in
- *" $module "*)
- build=true
- all_modobjs="$all_modobjs modobjs.${mddname}" ;;
- true@*)
- all_modules="$all_modules ${mddname}.\$(DL_EXT)" ;;
- esac
- all_mdds="$all_mdds ${mddname}.mdd"
- $build && all_mdhs="$all_mdhs ${mddname}.mdh"
- $build && all_proto="$all_proto proto.${mddname}"
- ;;
- esac
- done
- echo "MODOBJS =$all_modobjs"
- echo "MODULES =$all_modules"
- echo "MDDS =$all_mdds"
- echo "MDHS =$all_mdhs"
- echo "PROTOS =$all_proto"
- echo "SUBDIRS =$all_subdirs"
- echo
- echo "ENTRYOBJ = \$(dir_src)/modentry..o"
- echo "NNTRYOBJ ="
- echo "ENTRYOPT = -emodentry"
- echo "NNTRYOPT ="
- echo
-
- echo "##### ===== INCLUDING Makemod.in.in ===== #####"
- echo
- cat $top_srcdir/Src/Makemod.in.in
- echo
-
- case $the_subdir in
- Src) modobjs_sed= ;;
- Src/*) modobjs_sed="| sed 's\" \" "`echo $the_subdir | sed 's,^Src/,,'`"/\"g' " ;;
- *) modobjs_sed="| sed 's\" \" ../$the_subdir/\"g' " ;;
- esac
-
- other_mdhs=
- remote_mdhs=
- other_exports=
- remote_exports=
- other_modules=
- remote_modules=
- for mddname in $here_mddnames; do
-
- unset name moddeps nozshdep alwayslink hasexport
- unset autofeatures autofeatures_emu
- unset objects proto headers hdrdeps otherincs
- . $top_srcdir/$the_subdir/${mddname}.mdd
- q_name=`echo $name | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
- test -n "${moddeps+set}" || moddeps=
- test -n "$nozshdep" || moddeps="$moddeps zsh/main"
- test -n "${proto+set}" ||
- proto=`echo $objects '' | sed 's,\.o ,.syms ,g'`
-
- dobjects=`echo $objects '' | sed 's,\.o ,..o ,g'`
- modhdeps=
- mododeps=
- exportdeps=
- imports=
- q_moddeps=
- for dep in $moddeps; do
- depfile="`grep '^name='$dep' ' ./config.modules | \
- sed -e 's/^.* modfile=//' -e 's/ .*//'`"
- q_dep=`echo $dep | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
- q_moddeps="$q_moddeps $q_dep"
- eval `echo $depfile | sed 's,/\([^/]*\)\.mdd$,;depbase=\1,;s,^,loc=,'`
- case "$binmod" in
- *" $dep "* )
- dep=zsh/main
- ;;
- esac
-
- case $the_subdir in
- $loc)
- mdh="${depbase}.mdh"
- export="${depbase}.export"
- case "$dep" in
- zsh/main )
- mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
- ;;
- * )
- mdll="${depbase}.\$(DL_EXT) "
- ;;
- esac
- ;;
- $loc/*)
- mdh="\$(dir_top)/$loc/${depbase}.mdh"
- case "$other_mdhs " in
- *" $mdh "*) ;;
- *) other_mdhs="$other_mdhs $mdh" ;;
- esac
- export="\$(dir_top)/$loc/${depbase}.export"
- case "$other_exports " in
- *" $export "*) ;;
- *) other_exports="$other_exports $export" ;;
- esac
- case "$dep" in
- zsh/main )
- mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
- ;;
- * )
- mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
- ;;
- esac
- case "$other_modules " in
- *" $mdll "*) ;;
- *) other_modules="$other_modules $mdll" ;;
- esac
- ;;
- *)
- mdh="\$(dir_top)/$loc/${depbase}.mdh"
- case "$remote_mdhs " in
- *" $mdh "*) ;;
- *) remote_mdhs="$remote_mdhs $mdh" ;;
- esac
- export="\$(dir_top)/$loc/${depbase}.export"
- case "$remote_exports " in
- *" $export "*) ;;
- *) remote_exports="$remote_exports $export" ;;
- esac
- case "$dep" in
- zsh/main )
- mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
- ;;
- * )
- mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
- ;;
- esac
- case "$remote_modules " in
- *" $mdll "*) ;;
- *) remote_modules="$remote_modules $mdll" ;;
- esac
- ;;
- esac
- modhdeps="$modhdeps $mdh"
- exportdeps="$exportdeps $export"
- imports="$imports \$(IMPOPT)$export"
- case "$mododeps " in
- *" $mdll "* )
- :
- ;;
- * )
- mododeps="$mododeps $mdll"
- ;;
- esac
- done
-
- echo "##### ===== DEPENDENCIES GENERATED FROM ${mddname}.mdd ===== #####"
- echo
- echo "MODOBJS_${mddname} = $objects"
- echo "MODDOBJS_${mddname} = $dobjects \$(@E@NTRYOBJ)"
- echo "SYMS_${mddname} = $proto"
- echo "EPRO_${mddname} = "`echo $proto '' | sed 's,\.syms ,.epro ,g'`
- echo "INCS_${mddname} = \$(EPRO_${mddname}) $otherincs"
- echo "EXPIMP_${mddname} = $imports \$(EXPOPT)$mddname.export"
- echo "NXPIMP_${mddname} ="
- echo "LINKMODS_${mddname} = $mododeps"
- echo "NOLINKMODS_${mddname} = "
- echo
- echo "proto.${mddname}: \$(EPRO_${mddname})"
- echo "\$(SYMS_${mddname}): \$(PROTODEPS)"
- echo
- echo "${mddname}.export: \$(SYMS_${mddname})"
- echo " @( echo '#!'; cat \$(SYMS_${mddname}) | sed -n '/^X/{s/^X//;p;}' | sort -u ) > \$@"
- echo
- echo "modobjs.${mddname}: \$(MODOBJS_${mddname})"
- echo " @echo '' \$(MODOBJS_${mddname}) $modobjs_sed>> \$(dir_src)/stamp-modobjs.tmp"
- echo
- if test -z "$alwayslink"; then
- case " $all_modules" in *" ${mddname}."*)
- echo "install.modules-here: install.modules.${mddname}"
- echo "uninstall.modules-here: uninstall.modules.${mddname}"
- echo
- ;; esac
- instsubdir=`echo $name | sed 's,^,/,;s,/[^/]*$,,'`
- echo "install.modules.${mddname}: ${mddname}.\$(DL_EXT)"
- echo " \$(SHELL) \$(sdir_top)/mkinstalldirs \$(DESTDIR)\$(MODDIR)${instsubdir}"
- echo " \$(INSTALL_PROGRAM) \$(STRIPFLAGS) ${mddname}.\$(DL_EXT) \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
- echo
- echo "uninstall.modules.${mddname}:"
- echo " rm -f \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
- echo
- echo "${mddname}.\$(DL_EXT): \$(MODDOBJS_${mddname}) ${mddname}.export $exportdeps \$(@LINKMODS@_${mddname})"
- echo ' rm -f $@'
- echo " \$(DLLINK) \$(@E@XPIMP_$mddname) \$(@E@NTRYOPT) \$(MODDOBJS_${mddname}) \$(@LINKMODS@_${mddname}) \$(LIBS) "
- echo
- fi
- echo "${mddname}.mdhi: ${mddname}.mdhs \$(INCS_${mddname})"
- echo " @test -f \$@ || echo 'do not delete this file' > \$@"
- echo
- echo "${mddname}.mdhs: ${mddname}.mdd"
- echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
- echo " @if cmp -s ${mddname}.mdh ${mddname}.mdh.tmp; then \\"
- echo " rm -f ${mddname}.mdh.tmp; \\"
- echo " echo \"\\\`${mddname}.mdh' is up to date.\"; \\"
- echo " else \\"
- echo " mv -f ${mddname}.mdh.tmp ${mddname}.mdh; \\"
- echo " echo \"Updated \\\`${mddname}.mdh'.\"; \\"
- echo " fi"
- echo " echo 'timestamp for ${mddname}.mdh against ${mddname}.mdd' > \$@"
- echo
- echo "${mddname}.mdh: ${modhdeps} ${headers} ${hdrdeps} ${mddname}.mdhi"
- echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
- echo " @mv -f ${mddname}.mdh.tmp ${mddname}.mdh"
- echo " @echo \"Updated \\\`${mddname}.mdh'.\""
- echo
- echo "${mddname}.mdh.tmp:"
- echo " @( \\"
- echo " echo '#ifndef have_${q_name}_module'; \\"
- echo " echo '#define have_${q_name}_module'; \\"
- echo " echo; \\"
- echo " echo '# ifndef IMPORTING_MODULE_${q_name}'; \\"
- echo " if test @SHORTBOOTNAMES@ = yes; then \\"
- echo " echo '# ifndef MODULE'; \\"
- echo " fi; \\"
- echo " echo '# define boot_ boot_${q_name}'; \\"
- echo " echo '# define cleanup_ cleanup_${q_name}'; \\"
- echo " echo '# define features_ features_${q_name}'; \\"
- echo " echo '# define enables_ enables_${q_name}'; \\"
- echo " echo '# define setup_ setup_${q_name}'; \\"
- echo " echo '# define finish_ finish_${q_name}'; \\"
- echo " if test @SHORTBOOTNAMES@ = yes; then \\"
- echo " echo '# endif /* !MODULE */'; \\"
- echo " fi; \\"
- echo " echo '# endif /* !IMPORTING_MODULE_${q_name} */'; \\"
- echo " echo; \\"
- if test -n "$moddeps"; then (
- set x $q_moddeps
- echo " echo '/* Module dependencies */'; \\"
- for hdep in $modhdeps; do
- shift
- echo " echo '# define IMPORTING_MODULE_${1} 1'; \\"
- echo " echo '# include \"${hdep}\"'; \\"
- done
- echo " echo; \\"
- ) fi
- if test -n "$headers"; then
- echo " echo '/* Extra headers for this module */'; \\"
- echo " for hdr in $headers; do \\"
- echo " echo '# include \"'\$\$hdr'\"'; \\"
- echo " done; \\"
- echo " echo; \\"
- fi
- if test -n "$proto"; then
- echo " echo '# undef mod_import_variable'; \\"
- echo " echo '# undef mod_import_function'; \\"
- echo " echo '# if defined(IMPORTING_MODULE_${q_name}) && defined(MODULE)'; \\"
- echo " echo '# define mod_import_variable @MOD_IMPORT_VARIABLE@'; \\"
- echo " echo '# define mod_import_function @MOD_IMPORT_FUNCTION@'; \\"
- echo " echo '# else'; \\"
- echo " echo '# define mod_import_function'; \\"
- echo " echo '# define mod_import_variable'; \\"
- echo " echo '# endif /* IMPORTING_MODULE_${q_name} && MODULE */'; \\"
- echo " for epro in \$(EPRO_${mddname}); do \\"
- echo " echo '# include \"'\$\$epro'\"'; \\"
- echo " done; \\"
- echo " echo '# undef mod_import_variable'; \\"
- echo " echo '# define mod_import_variable'; \\"
- echo " echo '# undef mod_import_variable'; \\"
- echo " echo '# define mod_import_variable'; \\"
- echo " echo '# ifndef mod_export'; \\"
- echo " echo '# define mod_export @MOD_EXPORT@'; \\"
- echo " echo '# endif /* mod_export */'; \\"
- echo " echo; \\"
- fi
- echo " echo '#endif /* !have_${q_name}_module */'; \\"
- echo " ) > \$@"
- echo
- echo "\$(MODOBJS_${mddname}) \$(MODDOBJS_${mddname}): ${mddname}.mdh"
- sed -e '/^ *: *<< *\\Make *$/,/^Make$/!d' \
- -e 's/^ *: *<< *\\Make *$//; /^Make$/d' \
- < $top_srcdir/$the_subdir/${mddname}.mdd
- echo
-
- done
-
- if test -n "$remote_mdhs$other_mdhs$remote_exports$other_exports$remote_modules$other_modules"; then
- echo "##### ===== DEPENDENCIES FOR REMOTE MODULES ===== #####"
- echo
- for mdh in $remote_mdhs; do
- echo "$mdh: FORCE"
- echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$mdh"
- echo
- done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
- if test -n "$other_mdhs"; then
- echo "${other_mdhs}:" | sed 's,^ ,,'
- echo " false # A. should only happen with make -n"
- echo
- fi
- for export in $remote_exports; do
- echo "$export: FORCE"
- echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$export"
- echo
- done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
- if test -n "$other_exports"; then
- echo "${other_exports}:" | sed 's,^ ,,'
- echo " false # B. should only happen with make -n"
- echo
- fi
- for mdll in $remote_modules; do
- echo "$mdll: FORCE"
- echo " @cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$mdll"
- echo
- done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
- if test -n "$other_modules"; then
- echo "${other_modules}:" | sed 's,^ ,,'
- echo " false # C. should only happen with make -n"
- echo
- fi
- fi
-
- echo "##### End of ${the_makefile}.in"
-
- exec >&3 3>&-
-
-fi
-
-if $second_stage ; then
- trap "rm -f $the_subdir/${the_makefile}; exit 1" 1 2 15
-
- ${CONFIG_SHELL-/bin/sh} ./config.status \
- --file=$the_subdir/${the_makefile}:$the_subdir/${the_makefile}.in ||
- exit 1
-fi
-
-exit 0
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/module.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/module.c
deleted file mode 100644
index 4ae78310..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/module.c
+++ /dev/null
@@ -1,3641 +0,0 @@
-/*
- * module.c - deal with dynamic modules
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1996-1997 Zoltán Hidvégi
- * 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 Zoltán Hidvégi 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 Zoltán Hidvégi and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Zoltán Hidvégi 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 Zoltán Hidvégi and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- */
-
-#include "zsh.mdh"
-#include "module.pro"
-
-/*
- * List of linked-in modules.
- * This is set up at boot and remains for the life of the shell;
- * entries do not appear in "zmodload" listings.
- */
-
-/**/
-LinkList linkedmodules;
-
-/* $module_path ($MODULE_PATH) */
-
-/**/
-char **module_path;
-
-/* Hash of modules */
-
-/**/
-mod_export HashTable modulestab;
-
-/*
- * Bit flags passed as the "flags" argument of a autofeaturefn_t.
- * Used in other places, such as the final argument to
- * do_module_features().
- */
-enum {
- /*
- * `-i' option: ignore errors pertaining to redefinitions,
- * or indicate to do_module_features() that it should be
- * silent.
- */
- FEAT_IGNORE = 0x0001,
- /* If a condition, condition is infix rather than prefix */
- FEAT_INFIX = 0x0002,
- /*
- * Enable all features in the module when autoloading.
- * This is the traditional zmodload -a behaviour;
- * zmodload -Fa only enables features explicitly marked for
- * autoloading.
- */
- FEAT_AUTOALL = 0x0004,
- /*
- * Remove feature: alternative to "-X:NAME" used if
- * X is passed separately from NAME.
- */
- FEAT_REMOVE = 0x0008,
- /*
- * For do_module_features(). Check that any autoloads
- * for the module are actually provided.
- */
- FEAT_CHECKAUTO = 0x0010
-};
-
-/*
- * All functions to add or remove autoloadable features fit
- * the following prototype.
- *
- * "module" is the name of the module.
- *
- * "feature" is the name of the feature, minus any type prefix.
- *
- * "flags" is a set of the bits above.
- *
- * The return value is 0 for success, -1 for failure with no
- * message needed, and one of the following to indicate the calling
- * function should print a message:
- *
- * 1: failed to add [type] `[feature]'
- * 2: [feature]: no such [type]
- * 3: [feature]: [type] is already defined
- */
-typedef int (*autofeaturefn_t)(const char *module, const char *feature,
- int flags);
-
-/* Bits in the second argument to find_module. */
-enum {
- /*
- * Resolve any aliases to the underlying module.
- */
- FINDMOD_ALIASP = 0x0001,
- /*
- * Create an element for the module in the list if
- * it is not found.
- */
- FINDMOD_CREATE = 0x0002,
-};
-
-static void
-freemodulenode(HashNode hn)
-{
- Module m = (Module) hn;
-
- if (m->node.flags & MOD_ALIAS)
- zsfree(m->u.alias);
- zsfree(m->node.nam);
- if (m->autoloads)
- freelinklist(m->autoloads, freestr);
- if (m->deps)
- freelinklist(m->deps, freestr);
- zfree(m, sizeof(*m));
-}
-
-/* flags argument to printmodulenode */
-enum {
- /* -L flag, output zmodload commands */
- PRINTMOD_LIST = 0x0001,
- /* -e flag */
- PRINTMOD_EXIST = 0x0002,
- /* -A flag */
- PRINTMOD_ALIAS = 0x0004,
- /* -d flag */
- PRINTMOD_DEPS = 0x0008,
- /* -F flag */
- PRINTMOD_FEATURES = 0x0010,
- /* -l flag in combination with -L flag */
- PRINTMOD_LISTALL = 0x0020,
- /* -a flag */
- PRINTMOD_AUTO = 0x0040
-};
-
-/* Scan function for printing module details */
-
-static void
-printmodulenode(HashNode hn, int flags)
-{
- Module m = (Module)hn;
- /*
- * If we check for a module loaded under an alias, we
- * need the name of the alias. We can use it in other
- * cases, too.
- */
- const char *modname = m->node.nam;
-
- if (flags & PRINTMOD_DEPS) {
- /*
- * Print the module's dependencies.
- */
- LinkNode n;
-
- if (!m->deps)
- return;
-
- if (flags & PRINTMOD_LIST) {
- printf("zmodload -d ");
- if (modname[0] == '-')
- fputs("-- ", stdout);
- quotedzputs(modname, stdout);
- } else {
- nicezputs(modname, stdout);
- putchar(':');
- }
- for (n = firstnode(m->deps); n; incnode(n)) {
- putchar(' ');
- if (flags & PRINTMOD_LIST)
- quotedzputs((char *) getdata(n), stdout);
- else
- nicezputs((char *) getdata(n), stdout);
- }
- } else if (flags & PRINTMOD_EXIST) {
- /*
- * Just print the module name, provided the module is
- * present under an alias or otherwise.
- */
- if (m->node.flags & MOD_ALIAS) {
- if (!(flags & PRINTMOD_ALIAS) ||
- !(m = find_module(m->u.alias, FINDMOD_ALIASP, NULL)))
- return;
- }
- if (!m->u.handle || (m->node.flags & MOD_UNLOAD))
- return;
- nicezputs(modname, stdout);
- } else if (m->node.flags & MOD_ALIAS) {
- /*
- * Normal listing, but for aliases.
- */
- if (flags & PRINTMOD_LIST) {
- printf("zmodload -A ");
- if (modname[0] == '-')
- fputs("-- ", stdout);
- quotedzputs(modname, stdout);
- putchar('=');
- quotedzputs(m->u.alias, stdout);
- } else {
- nicezputs(modname, stdout);
- fputs(" -> ", stdout);
- nicezputs(m->u.alias, stdout);
- }
- } else if (m->u.handle || (flags & PRINTMOD_AUTO)) {
- /*
- * Loaded module.
- */
- if (flags & PRINTMOD_LIST) {
- /*
- * List with -L format. Possibly we are printing
- * features, either enables or autoloads.
- */
- char **features = NULL;
- int *enables = NULL;
- if (flags & PRINTMOD_AUTO) {
- if (!m->autoloads || !firstnode(m->autoloads))
- return;
- } else if (flags & PRINTMOD_FEATURES) {
- if (features_module(m, &features) ||
- enables_module(m, &enables) ||
- !*features)
- return;
- }
- printf("zmodload ");
- if (flags & PRINTMOD_AUTO) {
- fputs("-Fa ", stdout);
- } else if (features)
- fputs("-F ", stdout);
- if(modname[0] == '-')
- fputs("-- ", stdout);
- quotedzputs(modname, stdout);
- if (flags & PRINTMOD_AUTO) {
- LinkNode an;
- for (an = firstnode(m->autoloads); an; incnode(an)) {
- putchar(' ');
- quotedzputs((char *)getdata(an), stdout);
- }
- } else if (features) {
- const char *f;
- while ((f = *features++)) {
- int on = *enables++;
- if (flags & PRINTMOD_LISTALL)
- printf(" %s", on ? "+" : "-");
- else if (!on)
- continue;
- else
- putchar(' ');
- quotedzputs(f, stdout);
- }
- }
- } else /* -l */
- nicezputs(modname, stdout);
- } else
- return;
- putchar('\n');
-}
-
-/**/
-HashTable
-newmoduletable(int size, char const *name)
-{
- HashTable ht;
- ht = newhashtable(size, name, NULL);
-
- ht->hash = hasher;
- ht->emptytable = emptyhashtable;
- ht->filltable = NULL;
- ht->cmpnodes = strcmp;
- ht->addnode = addhashnode;
- /* DISABLED is not supported */
- ht->getnode = gethashnode2;
- ht->getnode2 = gethashnode2;
- ht->removenode = removehashnode;
- ht->disablenode = NULL;
- ht->enablenode = NULL;
- ht->freenode = freemodulenode;
- ht->printnode = printmodulenode;
-
- return ht;
-}
-
-/************************************************************************
- * zsh/main standard module functions
- ************************************************************************/
-
-/* The `zsh/main' module contains all the base code that can't actually be *
- * built as a separate module. It is initialised by main(), so there's *
- * nothing for the boot function to do. */
-
-/**/
-int
-setup_(UNUSED(Module m))
-{
- return 0;
-}
-
-/**/
-int
-features_(UNUSED(Module m), UNUSED(char ***features))
-{
- /*
- * There are lots and lots of features, but they're not
- * handled here.
- */
- return 1;
-}
-
-/**/
-int
-enables_(UNUSED(Module m), UNUSED(int **enables))
-{
- return 1;
-}
-
-/**/
-int
-boot_(UNUSED(Module m))
-{
- return 0;
-}
-
-/**/
-int
-cleanup_(UNUSED(Module m))
-{
- return 0;
-}
-
-/**/
-int
-finish_(UNUSED(Module m))
-{
- return 0;
-}
-
-
-/************************************************************************
- * Module utility functions
- ************************************************************************/
-
-/* This registers a builtin module. */
-
-/**/
-void
-register_module(char *n, Module_void_func setup,
- Module_features_func features,
- Module_enables_func enables,
- Module_void_func boot,
- Module_void_func cleanup,
- Module_void_func finish)
-{
- Linkedmod m;
-
- m = (Linkedmod) zalloc(sizeof(*m));
-
- m->name = ztrdup(n);
- m->setup = setup;
- m->features = features;
- m->enables = enables;
- m->boot = boot;
- m->cleanup = cleanup;
- m->finish = finish;
-
- zaddlinknode(linkedmodules, m);
-}
-
-/* Check if a module is linked in. */
-
-/**/
-Linkedmod
-module_linked(char const *name)
-{
- LinkNode node;
-
- for (node = firstnode(linkedmodules); node; incnode(node))
- if (!strcmp(((Linkedmod) getdata(node))->name, name))
- return (Linkedmod) getdata(node);
-
- return NULL;
-}
-
-
-/************************************************************************
- * Support for the various feature types.
- * First, builtins.
- ************************************************************************/
-
-/* addbuiltin() can be used to add a new builtin. It returns zero on *
- * success, 1 on failure. The only possible type of failure is that *
- * a builtin with the specified name already exists. An autoloaded *
- * builtin can be replaced using this function. */
-
-/**/
-static int
-addbuiltin(Builtin b)
-{
- Builtin bn = (Builtin) builtintab->getnode2(builtintab, b->node.nam);
- if (bn && (bn->node.flags & BINF_ADDED))
- return 1;
- if (bn)
- builtintab->freenode(builtintab->removenode(builtintab, b->node.nam));
- builtintab->addnode(builtintab, b->node.nam, b);
- return 0;
-}
-
-/* Define an autoloadable builtin. It returns 0 on success, or 1 on *
- * failure. The only possible cause of failure is that a builtin *
- * with the specified name already exists. */
-
-/**/
-static int
-add_autobin(const char *module, const char *bnam, int flags)
-{
- Builtin bn;
- int ret;
-
- bn = zshcalloc(sizeof(*bn));
- bn->node.nam = ztrdup(bnam);
- bn->optstr = ztrdup(module);
- if (flags & FEAT_AUTOALL)
- bn->node.flags |= BINF_AUTOALL;
- if ((ret = addbuiltin(bn))) {
- builtintab->freenode(&bn->node);
- if (!(flags & FEAT_IGNORE))
- return 1;
- }
- return 0;
-}
-
-/* Remove the builtin added previously by addbuiltin(). Returns *
- * zero on succes and -1 if there is no builtin with that name. */
-
-/**/
-int
-deletebuiltin(const char *nam)
-{
- Builtin bn;
-
- bn = (Builtin) builtintab->removenode(builtintab, nam);
- if (!bn)
- return -1;
- builtintab->freenode(&bn->node);
- return 0;
-}
-
-/* Remove an autoloaded added by add_autobin */
-
-/**/
-static int
-del_autobin(UNUSED(const char *module), const char *bnam, int flags)
-{
- Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam);
- if (!bn) {
- if(!(flags & FEAT_IGNORE))
- return 2;
- } else if (bn->node.flags & BINF_ADDED) {
- if (!(flags & FEAT_IGNORE))
- return 3;
- } else
- deletebuiltin(bnam);
-
- return 0;
-}
-
-/*
- * Manipulate a set of builtins. This should be called
- * via setfeatureenables() (or, usually, via the next level up,
- * handlefeatures()).
- *
- * "nam" is the name of the calling code builtin, probably "zmodload".
- *
- * "binl" is the builtin table containing an array of "size" builtins.
- *
- * "e" is either NULL, in which case all builtins in the
- * table are removed, or else an array corresponding to "binl"
- * with a 1 for builtins that are to be added and a 0 for builtins
- * that are to be removed. Any builtin already in the appropriate
- * state is left alone.
- *
- * Returns 1 on any error, 0 for success. The recommended way
- * of handling errors is to compare the enables passed down
- * with the set retrieved after the error to find what failed.
- */
-
-/**/
-static int
-setbuiltins(char const *nam, Builtin binl, int size, int *e)
-{
- int ret = 0, n;
-
- for(n = 0; n < size; n++) {
- Builtin b = &binl[n];
- if (e && *e++) {
- if (b->node.flags & BINF_ADDED)
- continue;
- if (addbuiltin(b)) {
- zwarnnam(nam,
- "name clash when adding builtin `%s'", b->node.nam);
- ret = 1;
- } else {
- b->node.flags |= BINF_ADDED;
- }
- } else {
- if (!(b->node.flags & BINF_ADDED))
- continue;
- if (deletebuiltin(b->node.nam)) {
- zwarnnam(nam, "builtin `%s' already deleted", b->node.nam);
- ret = 1;
- } else {
- b->node.flags &= ~BINF_ADDED;
- }
- }
- }
- return ret;
-}
-
-/*
- * Add multiple builtins. binl points to a table of `size' builtin
- * structures. Those for which (.flags & BINF_ADDED) is false are to be
- * added; that flag is set if they succeed.
- *
- * If any fail, an error message is printed, using nam as the leading name.
- * Returns 0 on success, 1 for any failure.
- *
- * This should not be used from a module; instead, use handlefeatures().
- */
-
-/**/
-mod_export int
-addbuiltins(char const *nam, Builtin binl, int size)
-{
- int ret = 0, n;
-
- for(n = 0; n < size; n++) {
- Builtin b = &binl[n];
- if(b->node.flags & BINF_ADDED)
- continue;
- if(addbuiltin(b)) {
- zwarnnam(nam, "name clash when adding builtin `%s'", b->node.nam);
- ret = 1;
- } else {
- b->node.flags |= BINF_ADDED;
- }
- }
- return ret;
-}
-
-
-/************************************************************************
- * Function wrappers.
- ************************************************************************/
-
-/* The list of function wrappers defined. */
-
-/**/
-FuncWrap wrappers;
-
-/* This adds a definition for a wrapper. Return value is one in case of *
- * error and zero if all went fine. */
-
-/**/
-mod_export int
-addwrapper(Module m, FuncWrap w)
-{
- FuncWrap p, q;
-
- /*
- * We can't add a wrapper to an alias, since it's supposed
- * to behave identically to the resolved module. This shouldn't
- * happen since we usually add wrappers when a real module is
- * loaded.
- */
- if (m->node.flags & MOD_ALIAS)
- return 1;
-
- if (w->flags & WRAPF_ADDED)
- return 1;
- for (p = wrappers, q = NULL; p; q = p, p = p->next);
- if (q)
- q->next = w;
- else
- wrappers = w;
- w->next = NULL;
- w->flags |= WRAPF_ADDED;
- w->module = m;
-
- return 0;
-}
-
-/* This removes the given wrapper definition from the list. Returned is *
- * one in case of error and zero otherwise. */
-
-/**/
-mod_export int
-deletewrapper(Module m, FuncWrap w)
-{
- FuncWrap p, q;
-
- if (m->node.flags & MOD_ALIAS)
- return 1;
-
- if (w->flags & WRAPF_ADDED) {
- for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next);
-
- if (p) {
- if (q)
- q->next = p->next;
- else
- wrappers = p->next;
- p->flags &= ~WRAPF_ADDED;
-
- return 0;
- }
- }
- return 1;
-}
-
-
-/************************************************************************
- * Conditions.
- ************************************************************************/
-
-/* The list of module-defined conditions. */
-
-/**/
-mod_export Conddef condtab;
-
-/* This gets a condition definition with the given name. The first *
- * argument says if we have to look for an infix condition. The last *
- * argument is non-zero if we should autoload modules if needed. */
-
-/**/
-Conddef
-getconddef(int inf, const char *name, int autol)
-{
- Conddef p;
- int f = 1;
- char *lookup, *s;
-
- /* detokenize the Dash to the form encoded in lookup tables */
- lookup = dupstring(name);
- if (!lookup)
- return NULL;
- for (s = lookup; *s != '\0'; s++) {
- if (*s == Dash)
- *s = '-';
- }
-
- do {
- for (p = condtab; p; p = p->next) {
- if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
- !strcmp(lookup, p->name))
- break;
- }
- if (autol && p && p->module) {
- /*
- * This is a definition for an autoloaded condition; load the
- * module if we haven't tried that already.
- */
- if (f) {
- (void)ensurefeature(p->module,
- (p->flags & CONDF_INFIX) ? "C:" : "c:",
- (p->flags & CONDF_AUTOALL) ? NULL : lookup);
- f = 0;
- p = NULL;
- } else {
- deleteconddef(p);
- return NULL;
- }
- } else
- break;
- } while (!p);
-
- return p;
-}
-
-/*
- * This adds the given condition definition. The return value is zero on *
- * success and 1 on failure. If there is a matching definition for an *
- * autoloaded condition, it is removed.
- *
- * This is used for adding both an autoload definition or
- * a real condition. In the latter case the caller is responsible
- * for setting the CONDF_ADDED flag.
- */
-
-/**/
-static int
-addconddef(Conddef c)
-{
- Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0);
-
- if (p) {
- if (!p->module || (p->flags & CONDF_ADDED))
- return 1;
- /* There is an autoload definition. */
-
- deleteconddef(p);
- }
- c->next = condtab;
- condtab = c;
- return 0;
-}
-
-/* This removes the given condition definition from the list(s). If this *
- * is a definition for a autoloaded condition, the memory is freed. */
-
-/**/
-int
-deleteconddef(Conddef c)
-{
- Conddef p, q;
-
- for (p = condtab, q = NULL; p && p != c; q = p, p = p->next);
-
- if (p) {
- if (q)
- q->next = p->next;
- else
- condtab = p->next;
-
- if (p->module) {
- /* autoloaded, free it */
- zsfree(p->name);
- zsfree(p->module);
- zfree(p, sizeof(*p));
- }
- return 0;
- }
- return -1;
-}
-
-/*
- * Add or remove sets of conditions. The interface is
- * identical to setbuiltins().
- */
-
-/**/
-static int
-setconddefs(char const *nam, Conddef c, int size, int *e)
-{
- int ret = 0;
-
- while (size--) {
- if (e && *e++) {
- if (c->flags & CONDF_ADDED) {
- c++;
- continue;
- }
- if (addconddef(c)) {
- zwarnnam(nam, "name clash when adding condition `%s'",
- c->name);
- ret = 1;
- } else {
- c->flags |= CONDF_ADDED;
- }
- } else {
- if (!(c->flags & CONDF_ADDED)) {
- c++;
- continue;
- }
- if (deleteconddef(c)) {
- zwarnnam(nam, "condition `%s' already deleted", c->name);
- ret = 1;
- } else {
- c->flags &= ~CONDF_ADDED;
- }
- }
- c++;
- }
- return ret;
-}
-
-/* This adds a definition for autoloading a module for a condition. */
-
-/**/
-static int
-add_autocond(const char *module, const char *cnam, int flags)
-{
- Conddef c;
-
- c = (Conddef) zalloc(sizeof(*c));
-
- c->name = ztrdup(cnam);
- c->flags = ((flags & FEAT_INFIX) ? CONDF_INFIX : 0);
- if (flags & FEAT_AUTOALL)
- c->flags |= CONDF_AUTOALL;
- c->module = ztrdup(module);
-
- if (addconddef(c)) {
- zsfree(c->name);
- zsfree(c->module);
- zfree(c, sizeof(*c));
-
- if (!(flags & FEAT_IGNORE))
- return 1;
- }
- return 0;
-}
-
-/* Remove a condition added with add_autocond */
-
-/**/
-static int
-del_autocond(UNUSED(const char *modnam), const char *cnam, int flags)
-{
- Conddef cd = getconddef((flags & FEAT_INFIX) ? 1 : 0, cnam, 0);
-
- if (!cd) {
- if (!(flags & FEAT_IGNORE)) {
- return 2;
- }
- } else if (cd->flags & CONDF_ADDED) {
- if (!(flags & FEAT_IGNORE))
- return 3;
- } else
- deleteconddef(cd);
-
- return 0;
-}
-
-/************************************************************************
- * Hook functions.
- ************************************************************************/
-
-/* This list of hook functions defined. */
-
-/**/
-Hookdef hooktab;
-
-/* Find a hook definition given the name. */
-
-/**/
-Hookdef
-gethookdef(char *n)
-{
- Hookdef p;
-
- for (p = hooktab; p; p = p->next)
- if (!strcmp(n, p->name))
- return p;
- return NULL;
-}
-
-/* This adds the given hook definition. The return value is zero on *
- * success and 1 on failure. */
-
-/**/
-int
-addhookdef(Hookdef h)
-{
- if (gethookdef(h->name))
- return 1;
-
- h->next = hooktab;
- hooktab = h;
- h->funcs = znewlinklist();
-
- return 0;
-}
-
-/*
- * This adds multiple hook definitions. This is like addbuiltins().
- * This allows a NULL module because we call it from init.c.
- */
-
-/**/
-mod_export int
-addhookdefs(Module m, Hookdef h, int size)
-{
- int ret = 0;
-
- while (size--) {
- if (addhookdef(h)) {
- zwarnnam(m ? m->node.nam : NULL,
- "name clash when adding hook `%s'", h->name);
- ret = 1;
- }
- h++;
- }
- return ret;
-}
-
-/* Delete hook definitions. */
-
-/**/
-int
-deletehookdef(Hookdef h)
-{
- Hookdef p, q;
-
- for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next);
-
- if (!p)
- return 1;
-
- if (q)
- q->next = p->next;
- else
- hooktab = p->next;
- freelinklist(p->funcs, NULL);
- return 0;
-}
-
-/* Remove multiple hook definitions. */
-
-/**/
-mod_export int
-deletehookdefs(UNUSED(Module m), Hookdef h, int size)
-{
- int ret = 0;
-
- while (size--) {
- if (deletehookdef(h))
- ret = 1;
- h++;
- }
- return ret;
-}
-
-/* Add a function to a hook. */
-
-/**/
-int
-addhookdeffunc(Hookdef h, Hookfn f)
-{
- zaddlinknode(h->funcs, (void *) f);
-
- return 0;
-}
-
-/**/
-mod_export int
-addhookfunc(char *n, Hookfn f)
-{
- Hookdef h = gethookdef(n);
-
- if (h)
- return addhookdeffunc(h, f);
- return 1;
-}
-
-/* Delete a function from a hook. */
-
-/**/
-int
-deletehookdeffunc(Hookdef h, Hookfn f)
-{
- LinkNode p;
-
- for (p = firstnode(h->funcs); p; incnode(p))
- if (f == (Hookfn) getdata(p)) {
- remnode(h->funcs, p);
- return 0;
- }
- return 1;
-}
-
-/* Delete a hook. */
-
-/**/
-mod_export int
-deletehookfunc(char *n, Hookfn f)
-{
- Hookdef h = gethookdef(n);
-
- if (h)
- return deletehookdeffunc(h, f);
- return 1;
-}
-
-/* Run the function(s) for a hook. */
-
-/**/
-mod_export int
-runhookdef(Hookdef h, void *d)
-{
- if (empty(h->funcs)) {
- if (h->def)
- return h->def(h, d);
- return 0;
- } else if (h->flags & HOOKF_ALL) {
- LinkNode p;
- int r;
-
- for (p = firstnode(h->funcs); p; incnode(p))
- if ((r = ((Hookfn) getdata(p))(h, d)))
- return r;
- if (h->def)
- return h->def(h, d);
- return 0;
- } else
- return ((Hookfn) getdata(lastnode(h->funcs)))(h, d);
-}
-
-
-
-/************************************************************************
- * Shell parameters.
- ************************************************************************/
-
-/*
- * Check that it's possible to add a parameter. This
- * requires that either there's no parameter already present,
- * or it's a global parameter marked for autoloading.
- *
- * The special status 2 is to indicate it didn't work but
- * -i was in use so we didn't print a warning.
- */
-
-static int
-checkaddparam(const char *nam, int opt_i)
-{
- Param pm;
-
- if (!(pm = (Param) gethashnode2(paramtab, nam)))
- return 0;
-
- if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) {
- /*
- * -i suppresses "it's already that way" warnings,
- * but not "this can't possibly work" warnings, so we print
- * the message anyway if there's a local parameter blocking
- * the parameter we want to add, not if there's a
- * non-autoloadable parameter already there. This
- * is consistent with the way add_auto* functions work.
- */
- if (!opt_i || !pm->level) {
- zwarn("Can't add module parameter `%s': %s",
- nam, pm->level ?
- "local parameter exists" :
- "parameter already exists");
- return 1;
- }
- return 2;
- }
-
- unsetparam_pm(pm, 0, 1);
- return 0;
-}
-
-/* This adds the given parameter definition. The return value is zero on *
- * success and 1 on failure. */
-
-/**/
-int
-addparamdef(Paramdef d)
-{
- Param pm;
-
- if (checkaddparam(d->name, 0))
- return 1;
-
- if (d->getnfn) {
- if (!(pm = createspecialhash(d->name, d->getnfn,
- d->scantfn, d->flags)))
- return 1;
- }
- else if (!(pm = createparam(d->name, d->flags)) &&
- !(pm = (Param) paramtab->getnode(paramtab, d->name)))
- return 1;
-
- d->pm = pm;
- pm->level = 0;
- if (d->var)
- pm->u.data = d->var;
- if (d->var || d->gsu) {
- /*
- * If no get/set/unset class, use the appropriate
- * variable type, else use the one supplied.
- */
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- pm->gsu.s = d->gsu ? (GsuScalar)d->gsu : &varscalar_gsu;
- break;
-
- case PM_INTEGER:
- pm->gsu.i = d->gsu ? (GsuInteger)d->gsu : &varinteger_gsu;
- break;
-
- case PM_FFLOAT:
- case PM_EFLOAT:
- pm->gsu.f = d->gsu;
- break;
-
- case PM_ARRAY:
- pm->gsu.a = d->gsu ? (GsuArray)d->gsu : &vararray_gsu;
- break;
-
- case PM_HASHED:
- /* hashes may behave like standard hashes */
- if (d->gsu)
- pm->gsu.h = (GsuHash)d->gsu;
- break;
-
- default:
- unsetparam_pm(pm, 0, 1);
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Delete parameters defined. No error checking yet. */
-
-/**/
-int
-deleteparamdef(Paramdef d)
-{
- Param pm = (Param) paramtab->getnode(paramtab, d->name);
-
- if (!pm)
- return 1;
- if (pm != d->pm) {
- /*
- * See if the parameter has been hidden. If so,
- * bring it to the front to unset it.
- */
- Param prevpm, searchpm;
- for (prevpm = pm, searchpm = pm->old;
- searchpm;
- prevpm = searchpm, searchpm = searchpm->old)
- if (searchpm == d->pm)
- break;
-
- if (!searchpm)
- return 1;
-
- paramtab->removenode(paramtab, pm->node.nam);
- prevpm->old = searchpm->old;
- searchpm->old = pm;
- paramtab->addnode(paramtab, searchpm->node.nam, searchpm);
-
- pm = searchpm;
- }
- pm->node.flags = (pm->node.flags & ~PM_READONLY) | PM_REMOVABLE;
- unsetparam_pm(pm, 0, 1);
- d->pm = NULL;
- return 0;
-}
-
-/*
- * Add or remove sets of parameters. The interface is
- * identical to setbuiltins().
- */
-
-/**/
-static int
-setparamdefs(char const *nam, Paramdef d, int size, int *e)
-{
- int ret = 0;
-
- while (size--) {
- if (e && *e++) {
- if (d->pm) {
- d++;
- continue;
- }
- if (addparamdef(d)) {
- zwarnnam(nam, "error when adding parameter `%s'", d->name);
- ret = 1;
- }
- } else {
- if (!d->pm) {
- d++;
- continue;
- }
- if (deleteparamdef(d)) {
- zwarnnam(nam, "parameter `%s' already deleted", d->name);
- ret = 1;
- }
- }
- d++;
- }
- return ret;
-}
-
-/* This adds a definition for autoloading a module for a parameter. */
-
-/**/
-static int
-add_autoparam(const char *module, const char *pnam, int flags)
-{
- Param pm;
- int ret;
-
- queue_signals();
- if ((ret = checkaddparam(pnam, (flags & FEAT_IGNORE)))) {
- unqueue_signals();
- /*
- * checkaddparam() has already printed a message if one was
- * needed. If it wasn't owing to the presence of -i, ret is 2;
- * for consistency with other add_auto* functions we return
- * status 0 to indicate there's already such a parameter and
- * we've been told not to worry if so.
- */
- return ret == 2 ? 0 : -1;
- }
-
- pm = setsparam(dupstring(pnam), ztrdup(module));
-
- pm->node.flags |= PM_AUTOLOAD;
- if (flags & FEAT_AUTOALL)
- pm->node.flags |= PM_AUTOALL;
- unqueue_signals();
-
- return 0;
-}
-
-/* Remove a parameter added with add_autoparam() */
-
-/**/
-static int
-del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags)
-{
- Param pm = (Param) gethashnode2(paramtab, pnam);
-
- if (!pm) {
- if (!(flags & FEAT_IGNORE))
- return 2;
- } else if (!(pm->node.flags & PM_AUTOLOAD)) {
- if (!(flags & FEAT_IGNORE))
- return 3;
- } else
- unsetparam_pm(pm, 0, 1);
-
- return 0;
-}
-
-/************************************************************************
- * Math functions.
- ************************************************************************/
-
-/* List of math functions. */
-
-/**/
-MathFunc mathfuncs;
-
-/*
- * Remove a single math function form the list (utility function).
- * This does not delete a module math function, that's deletemathfunc().
- */
-
-/**/
-void
-removemathfunc(MathFunc previous, MathFunc current)
-{
- if (previous)
- previous->next = current->next;
- else
- mathfuncs = current->next;
-
- zsfree(current->name);
- zsfree(current->module);
- zfree(current, sizeof(*current));
-}
-
-/* Find a math function in the list, handling autoload if necessary. */
-
-/**/
-MathFunc
-getmathfunc(const char *name, int autol)
-{
- MathFunc p, q = NULL;
-
- for (p = mathfuncs; p; q = p, p = p->next)
- if (!strcmp(name, p->name)) {
- if (autol && p->module && !(p->flags & MFF_USERFUNC)) {
- char *n = dupstring(p->module);
- int flags = p->flags;
-
- removemathfunc(q, p);
-
- (void)ensurefeature(n, "f:", (flags & MFF_AUTOALL) ? NULL :
- name);
-
- p = getmathfunc(name, 0);
- if (!p) {
- zerr("autoloading module %s failed to define math function: %s", n, name);
- }
- }
- return p;
- }
-
- return NULL;
-}
-
-/* Add a single math function */
-
-/**/
-static int
-addmathfunc(MathFunc f)
-{
- MathFunc p, q = NULL;
-
- if (f->flags & MFF_ADDED)
- return 1;
-
- for (p = mathfuncs; p; q = p, p = p->next)
- if (!strcmp(f->name, p->name)) {
- if (p->module && !(p->flags & MFF_USERFUNC)) {
- /*
- * Autoloadable, replace.
- */
- removemathfunc(q, p);
- break;
- }
- return 1;
- }
-
- f->next = mathfuncs;
- mathfuncs = f;
-
- return 0;
-}
-
-/* Delete a single math function */
-
-/**/
-mod_export int
-deletemathfunc(MathFunc f)
-{
- MathFunc p, q;
-
- for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next);
-
- if (p) {
- if (q)
- q->next = f->next;
- else
- mathfuncs = f->next;
-
- /* the following applies to both unloaded and user-defined functions */
- if (f->module) {
- zsfree(f->name);
- zsfree(f->module);
- zfree(f, sizeof(*f));
- } else
- f->flags &= ~MFF_ADDED;
-
- return 0;
- }
- return -1;
-}
-
-/*
- * Add or remove sets of math functions. The interface is
- * identical to setbuiltins().
- */
-
-/**/
-static int
-setmathfuncs(char const *nam, MathFunc f, int size, int *e)
-{
- int ret = 0;
-
- while (size--) {
- if (e && *e++) {
- if (f->flags & MFF_ADDED) {
- f++;
- continue;
- }
- if (addmathfunc(f)) {
- zwarnnam(nam, "name clash when adding math function `%s'",
- f->name);
- ret = 1;
- } else {
- f->flags |= MFF_ADDED;
- }
- } else {
- if (!(f->flags & MFF_ADDED)) {
- f++;
- continue;
- }
- if (deletemathfunc(f)) {
- zwarnnam(nam, "math function `%s' already deleted", f->name);
- ret = 1;
- } else {
- f->flags &= ~MFF_ADDED;
- }
- }
- f++;
- }
- return ret;
-}
-
-/* Add an autoload definition for a math function. */
-
-/**/
-static int
-add_automathfunc(const char *module, const char *fnam, int flags)
-{
- MathFunc f;
-
- f = (MathFunc) zalloc(sizeof(*f));
-
- f->name = ztrdup(fnam);
- f->module = ztrdup(module);
- f->flags = 0;
-
- if (addmathfunc(f)) {
- zsfree(f->name);
- zsfree(f->module);
- zfree(f, sizeof(*f));
-
- if (!(flags & FEAT_IGNORE))
- return 1;
- }
-
- return 0;
-}
-
-/* Remove a math function added with add_automathfunc() */
-
-/**/
-static int
-del_automathfunc(UNUSED(const char *modnam), const char *fnam, int flags)
-{
- MathFunc f = getmathfunc(fnam, 0);
-
- if (!f) {
- if (!(flags & FEAT_IGNORE))
- return 2;
- } else if (f->flags & MFF_ADDED) {
- if (!(flags & FEAT_IGNORE))
- return 3;
- } else
- deletemathfunc(f);
-
- return 0;
-}
-
-/************************************************************************
- * Now support for dynamical loading and the fallback functions
- * we use for loading if dynamical loading is not available.
- ************************************************************************/
-
-/**/
-#ifdef DYNAMIC
-
-/**/
-#ifdef AIXDYNAMIC
-
-#include
-
-static char *dlerrstr[256];
-
-static void *
-load_and_bind(const char *fn)
-{
- void *ret = (void *) load((char *) fn, L_NOAUTODEFER, NULL);
-
- if (ret) {
- Module m;
- int i, err = loadbind(0, (void *) addbuiltin, ret);
- for (i = 0; i < modulestab->hsize && !err; i++) {
- for (m = (Module)modulestab->nodes[i]; m && !err;
- m = (Module)m->node.next) {
- if (!(m->node.flags & MOD_ALIAS) &&
- m->u.handle && !(m->node.flags & MOD_LINKED))
- err |= loadbind(0, m->u.handle, ret);
- }
- }
-
- if (err) {
- loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr));
- unload(ret);
- ret = NULL;
- }
- } else
- loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr));
-
- return ret;
-}
-
-#define dlopen(X,Y) load_and_bind(X)
-#define dlclose(X) unload(X)
-#define dlerror() (dlerrstr[0])
-#ifndef HAVE_DLERROR
-# define HAVE_DLERROR 1
-#endif
-
-/**/
-#else
-
-#ifdef HAVE_DLFCN_H
-# if defined(HAVE_DL_H) && defined(HPUX10DYNAMIC)
-# include
-# else
-# include
-# endif
-#else
-# ifdef HAVE_DL_H
-# include
-# define RTLD_LAZY BIND_DEFERRED
-# define RTLD_GLOBAL DYNAMIC_PATH
-# else
-# include
-# include
-# include
-# endif
-#endif
-
-/**/
-#ifdef HPUX10DYNAMIC
-# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-# define dlclose(handle) shl_unload((shl_t)(handle))
-
-static
-void *
-hpux_dlsym(void *handle, char *name)
-{
- void *sym_addr;
- if (!shl_findsym((shl_t *)&handle, name, TYPE_UNDEFINED, &sym_addr))
- return sym_addr;
- return NULL;
-}
-
-# define dlsym(handle,name) hpux_dlsym(handle,name)
-# ifdef HAVE_DLERROR /* paranoia */
-# undef HAVE_DLERROR
-# endif
-#else
-# ifndef HAVE_DLCLOSE
-# define dlclose(X) ((X), 0)
-# endif
-/**/
-#endif
-
-#ifdef DLSYM_NEEDS_UNDERSCORE
-# define STR_SETUP "_setup_"
-# define STR_FEATURES "_features_"
-# define STR_ENABLES "_enables_"
-# define STR_BOOT "_boot_"
-# define STR_CLEANUP "_cleanup_"
-# define STR_FINISH "_finish_"
-#else /* !DLSYM_NEEDS_UNDERSCORE */
-# define STR_SETUP "setup_"
-# define STR_FEATURES "features_"
-# define STR_ENABLES "enables_"
-# define STR_BOOT "boot_"
-# define STR_CLEANUP "cleanup_"
-# define STR_FINISH "finish_"
-#endif /* !DLSYM_NEEDS_UNDERSCORE */
-
-/**/
-#endif /* !AIXDYNAMIC */
-
-#ifndef RTLD_LAZY
-# define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
-#endif
-
-/*
- * Attempt to load a module. This is the lowest level of
- * zsh function for dynamical modules. Returns the handle
- * from the dynamic loader.
- */
-
-/**/
-static void *
-try_load_module(char const *name)
-{
- char buf[PATH_MAX + 1];
- char **pp;
- void *ret = NULL;
- int l;
-
- l = 1 + strlen(name) + 1 + strlen(DL_EXT);
- for (pp = module_path; !ret && *pp; pp++) {
- if (l + (**pp ? strlen(*pp) : 1) > PATH_MAX)
- continue;
- sprintf(buf, "%s/%s.%s", **pp ? *pp : ".", name, DL_EXT);
- unmetafy(buf, NULL);
- if (*buf) /* dlopen(NULL) returns a handle to the main binary */
- ret = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
- }
-
- return ret;
-}
-
-/*
- * Load a module, with option to complain or not.
- * Returns the handle from the dynamic loader.
- */
-
-/**/
-static void *
-do_load_module(char const *name, int silent)
-{
- void *ret;
-
- ret = try_load_module(name);
- if (!ret && !silent) {
-#ifdef HAVE_DLERROR
- char *errstr = dlerror();
- zwarn("failed to load module `%s': %s", name,
- errstr ? metafy(errstr, -1, META_HEAPDUP) : "empty module path");
-#else
- zwarn("failed to load module: %s", name);
-#endif
- }
- return ret;
-}
-
-/**/
-#else /* !DYNAMIC */
-
-/*
- * Dummy loader when no dynamic loading available; always fails.
- */
-
-/**/
-static void *
-do_load_module(char const *name, int silent)
-{
- if (!silent)
- zwarn("failed to load module: %s", name);
-
- return NULL;
-}
-
-/**/
-#endif /* !DYNAMIC */
-
-/*
- * Find a module in the list.
- * flags is a set of bits defined in the enum above.
- * If namep is set, this is set to point to the last alias value resolved,
- * even if that module was not loaded. or the module name if no aliases.
- * Hence this is always the physical module to load in a chain of aliases.
- * Return NULL if the module named is not stored as a structure, or if we were
- * resolving aliases and the final module named is not stored as a
- * structure.
- */
-/**/
-static Module
-find_module(const char *name, int flags, const char **namep)
-{
- Module m;
-
- m = (Module)modulestab->getnode2(modulestab, name);
- if (m) {
- if ((flags & FINDMOD_ALIASP) && (m->node.flags & MOD_ALIAS)) {
- if (namep)
- *namep = m->u.alias;
- return find_module(m->u.alias, flags, namep);
- }
- if (namep)
- *namep = m->node.nam;
- return m;
- }
- if (!(flags & FINDMOD_CREATE))
- return NULL;
- m = zshcalloc(sizeof(*m));
- modulestab->addnode(modulestab, ztrdup(name), m);
- return m;
-}
-
-/*
- * Unlink and free a module node from the linked list.
- */
-
-/**/
-static void
-delete_module(Module m)
-{
- modulestab->removenode(modulestab, m->node.nam);
-
- modulestab->freenode(&m->node);
-}
-
-/*
- * Return 1 if a module is fully loaded else zero.
- * A linked module may be marked as unloaded even though
- * we can't fully unload it; this returns 0 to try to
- * make that state transparently like an unloaded module.
- */
-
-/**/
-mod_export int
-module_loaded(const char *name)
-{
- Module m;
-
- return ((m = find_module(name, FINDMOD_ALIASP, NULL)) &&
- m->u.handle &&
- !(m->node.flags & MOD_UNLOAD));
-}
-
-/*
- * Setup and cleanup functions: we don't search for aliases here,
- * since they should have been resolved before we try to load or unload
- * the module.
- */
-
-/**/
-#ifdef DYNAMIC
-
-/**/
-#ifdef AIXDYNAMIC
-
-/**/
-static int
-dyn_setup_module(Module m)
-{
- return ((int (*)_((int,Module, void*))) m->u.handle)(0, m, NULL);
-}
-
-/**/
-static int
-dyn_features_module(Module m, char ***features)
-{
- return ((int (*)_((int,Module, void*))) m->u.handle)(4, m, features);
-}
-
-/**/
-static int
-dyn_enables_module(Module m, int **enables)
-{
- return ((int (*)_((int,Module, void*))) m->u.handle)(5, m, enables);
-}
-
-/**/
-static int
-dyn_boot_module(Module m)
-{
- return ((int (*)_((int,Module, void*))) m->u.handle)(1, m, NULL);
-}
-
-/**/
-static int
-dyn_cleanup_module(Module m)
-{
- return ((int (*)_((int,Module, void*))) m->u.handle)(2, m, NULL);
-}
-
-/**/
-static int
-dyn_finish_module(Module m)
-{
- return ((int (*)_((int,Module,void *))) m->u.handle)(3, m, NULL);
-}
-
-/**/
-#else
-
-static Module_generic_func
-module_func(Module m, char *name)
-{
-#ifdef DYNAMIC_NAME_CLASH_OK
- return (Module_generic_func) dlsym(m->u.handle, name);
-#else /* !DYNAMIC_NAME_CLASH_OK */
- VARARR(char, buf, strlen(name) + strlen(m->node.nam)*2 + 1);
- char const *p;
- char *q;
- strcpy(buf, name);
- q = strchr(buf, 0);
- for(p = m->node.nam; *p; p++) {
- if(*p == '/') {
- *q++ = 'Q';
- *q++ = 's';
- } else if(*p == '_') {
- *q++ = 'Q';
- *q++ = 'u';
- } else if(*p == 'Q') {
- *q++ = 'Q';
- *q++ = 'q';
- } else
- *q++ = *p;
- }
- *q = 0;
- return (Module_generic_func) dlsym(m->u.handle, buf);
-#endif /* !DYNAMIC_NAME_CLASH_OK */
-}
-
-/**/
-static int
-dyn_setup_module(Module m)
-{
- Module_void_func fn = (Module_void_func)module_func(m, STR_SETUP);
-
- if (fn)
- return fn(m);
- zwarnnam(m->node.nam, "no setup function");
- return 1;
-}
-
-/**/
-static int
-dyn_features_module(Module m, char ***features)
-{
- Module_features_func fn =
- (Module_features_func)module_func(m, STR_FEATURES);
-
- if (fn)
- return fn(m, features);
- /* not a user-visible error if no features function */
- return 1;
-}
-
-/**/
-static int
-dyn_enables_module(Module m, int **enables)
-{
- Module_enables_func fn = (Module_enables_func)module_func(m, STR_ENABLES);
-
- if (fn)
- return fn(m, enables);
- /* not a user-visible error if no enables function */
- return 1;
-}
-
-/**/
-static int
-dyn_boot_module(Module m)
-{
- Module_void_func fn = (Module_void_func)module_func(m, STR_BOOT);
-
- if(fn)
- return fn(m);
- zwarnnam(m->node.nam, "no boot function");
- return 1;
-}
-
-/**/
-static int
-dyn_cleanup_module(Module m)
-{
- Module_void_func fn = (Module_void_func)module_func(m, STR_CLEANUP);
-
- if(fn)
- return fn(m);
- zwarnnam(m->node.nam, "no cleanup function");
- return 1;
-}
-
-/* Note that this function does more than just calling finish_foo(), *
- * it really unloads the module. */
-
-/**/
-static int
-dyn_finish_module(Module m)
-{
- Module_void_func fn = (Module_void_func)module_func(m, STR_FINISH);
- int r;
-
- if (fn)
- r = fn(m);
- else {
- zwarnnam(m->node.nam, "no finish function");
- r = 1;
- }
- dlclose(m->u.handle);
- return r;
-}
-
-/**/
-#endif /* !AIXDYNAMIC */
-
-/**/
-static int
-setup_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->setup)(m) : dyn_setup_module(m));
-}
-
-/**/
-static int
-features_module(Module m, char ***features)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->features)(m, features) :
- dyn_features_module(m, features));
-}
-
-/**/
-static int
-enables_module(Module m, int **enables)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->enables)(m, enables) :
- dyn_enables_module(m, enables));
-}
-
-/**/
-static int
-boot_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->boot)(m) : dyn_boot_module(m));
-}
-
-/**/
-static int
-cleanup_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->cleanup)(m) : dyn_cleanup_module(m));
-}
-
-/**/
-static int
-finish_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ?
- (m->u.linked->finish)(m) : dyn_finish_module(m));
-}
-
-/**/
-#else /* !DYNAMIC */
-
-/**/
-static int
-setup_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1);
-}
-
-/**/
-static int
-features_module(Module m, char ***features)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features)
- : 1);
-}
-
-/**/
-static int
-enables_module(Module m, int **enables)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables)
- : 1);
-}
-
-/**/
-static int
-boot_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1);
-}
-
-/**/
-static int
-cleanup_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1);
-}
-
-/**/
-static int
-finish_module(Module m)
-{
- return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1);
-}
-
-/**/
-#endif /* !DYNAMIC */
-
-
-/************************************************************************
- * Functions called when manipulating modules
- ************************************************************************/
-
-/*
- * Set the features for the module, which must be loaded
- * by now (though may not be fully set up).
- *
- * Return 0 for success, 1 for failure, 2 if some features
- * couldn't be set by the module itself (non-existent features
- * are tested here and cause 1 to be returned).
- */
-
-/**/
-static int
-do_module_features(Module m, Feature_enables enablesarr, int flags)
-{
- char **features;
- int ret = 0;
-
- if (features_module(m, &features) == 0) {
- /*
- * Features are supported. If we were passed
- * a NULL array, enable all features, else
- * enable only the features listed.
- * (This may in principle be an empty array,
- * although that's not very pointful.)
- */
- int *enables = NULL;
- if (enables_module(m, &enables)) {
- /* If features are supported, enables should be, too */
- if (!(flags & FEAT_IGNORE))
- zwarn("error getting enabled features for module `%s'",
- m->node.nam);
- return 1;
- }
-
- if ((flags & FEAT_CHECKAUTO) && m->autoloads) {
- /*
- * Check autoloads are available. Since these
- * have been requested at some other point, they
- * don't affect the return status unless something
- * in enablesstr doesn't work.
- */
- LinkNode an, nextn;
- for (an = firstnode(m->autoloads); an; an = nextn) {
- char *al = (char *)getdata(an), **ptr;
- /* careful, we can delete the current node */
- nextn = nextnode(an);
- for (ptr = features; *ptr; ptr++)
- if (!strcmp(al, *ptr))
- break;
- if (!*ptr) {
- char *arg[2];
- if (!(flags & FEAT_IGNORE))
- zwarn(
- "module `%s' has no such feature: `%s': autoload cancelled",
- m->node.nam, al);
- /*
- * This shouldn't happen, so it's not worth optimising
- * the call to autofeatures...
- */
- arg[0] = al = dupstring(al);
- arg[1] = NULL;
- (void)autofeatures(NULL, m->node.nam, arg, 0,
- FEAT_IGNORE|FEAT_REMOVE);
- /*
- * don't want to try to enable *that*...
- * expunge it from the enable string.
- */
- if (enablesarr) {
- Feature_enables fep;
- for (fep = enablesarr; fep->str; fep++) {
- char *str = fep->str;
- if (*str == '+' || *str == '-')
- str++;
- if (fep->pat ? pattry(fep->pat, al) :
- !strcmp(al, str)) {
- /* can't enable it after all, so return 1 */
- ret = 1;
- while (fep->str) {
- fep->str = fep[1].str;
- fep->pat = fep[1].pat;
- fep++;
- }
- if (!fep->pat)
- break;
- }
- }
- }
- }
- }
- }
-
- if (enablesarr) {
- Feature_enables fep;
- for (fep = enablesarr; fep->str; fep++) {
- char **fp, *esp = fep->str;
- int on = 1, found = 0;
- if (*esp == '+')
- esp++;
- else if (*esp == '-') {
- on = 0;
- esp++;
- }
- for (fp = features; *fp; fp++)
- if (fep->pat ? pattry(fep->pat, *fp) : !strcmp(*fp, esp)) {
- enables[fp - features] = on;
- found++;
- if (!fep->pat)
- break;
- }
- if (!found) {
- if (!(flags & FEAT_IGNORE))
- zwarn(fep->pat ?
- "module `%s' has no feature matching: `%s'" :
- "module `%s' has no such feature: `%s'",
- m->node.nam, esp);
- return 1;
- }
- }
- } else {
- /*
- * Enable all features. This is used when loading
- * without using zmodload -F.
- */
- int n_features = arrlen(features);
- int *ep;
- for (ep = enables; n_features--; ep++)
- *ep = 1;
- }
-
- if (enables_module(m, &enables))
- return 2;
- } else if (enablesarr) {
- if (!(flags & FEAT_IGNORE))
- zwarn("module `%s' does not support features", m->node.nam);
- return 1;
- }
- /* Else it doesn't support features but we don't care. */
-
- return ret;
-}
-
-/*
- * Boot the module, including setting up features.
- * As we've only just loaded the module, we don't yet
- * know what features it supports, so we get them passed
- * as a string.
- *
- * Returns 0 if OK, 1 if completely failed, 2 if some features
- * couldn't be set up.
- */
-
-/**/
-static int
-do_boot_module(Module m, Feature_enables enablesarr, int silent)
-{
- int ret = do_module_features(m, enablesarr,
- silent ? FEAT_IGNORE|FEAT_CHECKAUTO :
- FEAT_CHECKAUTO);
-
- if (ret == 1)
- return 1;
-
- if (boot_module(m))
- return 1;
- return ret;
-}
-
-/*
- * Cleanup the module.
- */
-
-/**/
-static int
-do_cleanup_module(Module m)
-{
- return (m->node.flags & MOD_LINKED) ?
- (m->u.linked && m->u.linked->cleanup(m)) :
- (m->u.handle && cleanup_module(m));
-}
-
-/*
- * Test a module name contains only valid characters: those
- * allowed in a shell identifier plus slash. Return 1 if so.
- */
-
-/**/
-static int
-modname_ok(char const *p)
-{
- do {
- p = itype_end(p, IIDENT, 0);
- if (!*p)
- return 1;
- } while(*p++ == '/');
- return 0;
-}
-
-/*
- * High level function to load a module, encapsulating
- * all the handling of module functions.
- *
- * "*enablesstr" is NULL if the caller is not feature-aware;
- * then the module should turn on all features. If it
- * is not NULL it points to an array of features to be
- * turned on. This function is responsible for testing whether
- * the module supports those features.
- *
- * If "silent" is 1, don't issue warnings for errors.
- *
- * Now returns 0 for success (changed post-4.3.4),
- * 1 for complete failure, 2 if some features couldn't be set.
- */
-
-/**/
-mod_export int
-load_module(char const *name, Feature_enables enablesarr, int silent)
-{
- Module m;
- void *handle = NULL;
- Linkedmod linked;
- int set, bootret;
-
- if (!modname_ok(name)) {
- if (!silent)
- zerr("invalid module name `%s'", name);
- return 1;
- }
- /*
- * The following function call may alter name to the final name in a
- * chain of aliases. This makes sure the actual module loaded
- * is the right one.
- */
- queue_signals();
- if (!(m = find_module(name, FINDMOD_ALIASP, &name))) {
- if (!(linked = module_linked(name)) &&
- !(handle = do_load_module(name, silent))) {
- unqueue_signals();
- return 1;
- }
- m = zshcalloc(sizeof(*m));
- if (handle) {
- m->u.handle = handle;
- m->node.flags |= MOD_SETUP;
- } else {
- m->u.linked = linked;
- m->node.flags |= MOD_SETUP | MOD_LINKED;
- }
- modulestab->addnode(modulestab, ztrdup(name), m);
-
- if ((set = setup_module(m)) ||
- (bootret = do_boot_module(m, enablesarr, silent)) == 1) {
- if (!set)
- do_cleanup_module(m);
- finish_module(m);
- delete_module(m);
- unqueue_signals();
- return 1;
- }
- m->node.flags |= MOD_INIT_S | MOD_INIT_B;
- m->node.flags &= ~MOD_SETUP;
- unqueue_signals();
- return bootret;
- }
- if (m->node.flags & MOD_SETUP) {
- unqueue_signals();
- return 0;
- }
- if (m->node.flags & MOD_UNLOAD)
- m->node.flags &= ~MOD_UNLOAD;
- else if ((m->node.flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
- unqueue_signals();
- return 0;
- }
- if (m->node.flags & MOD_BUSY) {
- unqueue_signals();
- zerr("circular dependencies for module ;%s", name);
- return 1;
- }
- m->node.flags |= MOD_BUSY;
- /*
- * TODO: shouldn't we unload the module if one of
- * its dependencies fails?
- */
- if (m->deps) {
- LinkNode n;
- for (n = firstnode(m->deps); n; incnode(n))
- if (load_module((char *) getdata(n), NULL, silent) == 1) {
- m->node.flags &= ~MOD_BUSY;
- unqueue_signals();
- return 1;
- }
- }
- m->node.flags &= ~MOD_BUSY;
- if (!m->u.handle) {
- handle = NULL;
- if (!(linked = module_linked(name)) &&
- !(handle = do_load_module(name, silent))) {
- unqueue_signals();
- return 1;
- }
- if (handle) {
- m->u.handle = handle;
- m->node.flags |= MOD_SETUP;
- } else {
- m->u.linked = linked;
- m->node.flags |= MOD_SETUP | MOD_LINKED;
- }
- if (setup_module(m)) {
- finish_module(m);
- if (handle)
- m->u.handle = NULL;
- else
- m->u.linked = NULL;
- m->node.flags &= ~MOD_SETUP;
- unqueue_signals();
- return 1;
- }
- m->node.flags |= MOD_INIT_S;
- }
- m->node.flags |= MOD_SETUP;
- if ((bootret = do_boot_module(m, enablesarr, silent)) == 1) {
- do_cleanup_module(m);
- finish_module(m);
- if (m->node.flags & MOD_LINKED)
- m->u.linked = NULL;
- else
- m->u.handle = NULL;
- m->node.flags &= ~MOD_SETUP;
- unqueue_signals();
- return 1;
- }
- m->node.flags |= MOD_INIT_B;
- m->node.flags &= ~MOD_SETUP;
- unqueue_signals();
- return bootret;
-}
-
-/* This ensures that the module with the name given as the first argument
- * is loaded.
- * The other argument is the array of features to set. If this is NULL
- * all features are enabled (even if the module was already loaded).
- *
- * If this is non-NULL the module features are set accordingly
- * whether or not the module is loaded; it is an error if the
- * module does not support the features passed (even if the feature
- * is to be turned off) or if the module does not support features
- * at all.
- * The return value is 0 if the module was found or loaded
- * (this changed post-4.3.4, because I got so confused---pws),
- * 1 if loading failed completely, 2 if some features couldn't be set.
- *
- * This function behaves like load_module() except that it
- * handles the case where the module was already loaded, and
- * sets features accordingly.
- */
-
-/**/
-mod_export int
-require_module(const char *module, Feature_enables features, int silent)
-{
- Module m = NULL;
- int ret = 0;
-
- /* Resolve aliases and actual loadable module as for load_module */
- queue_signals();
- m = find_module(module, FINDMOD_ALIASP, &module);
- if (!m || !m->u.handle ||
- (m->node.flags & MOD_UNLOAD))
- ret = load_module(module, features, silent);
- else
- ret = do_module_features(m, features, 0);
- unqueue_signals();
-
- return ret;
-}
-
-/*
- * Indicate that the module named "name" depends on the module
- * named "from".
- */
-
-/**/
-void
-add_dep(const char *name, char *from)
-{
- LinkNode node;
- Module m;
-
- /*
- * If we were passed an alias, we must resolve it to a final
- * module name (and maybe add the corresponding struct), since otherwise
- * we would need to check all modules to see if they happen
- * to be aliased to the same thing to implement dependencies properly.
- *
- * This should mean that an attempt to add an alias which would
- * have the same name as a module which has dependencies is correctly
- * rejected, because then the module named already exists as a non-alias.
- * Better make sure. (There's no problem making a an alias which
- * *points* to a module with dependencies, of course.)
- */
- m = find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name);
- if (!m->deps)
- m->deps = znewlinklist();
- for (node = firstnode(m->deps);
- node && strcmp((char *) getdata(node), from);
- incnode(node));
- if (!node)
- zaddlinknode(m->deps, ztrdup(from));
-}
-
-/*
- * Function to be used when scanning the builtins table to
- * find and print autoloadable builtins.
- */
-
-/**/
-static void
-autoloadscan(HashNode hn, int printflags)
-{
- Builtin bn = (Builtin) hn;
-
- if(bn->node.flags & BINF_ADDED)
- return;
- if(printflags & PRINT_LIST) {
- fputs("zmodload -ab ", stdout);
- if(bn->optstr[0] == '-')
- fputs("-- ", stdout);
- quotedzputs(bn->optstr, stdout);
- if(strcmp(bn->node.nam, bn->optstr)) {
- putchar(' ');
- quotedzputs(bn->node.nam, stdout);
- }
- } else {
- nicezputs(bn->node.nam, stdout);
- if(strcmp(bn->node.nam, bn->optstr)) {
- fputs(" (", stdout);
- nicezputs(bn->optstr, stdout);
- putchar(')');
- }
- }
- putchar('\n');
-}
-
-
-/************************************************************************
- * Handling for the zmodload builtin and its various options.
- ************************************************************************/
-
-/*
- * Main builtin entry point for zmodload.
- */
-
-/**/
-int
-bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
-{
- int ops_bcpf = OPT_ISSET(ops,'b') || OPT_ISSET(ops,'c') ||
- OPT_ISSET(ops,'p') || OPT_ISSET(ops,'f');
- int ops_au = OPT_ISSET(ops,'a') || OPT_ISSET(ops,'u');
- int ret = 1, autoopts;
- /* options only allowed with -F */
- char *fonly = "lP", *fp;
-
- if (ops_bcpf && !ops_au) {
- zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
- return 1;
- }
- if (OPT_ISSET(ops,'F') && (ops_bcpf || OPT_ISSET(ops,'u'))) {
- zwarnnam(nam, "-b, -c, -f, -p and -u cannot be combined with -F");
- return 1;
- }
- if (OPT_ISSET(ops,'A') || OPT_ISSET(ops,'R')) {
- if (ops_bcpf || ops_au || OPT_ISSET(ops,'d') ||
- (OPT_ISSET(ops,'R') && OPT_ISSET(ops,'e'))) {
- zwarnnam(nam, "illegal flags combined with -A or -R");
- return 1;
- }
- if (!OPT_ISSET(ops,'e'))
- return bin_zmodload_alias(nam, args, ops);
- }
- if (OPT_ISSET(ops,'d') && OPT_ISSET(ops,'a')) {
- zwarnnam(nam, "-d cannot be combined with -a");
- return 1;
- }
- if (OPT_ISSET(ops,'u') && !*args) {
- zwarnnam(nam, "what do you want to unload?");
- return 1;
- }
- if (OPT_ISSET(ops,'e') && (OPT_ISSET(ops,'I') || OPT_ISSET(ops,'L') ||
- (OPT_ISSET(ops,'a') && !OPT_ISSET(ops,'F'))
- || OPT_ISSET(ops,'d') ||
- OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) {
- zwarnnam(nam, "-e cannot be combined with other options");
- /* except -F ... */
- return 1;
- }
- for (fp = fonly; *fp; fp++) {
- if (OPT_ISSET(ops,STOUC(*fp)) && !OPT_ISSET(ops,'F')) {
- zwarnnam(nam, "-%c is only allowed with -F", *fp);
- return 1;
- }
- }
- queue_signals();
- if (OPT_ISSET(ops, 'F'))
- ret = bin_zmodload_features(nam, args, ops);
- else if (OPT_ISSET(ops,'e'))
- ret = bin_zmodload_exist(nam, args, ops);
- else if (OPT_ISSET(ops,'d'))
- ret = bin_zmodload_dep(nam, args, ops);
- else if ((autoopts = OPT_ISSET(ops, 'b') + OPT_ISSET(ops, 'c') +
- OPT_ISSET(ops, 'p') + OPT_ISSET(ops, 'f')) ||
- /* zmodload -a is equivalent to zmodload -ab, annoyingly */
- OPT_ISSET(ops, 'a')) {
- if (autoopts > 1) {
- zwarnnam(nam, "use only one of -b, -c, or -p");
- ret = 1;
- } else
- ret = bin_zmodload_auto(nam, args, ops);
- } else
- ret = bin_zmodload_load(nam, args, ops);
- unqueue_signals();
-
- return ret;
-}
-
-/* zmodload -A */
-
-/**/
-static int
-bin_zmodload_alias(char *nam, char **args, Options ops)
-{
- /*
- * TODO: while it would be too nasty to have aliases, as opposed
- * to real loadable modules, with dependencies --- just what would
- * we need to load when, exactly? --- there is in principle no objection
- * to making it possible to force an alias onto an existing unloaded
- * module which has dependencies. This would simply transfer
- * the dependencies down the line to the aliased-to module name.
- * This is actually useful, since then you can alias zsh/zle=mytestzle
- * to load another version of zle. But then what happens when the
- * alias is removed? Do you transfer the dependencies back? And
- * suppose other names are aliased to the same file? It might be
- * kettle of fish best left unwormed.
- */
- Module m;
-
- if (!*args) {
- if (OPT_ISSET(ops,'R')) {
- zwarnnam(nam, "no module alias to remove");
- return 1;
- }
- scanhashtable(modulestab, 1, MOD_ALIAS, 0,
- modulestab->printnode,
- OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
- return 0;
- }
-
- for (; *args; args++) {
- char *eqpos = strchr(*args, '=');
- char *aliasname = eqpos ? eqpos+1 : NULL;
- if (eqpos)
- *eqpos = '\0';
- if (!modname_ok(*args)) {
- zwarnnam(nam, "invalid module name `%s'", *args);
- return 1;
- }
- if (OPT_ISSET(ops,'R')) {
- if (aliasname) {
- zwarnnam(nam, "bad syntax for removing module alias: %s",
- *args);
- return 1;
- }
- m = find_module(*args, 0, NULL);
- if (m) {
- if (!(m->node.flags & MOD_ALIAS)) {
- zwarnnam(nam, "module is not an alias: %s", *args);
- return 1;
- }
- delete_module(m);
- } else {
- zwarnnam(nam, "no such module alias: %s", *args);
- return 1;
- }
- } else {
- if (aliasname) {
- const char *mname = aliasname;
- if (!modname_ok(aliasname)) {
- zwarnnam(nam, "invalid module name `%s'", aliasname);
- return 1;
- }
- do {
- if (!strcmp(mname, *args)) {
- zwarnnam(nam, "module alias would refer to itself: %s",
- *args);
- return 1;
- }
- } while ((m = find_module(mname, 0, NULL))
- && (m->node.flags & MOD_ALIAS)
- && (mname = m->u.alias));
- m = find_module(*args, 0, NULL);
- if (m) {
- if (!(m->node.flags & MOD_ALIAS)) {
- zwarnnam(nam, "module is not an alias: %s", *args);
- return 1;
- }
- zsfree(m->u.alias);
- } else {
- m = (Module) zshcalloc(sizeof(*m));
- m->node.flags = MOD_ALIAS;
- modulestab->addnode(modulestab, ztrdup(*args), m);
- }
- m->u.alias = ztrdup(aliasname);
- } else {
- if ((m = find_module(*args, 0, NULL))) {
- if (m->node.flags & MOD_ALIAS)
- modulestab->printnode(&m->node,
- OPT_ISSET(ops,'L') ?
- PRINTMOD_LIST : 0);
- else {
- zwarnnam(nam, "module is not an alias: %s", *args);
- return 1;
- }
- } else {
- zwarnnam(nam, "no such module alias: %s", *args);
- return 1;
- }
- }
- }
- }
-
- return 0;
-}
-
-/* zmodload -e (without -F) */
-
-/**/
-static int
-bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops)
-{
- Module m;
-
- if (!*args) {
- scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
- OPT_ISSET(ops,'A') ? PRINTMOD_EXIST|PRINTMOD_ALIAS :
- PRINTMOD_EXIST);
- return 0;
- } else {
- int ret = 0;
-
- for (; !ret && *args; args++) {
- if (!(m = find_module(*args, FINDMOD_ALIASP, NULL))
- || !m->u.handle
- || (m->node.flags & MOD_UNLOAD))
- ret = 1;
- }
- return ret;
- }
-}
-
-/* zmodload -d */
-
-/**/
-static int
-bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops)
-{
- Module m;
- if (OPT_ISSET(ops,'u')) {
- /* remove dependencies, which can't pertain to aliases */
- const char *tnam = *args++;
- m = find_module(tnam, FINDMOD_ALIASP, &tnam);
- if (!m)
- return 0;
- if (*args && m->deps) {
- do {
- LinkNode dnode;
- for (dnode = firstnode(m->deps); dnode; incnode(dnode))
- if (!strcmp(*args, getdata(dnode))) {
- zsfree(getdata(dnode));
- remnode(m->deps, dnode);
- break;
- }
- } while(*++args);
- if (empty(m->deps)) {
- freelinklist(m->deps, freestr);
- m->deps = NULL;
- }
- } else {
- if (m->deps) {
- freelinklist(m->deps, freestr);
- m->deps = NULL;
- }
- }
- if (!m->deps && !m->u.handle)
- delete_module(m);
- return 0;
- } else if (!args[0] || !args[1]) {
- /* list dependencies */
- int depflags = OPT_ISSET(ops,'L') ?
- PRINTMOD_DEPS|PRINTMOD_LIST : PRINTMOD_DEPS;
- if (args[0]) {
- if ((m = (Module)modulestab->getnode2(modulestab, args[0])))
- modulestab->printnode(&m->node, depflags);
- } else {
- scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
- depflags);
- }
- return 0;
- } else {
- /* add dependencies */
- int ret = 0;
- char *tnam = *args++;
-
- for (; *args; args++)
- add_dep(tnam, *args);
- return ret;
- }
-}
-
-/*
- * Function for scanning the parameter table to find and print
- * out autoloadable parameters.
- */
-
-static void
-printautoparams(HashNode hn, int lon)
-{
- Param pm = (Param) hn;
-
- if (pm->node.flags & PM_AUTOLOAD) {
- if (lon)
- printf("zmodload -ap %s %s\n", pm->u.str, pm->node.nam);
- else
- printf("%s (%s)\n", pm->node.nam, pm->u.str);
- }
-}
-
-/* zmodload -a/u [bcpf] */
-
-/**/
-static int
-bin_zmodload_auto(char *nam, char **args, Options ops)
-{
- int fchar, flags;
- char *modnam;
-
- if (OPT_ISSET(ops,'c')) {
- if (!*args) {
- /* list autoloaded conditions */
- Conddef p;
-
- for (p = condtab; p; p = p->next) {
- if (p->module) {
- if (OPT_ISSET(ops,'L')) {
- fputs("zmodload -ac", stdout);
- if (p->flags & CONDF_INFIX)
- putchar('I');
- printf(" %s %s\n", p->module, p->name);
- } else {
- if (p->flags & CONDF_INFIX)
- fputs("infix ", stdout);
- else
- fputs("post ", stdout);
- printf("%s (%s)\n",p->name, p->module);
- }
- }
- }
- return 0;
- }
- fchar = OPT_ISSET(ops,'I') ? 'C' : 'c';
- } else if (OPT_ISSET(ops,'p')) {
- if (!*args) {
- /* list autoloaded parameters */
- scanhashtable(paramtab, 1, 0, 0, printautoparams,
- OPT_ISSET(ops,'L'));
- return 0;
- }
- fchar = 'p';
- } else if (OPT_ISSET(ops,'f')) {
- if (!*args) {
- /* list autoloaded math functions */
- MathFunc p;
-
- for (p = mathfuncs; p; p = p->next) {
- if (!(p->flags & MFF_USERFUNC) && p->module) {
- if (OPT_ISSET(ops,'L')) {
- fputs("zmodload -af", stdout);
- printf(" %s %s\n", p->module, p->name);
- } else
- printf("%s (%s)\n",p->name, p->module);
- }
- }
- return 0;
- }
- fchar = 'f';
- } else {
- /* builtins are the default; zmodload -ab or just zmodload -a */
- if (!*args) {
- /* list autoloaded builtins */
- scanhashtable(builtintab, 1, 0, 0,
- autoloadscan, OPT_ISSET(ops,'L') ? PRINT_LIST : 0);
- return 0;
- }
- fchar = 'b';
- }
-
- flags = FEAT_AUTOALL;
- if (OPT_ISSET(ops,'i'))
- flags |= FEAT_IGNORE;
- if (OPT_ISSET(ops,'u')) {
- /* remove autoload */
- flags |= FEAT_REMOVE;
- modnam = NULL;
- } else {
- /* add autoload */
- modnam = *args;
-
- if (args[1])
- args++;
- }
- return autofeatures(nam, modnam, args, fchar, flags);
-}
-
-/* Backend handler for zmodload -u */
-
-/**/
-int
-unload_module(Module m)
-{
- int del;
-
- /*
- * Only unload the real module, so resolve aliases.
- */
- if (m->node.flags & MOD_ALIAS) {
- m = find_module(m->u.alias, FINDMOD_ALIASP, NULL);
- if (!m)
- return 1;
- }
- /*
- * We may need to clean up the module any time setup_ has been
- * called. After cleanup_ is successful we are no longer in the
- * booted state (because features etc. are deregistered), so remove
- * MOD_INIT_B, and also MOD_INIT_S since we won't need to cleanup
- * again if this succeeded.
- */
- if ((m->node.flags & MOD_INIT_S) &&
- !(m->node.flags & MOD_UNLOAD) &&
- do_cleanup_module(m))
- return 1;
- m->node.flags &= ~(MOD_INIT_B|MOD_INIT_S);
-
- del = (m->node.flags & MOD_UNLOAD);
-
- if (m->wrapper) {
- m->node.flags |= MOD_UNLOAD;
- return 0;
- }
- m->node.flags &= ~MOD_UNLOAD;
-
- /*
- * We always need to finish the module (and unload it)
- * if it is present.
- */
- if (m->node.flags & MOD_LINKED) {
- if (m->u.linked) {
- m->u.linked->finish(m);
- m->u.linked = NULL;
- }
- } else {
- if (m->u.handle) {
- finish_module(m);
- m->u.handle = NULL;
- }
- }
-
- if (del && m->deps) {
- /* The module was unloaded delayed, unload all modules *
- * on which it depended. */
- LinkNode n;
-
- for (n = firstnode(m->deps); n; incnode(n)) {
- Module dm = find_module((char *) getdata(n),
- FINDMOD_ALIASP, NULL);
-
- if (dm &&
- (dm->node.flags & MOD_UNLOAD)) {
- /* See if this is the only module depending on it. */
- Module am;
- int du = 1, i;
- /* Scan hash table the hard way */
- for (i = 0; du && i < modulestab->hsize; i++) {
- for (am = (Module)modulestab->nodes[i]; du && am;
- am = (Module)am->node.next) {
- LinkNode sn;
- /*
- * Don't scan the module we're unloading;
- * ignore if no dependencies.
- */
- if (am == m || !am->deps)
- continue;
- /* Don't scan if not loaded nor linked */
- if ((am->node.flags & MOD_LINKED) ?
- !am->u.linked : !am->u.handle)
- continue;
- for (sn = firstnode(am->deps); du && sn;
- incnode(sn)) {
- if (!strcmp((char *) getdata(sn),
- dm->node.nam))
- du = 0;
- }
- }
- }
- if (du)
- unload_module(dm);
- }
- }
- }
- if (m->autoloads && firstnode(m->autoloads)) {
- /*
- * Module has autoloadable features. Restore them
- * so that the module will be reloaded when needed.
- */
- autofeatures("zsh", m->node.nam,
- hlinklist2array(m->autoloads, 0), 0, FEAT_IGNORE);
- } else if (!m->deps) {
- delete_module(m);
- }
- return 0;
-}
-
-/*
- * Unload a module by name (modname); nam is the command name.
- * Optionally don't print some error messages (always print
- * dependency errors).
- */
-
-/**/
-int
-unload_named_module(char *modname, char *nam, int silent)
-{
- const char *mname;
- Module m;
- int ret = 0;
-
- m = find_module(modname, FINDMOD_ALIASP, &mname);
- if (m) {
- int i, del = 0;
- Module dm;
-
- for (i = 0; i < modulestab->hsize; i++) {
- for (dm = (Module)modulestab->nodes[i]; dm;
- dm = (Module)dm->node.next) {
- LinkNode dn;
- if (!dm->deps || !dm->u.handle)
- continue;
- for (dn = firstnode(dm->deps); dn; incnode(dn)) {
- if (!strcmp((char *) getdata(dn), mname)) {
- if (dm->node.flags & MOD_UNLOAD)
- del = 1;
- else {
- zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname);
- return 1;
- }
- }
- }
- }
- }
- if (del)
- m->wrapper++;
- if (unload_module(m))
- ret = 1;
- if (del)
- m->wrapper--;
- } else if (!silent) {
- zwarnnam(nam, "no such module %s", modname);
- ret = 1;
- }
-
- return ret;
-}
-
-/* zmodload -u without -d */
-
-/**/
-static int
-bin_zmodload_load(char *nam, char **args, Options ops)
-{
- int ret = 0;
- if(OPT_ISSET(ops,'u')) {
- /* unload modules */
- for(; *args; args++) {
- if (unload_named_module(*args, nam, OPT_ISSET(ops,'i')))
- ret = 1;
- }
- return ret;
- } else if(!*args) {
- /* list modules */
- scanhashtable(modulestab, 1, 0, MOD_UNLOAD|MOD_ALIAS,
- modulestab->printnode,
- OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
- return 0;
- } else {
- /* load modules */
- for (; *args; args++) {
- int tmpret = require_module(*args, NULL, OPT_ISSET(ops,'s'));
- if (tmpret && ret != 1)
- ret = tmpret;
- }
-
- return ret;
- }
-}
-
-/* zmodload -F */
-
-/**/
-static int
-bin_zmodload_features(const char *nam, char **args, Options ops)
-{
- int iarg;
- char *modname = *args;
- Patprog *patprogs;
- Feature_enables features, fep;
-
- if (modname)
- args++;
- else if (OPT_ISSET(ops,'L')) {
- int printflags = PRINTMOD_LIST|PRINTMOD_FEATURES;
- if (OPT_ISSET(ops,'P')) {
- zwarnnam(nam, "-P is only allowed with a module name");
- return 1;
- }
- if (OPT_ISSET(ops,'l'))
- printflags |= PRINTMOD_LISTALL;
- if (OPT_ISSET(ops,'a'))
- printflags |= PRINTMOD_AUTO;
- scanhashtable(modulestab, 1, 0, MOD_ALIAS,
- modulestab->printnode, printflags);
- return 0;
- }
-
- if (!modname) {
- zwarnnam(nam, "-F requires a module name");
- return 1;
- }
-
- if (OPT_ISSET(ops,'m')) {
- char **argp;
- Patprog *patprogp;
-
- /* not NULL terminated */
- patprogp = patprogs =
- (Patprog *)zhalloc(arrlen(args)*sizeof(Patprog));
- for (argp = args; *argp; argp++, patprogp++) {
- char *arg = *argp;
- if (*arg == '+' || *arg == '-')
- arg++;
- tokenize(arg);
- *patprogp = patcompile(arg, 0, 0);
- }
- } else
- patprogs = NULL;
-
- if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) {
- /*
- * With option 'l', list all features one per line with + or -.
- * With option 'L', list as zmodload statement showing
- * only options turned on.
- * With both options, list as zmodload showing options
- * to be turned both on and off.
- */
- Module m;
- char **features, **fp, **arrset = NULL, **arrp = NULL;
- int *enables = NULL, *ep;
- char *param = OPT_ARG_SAFE(ops,'P');
-
- m = find_module(modname, FINDMOD_ALIASP, NULL);
- if (OPT_ISSET(ops,'a')) {
- LinkNode ln;
- /*
- * If there are no autoloads defined, return status 1.
- */
- if (!m || !m->autoloads)
- return 1;
- if (OPT_ISSET(ops,'e')) {
- for (fp = args; *fp; fp++) {
- char *fstr = *fp;
- int sense = 1;
- if (*fstr == '+')
- fstr++;
- else if (*fstr == '-') {
- fstr++;
- sense = 0;
- }
- if ((linknodebystring(m->autoloads, fstr) != NULL) !=
- sense)
- return 1;
- }
- return 0;
- }
- if (param) {
- arrp = arrset = (char **)zalloc(sizeof(char*) *
- (countlinknodes(m->autoloads)+1));
- } else if (OPT_ISSET(ops,'L')) {
- printf("zmodload -aF %s%c", m->node.nam,
- m->autoloads && firstnode(m->autoloads) ? ' ' : '\n');
- arrp = NULL;
- }
- for (ln = firstnode(m->autoloads); ln; incnode(ln)) {
- char *al = (char *)getdata(ln);
- if (param)
- *arrp++ = ztrdup(al);
- else
- printf("%s%c", al,
- OPT_ISSET(ops,'L') && nextnode(ln) ? ' ' : '\n');
- }
- if (param) {
- *arrp = NULL;
- if (!setaparam(param, arrset))
- return 1;
- }
- return 0;
- }
- if (!m || !m->u.handle || (m->node.flags & MOD_UNLOAD)) {
- if (!OPT_ISSET(ops,'e'))
- zwarnnam(nam, "module `%s' is not yet loaded", modname);
- return 1;
- }
- if (features_module(m, &features)) {
- if (!OPT_ISSET(ops,'e'))
- zwarnnam(nam, "module `%s' does not support features",
- m->node.nam);
- return 1;
- }
- if (enables_module(m, &enables)) {
- /* this shouldn't ever happen, so don't silence this error */
- zwarnnam(nam, "error getting enabled features for module `%s'",
- m->node.nam);
- return 1;
- }
- for (arrp = args, iarg = 0; *arrp; arrp++, iarg++) {
- char *arg = *arrp;
- int on, found = 0;
- if (*arg == '-') {
- on = 0;
- arg++;
- } else if (*arg == '+') {
- on = 1;
- arg++;
- } else
- on = -1;
- for (fp = features, ep = enables; *fp; fp++, ep++) {
- if (patprogs ? pattry(patprogs[iarg], *fp) :
- !strcmp(arg, *fp)) {
- /* for -e, check given state, if any */
- if (OPT_ISSET(ops,'e') && on != -1 &&
- on != (*ep & 1))
- return 1;
- found++;
- if (!patprogs)
- break;
- }
- }
- if (!found) {
- if (!OPT_ISSET(ops,'e'))
- zwarnnam(nam, patprogs ?
- "module `%s' has no feature matching: `%s'" :
- "module `%s' has no such feature: `%s'",
- modname, *arrp);
- return 1;
- }
- }
- if (OPT_ISSET(ops,'e')) /* yep, everything we want exists */
- return 0;
- if (param) {
- int arrlen = 0;
- for (fp = features, ep = enables; *fp; fp++, ep++) {
- if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') &&
- !*ep)
- continue;
- if (*args) {
- char **argp;
- for (argp = args, iarg = 0; *argp; argp++, iarg++) {
- char *arg = *argp;
- /* ignore +/- for consistency */
- if (*arg == '+' || *arg == '-')
- arg++;
- if (patprogs ? pattry(patprogs[iarg], *fp) :
- !strcmp(*fp, arg))
- break;
- }
- if (!*argp)
- continue;
- }
- arrlen++;
- }
- arrp = arrset = zalloc(sizeof(char *) * (arrlen+1));
- } else if (OPT_ISSET(ops, 'L'))
- printf("zmodload -F %s ", m->node.nam);
- for (fp = features, ep = enables; *fp; fp++, ep++) {
- char *onoff;
- int term;
- if (*args) {
- char **argp;
- for (argp = args, iarg = 0; *argp; argp++, iarg++) {
- char *arg = *argp;
- if (*arg == '+' || *arg == '-')
- arg++;
- if (patprogs ? pattry(patprogs[iarg], *fp) :
- !strcmp(*fp, *argp))
- break;
- }
- if (!*argp)
- continue;
- }
- if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l')) {
- if (!*ep)
- continue;
- onoff = "";
- } else if (*ep) {
- onoff = "+";
- } else {
- onoff = "-";
- }
- if (param) {
- *arrp++ = bicat(onoff, *fp);
- } else {
- if (OPT_ISSET(ops, 'L') && fp[1]) {
- term = ' ';
- } else {
- term = '\n';
- }
- printf("%s%s%c", onoff, *fp, term);
- }
- }
- if (param) {
- *arrp = NULL;
- if (!setaparam(param, arrset))
- return 1;
- }
- return 0;
- } else if (OPT_ISSET(ops,'P')) {
- zwarnnam(nam, "-P can only be used with -l or -L");
- return 1;
- } else if (OPT_ISSET(ops,'a')) {
- if (OPT_ISSET(ops,'m')) {
- zwarnnam(nam, "-m cannot be used with -a");
- return 1;
- }
- /*
- * With zmodload -aF, we always use the effect of -i.
- * The thinking is that marking a feature for
- * autoload is separate from enabling or disabling it.
- * Arguably we could do this with the zmodload -ab method
- * but I've kept it there for old time's sake.
- * The decoupling has meant FEAT_IGNORE/-i also
- * suppresses an error for attempting to remove an
- * autoload when the feature is enabled, which used
- * to be a hard error before.
- */
- return autofeatures(nam, modname, args, 0, FEAT_IGNORE);
- }
-
- fep = features =
- (Feature_enables)zhalloc((arrlen(args)+1)*sizeof(*fep));
-
- while (*args) {
- fep->str = *args++;
- fep->pat = patprogs ? *patprogs++ : NULL;
- fep++;
- }
- fep->str = NULL;
- fep->pat = NULL;
-
- return require_module(modname, features, OPT_ISSET(ops,'s'));
-}
-
-
-/************************************************************************
- * Generic feature support.
- * These functions are designed to be called by modules.
- ************************************************************************/
-
-/*
- * Construct a features array out of the list of concrete
- * features given, leaving space for any abstract features
- * to be added by the module itself.
- *
- * Note the memory is from the heap.
- */
-
-/**/
-mod_export char **
-featuresarray(UNUSED(Module m), Features f)
-{
- int bn_size = f->bn_size, cd_size = f->cd_size;
- int mf_size = f->mf_size, pd_size = f->pd_size;
- int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
- Builtin bnp = f->bn_list;
- Conddef cdp = f->cd_list;
- MathFunc mfp = f->mf_list;
- Paramdef pdp = f->pd_list;
- char **features = (char **)zhalloc((features_size + 1) * sizeof(char *));
- char **featurep = features;
-
- while (bn_size--)
- *featurep++ = dyncat("b:", (bnp++)->node.nam);
- while (cd_size--) {
- *featurep++ = dyncat((cdp->flags & CONDF_INFIX) ? "C:" : "c:",
- cdp->name);
- cdp++;
- }
- while (mf_size--)
- *featurep++ = dyncat("f:", (mfp++)->name);
- while (pd_size--)
- *featurep++ = dyncat("p:", (pdp++)->name);
-
- features[features_size] = NULL;
- return features;
-}
-
-/*
- * Return the current set of enables for the features in a
- * module using heap memory. Leave space for abstract
- * features. The array is not zero terminated.
- */
-/**/
-mod_export int *
-getfeatureenables(UNUSED(Module m), Features f)
-{
- int bn_size = f->bn_size, cd_size = f->cd_size;
- int mf_size = f->mf_size, pd_size = f->pd_size;
- int features_size = bn_size + cd_size + mf_size + pd_size + f->n_abstract;
- Builtin bnp = f->bn_list;
- Conddef cdp = f->cd_list;
- MathFunc mfp = f->mf_list;
- Paramdef pdp = f->pd_list;
- int *enables = zhalloc(sizeof(int) * features_size);
- int *enablep = enables;
-
- while (bn_size--)
- *enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0;
- while (cd_size--)
- *enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0;
- while (mf_size--)
- *enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0;
- while (pd_size--)
- *enablep++ = (pdp++)->pm ? 1 : 0;
-
- return enables;
-}
-
-/*
- * Add or remove the concrete features passed in arguments,
- * depending on the corresponding element of the array e.
- * If e is NULL, disable everything.
- * Return 0 for success, 1 for failure; does not attempt
- * to imitate the return values of addbuiltins() etc.
- * Any failure in adding a requested feature is an
- * error.
- */
-
-/**/
-mod_export int
-setfeatureenables(Module m, Features f, int *e)
-{
- int ret = 0;
-
- if (f->bn_size) {
- if (setbuiltins(m->node.nam, f->bn_list, f->bn_size, e))
- ret = 1;
- if (e)
- e += f->bn_size;
- }
- if (f->cd_size) {
- if (setconddefs(m->node.nam, f->cd_list, f->cd_size, e))
- ret = 1;
- if (e)
- e += f->cd_size;
- }
- if (f->mf_size) {
- if (setmathfuncs(m->node.nam, f->mf_list, f->mf_size, e))
- ret = 1;
- if (e)
- e += f->mf_size;
- }
- if (f->pd_size) {
- if (setparamdefs(m->node.nam, f->pd_list, f->pd_size, e))
- ret = 1;
- if (e)
- e += f->pd_size;
- }
- return ret;
-}
-
-/*
- * Convenient front-end to get or set features which
- * can be used in a module enables_() function.
- */
-
-/**/
-mod_export int
-handlefeatures(Module m, Features f, int **enables)
-{
- if (!enables || *enables)
- return setfeatureenables(m, f, enables ? *enables : NULL);
- *enables = getfeatureenables(m, f);
- return 0;
-}
-
-/*
- * Ensure module "modname" is providing feature with "prefix"
- * and "feature" (e.g. "b:", "limit"). If feature is NULL,
- * ensure all features are loaded (used for compatibility
- * with the pre-feature autoloading behaviour).
- *
- * This will usually be called from the main shell to handle
- * loading of an autoloadable feature.
- *
- * Returns 0 on success, 1 for error in module, 2 for error
- * setting the feature. However, this isn't actually all
- * that useful for testing immediately on an autoload since
- * it could be a failure to autoload a different feature
- * from the one we want. We could fix this but it's
- * possible to test other ways.
- */
-
-/**/
-mod_export int
-ensurefeature(const char *modname, const char *prefix, const char *feature)
-{
- char *f;
- struct feature_enables features[2];
-
- if (!feature)
- return require_module(modname, NULL, 0);
- f = dyncat(prefix, feature);
-
- features[0].str = f;
- features[0].pat = NULL;
- features[1].str = NULL;
- features[1].pat = NULL;
- return require_module(modname, features, 0);
-}
-
-/*
- * Add autoloadable features for a given module.
- */
-
-/**/
-int
-autofeatures(const char *cmdnam, const char *module, char **features,
- int prefchar, int defflags)
-{
- int ret = 0, subret;
- Module defm, m;
- char **modfeatures = NULL;
- int *modenables = NULL;
- if (module) {
- defm = (Module)find_module(module,
- FINDMOD_ALIASP|FINDMOD_CREATE, NULL);
- if ((defm->node.flags & MOD_LINKED) ? defm->u.linked :
- defm->u.handle) {
- (void)features_module(defm, &modfeatures);
- (void)enables_module(defm, &modenables);
- }
- } else
- defm = NULL;
-
- for (; *features; features++) {
- char *fnam, *typnam, *feature;
- int add, fchar, flags = defflags;
- autofeaturefn_t fn;
-
- if (prefchar) {
- /*
- * "features" is list of bare features with no
- * type prefix; prefchar gives type character.
- */
- add = 1; /* unless overridden by flag */
- fchar = prefchar;
- fnam = *features;
- feature = zhalloc(strlen(fnam) + 3);
- sprintf(feature, "%c:%s", fchar, fnam);
- } else {
- feature = *features;
- if (*feature == '-') {
- add = 0;
- feature++;
- } else {
- add = 1;
- if (*feature == '+')
- feature++;
- }
-
- if (!*feature || feature[1] != ':') {
- zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'",
- feature);
- ret = 1;
- continue;
- }
- fnam = feature + 2;
- fchar = feature[0];
- }
- if (flags & FEAT_REMOVE)
- add = 0;
-
- switch (fchar) {
- case 'b':
- fn = add ? add_autobin : del_autobin;
- typnam = "builtin";
- break;
-
- case 'C':
- flags |= FEAT_INFIX;
- /* FALLTHROUGH */
- case 'c':
- fn = add ? add_autocond : del_autocond;
- typnam = "condition";
- break;
-
- case 'f':
- fn = add ? add_automathfunc : del_automathfunc;
- typnam = "math function";
- break;
-
- case 'p':
- fn = add ? add_autoparam : del_autoparam;
- typnam = "parameter";
- break;
-
- default:
- zwarnnam(cmdnam, "bad autoloadable feature type: `%c'",
- fchar);
- ret = 1;
- continue;
- }
-
- if (strchr(fnam, '/')) {
- zwarnnam(cmdnam, "%s: `/' is illegal in a %s", fnam, typnam);
- ret = 1;
- continue;
- }
-
- if (!module) {
- /*
- * Traditional un-autoload syntax doesn't tell us
- * which module this came from.
- */
- int i;
- for (i = 0, m = NULL; !m && i < modulestab->hsize; i++) {
- for (m = (Module)modulestab->nodes[i]; m;
- m = (Module)m->node.next) {
- if (m->autoloads &&
- linknodebystring(m->autoloads, feature))
- break;
- }
- }
- if (!m) {
- if (!(flags & FEAT_IGNORE)) {
- ret = 1;
- zwarnnam(cmdnam, "%s: no such %s", fnam, typnam);
- }
- continue;
- }
- } else
- m = defm;
-
- subret = 0;
- if (add) {
- char **ptr;
- if (modfeatures) {
- /*
- * If the module is already available, check that
- * it does in fact provide the necessary feature.
- */
- for (ptr = modfeatures; *ptr; ptr++)
- if (!strcmp(*ptr, feature))
- break;
- if (!*ptr) {
- zwarnnam(cmdnam, "module `%s' has no such feature: `%s'",
- m->node.nam, feature);
- ret = 1;
- continue;
- }
- /*
- * If the feature is already provided by the module, there's
- * nothing more to do.
- */
- if (modenables[ptr-modfeatures])
- continue;
- /*
- * Otherwise, marking it for autoload will do the
- * right thing when the feature is eventually used.
- */
- }
- if (!m->autoloads) {
- m->autoloads = znewlinklist();
- zaddlinknode(m->autoloads, ztrdup(feature));
- } else {
- /* Insert in lexical order */
- LinkNode ln, prev = (LinkNode)m->autoloads;
- while ((ln = nextnode(prev))) {
- int cmp = strcmp(feature, (char *)getdata(ln));
- if (cmp == 0) {
- /* Already there. Never an error. */
- break;
- }
- if (cmp < 0) {
- zinsertlinknode(m->autoloads, prev,
- ztrdup(feature));
- break;
- }
- prev = ln;
- }
- if (!ln)
- zaddlinknode(m->autoloads, ztrdup(feature));
- }
- } else if (m->autoloads) {
- LinkNode ln;
- if ((ln = linknodebystring(m->autoloads, feature)))
- zsfree((char *)remnode(m->autoloads, ln));
- else {
- /*
- * With -i (or zmodload -Fa), removing an autoload
- * that's not there is not an error.
- */
- subret = (flags & FEAT_IGNORE) ? -2 : 2;
- }
- }
-
- if (subret == 0)
- subret = fn(module, fnam, flags);
-
- if (subret != 0) {
- /* -2 indicates not an error, just skip running fn() */
- if (subret != -2)
- ret = 1;
- switch (subret) {
- case 1:
- zwarnnam(cmdnam, "failed to add %s `%s'", typnam, fnam);
- break;
-
- case 2:
- zwarnnam(cmdnam, "%s: no such %s", fnam, typnam);
- break;
-
- case 3:
- zwarnnam(cmdnam, "%s: %s is already defined", fnam, typnam);
- break;
-
- default:
- /* no (further) message needed */
- break;
- }
- }
- }
-
- return ret;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/options.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/options.c
deleted file mode 100644
index 600b649e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/options.c
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * options.c - shell options
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zsh.mdh"
-#include "options.pro"
-
-/* current emulation (used to decide which set of option letters is used) */
-
-/**/
-mod_export int emulation;
-
-/* current sticky emulation: sticky = NULL means none */
-
-/**/
-mod_export Emulation_options sticky;
-
-/* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
-
-/**/
-mod_export char opts[OPT_SIZE];
-
-/* Option name hash table */
-
-/**/
-mod_export HashTable optiontab;
-
-/* The canonical option name table */
-
-#define OPT_CSH EMULATE_CSH
-#define OPT_KSH EMULATE_KSH
-#define OPT_SH EMULATE_SH
-#define OPT_ZSH EMULATE_ZSH
-
-#define OPT_ALL (OPT_CSH|OPT_KSH|OPT_SH|OPT_ZSH)
-#define OPT_BOURNE (OPT_KSH|OPT_SH)
-#define OPT_BSHELL (OPT_KSH|OPT_SH|OPT_ZSH)
-#define OPT_NONBOURNE (OPT_ALL & ~OPT_BOURNE)
-#define OPT_NONZSH (OPT_ALL & ~OPT_ZSH)
-
-/* option is relevant to emulation */
-#define OPT_EMULATE (EMULATE_UNUSED)
-/* option should never be set by emulate() */
-#define OPT_SPECIAL (EMULATE_UNUSED<<1)
-/* option is an alias to an other option */
-#define OPT_ALIAS (EMULATE_UNUSED<<2)
-
-#define defset(X, my_emulation) (!!((X)->node.flags & my_emulation))
-
-/*
- * Note that option names should usually be fewer than 20 characters long
- * to avoid formatting problems.
- */
-static struct optname optns[] = {
-{{NULL, "aliases", OPT_EMULATE|OPT_ALL}, ALIASESOPT},
-{{NULL, "aliasfuncdef", OPT_EMULATE|OPT_BOURNE}, ALIASFUNCDEF},
-{{NULL, "allexport", OPT_EMULATE}, ALLEXPORT},
-{{NULL, "alwayslastprompt", OPT_ALL}, ALWAYSLASTPROMPT},
-{{NULL, "alwaystoend", 0}, ALWAYSTOEND},
-{{NULL, "appendcreate", OPT_EMULATE|OPT_BOURNE}, APPENDCREATE},
-{{NULL, "appendhistory", OPT_ALL}, APPENDHISTORY},
-{{NULL, "autocd", OPT_EMULATE}, AUTOCD},
-{{NULL, "autocontinue", 0}, AUTOCONTINUE},
-{{NULL, "autolist", OPT_ALL}, AUTOLIST},
-{{NULL, "automenu", OPT_ALL}, AUTOMENU},
-{{NULL, "autonamedirs", 0}, AUTONAMEDIRS},
-{{NULL, "autoparamkeys", OPT_ALL}, AUTOPARAMKEYS},
-{{NULL, "autoparamslash", OPT_ALL}, AUTOPARAMSLASH},
-{{NULL, "autopushd", 0}, AUTOPUSHD},
-{{NULL, "autoremoveslash", OPT_ALL}, AUTOREMOVESLASH},
-{{NULL, "autoresume", 0}, AUTORESUME},
-{{NULL, "badpattern", OPT_EMULATE|OPT_NONBOURNE},BADPATTERN},
-{{NULL, "banghist", OPT_NONBOURNE}, BANGHIST},
-{{NULL, "bareglobqual", OPT_EMULATE|OPT_ZSH}, BAREGLOBQUAL},
-{{NULL, "bashautolist", 0}, BASHAUTOLIST},
-{{NULL, "bashrematch", 0}, BASHREMATCH},
-{{NULL, "beep", OPT_ALL}, BEEP},
-{{NULL, "bgnice", OPT_EMULATE|OPT_NONBOURNE},BGNICE},
-{{NULL, "braceccl", OPT_EMULATE}, BRACECCL},
-{{NULL, "bsdecho", OPT_EMULATE|OPT_SH}, BSDECHO},
-{{NULL, "caseglob", OPT_ALL}, CASEGLOB},
-{{NULL, "casematch", OPT_ALL}, CASEMATCH},
-{{NULL, "cbases", 0}, CBASES},
-{{NULL, "cprecedences", OPT_EMULATE|OPT_NONZSH}, CPRECEDENCES},
-{{NULL, "cdablevars", OPT_EMULATE}, CDABLEVARS},
-{{NULL, "chasedots", OPT_EMULATE}, CHASEDOTS},
-{{NULL, "chaselinks", OPT_EMULATE}, CHASELINKS},
-{{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS},
-{{NULL, "checkrunningjobs", OPT_EMULATE|OPT_ZSH}, CHECKRUNNINGJOBS},
-{{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER},
-{{NULL, "combiningchars", 0}, COMBININGCHARS},
-{{NULL, "completealiases", 0}, COMPLETEALIASES},
-{{NULL, "completeinword", 0}, COMPLETEINWORD},
-{{NULL, "continueonerror", 0}, CONTINUEONERROR},
-{{NULL, "correct", 0}, CORRECT},
-{{NULL, "correctall", 0}, CORRECTALL},
-{{NULL, "cshjunkiehistory", OPT_EMULATE|OPT_CSH}, CSHJUNKIEHISTORY},
-{{NULL, "cshjunkieloops", OPT_EMULATE|OPT_CSH}, CSHJUNKIELOOPS},
-{{NULL, "cshjunkiequotes", OPT_EMULATE|OPT_CSH}, CSHJUNKIEQUOTES},
-{{NULL, "cshnullcmd", OPT_EMULATE|OPT_CSH}, CSHNULLCMD},
-{{NULL, "cshnullglob", OPT_EMULATE|OPT_CSH}, CSHNULLGLOB},
-{{NULL, "debugbeforecmd", OPT_ALL}, DEBUGBEFORECMD},
-{{NULL, "emacs", 0}, EMACSMODE},
-{{NULL, "equals", OPT_EMULATE|OPT_ZSH}, EQUALS},
-{{NULL, "errexit", OPT_EMULATE}, ERREXIT},
-{{NULL, "errreturn", OPT_EMULATE}, ERRRETURN},
-{{NULL, "exec", OPT_ALL}, EXECOPT},
-{{NULL, "extendedglob", OPT_EMULATE}, EXTENDEDGLOB},
-{{NULL, "extendedhistory", OPT_CSH}, EXTENDEDHISTORY},
-{{NULL, "evallineno", OPT_EMULATE|OPT_ZSH}, EVALLINENO},
-{{NULL, "flowcontrol", OPT_ALL}, FLOWCONTROL},
-{{NULL, "forcefloat", 0}, FORCEFLOAT},
-{{NULL, "functionargzero", OPT_EMULATE|OPT_NONBOURNE},FUNCTIONARGZERO},
-{{NULL, "glob", OPT_EMULATE|OPT_ALL}, GLOBOPT},
-{{NULL, "globalexport", OPT_EMULATE|OPT_ZSH}, GLOBALEXPORT},
-{{NULL, "globalrcs", OPT_ALL}, GLOBALRCS},
-{{NULL, "globassign", OPT_EMULATE|OPT_CSH}, GLOBASSIGN},
-{{NULL, "globcomplete", 0}, GLOBCOMPLETE},
-{{NULL, "globdots", OPT_EMULATE}, GLOBDOTS},
-{{NULL, "globstarshort", OPT_EMULATE}, GLOBSTARSHORT},
-{{NULL, "globsubst", OPT_EMULATE|OPT_NONZSH}, GLOBSUBST},
-{{NULL, "hashcmds", OPT_ALL}, HASHCMDS},
-{{NULL, "hashdirs", OPT_ALL}, HASHDIRS},
-{{NULL, "hashexecutablesonly", 0}, HASHEXECUTABLESONLY},
-{{NULL, "hashlistall", OPT_ALL}, HASHLISTALL},
-{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER},
-{{NULL, "histbeep", OPT_ALL}, HISTBEEP},
-{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST},
-{{NULL, "histfcntllock", 0}, HISTFCNTLLOCK},
-{{NULL, "histfindnodups", 0}, HISTFINDNODUPS},
-{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS},
-{{NULL, "histignoredups", 0}, HISTIGNOREDUPS},
-{{NULL, "histignorespace", 0}, HISTIGNORESPACE},
-{{NULL, "histlexwords", 0}, HISTLEXWORDS},
-{{NULL, "histnofunctions", 0}, HISTNOFUNCTIONS},
-{{NULL, "histnostore", 0}, HISTNOSTORE},
-{{NULL, "histsubstpattern", OPT_EMULATE}, HISTSUBSTPATTERN},
-{{NULL, "histreduceblanks", 0}, HISTREDUCEBLANKS},
-{{NULL, "histsavebycopy", OPT_ALL}, HISTSAVEBYCOPY},
-{{NULL, "histsavenodups", 0}, HISTSAVENODUPS},
-{{NULL, "histverify", 0}, HISTVERIFY},
-{{NULL, "hup", OPT_EMULATE|OPT_ZSH}, HUP},
-{{NULL, "ignorebraces", OPT_EMULATE|OPT_SH}, IGNOREBRACES},
-{{NULL, "ignoreclosebraces", OPT_EMULATE}, IGNORECLOSEBRACES},
-{{NULL, "ignoreeof", 0}, IGNOREEOF},
-{{NULL, "incappendhistory", 0}, INCAPPENDHISTORY},
-{{NULL, "incappendhistorytime", 0}, INCAPPENDHISTORYTIME},
-{{NULL, "interactive", OPT_SPECIAL}, INTERACTIVE},
-{{NULL, "interactivecomments",OPT_BOURNE}, INTERACTIVECOMMENTS},
-{{NULL, "ksharrays", OPT_EMULATE|OPT_BOURNE}, KSHARRAYS},
-{{NULL, "kshautoload", OPT_EMULATE|OPT_BOURNE}, KSHAUTOLOAD},
-{{NULL, "kshglob", OPT_EMULATE|OPT_KSH}, KSHGLOB},
-{{NULL, "kshoptionprint", OPT_EMULATE|OPT_KSH}, KSHOPTIONPRINT},
-{{NULL, "kshtypeset", 0}, KSHTYPESET},
-{{NULL, "kshzerosubscript", 0}, KSHZEROSUBSCRIPT},
-{{NULL, "listambiguous", OPT_ALL}, LISTAMBIGUOUS},
-{{NULL, "listbeep", OPT_ALL}, LISTBEEP},
-{{NULL, "listpacked", 0}, LISTPACKED},
-{{NULL, "listrowsfirst", 0}, LISTROWSFIRST},
-{{NULL, "listtypes", OPT_ALL}, LISTTYPES},
-{{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS},
-{{NULL, "localloops", OPT_EMULATE}, LOCALLOOPS},
-{{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS},
-{{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS},
-{{NULL, "login", OPT_SPECIAL}, LOGINSHELL},
-{{NULL, "longlistjobs", 0}, LONGLISTJOBS},
-{{NULL, "magicequalsubst", OPT_EMULATE}, MAGICEQUALSUBST},
-{{NULL, "mailwarning", 0}, MAILWARNING},
-{{NULL, "markdirs", 0}, MARKDIRS},
-{{NULL, "menucomplete", 0}, MENUCOMPLETE},
-{{NULL, "monitor", OPT_SPECIAL}, MONITOR},
-{{NULL, "multibyte",
-#ifdef MULTIBYTE_SUPPORT
- OPT_ALL
-#else
- 0
-#endif
- }, MULTIBYTE},
-{{NULL, "multifuncdef", OPT_EMULATE|OPT_ZSH}, MULTIFUNCDEF},
-{{NULL, "multios", OPT_EMULATE|OPT_ZSH}, MULTIOS},
-{{NULL, "nomatch", OPT_EMULATE|OPT_NONBOURNE},NOMATCH},
-{{NULL, "notify", OPT_ZSH}, NOTIFY},
-{{NULL, "nullglob", OPT_EMULATE}, NULLGLOB},
-{{NULL, "numericglobsort", OPT_EMULATE}, NUMERICGLOBSORT},
-{{NULL, "octalzeroes", OPT_EMULATE|OPT_SH}, OCTALZEROES},
-{{NULL, "overstrike", 0}, OVERSTRIKE},
-{{NULL, "pathdirs", OPT_EMULATE}, PATHDIRS},
-{{NULL, "pathscript", OPT_EMULATE|OPT_BOURNE}, PATHSCRIPT},
-{{NULL, "pipefail", OPT_EMULATE}, PIPEFAIL},
-{{NULL, "posixaliases", OPT_EMULATE|OPT_BOURNE}, POSIXALIASES},
-{{NULL, "posixargzero", OPT_EMULATE}, POSIXARGZERO},
-{{NULL, "posixbuiltins", OPT_EMULATE|OPT_BOURNE}, POSIXBUILTINS},
-{{NULL, "posixcd", OPT_EMULATE|OPT_BOURNE}, POSIXCD},
-{{NULL, "posixidentifiers", OPT_EMULATE|OPT_BOURNE}, POSIXIDENTIFIERS},
-{{NULL, "posixjobs", OPT_EMULATE|OPT_BOURNE}, POSIXJOBS},
-{{NULL, "posixstrings", OPT_EMULATE|OPT_BOURNE}, POSIXSTRINGS},
-{{NULL, "posixtraps", OPT_EMULATE|OPT_BOURNE}, POSIXTRAPS},
-{{NULL, "printeightbit", 0}, PRINTEIGHTBIT},
-{{NULL, "printexitvalue", 0}, PRINTEXITVALUE},
-{{NULL, "privileged", OPT_SPECIAL}, PRIVILEGED},
-{{NULL, "promptbang", OPT_KSH}, PROMPTBANG},
-{{NULL, "promptcr", OPT_ALL}, PROMPTCR},
-{{NULL, "promptpercent", OPT_NONBOURNE}, PROMPTPERCENT},
-{{NULL, "promptsp", OPT_ALL}, PROMPTSP},
-{{NULL, "promptsubst", OPT_BOURNE}, PROMPTSUBST},
-{{NULL, "pushdignoredups", OPT_EMULATE}, PUSHDIGNOREDUPS},
-{{NULL, "pushdminus", OPT_EMULATE}, PUSHDMINUS},
-{{NULL, "pushdsilent", 0}, PUSHDSILENT},
-{{NULL, "pushdtohome", OPT_EMULATE}, PUSHDTOHOME},
-{{NULL, "rcexpandparam", OPT_EMULATE}, RCEXPANDPARAM},
-{{NULL, "rcquotes", OPT_EMULATE}, RCQUOTES},
-{{NULL, "rcs", OPT_ALL}, RCS},
-{{NULL, "recexact", 0}, RECEXACT},
-{{NULL, "rematchpcre", 0}, REMATCHPCRE},
-{{NULL, "restricted", OPT_SPECIAL}, RESTRICTED},
-{{NULL, "rmstarsilent", OPT_BOURNE}, RMSTARSILENT},
-{{NULL, "rmstarwait", 0}, RMSTARWAIT},
-{{NULL, "sharehistory", OPT_KSH}, SHAREHISTORY},
-{{NULL, "shfileexpansion", OPT_EMULATE|OPT_BOURNE}, SHFILEEXPANSION},
-{{NULL, "shglob", OPT_EMULATE|OPT_BOURNE}, SHGLOB},
-{{NULL, "shinstdin", OPT_SPECIAL}, SHINSTDIN},
-{{NULL, "shnullcmd", OPT_EMULATE|OPT_BOURNE}, SHNULLCMD},
-{{NULL, "shoptionletters", OPT_EMULATE|OPT_BOURNE}, SHOPTIONLETTERS},
-{{NULL, "shortloops", OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS},
-{{NULL, "shwordsplit", OPT_EMULATE|OPT_BOURNE}, SHWORDSPLIT},
-{{NULL, "singlecommand", OPT_SPECIAL}, SINGLECOMMAND},
-{{NULL, "singlelinezle", OPT_KSH}, SINGLELINEZLE},
-{{NULL, "sourcetrace", 0}, SOURCETRACE},
-{{NULL, "sunkeyboardhack", 0}, SUNKEYBOARDHACK},
-{{NULL, "transientrprompt", 0}, TRANSIENTRPROMPT},
-{{NULL, "trapsasync", 0}, TRAPSASYNC},
-{{NULL, "typesetsilent", OPT_EMULATE|OPT_BOURNE}, TYPESETSILENT},
-{{NULL, "unset", OPT_EMULATE|OPT_BSHELL}, UNSET},
-{{NULL, "verbose", 0}, VERBOSE},
-{{NULL, "vi", 0}, VIMODE},
-{{NULL, "warncreateglobal", OPT_EMULATE}, WARNCREATEGLOBAL},
-{{NULL, "warnnestedvar", OPT_EMULATE}, WARNNESTEDVAR},
-{{NULL, "xtrace", 0}, XTRACE},
-{{NULL, "zle", OPT_SPECIAL}, USEZLE},
-{{NULL, "braceexpand", OPT_ALIAS}, /* ksh/bash */ -IGNOREBRACES},
-{{NULL, "dotglob", OPT_ALIAS}, /* bash */ GLOBDOTS},
-{{NULL, "hashall", OPT_ALIAS}, /* bash */ HASHCMDS},
-{{NULL, "histappend", OPT_ALIAS}, /* bash */ APPENDHISTORY},
-{{NULL, "histexpand", OPT_ALIAS}, /* bash */ BANGHIST},
-{{NULL, "log", OPT_ALIAS}, /* ksh */ -HISTNOFUNCTIONS},
-{{NULL, "mailwarn", OPT_ALIAS}, /* bash */ MAILWARNING},
-{{NULL, "onecmd", OPT_ALIAS}, /* bash */ SINGLECOMMAND},
-{{NULL, "physical", OPT_ALIAS}, /* ksh/bash */ CHASELINKS},
-{{NULL, "promptvars", OPT_ALIAS}, /* bash */ PROMPTSUBST},
-{{NULL, "stdin", OPT_ALIAS}, /* ksh */ SHINSTDIN},
-{{NULL, "trackall", OPT_ALIAS}, /* ksh */ HASHCMDS},
-{{NULL, "dvorak", 0}, DVORAK},
-{{NULL, NULL, 0}, 0}
-};
-
-/* Option letters */
-
-#define optletters (isset(SHOPTIONLETTERS) ? kshletters : zshletters)
-
-#define FIRST_OPT '0'
-#define LAST_OPT 'y'
-
-static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
- /* 0 */ CORRECT,
- /* 1 */ PRINTEXITVALUE,
- /* 2 */ -BADPATTERN,
- /* 3 */ -NOMATCH,
- /* 4 */ GLOBDOTS,
- /* 5 */ NOTIFY,
- /* 6 */ BGNICE,
- /* 7 */ IGNOREEOF,
- /* 8 */ MARKDIRS,
- /* 9 */ AUTOLIST,
- /* : */ 0,
- /* ; */ 0,
- /* < */ 0,
- /* = */ 0,
- /* > */ 0,
- /* ? */ 0,
- /* @ */ 0,
- /* A */ 0, /* use with set for arrays */
- /* B */ -BEEP,
- /* C */ -CLOBBER,
- /* D */ PUSHDTOHOME,
- /* E */ PUSHDSILENT,
- /* F */ -GLOBOPT,
- /* G */ NULLGLOB,
- /* H */ RMSTARSILENT,
- /* I */ IGNOREBRACES,
- /* J */ AUTOCD,
- /* K */ -BANGHIST,
- /* L */ SUNKEYBOARDHACK,
- /* M */ SINGLELINEZLE,
- /* N */ AUTOPUSHD,
- /* O */ CORRECTALL,
- /* P */ RCEXPANDPARAM,
- /* Q */ PATHDIRS,
- /* R */ LONGLISTJOBS,
- /* S */ RECEXACT,
- /* T */ CDABLEVARS,
- /* U */ MAILWARNING,
- /* V */ -PROMPTCR,
- /* W */ AUTORESUME,
- /* X */ LISTTYPES,
- /* Y */ MENUCOMPLETE,
- /* Z */ USEZLE,
- /* [ */ 0,
- /* \ */ 0,
- /* ] */ 0,
- /* ^ */ 0,
- /* _ */ 0,
- /* ` */ 0,
- /* a */ ALLEXPORT,
- /* b */ 0, /* in non-Bourne shells, end of options */
- /* c */ 0, /* command follows */
- /* d */ -GLOBALRCS,
- /* e */ ERREXIT,
- /* f */ -RCS,
- /* g */ HISTIGNORESPACE,
- /* h */ HISTIGNOREDUPS,
- /* i */ INTERACTIVE,
- /* j */ 0,
- /* k */ INTERACTIVECOMMENTS,
- /* l */ LOGINSHELL,
- /* m */ MONITOR,
- /* n */ -EXECOPT,
- /* o */ 0, /* long option name follows */
- /* p */ PRIVILEGED,
- /* q */ 0,
- /* r */ RESTRICTED,
- /* s */ SHINSTDIN,
- /* t */ SINGLECOMMAND,
- /* u */ -UNSET,
- /* v */ VERBOSE,
- /* w */ CHASELINKS,
- /* x */ XTRACE,
- /* y */ SHWORDSPLIT,
-};
-
-static short kshletters[LAST_OPT - FIRST_OPT + 1] = {
- /* 0 */ 0,
- /* 1 */ 0,
- /* 2 */ 0,
- /* 3 */ 0,
- /* 4 */ 0,
- /* 5 */ 0,
- /* 6 */ 0,
- /* 7 */ 0,
- /* 8 */ 0,
- /* 9 */ 0,
- /* : */ 0,
- /* ; */ 0,
- /* < */ 0,
- /* = */ 0,
- /* > */ 0,
- /* ? */ 0,
- /* @ */ 0,
- /* A */ 0,
- /* B */ 0,
- /* C */ -CLOBBER,
- /* D */ 0,
- /* E */ 0,
- /* F */ 0,
- /* G */ 0,
- /* H */ 0,
- /* I */ 0,
- /* J */ 0,
- /* K */ 0,
- /* L */ 0,
- /* M */ 0,
- /* N */ 0,
- /* O */ 0,
- /* P */ 0,
- /* Q */ 0,
- /* R */ 0,
- /* S */ 0,
- /* T */ TRAPSASYNC,
- /* U */ 0,
- /* V */ 0,
- /* W */ 0,
- /* X */ MARKDIRS,
- /* Y */ 0,
- /* Z */ 0,
- /* [ */ 0,
- /* \ */ 0,
- /* ] */ 0,
- /* ^ */ 0,
- /* _ */ 0,
- /* ` */ 0,
- /* a */ ALLEXPORT,
- /* b */ NOTIFY,
- /* c */ 0,
- /* d */ 0,
- /* e */ ERREXIT,
- /* f */ -GLOBOPT,
- /* g */ 0,
- /* h */ 0,
- /* i */ INTERACTIVE,
- /* j */ 0,
- /* k */ 0,
- /* l */ LOGINSHELL,
- /* m */ MONITOR,
- /* n */ -EXECOPT,
- /* o */ 0,
- /* p */ PRIVILEGED,
- /* q */ 0,
- /* r */ RESTRICTED,
- /* s */ SHINSTDIN,
- /* t */ SINGLECOMMAND,
- /* u */ -UNSET,
- /* v */ VERBOSE,
- /* w */ 0,
- /* x */ XTRACE,
- /* y */ 0,
-};
-
-/* Initialisation of the option name hash table */
-
-/**/
-static void
-printoptionnode(HashNode hn, int set)
-{
- Optname on = (Optname) hn;
- int optno = on->optno;
-
- if (optno < 0)
- optno = -optno;
- if (isset(KSHOPTIONPRINT)) {
- if (defset(on, emulation))
- printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
- else
- printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
- } else if (set == (isset(optno) ^ defset(on, emulation))) {
- if (set ^ isset(optno))
- fputs("no", stdout);
- puts(on->node.nam);
- }
-}
-
-/**/
-void
-createoptiontable(void)
-{
- Optname on;
-
- optiontab = newhashtable(101, "optiontab", NULL);
-
- optiontab->hash = hasher;
- optiontab->emptytable = NULL;
- optiontab->filltable = NULL;
- optiontab->cmpnodes = strcmp;
- optiontab->addnode = addhashnode;
- optiontab->getnode = gethashnode;
- optiontab->getnode2 = gethashnode2;
- optiontab->removenode = NULL;
- optiontab->disablenode = disablehashnode;
- optiontab->enablenode = enablehashnode;
- optiontab->freenode = NULL;
- optiontab->printnode = printoptionnode;
-
- for (on = optns; on->node.nam; on++)
- optiontab->addnode(optiontab, on->node.nam, on);
-}
-
-/* Emulation appropriate to the setemulate function */
-
-static int setemulate_emulation;
-
-/* Option array manipulated within the setemulate function */
-
-/**/
-static char *setemulate_opts;
-
-/* Setting of default options */
-
-/**/
-static void
-setemulate(HashNode hn, int fully)
-{
- Optname on = (Optname) hn;
-
- /* Set options: each non-special option is set according to the *
- * current emulation mode if either it is considered relevant *
- * to emulation or we are doing a full emulation (as indicated *
- * by the `fully' parameter). */
- if (!(on->node.flags & OPT_ALIAS) &&
- ((fully && !(on->node.flags & OPT_SPECIAL)) ||
- (on->node.flags & OPT_EMULATE)))
- setemulate_opts[on->optno] = defset(on, setemulate_emulation);
-}
-
-/**/
-void
-installemulation(int new_emulation, char *new_opts)
-{
- setemulate_emulation = new_emulation;
- setemulate_opts = new_opts;
- scanhashtable(optiontab, 0, 0, 0, setemulate,
- !!(new_emulation & EMULATE_FULLY));
-}
-
-/**/
-void
-emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts)
-{
- char ch = *zsh_name;
-
- if (ch == 'r')
- ch = zsh_name[1];
-
- /* Work out the new emulation mode */
- if (ch == 'c')
- *new_emulation = EMULATE_CSH;
- else if (ch == 'k')
- *new_emulation = EMULATE_KSH;
- else if (ch == 's' || ch == 'b')
- *new_emulation = EMULATE_SH;
- else
- *new_emulation = EMULATE_ZSH;
-
- if (fully)
- *new_emulation |= EMULATE_FULLY;
- installemulation(*new_emulation, new_opts);
-
- if (funcstack && funcstack->tp == FS_FUNC) {
- /*
- * We are inside a function. Decide if it's traced.
- * Pedantic note: the function in the function table isn't
- * guaranteed to be what we're executing, but it's
- * close enough.
- */
- Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name);
- if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) {
- /* Tracing is on, so set xtrace */
- new_opts[XTRACE] = 1;
- }
- }
-}
-
-/* setopt, unsetopt */
-
-/**/
-static void
-setoption(HashNode hn, int value)
-{
- dosetopt(((Optname) hn)->optno, value, 0, opts);
-}
-
-/**/
-int
-bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
-{
- int action, optno, match = 0;
-
- /* With no arguments or options, display options. */
- if (!*args) {
- scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun);
- return 0;
- }
-
- /* loop through command line options (begins with "-" or "+") */
- while (*args && (**args == '-' || **args == '+')) {
- action = (**args == '-') ^ isun;
- if(!args[0][1])
- *args = "--";
- while (*++*args) {
- if(**args == Meta)
- *++*args ^= 32;
- /* The pseudo-option `--' signifies the end of options. */
- if (**args == '-') {
- args++;
- goto doneoptions;
- } else if (**args == 'o') {
- if (!*++*args)
- args++;
- if (!*args) {
- zwarnnam(nam, "string expected after -o");
- inittyptab();
- return 1;
- }
- if(!(optno = optlookup(*args)))
- zwarnnam(nam, "no such option: %s", *args);
- else if(dosetopt(optno, action, 0, opts))
- zwarnnam(nam, "can't change option: %s", *args);
- break;
- } else if(**args == 'm') {
- match = 1;
- } else {
- if (!(optno = optlookupc(**args)))
- zwarnnam(nam, "bad option: -%c", **args);
- else if(dosetopt(optno, action, 0, opts))
- zwarnnam(nam, "can't change option: -%c", **args);
- }
- }
- args++;
- }
- doneoptions:
-
- if (!match) {
- /* Not globbing the arguments -- arguments are simply option names. */
- while (*args) {
- if(!(optno = optlookup(*args++)))
- zwarnnam(nam, "no such option: %s", args[-1]);
- else if(dosetopt(optno, !isun, 0, opts))
- zwarnnam(nam, "can't change option: %s", args[-1]);
- }
- } else {
- /* Globbing option (-m) set. */
- while (*args) {
- Patprog pprog;
- char *s, *t;
-
- t = s = dupstring(*args);
- while (*t)
- if (*t == '_')
- chuck(t);
- else {
- /* See comment in optlookup() */
- if (*t >= 'A' && *t <= 'Z')
- *t = (*t - 'A') + 'a';
- t++;
- }
-
- /* Expand the current arg. */
- tokenize(s);
- if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) {
- zwarnnam(nam, "bad pattern: %s", *args);
- continue;
- }
- /* Loop over expansions. */
- scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
- setoption, !isun);
- args++;
- }
- }
- inittyptab();
- return 0;
-}
-
-/* Identify an option name */
-
-/**/
-mod_export int
-optlookup(char const *name)
-{
- char *s, *t;
- Optname n;
-
- s = t = dupstring(name);
-
- /* exorcise underscores, and change to lowercase */
- while (*t)
- if (*t == '_')
- chuck(t);
- else {
- /*
- * Some locales (in particular tr_TR.UTF-8) may
- * have non-standard mappings of ASCII characters,
- * so be careful. Option names must be ASCII so
- * we don't need to be too clever.
- */
- if (*t >= 'A' && *t <= 'Z')
- *t = (*t - 'A') + 'a';
- t++;
- }
-
- /* look up name in the table */
- if (s[0] == 'n' && s[1] == 'o' &&
- (n = (Optname) optiontab->getnode(optiontab, s + 2))) {
- return -n->optno;
- } else if ((n = (Optname) optiontab->getnode(optiontab, s)))
- return n->optno;
- else
- return OPT_INVALID;
-}
-
-/* Identify an option letter */
-
-/**/
-int
-optlookupc(char c)
-{
- if(c < FIRST_OPT || c > LAST_OPT)
- return 0;
-
- return optletters[c - FIRST_OPT];
-}
-
-/**/
-static void
-restrictparam(char *nam)
-{
- Param pm = (Param) paramtab->getnode(paramtab, nam);
-
- if (pm) {
- pm->node.flags |= PM_SPECIAL | PM_RESTRICTED;
- return;
- }
- createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED);
-}
-
-/* list of restricted parameters which are not otherwise special */
-static char *rparams[] = {
- "SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH",
- "LD_PRELOAD", "LD_AOUT_PRELOAD", NULL
-};
-
-/* Set or unset an option, as a result of user request. The option *
- * number may be negative, indicating that the sense is reversed *
- * from the usual meaning of the option. */
-
-/**/
-mod_export int
-dosetopt(int optno, int value, int force, char *new_opts)
-{
- if(!optno)
- return -1;
- if(optno < 0) {
- optno = -optno;
- value = !value;
- }
- if (optno == RESTRICTED) {
- if (isset(RESTRICTED))
- return value ? 0 : -1;
- if (value) {
- char **s;
-
- for (s = rparams; *s; s++)
- restrictparam(*s);
- }
- } else if(!force && optno == EXECOPT && !value && interact) {
- /* cannot set noexec when interactive */
- return -1;
- } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
- optno == SINGLECOMMAND)) {
- if (new_opts[optno] == value)
- return 0;
- /* it is not permitted to change the value of these options */
- return -1;
- } else if(!force && optno == USEZLE && value) {
- /* we require a terminal in order to use ZLE */
- if(!interact || SHTTY == -1 || !shout)
- return -1;
- } else if(optno == PRIVILEGED && !value) {
- /* unsetting PRIVILEGED causes the shell to make itself unprivileged */
-#ifdef HAVE_SETUID
- int ignore_err;
- errno = 0;
- /*
- * Set the GID first as if we set the UID to non-privileged it
- * might be impossible to restore the GID.
- *
- * Some OSes (possibly no longer around) have been known to
- * fail silently the first time, so we attempt the change twice.
- * If it fails we are guaranteed to pick this up the second
- * time, so ignore the first time.
- *
- * Some versions of gcc make it hard to ignore the results the
- * first time, hence the following. (These are probably not
- * systems that require the doubled calls.)
- */
- ignore_err = setgid(getgid());
- (void)ignore_err;
- ignore_err = setuid(getuid());
- (void)ignore_err;
- if (setgid(getgid())) {
- zwarn("failed to change group ID: %e", errno);
- return -1;
- } else if (setuid(getuid())) {
- zwarn("failed to change user ID: %e", errno);
- return -1;
- }
-#else
- zwarn("setuid not available");
- return -1;
-#endif /* not HAVE_SETUID */
-#ifdef JOB_CONTROL
- } else if (!force && optno == MONITOR && value) {
- if (new_opts[optno] == value)
- return 0;
- if (SHTTY != -1) {
- origpgrp = GETPGRP();
- acquire_pgrp();
- } else
- return -1;
-#else
- } else if(optno == MONITOR && value) {
- return -1;
-#endif /* not JOB_CONTROL */
-#ifdef GETPWNAM_FAKED
- } else if(optno == CDABLEVARS && value) {
- return -1;
-#endif /* GETPWNAM_FAKED */
- } else if ((optno == EMACSMODE || optno == VIMODE) && value) {
- if (sticky && sticky->emulation)
- return -1;
- zleentry(ZLE_CMD_SET_KEYMAP, optno);
- new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
- } else if (optno == SUNKEYBOARDHACK) {
- /* for backward compatibility */
- keyboardhackchar = (value ? '`' : '\0');
- }
- new_opts[optno] = value;
- if (optno == BANGHIST || optno == SHINSTDIN)
- inittyptab();
- return 0;
-}
-
-/* Function to get value for special parameter `-' */
-
-/**/
-char *
-dashgetfn(UNUSED(Param pm))
-{
- static char buf[LAST_OPT - FIRST_OPT + 2];
- char *val = buf;
- int i;
-
- for(i = 0; i <= LAST_OPT - FIRST_OPT; i++) {
- int optno = optletters[i];
- if(optno && ((optno > 0) ? isset(optno) : unset(-optno)))
- *val++ = FIRST_OPT + i;
- }
- *val = '\0';
- return buf;
-}
-
-/* print options for set -o/+o */
-
-/**/
-void
-printoptionstates(int hadplus)
-{
- scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionnodestate, hadplus);
-}
-
-/**/
-static void
-printoptionnodestate(HashNode hn, int hadplus)
-{
- Optname on = (Optname) hn;
- int optno = on->optno;
-
- if (hadplus) {
- printf("set %co %s%s\n",
- defset(on, emulation) != isset(optno) ? '-' : '+',
- defset(on, emulation) ? "no" : "",
- on->node.nam);
- } else {
- if (defset(on, emulation))
- printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
- else
- printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
- }
-}
-
-/* Print option list for --help */
-
-/**/
-void
-printoptionlist(void)
-{
- short *lp;
- char c;
-
- printf("\nNamed options:\n");
- scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
- printf("\nOption aliases:\n");
- scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
- printf("\nOption letters:\n");
- for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
- if(!*lp)
- continue;
- printf(" -%c ", c);
- printoptionlist_printequiv(*lp);
- }
-}
-
-/**/
-static void
-printoptionlist_printoption(HashNode hn, UNUSED(int ignored))
-{
- Optname on = (Optname) hn;
-
- if(on->node.flags & OPT_ALIAS) {
- printf(" --%-19s ", on->node.nam);
- printoptionlist_printequiv(on->optno);
- } else
- printf(" --%s\n", on->node.nam);
-}
-
-/**/
-static void
-printoptionlist_printequiv(int optno)
-{
- int isneg = optno < 0;
-
- optno *= (isneg ? -1 : 1);
- printf(" equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam);
-}
-
-/**/
-static char *print_emulate_opts;
-
-/**/
-static void
-print_emulate_option(HashNode hn, int fully)
-{
- Optname on = (Optname) hn;
-
- if (!(on->node.flags & OPT_ALIAS) &&
- ((fully && !(on->node.flags & OPT_SPECIAL)) ||
- (on->node.flags & OPT_EMULATE)))
- {
- if (!print_emulate_opts[on->optno])
- fputs("no", stdout);
- puts(on->node.nam);
- }
-}
-
-/*
- * List the settings of options associated with an emulation
- */
-
-/**/
-void list_emulate_options(char *cmdopts, int fully)
-{
- print_emulate_opts = cmdopts;
- scanhashtable(optiontab, 1, 0, 0, print_emulate_option, fully);
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/params.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/params.c
deleted file mode 100644
index a1c299f6..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/params.c
+++ /dev/null
@@ -1,5884 +0,0 @@
-/*
- * params.c - parameters
- *
- * 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 "params.pro"
-
-#include "version.h"
-#ifdef CUSTOM_PATCHLEVEL
-#define ZSH_PATCHLEVEL CUSTOM_PATCHLEVEL
-#else
-#include "patchlevel.h"
-
-#include
-
-/* If removed from the ChangeLog for some reason */
-#ifndef ZSH_PATCHLEVEL
-#define ZSH_PATCHLEVEL "unknown"
-#endif
-#endif
-
-/* what level of localness we are at */
-
-/**/
-mod_export int locallevel;
-
-/* Variables holding values of special parameters */
-
-/**/
-mod_export
-char **pparams, /* $argv */
- **cdpath, /* $cdpath */
- **fpath, /* $fpath */
- **mailpath, /* $mailpath */
- **manpath, /* $manpath */
- **psvar, /* $psvar */
- **watch, /* $watch */
- **zsh_eval_context; /* $zsh_eval_context */
-/**/
-mod_export
-char **path, /* $path */
- **fignore; /* $fignore */
-
-/**/
-mod_export
-char *argzero, /* $0 */
- *posixzero, /* $0 */
- *home, /* $HOME */
- *nullcmd, /* $NULLCMD */
- *oldpwd, /* $OLDPWD */
- *zoptarg, /* $OPTARG */
- *prompt, /* $PROMPT */
- *prompt2, /* $PROMPT2 */
- *prompt3, /* $PROMPT3 */
- *prompt4, /* $PROMPT4 */
- *readnullcmd, /* $READNULLCMD */
- *rprompt, /* $RPROMPT */
- *rprompt2, /* $RPROMPT2 */
- *sprompt, /* $SPROMPT */
- *wordchars; /* $WORDCHARS */
-/**/
-mod_export
-char *ifs, /* $IFS */
- *postedit, /* $POSTEDIT */
- *term, /* $TERM */
- *zsh_terminfo, /* $TERMINFO */
- *zsh_terminfodirs, /* $TERMINFO_DIRS */
- *ttystrname, /* $TTY */
- *pwd; /* $PWD */
-
-/**/
-mod_export
-zlong lastval, /* $? */
- mypid, /* $$ */
- lastpid, /* $! */
- zterm_columns, /* $COLUMNS */
- zterm_lines, /* $LINES */
- rprompt_indent, /* $ZLE_RPROMPT_INDENT */
- ppid, /* $PPID */
- zsh_subshell; /* $ZSH_SUBSHELL */
-
-/* $FUNCNEST */
-/**/
-mod_export
-zlong zsh_funcnest =
-#ifdef MAX_FUNCTION_DEPTH
- MAX_FUNCTION_DEPTH
-#else
- /* Disabled by default but can be enabled at run time */
- -1
-#endif
- ;
-
-/**/
-zlong lineno, /* $LINENO */
- zoptind, /* $OPTIND */
- shlvl; /* $SHLVL */
-
-/* $histchars */
-
-/**/
-mod_export unsigned char bangchar;
-/**/
-unsigned char hatchar, hashchar;
-
-/**/
-unsigned char keyboardhackchar = '\0';
-
-/* $SECONDS = now.tv_sec - shtimer.tv_sec
- * + (now.tv_usec - shtimer.tv_usec) / 1000000.0
- * (rounded to an integer if the parameter is not set to float) */
-
-/**/
-struct timeval shtimer;
-
-/* 0 if this $TERM setup is usable, otherwise it contains TERM_* flags */
-
-/**/
-mod_export int termflags;
-
-/* Forward declaration */
-
-static void
-rprompt_indent_unsetfn(Param pm, int exp);
-
-/* Standard methods for get/set/unset pointers in parameters */
-
-/**/
-mod_export const struct gsu_scalar stdscalar_gsu =
-{ strgetfn, strsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_scalar varscalar_gsu =
-{ strvargetfn, strvarsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_scalar nullsetscalar_gsu =
-{ strgetfn, nullstrsetfn, NULL };
-
-/**/
-mod_export const struct gsu_integer stdinteger_gsu =
-{ intgetfn, intsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_integer varinteger_gsu =
-{ intvargetfn, intvarsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_integer nullsetinteger_gsu =
-{ intgetfn, NULL, NULL };
-
-/**/
-mod_export const struct gsu_float stdfloat_gsu =
-{ floatgetfn, floatsetfn, stdunsetfn };
-
-/**/
-mod_export const struct gsu_array stdarray_gsu =
-{ arrgetfn, arrsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_array vararray_gsu =
-{ arrvargetfn, arrvarsetfn, stdunsetfn };
-
-/**/
-mod_export const struct gsu_hash stdhash_gsu =
-{ hashgetfn, hashsetfn, stdunsetfn };
-/**/
-mod_export const struct gsu_hash nullsethash_gsu =
-{ hashgetfn, nullsethashfn, nullunsetfn };
-
-
-/* Non standard methods (not exported) */
-static const struct gsu_integer pound_gsu =
-{ poundgetfn, nullintsetfn, stdunsetfn };
-static const struct gsu_integer errno_gsu =
-{ errnogetfn, errnosetfn, stdunsetfn };
-static const struct gsu_integer gid_gsu =
-{ gidgetfn, gidsetfn, stdunsetfn };
-static const struct gsu_integer egid_gsu =
-{ egidgetfn, egidsetfn, stdunsetfn };
-static const struct gsu_integer histsize_gsu =
-{ histsizegetfn, histsizesetfn, stdunsetfn };
-static const struct gsu_integer random_gsu =
-{ randomgetfn, randomsetfn, stdunsetfn };
-static const struct gsu_integer savehist_gsu =
-{ savehistsizegetfn, savehistsizesetfn, stdunsetfn };
-static const struct gsu_integer intseconds_gsu =
-{ intsecondsgetfn, intsecondssetfn, stdunsetfn };
-static const struct gsu_float floatseconds_gsu =
-{ floatsecondsgetfn, floatsecondssetfn, stdunsetfn };
-static const struct gsu_integer uid_gsu =
-{ uidgetfn, uidsetfn, stdunsetfn };
-static const struct gsu_integer euid_gsu =
-{ euidgetfn, euidsetfn, stdunsetfn };
-static const struct gsu_integer ttyidle_gsu =
-{ ttyidlegetfn, nullintsetfn, stdunsetfn };
-
-static const struct gsu_scalar argzero_gsu =
-{ argzerogetfn, argzerosetfn, nullunsetfn };
-static const struct gsu_scalar username_gsu =
-{ usernamegetfn, usernamesetfn, stdunsetfn };
-static const struct gsu_scalar dash_gsu =
-{ dashgetfn, nullstrsetfn, stdunsetfn };
-static const struct gsu_scalar histchars_gsu =
-{ histcharsgetfn, histcharssetfn, stdunsetfn };
-static const struct gsu_scalar home_gsu =
-{ homegetfn, homesetfn, stdunsetfn };
-static const struct gsu_scalar term_gsu =
-{ termgetfn, termsetfn, stdunsetfn };
-static const struct gsu_scalar terminfo_gsu =
-{ terminfogetfn, terminfosetfn, stdunsetfn };
-static const struct gsu_scalar terminfodirs_gsu =
-{ terminfodirsgetfn, terminfodirssetfn, stdunsetfn };
-static const struct gsu_scalar wordchars_gsu =
-{ wordcharsgetfn, wordcharssetfn, stdunsetfn };
-static const struct gsu_scalar ifs_gsu =
-{ ifsgetfn, ifssetfn, stdunsetfn };
-static const struct gsu_scalar underscore_gsu =
-{ underscoregetfn, nullstrsetfn, stdunsetfn };
-static const struct gsu_scalar keyboard_hack_gsu =
-{ keyboardhackgetfn, keyboardhacksetfn, stdunsetfn };
-#ifdef USE_LOCALE
-static const struct gsu_scalar lc_blah_gsu =
-{ strgetfn, lcsetfn, stdunsetfn };
-static const struct gsu_scalar lang_gsu =
-{ strgetfn, langsetfn, stdunsetfn };
-static const struct gsu_scalar lc_all_gsu =
-{ strgetfn, lc_allsetfn, stdunsetfn };
-#endif
-
-static const struct gsu_integer varint_readonly_gsu =
-{ intvargetfn, nullintsetfn, stdunsetfn };
-static const struct gsu_integer zlevar_gsu =
-{ intvargetfn, zlevarsetfn, stdunsetfn };
-
-static const struct gsu_scalar colonarr_gsu =
-{ colonarrgetfn, colonarrsetfn, stdunsetfn };
-
-static const struct gsu_integer argc_gsu =
-{ poundgetfn, nullintsetfn, stdunsetfn };
-static const struct gsu_array pipestatus_gsu =
-{ pipestatgetfn, pipestatsetfn, stdunsetfn };
-
-static const struct gsu_integer rprompt_indent_gsu =
-{ intvargetfn, zlevarsetfn, rprompt_indent_unsetfn };
-
-/* Nodes for special parameters for parameter hash table */
-
-#ifdef HAVE_UNION_INIT
-# define BR(X) {X}
-typedef struct param initparam;
-#else
-# define BR(X) X
-typedef struct iparam {
- struct hashnode *next;
- char *nam; /* hash data */
- int flags; /* PM_* flags (defined in zsh.h) */
- void *value;
- void *gsu; /* get/set/unset methods */
- int base; /* output base */
- int width; /* output field width */
- char *env; /* location in environment, if exported */
- char *ename; /* name of corresponding environment var */
- Param old; /* old struct for use with local */
- int level; /* if (old != NULL), level of localness */
-} initparam;
-#endif
-
-static initparam special_params[] ={
-#define GSU(X) BR((GsuScalar)(void *)(&(X)))
-#define NULL_GSU BR((GsuScalar)(void *)NULL)
-#define IPDEF1(A,B,C) {{NULL,A,PM_INTEGER|PM_SPECIAL|C},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0}
-IPDEF1("#", pound_gsu, PM_READONLY),
-IPDEF1("ERRNO", errno_gsu, PM_UNSET),
-IPDEF1("GID", gid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
-IPDEF1("EGID", egid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
-IPDEF1("HISTSIZE", histsize_gsu, PM_RESTRICTED),
-IPDEF1("RANDOM", random_gsu, 0),
-IPDEF1("SAVEHIST", savehist_gsu, PM_RESTRICTED),
-IPDEF1("SECONDS", intseconds_gsu, 0),
-IPDEF1("UID", uid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
-IPDEF1("EUID", euid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
-IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY),
-
-#define IPDEF2(A,B,C) {{NULL,A,PM_SCALAR|PM_SPECIAL|C},BR(NULL),GSU(B),0,0,NULL,NULL,NULL,0}
-IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT|PM_RESTRICTED),
-IPDEF2("-", dash_gsu, PM_READONLY),
-IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT),
-IPDEF2("HOME", home_gsu, PM_UNSET),
-IPDEF2("TERM", term_gsu, PM_UNSET),
-IPDEF2("TERMINFO", terminfo_gsu, PM_UNSET),
-IPDEF2("TERMINFO_DIRS", terminfodirs_gsu, PM_UNSET),
-IPDEF2("WORDCHARS", wordchars_gsu, 0),
-IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT | PM_RESTRICTED),
-IPDEF2("_", underscore_gsu, PM_DONTIMPORT),
-IPDEF2("KEYBOARD_HACK", keyboard_hack_gsu, PM_DONTIMPORT),
-IPDEF2("0", argzero_gsu, 0),
-
-#ifdef USE_LOCALE
-# define LCIPDEF(name) IPDEF2(name, lc_blah_gsu, PM_UNSET)
-IPDEF2("LANG", lang_gsu, PM_UNSET),
-IPDEF2("LC_ALL", lc_all_gsu, PM_UNSET),
-# ifdef LC_COLLATE
-LCIPDEF("LC_COLLATE"),
-# endif
-# ifdef LC_CTYPE
-LCIPDEF("LC_CTYPE"),
-# endif
-# ifdef LC_MESSAGES
-LCIPDEF("LC_MESSAGES"),
-# endif
-# ifdef LC_NUMERIC
-LCIPDEF("LC_NUMERIC"),
-# endif
-# ifdef LC_TIME
-LCIPDEF("LC_TIME"),
-# endif
-#endif /* USE_LOCALE */
-
-#define IPDEF4(A,B) {{NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL},BR((void *)B),GSU(varint_readonly_gsu),10,0,NULL,NULL,NULL,0}
-IPDEF4("!", &lastpid),
-IPDEF4("$", &mypid),
-IPDEF4("?", &lastval),
-IPDEF4("HISTCMD", &curhist),
-IPDEF4("LINENO", &lineno),
-IPDEF4("PPID", &ppid),
-IPDEF4("ZSH_SUBSHELL", &zsh_subshell),
-
-#define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
-#define IPDEF5U(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
-IPDEF5("COLUMNS", &zterm_columns, zlevar_gsu),
-IPDEF5("LINES", &zterm_lines, zlevar_gsu),
-IPDEF5U("ZLE_RPROMPT_INDENT", &rprompt_indent, rprompt_indent_gsu),
-IPDEF5("SHLVL", &shlvl, varinteger_gsu),
-IPDEF5("FUNCNEST", &zsh_funcnest, varinteger_gsu),
-
-/* Don't import internal integer status variables. */
-#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
-IPDEF6("OPTIND", &zoptind, varinteger_gsu),
-IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
-IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu),
-
-#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
-#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_SUID},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
-#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
-IPDEF7("OPTARG", &zoptarg),
-IPDEF7("NULLCMD", &nullcmd),
-IPDEF7U("POSTEDIT", &postedit),
-IPDEF7("READNULLCMD", &readnullcmd),
-IPDEF7("PS1", &prompt),
-IPDEF7U("RPS1", &rprompt),
-IPDEF7U("RPROMPT", &rprompt),
-IPDEF7("PS2", &prompt2),
-IPDEF7U("RPS2", &rprompt2),
-IPDEF7U("RPROMPT2", &rprompt2),
-IPDEF7("PS3", &prompt3),
-IPDEF7R("PS4", &prompt4),
-IPDEF7("SPROMPT", &sprompt),
-
-#define IPDEF9F(A,B,C,D) {{NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(vararray_gsu),0,0,NULL,C,NULL,0}
-#define IPDEF9(A,B,C) IPDEF9F(A,B,C,0)
-IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY),
-IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY),
-
-/*
- * This empty row indicates the end of parameters available in
- * all emulations.
- */
-{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},
-
-#define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0}
-IPDEF8("CDPATH", &cdpath, "cdpath", 0),
-IPDEF8("FIGNORE", &fignore, "fignore", 0),
-IPDEF8("FPATH", &fpath, "fpath", 0),
-IPDEF8("MAILPATH", &mailpath, "mailpath", 0),
-IPDEF8("WATCH", &watch, "watch", 0),
-IPDEF8("PATH", &path, "path", PM_RESTRICTED),
-IPDEF8("PSVAR", &psvar, "psvar", 0),
-IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY),
-
-/* MODULE_PATH is not imported for security reasons */
-IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED),
-
-#define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0}
-
-/*
- * The following parameters are not available in sh/ksh compatibility *
- * mode.
- */
-
-/* All of these have sh compatible equivalents. */
-IPDEF1("ARGC", argc_gsu, PM_READONLY),
-IPDEF2("HISTCHARS", histchars_gsu, PM_DONTIMPORT),
-IPDEF4("status", &lastval),
-IPDEF7("prompt", &prompt),
-IPDEF7("PROMPT", &prompt),
-IPDEF7("PROMPT2", &prompt2),
-IPDEF7("PROMPT3", &prompt3),
-IPDEF7("PROMPT4", &prompt4),
-IPDEF8("MANPATH", &manpath, "manpath", 0),
-IPDEF9("argv", &pparams, NULL),
-IPDEF9("fignore", &fignore, "FIGNORE"),
-IPDEF9("cdpath", &cdpath, "CDPATH"),
-IPDEF9("fpath", &fpath, "FPATH"),
-IPDEF9("mailpath", &mailpath, "MAILPATH"),
-IPDEF9("manpath", &manpath, "MANPATH"),
-IPDEF9("psvar", &psvar, "PSVAR"),
-IPDEF9("watch", &watch, "WATCH"),
-
-IPDEF9F("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_READONLY),
-
-IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED),
-IPDEF9F("path", &path, "PATH", PM_RESTRICTED),
-
-/* These are known to zsh alone. */
-
-IPDEF10("pipestatus", pipestatus_gsu),
-
-{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},
-};
-
-/*
- * Alternative versions of colon-separated path parameters for
- * sh emulation. These don't link to the array versions.
- */
-static initparam special_params_sh[] = {
-IPDEF8("CDPATH", &cdpath, NULL, 0),
-IPDEF8("FIGNORE", &fignore, NULL, 0),
-IPDEF8("FPATH", &fpath, NULL, 0),
-IPDEF8("MAILPATH", &mailpath, NULL, 0),
-IPDEF8("WATCH", &watch, NULL, 0),
-IPDEF8("PATH", &path, NULL, PM_RESTRICTED),
-IPDEF8("PSVAR", &psvar, NULL, 0),
-IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, NULL, PM_READONLY),
-
-/* MODULE_PATH is not imported for security reasons */
-IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT|PM_RESTRICTED),
-
-{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},
-};
-
-/*
- * Special way of referring to the positional parameters. Unlike $*
- * and $@, this is not readonly. This parameter is not directly
- * visible in user space.
- */
-static initparam argvparam_pm = IPDEF9F("", &pparams, NULL, \
- PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT);
-
-#undef BR
-
-#define IS_UNSET_VALUE(V) \
- ((V) && (!(V)->pm || ((V)->pm->node.flags & PM_UNSET) || \
- !(V)->pm->node.nam || !*(V)->pm->node.nam))
-
-static Param argvparam;
-
-/* hash table containing the parameters */
-
-/**/
-mod_export HashTable paramtab, realparamtab;
-
-/**/
-mod_export HashTable
-newparamtable(int size, char const *name)
-{
- HashTable ht;
- if (!size)
- size = 17;
- ht = newhashtable(size, name, NULL);
-
- ht->hash = hasher;
- ht->emptytable = emptyhashtable;
- ht->filltable = NULL;
- ht->cmpnodes = strcmp;
- ht->addnode = addhashnode;
- ht->getnode = getparamnode;
- ht->getnode2 = gethashnode2;
- ht->removenode = removehashnode;
- ht->disablenode = NULL;
- ht->enablenode = NULL;
- ht->freenode = freeparamnode;
- ht->printnode = printparamnode;
-
- return ht;
-}
-
-/**/
-static HashNode
-getparamnode(HashTable ht, const char *nam)
-{
- HashNode hn = gethashnode2(ht, nam);
- Param pm = (Param) hn;
-
- if (pm && pm->u.str && (pm->node.flags & PM_AUTOLOAD)) {
- char *mn = dupstring(pm->u.str);
-
- (void)ensurefeature(mn, "p:", (pm->node.flags & PM_AUTOALL) ? NULL :
- nam);
- hn = gethashnode2(ht, nam);
- if (!hn) {
- /*
- * This used to be a warning, but surely if we allow
- * stuff to go ahead with the autoload stub with
- * no error status we're in for all sorts of mayhem?
- */
- zerr("autoloading module %s failed to define parameter: %s", mn,
- nam);
- }
- }
- return hn;
-}
-
-/* Copy a parameter hash table */
-
-static HashTable outtable;
-
-/**/
-static void
-scancopyparams(HashNode hn, UNUSED(int flags))
-{
- /* Going into a real parameter, so always use permanent storage */
- Param pm = (Param)hn;
- Param tpm = (Param) zshcalloc(sizeof *tpm);
- tpm->node.nam = ztrdup(pm->node.nam);
- copyparam(tpm, pm, 0);
- addhashnode(outtable, tpm->node.nam, tpm);
-}
-
-/**/
-HashTable
-copyparamtable(HashTable ht, char *name)
-{
- HashTable nht = 0;
- if (ht) {
- nht = newparamtable(ht->hsize, name);
- outtable = nht;
- scanhashtable(ht, 0, 0, 0, scancopyparams, 0);
- outtable = NULL;
- }
- return nht;
-}
-
-/* Flag to freeparamnode to unset the struct */
-
-static int delunset;
-
-/* Function to delete a parameter table. */
-
-/**/
-mod_export void
-deleteparamtable(HashTable t)
-{
- /* The parameters in the hash table need to be unset *
- * before being deleted. */
- int odelunset = delunset;
- delunset = 1;
- deletehashtable(t);
- delunset = odelunset;
-}
-
-static unsigned numparamvals;
-
-/**/
-mod_export void
-scancountparams(UNUSED(HashNode hn), int flags)
-{
- ++numparamvals;
- if ((flags & SCANPM_WANTKEYS) && (flags & SCANPM_WANTVALS))
- ++numparamvals;
-}
-
-static Patprog scanprog;
-static char *scanstr;
-static char **paramvals;
-static Param foundparam;
-
-/**/
-static void
-scanparamvals(HashNode hn, int flags)
-{
- struct value v;
- Patprog prog;
-
- if (numparamvals && !(flags & SCANPM_MATCHMANY) &&
- (flags & (SCANPM_MATCHVAL|SCANPM_MATCHKEY|SCANPM_KEYMATCH)))
- return;
- v.pm = (Param)hn;
- if ((flags & SCANPM_KEYMATCH)) {
- char *tmp = dupstring(v.pm->node.nam);
-
- tokenize(tmp);
- remnulargs(tmp);
-
- if (!(prog = patcompile(tmp, 0, NULL)) || !pattry(prog, scanstr))
- return;
- } else if ((flags & SCANPM_MATCHKEY) && !pattry(scanprog, v.pm->node.nam)) {
- return;
- }
- foundparam = v.pm;
- if (flags & SCANPM_WANTKEYS) {
- paramvals[numparamvals++] = v.pm->node.nam;
- if (!(flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)))
- return;
- }
- v.isarr = (PM_TYPE(v.pm->node.flags) & (PM_ARRAY|PM_HASHED));
- v.flags = 0;
- v.start = 0;
- v.end = -1;
- paramvals[numparamvals] = getstrvalue(&v);
- if (flags & SCANPM_MATCHVAL) {
- if (pattry(scanprog, paramvals[numparamvals])) {
- numparamvals += ((flags & SCANPM_WANTVALS) ? 1 :
- !(flags & SCANPM_WANTKEYS));
- } else if (flags & SCANPM_WANTKEYS)
- --numparamvals; /* Value didn't match, discard key */
- } else
- ++numparamvals;
- foundparam = NULL;
-}
-
-/**/
-char **
-paramvalarr(HashTable ht, int flags)
-{
- DPUTS((flags & (SCANPM_MATCHKEY|SCANPM_MATCHVAL)) && !scanprog,
- "BUG: scanning hash without scanprog set");
- numparamvals = 0;
- if (ht)
- scanhashtable(ht, 0, 0, PM_UNSET, scancountparams, flags);
- paramvals = (char **) zhalloc((numparamvals + 1) * sizeof(char *));
- if (ht) {
- numparamvals = 0;
- scanhashtable(ht, 0, 0, PM_UNSET, scanparamvals, flags);
- }
- paramvals[numparamvals] = 0;
- return paramvals;
-}
-
-/* Return the full array (no indexing) referred to by a Value. *
- * The array value is cached for the lifetime of the Value. */
-
-/**/
-static char **
-getvaluearr(Value v)
-{
- if (v->arr)
- return v->arr;
- else if (PM_TYPE(v->pm->node.flags) == PM_ARRAY)
- return v->arr = v->pm->gsu.a->getfn(v->pm);
- else if (PM_TYPE(v->pm->node.flags) == PM_HASHED) {
- v->arr = paramvalarr(v->pm->gsu.h->getfn(v->pm), v->isarr);
- /* Can't take numeric slices of associative arrays */
- v->start = 0;
- v->end = numparamvals + 1;
- return v->arr;
- } else
- return NULL;
-}
-
-/* Return whether the variable is set *
- * checks that array slices are within range *
- * used for [[ -v ... ]] condition test */
-
-/**/
-int
-issetvar(char *name)
-{
- struct value vbuf;
- Value v;
- int slice;
- char **arr;
-
- if (!(v = getvalue(&vbuf, &name, 1)) || *name)
- return 0; /* no value or more chars after the variable name */
- if (v->isarr & ~SCANPM_ARRONLY)
- return v->end > 1; /* for extracted elements, end gives us a count */
-
- slice = v->start != 0 || v->end != -1;
- if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice)
- return !slice && !(v->pm->node.flags & PM_UNSET);
-
- if (!v->end) /* empty array slice */
- return 0;
- /* get the array and check end is within range */
- if (!(arr = getvaluearr(v)))
- return 0;
- return arrlen_ge(arr, v->end < 0 ? - v->end : v->end);
-}
-
-/*
- * Split environment string into (name, value) pair.
- * this is used to avoid in-place editing of environment table
- * that results in core dump on some systems
- */
-
-static int
-split_env_string(char *env, char **name, char **value)
-{
- char *str, *tenv;
-
- if (!env || !name || !value)
- return 0;
-
- tenv = strcpy(zhalloc(strlen(env) + 1), env);
- for (str = tenv; *str && *str != '='; str++) {
- if (STOUC(*str) >= 128) {
- /*
- * We'll ignore environment variables with names not
- * from the portable character set since we don't
- * know of a good reason to accept them.
- */
- return 0;
- }
- }
- if (str != tenv && *str == '=') {
- *str = '\0';
- *name = tenv;
- *value = str + 1;
- return 1;
- } else
- return 0;
-}
-
-/**
- * Check parameter flags to see if parameter shouldn't be imported
- * from environment at start.
- *
- * return 1: don't import: 0: ok to import.
- */
-static int dontimport(int flags)
-{
- /* If explicitly marked as don't export */
- if (flags & PM_DONTIMPORT)
- return 1;
- /* If value already exported */
- if (flags & PM_EXPORTED)
- return 1;
- /* If security issue when importing and running with some privilege */
- if ((flags & PM_DONTIMPORT_SUID) && isset(PRIVILEGED))
- return 1;
- /* OK to import */
- return 0;
-}
-
-/* Set up parameter hash table. This will add predefined *
- * parameter entries as well as setting up parameter table *
- * entries for environment variables we inherit. */
-
-/**/
-void
-createparamtable(void)
-{
- Param ip, pm;
-#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
- char **new_environ;
- int envsize;
-#endif
-#ifndef USE_SET_UNSET_ENV
- char **envp;
-#endif
- char **envp2, **sigptr, **t;
- char buf[50], *str, *iname, *ivalue, *hostnam;
- int oae = opts[ALLEXPORT];
-#ifdef HAVE_UNAME
- struct utsname unamebuf;
- char *machinebuf;
-#endif
-
- paramtab = realparamtab = newparamtable(151, "paramtab");
-
- /* Add the special parameters to the hash table */
- for (ip = special_params; ip->node.nam; ip++)
- paramtab->addnode(paramtab, ztrdup(ip->node.nam), ip);
- if (EMULATION(EMULATE_SH|EMULATE_KSH)) {
- for (ip = special_params_sh; ip->node.nam; ip++)
- paramtab->addnode(paramtab, ztrdup(ip->node.nam), ip);
- } else {
- while ((++ip)->node.nam)
- paramtab->addnode(paramtab, ztrdup(ip->node.nam), ip);
- }
-
- argvparam = (Param) &argvparam_pm;
-
- noerrs = 2;
-
- /* Add the standard non-special parameters which have to *
- * be initialized before we copy the environment variables. *
- * We don't want to override whatever values the user has *
- * given them in the environment. */
- opts[ALLEXPORT] = 0;
- setiparam("MAILCHECK", 60);
- setiparam("LOGCHECK", 60);
- setiparam("KEYTIMEOUT", 40);
- setiparam("LISTMAX", 100);
- /*
- * We used to get the output baud rate here. However, that's
- * pretty irrelevant to a terminal on an X display and can lead
- * to unnecessary delays if it's wrong (which it probably is).
- * Furthermore, even if the output is slow it's very likely
- * to be because of WAN delays, not covered by the output
- * baud rate.
- * So allow the user to set it in the special cases where it's
- * useful.
- */
- setsparam("TMPPREFIX", ztrdup_metafy(DEFAULT_TMPPREFIX));
- setsparam("TIMEFMT", ztrdup_metafy(DEFAULT_TIMEFMT));
- setsparam("WATCHFMT", ztrdup_metafy(default_watchfmt));
-
- hostnam = (char *)zalloc(256);
- gethostname(hostnam, 256);
- setsparam("HOST", ztrdup_metafy(hostnam));
- zfree(hostnam, 256);
-
- setsparam("LOGNAME",
- ztrdup_metafy((str = getlogin()) && *str ?
- str : cached_username));
-
-#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
- /* Copy the environment variables we are inheriting to dynamic *
- * memory, so we can do mallocs and frees on it. */
- envsize = sizeof(char *)*(1 + arrlen(environ));
- new_environ = (char **) zalloc(envsize);
- memcpy(new_environ, environ, envsize);
- environ = new_environ;
-#endif
-
- /* Use heap allocation to avoid many small alloc/free calls */
- pushheap();
-
- /* Now incorporate environment variables we are inheriting *
- * into the parameter hash table. Copy them into dynamic *
- * memory so that we can free them if needed */
- for (
-#ifndef USE_SET_UNSET_ENV
- envp =
-#endif
- envp2 = environ; *envp2; envp2++) {
- if (split_env_string(*envp2, &iname, &ivalue)) {
- if (!idigit(*iname) && isident(iname) && !strchr(iname, '[')) {
- /*
- * Parameters that aren't already in the parameter table
- * aren't special to the shell, so it's always OK to
- * import. Otherwise, check parameter flags.
- */
- if ((!(pm = (Param) paramtab->getnode(paramtab, iname)) ||
- !dontimport(pm->node.flags)) &&
- (pm = assignsparam(iname, metafy(ivalue, -1, META_DUP),
- ASSPM_ENV_IMPORT))) {
- pm->node.flags |= PM_EXPORTED;
- if (pm->node.flags & PM_SPECIAL)
- pm->env = mkenvstr (pm->node.nam,
- getsparam(pm->node.nam), pm->node.flags);
- else
- pm->env = ztrdup(*envp2);
-#ifndef USE_SET_UNSET_ENV
- *envp++ = pm->env;
-#endif
- }
- }
- }
- }
- popheap();
-#ifndef USE_SET_UNSET_ENV
- *envp = NULL;
-#endif
- opts[ALLEXPORT] = oae;
-
- /*
- * For native emulation we always set the variable home
- * (see setupvals()).
- */
- pm = (Param) paramtab->getnode(paramtab, "HOME");
- if (EMULATION(EMULATE_ZSH))
- {
- pm->node.flags &= ~PM_UNSET;
- if (!(pm->node.flags & PM_EXPORTED))
- addenv(pm, home);
- } else if (!home)
- pm->node.flags |= PM_UNSET;
- pm = (Param) paramtab->getnode(paramtab, "LOGNAME");
- if (!(pm->node.flags & PM_EXPORTED))
- addenv(pm, pm->u.str);
- pm = (Param) paramtab->getnode(paramtab, "SHLVL");
- sprintf(buf, "%d", (int)++shlvl);
- /* shlvl value in environment needs updating unconditionally */
- addenv(pm, buf);
-
- /* Add the standard non-special parameters */
- set_pwd_env();
-#ifdef HAVE_UNAME
- if(uname(&unamebuf)) setsparam("CPUTYPE", ztrdup("unknown"));
- else
- {
- machinebuf = ztrdup_metafy(unamebuf.machine);
- setsparam("CPUTYPE", machinebuf);
- }
-
-#else
- setsparam("CPUTYPE", ztrdup_metafy("unknown"));
-#endif
- setsparam("MACHTYPE", ztrdup_metafy(MACHTYPE));
- setsparam("OSTYPE", ztrdup_metafy(OSTYPE));
- setsparam("TTY", ztrdup_metafy(ttystrname));
- setsparam("VENDOR", ztrdup_metafy(VENDOR));
- setsparam("ZSH_ARGZERO", ztrdup(posixzero));
- setsparam("ZSH_VERSION", ztrdup_metafy(ZSH_VERSION));
- setsparam("ZSH_PATCHLEVEL", ztrdup_metafy(ZSH_PATCHLEVEL));
- setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
- for (t = sigs; (*sigptr++ = ztrdup_metafy(*t++)); );
-
- noerrs = 0;
-}
-
-/* assign various functions used for non-special parameters */
-
-/**/
-mod_export void
-assigngetset(Param pm)
-{
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- pm->gsu.s = &stdscalar_gsu;
- break;
- case PM_INTEGER:
- pm->gsu.i = &stdinteger_gsu;
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- pm->gsu.f = &stdfloat_gsu;
- break;
- case PM_ARRAY:
- pm->gsu.a = &stdarray_gsu;
- break;
- case PM_HASHED:
- pm->gsu.h = &stdhash_gsu;
- break;
- default:
- DPUTS(1, "BUG: tried to create param node without valid flag");
- break;
- }
-}
-
-/* Create a parameter, so that it can be assigned to. Returns NULL if the *
- * parameter already exists or can't be created, otherwise returns the *
- * parameter node. If a parameter of the same name exists in an outer *
- * scope, it is hidden by a newly created parameter. An already existing *
- * parameter node at the current level may be `created' and returned *
- * provided it is unset and not special. If the parameter can't be *
- * created because it already exists, the PM_UNSET flag is cleared. */
-
-/**/
-mod_export Param
-createparam(char *name, int flags)
-{
- Param pm, oldpm;
-
- if (paramtab != realparamtab)
- flags = (flags & ~PM_EXPORTED) | PM_HASHELEM;
-
- if (name != nulstring) {
- oldpm = (Param) (paramtab == realparamtab ?
- /* gethashnode2() for direct table read */
- gethashnode2(paramtab, name) :
- paramtab->getnode(paramtab, name));
-
- DPUTS(oldpm && oldpm->level > locallevel,
- "BUG: old local parameter not deleted");
- if (oldpm && (oldpm->level == locallevel || !(flags & PM_LOCAL))) {
- if (isset(POSIXBUILTINS) && (oldpm->node.flags & PM_READONLY)) {
- zerr("read-only variable: %s", name);
- return NULL;
- }
- if ((oldpm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerr("%s: restricted", name);
- return NULL;
- }
- if (!(oldpm->node.flags & PM_UNSET) ||
- (oldpm->node.flags & PM_SPECIAL) ||
- /* POSIXBUILTINS horror: we need to retain 'export' flags */
- (isset(POSIXBUILTINS) && (oldpm->node.flags & PM_EXPORTED))) {
- oldpm->node.flags &= ~PM_UNSET;
- if ((oldpm->node.flags & PM_SPECIAL) && oldpm->ename) {
- Param altpm =
- (Param) paramtab->getnode(paramtab, oldpm->ename);
- if (altpm)
- altpm->node.flags &= ~PM_UNSET;
- }
- return NULL;
- }
-
- pm = oldpm;
- pm->base = pm->width = 0;
- oldpm = pm->old;
- } else {
- pm = (Param) zshcalloc(sizeof *pm);
- if ((pm->old = oldpm)) {
- /*
- * needed to avoid freeing oldpm, but we do take it
- * out of the environment when it's hidden.
- */
- if (oldpm->env)
- delenv(oldpm);
- paramtab->removenode(paramtab, name);
- }
- paramtab->addnode(paramtab, ztrdup(name), pm);
- }
-
- if (isset(ALLEXPORT) && !(flags & PM_HASHELEM))
- flags |= PM_EXPORTED;
- } else {
- pm = (Param) hcalloc(sizeof *pm);
- pm->node.nam = nulstring;
- }
- pm->node.flags = flags & ~PM_LOCAL;
-
- if(!(pm->node.flags & PM_SPECIAL))
- assigngetset(pm);
- return pm;
-}
-
-/* Empty dummy function for special hash parameters. */
-
-/**/
-static void
-shempty(void)
-{
-}
-
-/*
- * Create a simple special hash parameter.
- *
- * This is for hashes added internally --- it's not possible to add
- * special hashes from shell commands. It's currently used
- * - by addparamdef() for special parameters in the zsh/parameter
- * module
- * - by ztie for special parameters tied to databases.
- */
-
-/**/
-mod_export Param
-createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan, int flags)
-{
- Param pm;
- HashTable ht;
-
- if (!(pm = createparam(name, PM_SPECIAL|PM_HASHED|flags)))
- return NULL;
-
- /*
- * If there's an old parameter, we'll put the new one at
- * the current locallevel, so that the old parameter is
- * exposed again after leaving the function. Otherwise,
- * we'll leave it alone. Usually this means the parameter
- * will stay in place until explicitly unloaded, however
- * if the parameter was previously unset within a function
- * we'll inherit the level of that function and follow the
- * standard convention that the parameter remains local
- * even if unset.
- *
- * These semantics are similar to those of a normal parameter set
- * within a function without a local definition.
- */
- if (pm->old)
- pm->level = locallevel;
- pm->gsu.h = (flags & PM_READONLY) ? &stdhash_gsu :
- &nullsethash_gsu;
- pm->u.hash = ht = newhashtable(0, name, NULL);
-
- ht->hash = hasher;
- ht->emptytable = (TableFunc) shempty;
- ht->filltable = NULL;
- ht->addnode = (AddNodeFunc) shempty;
- ht->getnode = ht->getnode2 = get;
- ht->removenode = (RemoveNodeFunc) shempty;
- ht->disablenode = NULL;
- ht->enablenode = NULL;
- ht->freenode = (FreeNodeFunc) shempty;
- ht->printnode = printparamnode;
- ht->scantab = scan;
-
- return pm;
-}
-
-
-/*
- * Copy a parameter
- *
- * If fakecopy is set, we are just saving the details of a special
- * parameter. Otherwise, the result will be used as a real parameter
- * and we need to do more work.
- */
-
-/**/
-void
-copyparam(Param tpm, Param pm, int fakecopy)
-{
- /*
- * Note that tpm, into which we're copying, may not be in permanent
- * storage. However, the values themselves are later used directly
- * to set the parameter, so must be permanently allocated (in accordance
- * with sets.?fn() usage).
- */
- tpm->node.flags = pm->node.flags;
- tpm->base = pm->base;
- tpm->width = pm->width;
- tpm->level = pm->level;
- if (!fakecopy)
- tpm->node.flags &= ~PM_SPECIAL;
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- tpm->u.str = ztrdup(pm->gsu.s->getfn(pm));
- break;
- case PM_INTEGER:
- tpm->u.val = pm->gsu.i->getfn(pm);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- tpm->u.dval = pm->gsu.f->getfn(pm);
- break;
- case PM_ARRAY:
- tpm->u.arr = zarrdup(pm->gsu.a->getfn(pm));
- break;
- case PM_HASHED:
- tpm->u.hash = copyparamtable(pm->gsu.h->getfn(pm), pm->node.nam);
- break;
- }
- /*
- * If the value is going to be passed as a real parameter (e.g. this is
- * called from inside an associative array), we need the gets and sets
- * functions to be useful.
- *
- * In this case we assume the saved parameter is not itself special,
- * so we just use the standard functions. This is also why we switch off
- * PM_SPECIAL.
- */
- if (!fakecopy)
- assigngetset(tpm);
-}
-
-/* Return 1 if the string s is a valid identifier, else return 0. */
-
-/**/
-mod_export int
-isident(char *s)
-{
- char *ss;
-
- if (!*s) /* empty string is definitely not valid */
- return 0;
-
- if (idigit(*s)) {
- /* If the first character is `s' is a digit, then all must be */
- for (ss = ++s; *ss; ss++)
- if (!idigit(*ss))
- break;
- } else {
- /* Find the first character in `s' not in the iident type table */
- ss = itype_end(s, IIDENT, 0);
- }
-
- /* If the next character is not [, then it is *
- * definitely not a valid identifier. */
- if (!*ss)
- return 1;
- if (s == ss)
- return 0;
- if (*ss != '[')
- return 0;
-
- /* Require balanced [ ] pairs with something between */
- if (!(ss = parse_subscript(++ss, 1, ']')))
- return 0;
- untokenize(s);
- return !ss[1];
-}
-
-/*
- * Parse a single argument to a parameter subscript.
- * The subscripts starts at *str; *str is updated (input/output)
- *
- * *inv is set to indicate if the subscript is reversed (output)
- * v is the Value for the parameter being accessed (input; note
- * v->isarr may be modified, and if v is a hash the parameter will
- * be updated to the element of the hash)
- * a2 is 1 if this is the second subscript of a range (input)
- * *w is only set if we need to find the end of a word (input; should
- * be set to 0 by the caller).
- *
- * The final two arguments are to support multibyte characters.
- * If supplied they are set to the length of the character before
- * the index position and the one at the index position. If
- * multibyte characters are not in use they are set to 1 for
- * consistency. Note they aren't fully handled if a2 is non-zero,
- * since they aren't needed.
- *
- * Returns a raw offset into the value from the start or end (i.e.
- * after the arithmetic for Meta and possible multibyte characters has
- * been taken into account). This actually gives the offset *after*
- * the character in question; subtract *prevcharlen if necessary.
- */
-
-/**/
-static zlong
-getarg(char **str, int *inv, Value v, int a2, zlong *w,
- int *prevcharlen, int *nextcharlen, int flags)
-{
- int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
- int keymatch = 0, needtok = 0, arglen, len, inpar = 0;
- char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt, c;
- zlong num = 1, beg = 0, r = 0, quote_arg = 0;
- Patprog pprog = NULL;
-
- /*
- * If in NO_EXEC mode, the parameters won't be set up properly,
- * so just pretend everything is a hash for subscript parsing
- */
-
- ishash = (unset(EXECOPT) ||
- (v->pm && PM_TYPE(v->pm->node.flags) == PM_HASHED));
- if (prevcharlen)
- *prevcharlen = 1;
- if (nextcharlen)
- *nextcharlen = 1;
-
- /* first parse any subscription flags */
- if (v->pm && (*s == '(' || *s == Inpar)) {
- int escapes = 0;
- int waste;
- for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
- switch (*s) {
- case 'r':
- rev = 1;
- keymatch = down = ind = 0;
- break;
- case 'R':
- rev = down = 1;
- keymatch = ind = 0;
- break;
- case 'k':
- keymatch = ishash;
- rev = 1;
- down = ind = 0;
- break;
- case 'K':
- keymatch = ishash;
- rev = down = 1;
- ind = 0;
- break;
- case 'i':
- rev = ind = 1;
- down = keymatch = 0;
- break;
- case 'I':
- rev = ind = down = 1;
- keymatch = 0;
- break;
- case 'w':
- /* If the parameter is a scalar, then make subscription *
- * work on a per-word basis instead of characters. */
- word = 1;
- break;
- case 'f':
- word = 1;
- sep = "\n";
- break;
- case 'e':
- quote_arg = 1;
- break;
- case 'n':
- t = get_strarg(++s, &arglen);
- if (!*t)
- goto flagerr;
- sav = *t;
- *t = '\0';
- num = mathevalarg(s + arglen, &d);
- if (!num)
- num = 1;
- *t = sav;
- s = t + arglen - 1;
- break;
- case 'b':
- hasbeg = 1;
- t = get_strarg(++s, &arglen);
- if (!*t)
- goto flagerr;
- sav = *t;
- *t = '\0';
- if ((beg = mathevalarg(s + arglen, &d)) > 0)
- beg--;
- *t = sav;
- s = t + arglen - 1;
- break;
- case 'p':
- escapes = 1;
- break;
- case 's':
- /* This gives the string that separates words *
- * (for use with the `w' flag). */
- t = get_strarg(++s, &arglen);
- if (!*t)
- goto flagerr;
- sav = *t;
- *t = '\0';
- s += arglen;
- sep = escapes ? getkeystring(s, &waste, GETKEYS_SEP, NULL)
- : dupstring(s);
- *t = sav;
- s = t + arglen - 1;
- break;
- default:
- flagerr:
- num = 1;
- word = rev = ind = down = keymatch = 0;
- sep = NULL;
- s = *str - 1;
- }
- }
- if (s != *str)
- s++;
- }
- if (num < 0) {
- down = !down;
- num = -num;
- }
- if (v->isarr & SCANPM_WANTKEYS)
- *inv = (ind || !(v->isarr & SCANPM_WANTVALS));
- else if (v->isarr & SCANPM_WANTVALS)
- *inv = 0;
- else {
- if (v->isarr) {
- if (ind) {
- v->isarr |= SCANPM_WANTKEYS;
- v->isarr &= ~SCANPM_WANTVALS;
- } else if (rev)
- v->isarr |= SCANPM_WANTVALS;
- /*
- * This catches the case where we are using "k" (rather
- * than "K") on a hash.
- */
- if (!down && keymatch && ishash)
- v->isarr &= ~SCANPM_MATCHMANY;
- }
- *inv = ind;
- }
-
- for (t = s, i = 0;
- (c = *t) &&
- ((c != Outbrack && (ishash || c != ',')) || i || inpar);
- t++) {
- /* Untokenize inull() except before brackets and double-quotes */
- if (inull(c)) {
- c = t[1];
- if (c == '[' || c == ']' ||
- c == '(' || c == ')' ||
- c == '{' || c == '}') {
- /* This test handles nested subscripts in hash keys */
- if (ishash && i)
- *t = ztokens[*t - Pound];
- needtok = 1;
- ++t;
- } else if (c != '"')
- *t = ztokens[*t - Pound];
- continue;
- }
- /* Inbrack and Outbrack are probably never found here ... */
- if (c == '[' || c == Inbrack)
- i++;
- else if (c == ']' || c == Outbrack)
- i--;
- if (c == '(' || c == Inpar)
- inpar++;
- else if (c == ')' || c == Outpar)
- inpar--;
- if (ispecial(c))
- needtok = 1;
- }
- if (!c)
- return 0;
- *str = tt = t;
-
- /*
- * If in NO_EXEC mode, the parameters won't be set up properly,
- * so there's no additional sanity checking we can do.
- * Just return 0 now.
- */
- if (unset(EXECOPT))
- return 0;
-
- s = dupstrpfx(s, t - s);
-
- /* If we're NOT reverse subscripting, strip the inull()s so brackets *
- * are not backslashed after parsestr(). Otherwise leave them alone *
- * so that the brackets will be escaped when we patcompile() or when *
- * subscript arithmetic is performed (for nested subscripts). */
- if (ishash && (keymatch || !rev))
- remnulargs(s);
- if (needtok) {
- s = dupstring(s);
- if (parsestr(&s))
- return 0;
- singsub(&s);
- } else if (rev)
- remnulargs(s); /* This is probably always a no-op, but ... */
- if (!rev) {
- if (ishash) {
- HashTable ht = v->pm->gsu.h->getfn(v->pm);
- if (!ht) {
- if (flags & SCANPM_CHECKING)
- return 0;
- ht = newparamtable(17, v->pm->node.nam);
- v->pm->gsu.h->setfn(v->pm, ht);
- }
- untokenize(s);
- if (!(v->pm = (Param) ht->getnode(ht, s))) {
- HashTable tht = paramtab;
- paramtab = ht;
- v->pm = createparam(s, PM_SCALAR|PM_UNSET);
- paramtab = tht;
- }
- v->isarr = (*inv ? SCANPM_WANTINDEX : 0);
- v->start = 0;
- *inv = 0; /* We've already obtained the "index" (key) */
- *w = v->end = -1;
- r = isset(KSHARRAYS) ? 1 : 0;
- } else {
- r = mathevalarg(s, &s);
- if (isset(KSHARRAYS) && r >= 0)
- r++;
- }
- if (word && !v->isarr) {
- s = t = getstrvalue(v);
- i = wordcount(s, sep, 0);
- if (r < 0)
- r += i + 1;
- if (r < 1)
- r = 1;
- if (r > i)
- r = i;
- if (!s || !*s)
- return 0;
- while ((d = findword(&s, sep)) && --r);
- if (!d)
- return 0;
-
- if (!a2 && *tt != ',')
- *w = (zlong)(s - t);
-
- return (a2 ? s : d + 1) - t;
- } else if (!v->isarr && !word) {
- int lastcharlen = 1;
- s = getstrvalue(v);
- /*
- * Note for the confused (= pws): the index r we
- * have so far is that specified by the user. The value
- * passed back is an offset from the start or end of
- * the string. Hence it needs correcting at least
- * for Meta characters and maybe for multibyte characters.
- */
- if (r > 0) {
- zlong nchars = r;
-
- MB_METACHARINIT();
- for (t = s; nchars && *t; nchars--)
- t += (lastcharlen = MB_METACHARLEN(t));
- /* for consistency, keep any remainder off the end */
- r = (zlong)(t - s) + nchars;
- if (prevcharlen && !nchars /* ignore if off the end */)
- *prevcharlen = lastcharlen;
- if (nextcharlen && *t)
- *nextcharlen = MB_METACHARLEN(t);
- } else if (r == 0) {
- if (prevcharlen)
- *prevcharlen = 0;
- if (nextcharlen && *s) {
- MB_METACHARINIT();
- *nextcharlen = MB_METACHARLEN(s);
- }
- } else {
- zlong nchars = (zlong)MB_METASTRLEN(s) + r;
-
- if (nchars < 0) {
- /* make sure this isn't valid as a raw pointer */
- r -= (zlong)strlen(s);
- } else {
- MB_METACHARINIT();
- for (t = s; nchars && *t; nchars--)
- t += (lastcharlen = MB_METACHARLEN(t));
- r = - (zlong)strlen(t); /* keep negative */
- if (prevcharlen)
- *prevcharlen = lastcharlen;
- if (nextcharlen && *t)
- *nextcharlen = MB_METACHARLEN(t);
- }
- }
- }
- } else {
- if (!v->isarr && !word && !quote_arg) {
- l = strlen(s);
- if (a2) {
- if (!l || *s != '*') {
- d = (char *) hcalloc(l + 2);
- *d = '*';
- strcpy(d + 1, s);
- s = d;
- }
- } else {
- if (!l || s[l - 1] != '*' || (l > 1 && s[l - 2] == '\\')) {
- d = (char *) hcalloc(l + 2);
- strcpy(d, s);
- strcat(d, "*");
- s = d;
- }
- }
- }
- if (!keymatch) {
- if (quote_arg) {
- untokenize(s);
- /* Scalar (e) needs implicit asterisk tokens */
- if (!v->isarr && !word) {
- l = strlen(s);
- d = (char *) hcalloc(l + 2);
- if (a2) {
- *d = Star;
- strcpy(d + 1, s);
- } else {
- strcpy(d, s);
- d[l] = Star;
- d[l + 1] = '\0';
- }
- s = d;
- }
- } else
- tokenize(s);
- remnulargs(s);
- pprog = patcompile(s, 0, NULL);
- } else
- pprog = NULL;
-
- if (v->isarr) {
- if (ishash) {
- scanprog = pprog;
- scanstr = s;
- if (keymatch)
- v->isarr |= SCANPM_KEYMATCH;
- else {
- if (!pprog)
- return 1;
- if (ind)
- v->isarr |= SCANPM_MATCHKEY;
- else
- v->isarr |= SCANPM_MATCHVAL;
- }
- if (down)
- v->isarr |= SCANPM_MATCHMANY;
- if ((ta = getvaluearr(v)) &&
- (*ta || ((v->isarr & SCANPM_MATCHMANY) &&
- (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
- SCANPM_KEYMATCH))))) {
- *inv = (v->flags & VALFLAG_INV) ? 1 : 0;
- *w = v->end;
- scanprog = NULL;
- return 1;
- }
- scanprog = NULL;
- } else
- ta = getarrvalue(v);
- if (!ta || !*ta)
- return !down;
- len = arrlen(ta);
- if (beg < 0)
- beg += len;
- if (down) {
- if (beg < 0)
- return 0;
- } else if (beg >= len)
- return len + 1;
- if (beg >= 0 && beg < len) {
- if (down) {
- if (!hasbeg)
- beg = len - 1;
- for (r = 1 + beg, p = ta + beg; p >= ta; r--, p--) {
- if (pprog && pattry(pprog, *p) && !--num)
- return r;
- }
- } else
- for (r = 1 + beg, p = ta + beg; *p; r++, p++)
- if (pprog && pattry(pprog, *p) && !--num)
- return r;
- }
- } else if (word) {
- ta = sepsplit(d = s = getstrvalue(v), sep, 1, 1);
- len = arrlen(ta);
- if (beg < 0)
- beg += len;
- if (down) {
- if (beg < 0)
- return 0;
- } else if (beg >= len)
- return len + 1;
- if (beg >= 0 && beg < len) {
- if (down) {
- if (!hasbeg)
- beg = len - 1;
- for (r = 1 + beg, p = ta + beg; p >= ta; p--, r--)
- if (pprog && pattry(pprog, *p) && !--num)
- break;
- if (p < ta)
- return 0;
- } else {
- for (r = 1 + beg, p = ta + beg; *p; r++, p++)
- if (pprog && pattry(pprog, *p) && !--num)
- break;
- if (!*p)
- return 0;
- }
- }
- if (a2)
- r++;
- for (i = 0; (t = findword(&d, sep)) && *t; i++)
- if (!--r) {
- r = (zlong)(t - s + (a2 ? -1 : 1));
- if (!a2 && *tt != ',')
- *w = r + strlen(ta[i]) - 1;
- return r;
- }
- return a2 ? -1 : 0;
- } else {
- /* Searching characters */
- int slen;
- d = getstrvalue(v);
- if (!d || !*d)
- return 0;
- /*
- * beg and len are character counts, not raw offsets.
- * Remember we need to return a raw offset.
- */
- len = MB_METASTRLEN(d);
- slen = strlen(d);
- if (beg < 0)
- beg += len;
- MB_METACHARINIT();
- if (beg >= 0 && beg < len) {
- char *de = d + slen;
-
- if (a2) {
- /*
- * Second argument: we don't need to
- * handle prevcharlen or nextcharlen, but
- * we do need to handle characters appropriately.
- */
- if (down) {
- int nmatches = 0;
- char *lastpos = NULL;
-
- if (!hasbeg)
- beg = len;
-
- /*
- * See below: we have to move forward,
- * but need to count from the end.
- */
- for (t = d, r = 0; r <= beg; r++) {
- sav = *t;
- *t = '\0';
- if (pprog && pattry(pprog, d)) {
- nmatches++;
- lastpos = t;
- }
- *t = sav;
- if (t == de)
- break;
- t += MB_METACHARLEN(t);
- }
-
- if (nmatches >= num) {
- if (num > 1) {
- nmatches -= num;
- MB_METACHARINIT();
- for (t = d, r = 0; ; r++) {
- sav = *t;
- *t = '\0';
- if (pprog && pattry(pprog, d) &&
- nmatches-- == 0) {
- lastpos = t;
- *t = sav;
- break;
- }
- *t = sav;
- t += MB_METACHARLEN(t);
- }
- }
- /* else lastpos is already OK */
-
- return lastpos - d;
- }
- } else {
- /*
- * This handling of the b flag
- * gives odd results, but this is the
- * way it's always worked.
- */
- for (t = d; beg && t <= de; beg--)
- t += MB_METACHARLEN(t);
- for (;;) {
- sav = *t;
- *t = '\0';
- if (pprog && pattry(pprog, d) && !--num) {
- *t = sav;
- /*
- * This time, don't increment
- * pointer, since it's already
- * after everything we matched.
- */
- return t - d;
- }
- *t = sav;
- if (t == de)
- break;
- t += MB_METACHARLEN(t);
- }
- }
- } else {
- /*
- * First argument: this is the only case
- * where we need prevcharlen and nextcharlen.
- */
- int lastcharlen;
-
- if (down) {
- int nmatches = 0;
- char *lastpos = NULL;
-
- if (!hasbeg)
- beg = len;
-
- /*
- * We can only move forward through
- * multibyte strings, so record the
- * matches.
- * Unfortunately the count num works
- * from the end, so it's easy to get the
- * last one but we need to repeat if
- * we want another one.
- */
- for (t = d, r = 0; r <= beg; r++) {
- if (pprog && pattry(pprog, t)) {
- nmatches++;
- lastpos = t;
- }
- if (t == de)
- break;
- t += MB_METACHARLEN(t);
- }
-
- if (nmatches >= num) {
- if (num > 1) {
- /*
- * Need to start again and repeat
- * to get the right match.
- */
- nmatches -= num;
- MB_METACHARINIT();
- for (t = d, r = 0; ; r++) {
- if (pprog && pattry(pprog, t) &&
- nmatches-- == 0) {
- lastpos = t;
- break;
- }
- t += MB_METACHARLEN(t);
- }
- }
- /* else lastpos is already OK */
-
- /* return pointer after matched char */
- lastpos +=
- (lastcharlen = MB_METACHARLEN(lastpos));
- if (prevcharlen)
- *prevcharlen = lastcharlen;
- if (nextcharlen)
- *nextcharlen = MB_METACHARLEN(lastpos);
- return lastpos - d;
- }
-
- for (r = beg + 1, t = d + beg; t >= d; r--, t--) {
- if (pprog && pattry(pprog, t) &&
- !--num)
- return r;
- }
- } else {
- for (t = d; beg && t <= de; beg--)
- t += MB_METACHARLEN(t);
- for (;;) {
- if (pprog && pattry(pprog, t) && !--num) {
- /* return pointer after matched char */
- t += (lastcharlen = MB_METACHARLEN(t));
- if (prevcharlen)
- *prevcharlen = lastcharlen;
- if (nextcharlen)
- *nextcharlen = MB_METACHARLEN(t);
- return t - d;
- }
- if (t == de)
- break;
- t += MB_METACHARLEN(t);
- }
- }
- }
- }
- return down ? 0 : slen + 1;
- }
- }
- return r;
-}
-
-/*
- * Parse a subscript.
- *
- * pptr: In/Out parameter. On entry, *ptr points to a "[foo]" string. On exit
- * it will point one past the closing bracket.
- *
- * v: In/Out parameter. Its .start and .end members (at least) will be updated
- * with the parsed indices.
- *
- * flags: can be either SCANPM_DQUOTED or zero. Other bits are not used.
- */
-
-/**/
-int
-getindex(char **pptr, Value v, int flags)
-{
- int start, end, inv = 0;
- char *s = *pptr, *tbrack;
-
- *s++ = '[';
- /* Error handled after untokenizing */
- s = parse_subscript(s, flags & SCANPM_DQUOTED, ']');
- /* Now we untokenize everything except inull() markers so we can check *
- * for the '*' and '@' special subscripts. The inull()s are removed *
- * in getarg() after we know whether we're doing reverse indexing. */
- for (tbrack = *pptr + 1; *tbrack && tbrack != s; tbrack++) {
- if (inull(*tbrack) && !*++tbrack)
- break;
- if (itok(*tbrack)) /* Need to check for Nularg here? */
- *tbrack = ztokens[*tbrack - Pound];
- }
- /* If we reached the end of the string (s == NULL) we have an error */
- if (*tbrack)
- *tbrack = Outbrack;
- else {
- zerr("invalid subscript");
- *pptr = tbrack;
- return 1;
- }
- s = *pptr + 1;
- if ((s[0] == '*' || s[0] == '@') && s + 1 == tbrack) {
- if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
- v->isarr |= SCANPM_ISVAR_AT;
- v->start = 0;
- v->end = -1;
- s += 2;
- } else {
- zlong we = 0, dummy;
- int startprevlen, startnextlen;
-
- start = getarg(&s, &inv, v, 0, &we, &startprevlen, &startnextlen,
- flags);
-
- if (inv) {
- if (!v->isarr && start != 0) {
- char *t, *p;
- t = getstrvalue(v);
- /*
- * Note for the confused (= pws): this is an inverse
- * offset so at this stage we need to convert from
- * the immediate offset into the value that we have
- * into a logical character position.
- */
- if (start > 0) {
- int nstart = 0;
- char *target = t + start - startprevlen;
-
- p = t;
- MB_METACHARINIT();
- while (*p) {
- /*
- * move up characters, counting how many we
- * found
- */
- p += MB_METACHARLEN(p);
- if (p < target)
- nstart++;
- else {
- if (p == target)
- nstart++;
- else
- p = target; /* pretend we hit exactly */
- break;
- }
- }
- /* if start was too big, keep the difference */
- start = nstart + (target - p) + 1;
- } else {
- zlong startoff = start + strlen(t);
-#ifdef DEBUG
- dputs("BUG: can't have negative inverse offsets???");
-#endif
- if (startoff < 0) {
- /* invalid: keep index but don't dereference */
- start = startoff;
- } else {
- /* find start in full characters */
- MB_METACHARINIT();
- for (p = t; p < t + startoff;)
- p += MB_METACHARLEN(p);
- start = - MB_METASTRLEN(p);
- }
- }
- }
- if (start > 0 && (isset(KSHARRAYS) || (v->pm->node.flags & PM_HASHED)))
- start--;
- if (v->isarr != SCANPM_WANTINDEX) {
- v->flags |= VALFLAG_INV;
- v->isarr = 0;
- v->start = start;
- v->end = start + 1;
- }
- if (*s == ',') {
- zerr("invalid subscript");
- *tbrack = ']';
- *pptr = tbrack+1;
- return 1;
- }
- if (s == tbrack)
- s++;
- } else {
- int com;
-
- if ((com = (*s == ','))) {
- s++;
- end = getarg(&s, &inv, v, 1, &dummy, NULL, NULL, flags);
- } else {
- end = we ? we : start;
- }
- if (start != end)
- com = 1;
- /*
- * Somehow the logic sometimes forces us to use the previous
- * or next character to what we would expect, which is
- * why we had to calculate them in getarg().
- */
- if (start > 0)
- start -= startprevlen;
- else if (start == 0 && end == 0)
- {
- /*
- * Strictly, this range is entirely off the
- * start of the available index range.
- * This can't happen with KSH_ARRAYS; we already
- * altered the start index in getarg().
- * Are we being strict?
- */
- if (isset(KSHZEROSUBSCRIPT)) {
- /*
- * We're not.
- * Treat this as accessing the first element of the
- * array.
- */
- end = startnextlen;
- } else {
- /*
- * We are. Flag that this range is invalid
- * for setting elements. Set the indexes
- * to a range that returns empty for other accesses.
- */
- v->flags |= VALFLAG_EMPTY;
- start = -1;
- com = 1;
- }
- }
- if (s == tbrack) {
- s++;
- if (v->isarr && !com &&
- (!(v->isarr & SCANPM_MATCHMANY) ||
- !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
- SCANPM_KEYMATCH))))
- v->isarr = 0;
- v->start = start;
- v->end = end;
- } else
- s = *pptr;
- }
- }
- *tbrack = ']';
- *pptr = s;
- return 0;
-}
-
-
-/**/
-mod_export Value
-getvalue(Value v, char **pptr, int bracks)
-{
- return fetchvalue(v, pptr, bracks, 0);
-}
-
-/**/
-mod_export Value
-fetchvalue(Value v, char **pptr, int bracks, int flags)
-{
- char *s, *t, *ie;
- char sav, c;
- int ppar = 0;
-
- s = t = *pptr;
-
- if (idigit(c = *s)) {
- if (bracks >= 0)
- ppar = zstrtol(s, &s, 10);
- else
- ppar = *s++ - '0';
- }
- else if ((ie = itype_end(s, IIDENT, 0)) != s)
- s = ie;
- else if (c == Quest)
- *s++ = '?';
- else if (c == Pound)
- *s++ = '#';
- else if (c == String)
- *s++ = '$';
- else if (c == Qstring)
- *s++ = '$';
- else if (c == Star)
- *s++ = '*';
- else if (IS_DASH(c))
- *s++ = '-';
- else if (c == '#' || c == '?' || c == '$' ||
- c == '!' || c == '@' || c == '*')
- s++;
- else
- return NULL;
-
- if ((sav = *s))
- *s = '\0';
- if (ppar) {
- if (v)
- memset(v, 0, sizeof(*v));
- else
- v = (Value) hcalloc(sizeof *v);
- v->pm = argvparam;
- v->flags = 0;
- v->start = ppar - 1;
- v->end = ppar;
- if (sav)
- *s = sav;
- } else {
- Param pm;
- int isvarat;
-
- isvarat = (t[0] == '@' && !t[1]);
- pm = (Param) paramtab->getnode(paramtab, *t == '0' ? "0" : t);
- if (sav)
- *s = sav;
- *pptr = s;
- if (!pm || (pm->node.flags & PM_UNSET))
- return NULL;
- if (v)
- memset(v, 0, sizeof(*v));
- else
- v = (Value) hcalloc(sizeof *v);
- if (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) {
- /* Overload v->isarr as the flag bits for hashed arrays. */
- v->isarr = flags | (isvarat ? SCANPM_ISVAR_AT : 0);
- /* If no flags were passed, we need something to represent *
- * `true' yet differ from an explicit WANTVALS. Use a *
- * special flag for this case. */
- if (!v->isarr)
- v->isarr = SCANPM_ARRONLY;
- }
- v->pm = pm;
- v->flags = 0;
- v->start = 0;
- v->end = -1;
- if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
- if (getindex(&s, v, flags)) {
- *pptr = s;
- return v;
- }
- } else if (!(flags & SCANPM_ASSIGNING) && v->isarr &&
- itype_end(t, IIDENT, 1) != t && isset(KSHARRAYS))
- v->end = 1, v->isarr = 0;
- }
- if (!bracks && *s)
- return NULL;
- *pptr = s;
-#if 0
- /*
- * Check for large subscripts that might be erroneous.
- * This code is too gross in several ways:
- * - the limit is completely arbitrary
- * - the test vetoes operations on existing arrays
- * - it's not at all clear a general test on large arrays of
- * this kind is any use.
- *
- * Until someone comes up with workable replacement code it's
- * therefore commented out.
- */
- if (v->start > MAX_ARRLEN) {
- zerr("subscript too %s: %d", "big", v->start + !isset(KSHARRAYS));
- return NULL;
- }
- if (v->start < -MAX_ARRLEN) {
- zerr("subscript too %s: %d", "small", v->start);
- return NULL;
- }
- if (v->end > MAX_ARRLEN+1) {
- zerr("subscript too %s: %d", "big", v->end - !!isset(KSHARRAYS));
- return NULL;
- }
- if (v->end < -MAX_ARRLEN) {
- zerr("subscript too %s: %d", "small", v->end);
- return NULL;
- }
-#endif
- return v;
-}
-
-/**/
-mod_export char *
-getstrvalue(Value v)
-{
- char *s, **ss;
- char buf[BDIGBUFSIZE];
- int len;
-
- if (!v)
- return hcalloc(1);
-
- if ((v->flags & VALFLAG_INV) && !(v->pm->node.flags & PM_HASHED)) {
- sprintf(buf, "%d", v->start);
- s = dupstring(buf);
- return s;
- }
-
- switch(PM_TYPE(v->pm->node.flags)) {
- case PM_HASHED:
- /* (!v->isarr) should be impossible unless emulating ksh */
- if (!v->isarr && EMULATION(EMULATE_KSH)) {
- s = dupstring("[0]");
- if (getindex(&s, v, 0) == 0)
- s = getstrvalue(v);
- return s;
- } /* else fall through */
- case PM_ARRAY:
- ss = getvaluearr(v);
- if (v->isarr)
- s = sepjoin(ss, NULL, 1);
- else {
- if (v->start < 0)
- v->start += arrlen(ss);
- s = (arrlen_le(ss, v->start) || v->start < 0) ?
- (char *) hcalloc(1) : ss[v->start];
- }
- return s;
- case PM_INTEGER:
- convbase(buf, v->pm->gsu.i->getfn(v->pm), v->pm->base);
- s = dupstring(buf);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- s = convfloat(v->pm->gsu.f->getfn(v->pm),
- v->pm->base, v->pm->node.flags, NULL);
- break;
- case PM_SCALAR:
- s = v->pm->gsu.s->getfn(v->pm);
- break;
- default:
- s = "";
- DPUTS(1, "BUG: param node without valid type");
- break;
- }
-
- if (v->flags & VALFLAG_SUBST) {
- if (v->pm->node.flags & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) {
- unsigned int fwidth = v->pm->width ? v->pm->width : MB_METASTRLEN(s);
- switch (v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
- char *t, *tend;
- unsigned int t0;
-
- case PM_LEFT:
- case PM_LEFT | PM_RIGHT_Z:
- t = s;
- if (v->pm->node.flags & PM_RIGHT_Z)
- while (*t == '0')
- t++;
- else
- while (iblank(*t))
- t++;
- MB_METACHARINIT();
- for (tend = t, t0 = 0; t0 < fwidth && *tend; t0++)
- tend += MB_METACHARLEN(tend);
- /*
- * t0 is the number of characters from t used,
- * hence (fwidth - t0) is the number of padding
- * characters. fwidth is a misnomer: we use
- * character counts, not character widths.
- *
- * (tend - t) is the number of bytes we need
- * to get fwidth characters or the entire string;
- * the characters may be multiple bytes.
- */
- fwidth -= t0; /* padding chars remaining */
- t0 = tend - t; /* bytes to copy from string */
- s = (char *) hcalloc(t0 + fwidth + 1);
- memcpy(s, t, t0);
- if (fwidth)
- memset(s + t0, ' ', fwidth);
- s[t0 + fwidth] = '\0';
- break;
- case PM_RIGHT_B:
- case PM_RIGHT_Z:
- case PM_RIGHT_Z | PM_RIGHT_B:
- {
- int zero = 1;
- /* Calculate length in possibly multibyte chars */
- unsigned int charlen = MB_METASTRLEN(s);
-
- if (charlen < fwidth) {
- char *valprefend = s;
- int preflen;
- if (v->pm->node.flags & PM_RIGHT_Z) {
- /*
- * This is a documented feature: when deciding
- * whether to pad with zeroes, ignore
- * leading blanks already in the value;
- * only look for numbers after that.
- * Not sure how useful this really is.
- * It's certainly confusing to code around.
- */
- for (t = s; iblank(*t); t++)
- ;
- /*
- * Allow padding after initial minus
- * for numeric variables.
- */
- if ((v->pm->node.flags &
- (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) &&
- *t == '-')
- t++;
- /*
- * Allow padding after initial 0x or
- * base# for integer variables.
- */
- if (v->pm->node.flags & PM_INTEGER) {
- if (isset(CBASES) &&
- t[0] == '0' && t[1] == 'x')
- t += 2;
- else if ((valprefend = strchr(t, '#')))
- t = valprefend + 1;
- }
- valprefend = t;
- if (!*t)
- zero = 0;
- else if (v->pm->node.flags &
- (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) {
- /* zero always OK */
- } else if (!idigit(*t))
- zero = 0;
- }
- /* number of characters needed for padding */
- fwidth -= charlen;
- /* bytes from original string */
- t0 = strlen(s);
- t = (char *) hcalloc(fwidth + t0 + 1);
- /* prefix guaranteed to be single byte chars */
- preflen = valprefend - s;
- memset(t + preflen,
- (((v->pm->node.flags & PM_RIGHT_B)
- || !zero) ? ' ' : '0'), fwidth);
- /*
- * Copy - or 0x or base# before any padding
- * zeroes.
- */
- if (preflen)
- memcpy(t, s, preflen);
- memcpy(t + preflen + fwidth,
- valprefend, t0 - preflen);
- t[fwidth + t0] = '\0';
- s = t;
- } else {
- /* Need to skip (charlen - fwidth) chars */
- for (t0 = charlen - fwidth; t0; t0--)
- s += MB_METACHARLEN(s);
- }
- }
- break;
- }
- }
- switch (v->pm->node.flags & (PM_LOWER | PM_UPPER)) {
- case PM_LOWER:
- s = casemodify(s, CASMOD_LOWER);
- break;
- case PM_UPPER:
- s = casemodify(s, CASMOD_UPPER);
- break;
- }
- }
- if (v->start == 0 && v->end == -1)
- return s;
-
- len = strlen(s);
- if (v->start < 0) {
- v->start += len;
- if (v->start < 0)
- v->start = 0;
- }
- if (v->end < 0) {
- v->end += len;
- if (v->end >= 0) {
- char *eptr = s + v->end;
- if (*eptr)
- v->end += MB_METACHARLEN(eptr);
- }
- }
-
- s = (v->start > len) ? dupstring("") :
- dupstring_wlen(s + v->start, len - v->start);
-
- if (v->end <= v->start)
- s[0] = '\0';
- else if (v->end - v->start <= len - v->start)
- s[v->end - v->start] = '\0';
-
- return s;
-}
-
-static char *nular[] = {"", NULL};
-
-/**/
-mod_export char **
-getarrvalue(Value v)
-{
- char **s;
-
- if (!v)
- return arrdup(nular);
- else if (IS_UNSET_VALUE(v))
- return arrdup(&nular[1]);
- if (v->flags & VALFLAG_INV) {
- char buf[DIGBUFSIZE];
-
- s = arrdup(nular);
- sprintf(buf, "%d", v->start);
- s[0] = dupstring(buf);
- return s;
- }
- s = getvaluearr(v);
- if (v->start == 0 && v->end == -1)
- return s;
- if (v->start < 0)
- v->start += arrlen(s);
- if (v->end < 0)
- v->end += arrlen(s) + 1;
-
- /* Null if 1) array too short, 2) index still negative */
- if (v->end <= v->start) {
- s = arrdup_max(nular, 0);
- }
- else if (v->start < 0) {
- s = arrdup_max(nular, 1);
- }
- else if (arrlen_le(s, v->start)) {
- /* Handle $ary[i,i] consistently for any $i > $#ary
- * and $ary[i,j] consistently for any $j > $i > $#ary
- */
- s = arrdup_max(nular, v->end - (v->start + 1));
- }
- else {
- /* Copy to a point before the end of the source array:
- * arrdup_max will copy at most v->end - v->start elements,
- * starting from v->start element. Original code said:
- * s[v->end - v->start] = NULL
- * which means that there are exactly the same number of
- * elements as the value of the above *0-based* index.
- */
- s = arrdup_max(s + v->start, v->end - v->start);
- }
-
- return s;
-}
-
-/**/
-mod_export zlong
-getintvalue(Value v)
-{
- if (!v)
- return 0;
- if (v->flags & VALFLAG_INV)
- return v->start;
- if (v->isarr) {
- char **arr = getarrvalue(v);
- if (arr) {
- char *scal = sepjoin(arr, NULL, 1);
- return mathevali(scal);
- } else
- return 0;
- }
- if (PM_TYPE(v->pm->node.flags) == PM_INTEGER)
- return v->pm->gsu.i->getfn(v->pm);
- if (v->pm->node.flags & (PM_EFLOAT|PM_FFLOAT))
- return (zlong)v->pm->gsu.f->getfn(v->pm);
- return mathevali(getstrvalue(v));
-}
-
-/**/
-mnumber
-getnumvalue(Value v)
-{
- mnumber mn;
- mn.type = MN_INTEGER;
-
-
- if (!v) {
- mn.u.l = 0;
- } else if (v->flags & VALFLAG_INV) {
- mn.u.l = v->start;
- } else if (v->isarr) {
- char **arr = getarrvalue(v);
- if (arr) {
- char *scal = sepjoin(arr, NULL, 1);
- return matheval(scal);
- } else
- mn.u.l = 0;
- } else if (PM_TYPE(v->pm->node.flags) == PM_INTEGER) {
- mn.u.l = v->pm->gsu.i->getfn(v->pm);
- } else if (v->pm->node.flags & (PM_EFLOAT|PM_FFLOAT)) {
- mn.type = MN_FLOAT;
- mn.u.d = v->pm->gsu.f->getfn(v->pm);
- } else
- return matheval(getstrvalue(v));
- return mn;
-}
-
-/**/
-void
-export_param(Param pm)
-{
- char buf[BDIGBUFSIZE], *val;
-
- if (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) {
-#if 0 /* Requires changes elsewhere in params.c and builtin.c */
- if (EMULATION(EMULATE_KSH) /* isset(KSHARRAYS) */) {
- struct value v;
- v.isarr = 1;
- v.flags = 0;
- v.start = 0;
- v.end = -1;
- val = getstrvalue(&v);
- } else
-#endif
- return;
- } else if (PM_TYPE(pm->node.flags) == PM_INTEGER)
- convbase(val = buf, pm->gsu.i->getfn(pm), pm->base);
- else if (pm->node.flags & (PM_EFLOAT|PM_FFLOAT))
- val = convfloat(pm->gsu.f->getfn(pm), pm->base,
- pm->node.flags, NULL);
- else
- val = pm->gsu.s->getfn(pm);
-
- addenv(pm, val);
-}
-
-/**/
-mod_export void
-setstrvalue(Value v, char *val)
-{
- assignstrvalue(v, val, 0);
-}
-
-/**/
-mod_export void
-assignstrvalue(Value v, char *val, int flags)
-{
- if (unset(EXECOPT))
- return;
- if (v->pm->node.flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->node.nam);
- zsfree(val);
- return;
- }
- if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerr("%s: restricted", v->pm->node.nam);
- zsfree(val);
- return;
- }
- if ((v->pm->node.flags & PM_HASHED) &&
- (v->isarr & (SCANPM_MATCHMANY|SCANPM_ARRONLY))) {
- zerr("%s: attempt to set slice of associative array", v->pm->node.nam);
- zsfree(val);
- return;
- }
- if (v->flags & VALFLAG_EMPTY) {
- zerr("%s: assignment to invalid subscript range", v->pm->node.nam);
- zsfree(val);
- return;
- }
- v->pm->node.flags &= ~PM_UNSET;
- switch (PM_TYPE(v->pm->node.flags)) {
- case PM_SCALAR:
- if (v->start == 0 && v->end == -1) {
- v->pm->gsu.s->setfn(v->pm, val);
- if ((v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) &&
- !v->pm->width)
- v->pm->width = strlen(val);
- } else {
- char *z, *x;
- int zlen, vlen, newsize;
-
- z = v->pm->gsu.s->getfn(v->pm);
- zlen = strlen(z);
-
- if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS))
- v->start--, v->end--;
- if (v->start < 0) {
- v->start += zlen;
- if (v->start < 0)
- v->start = 0;
- }
- if (v->start > zlen)
- v->start = zlen;
- if (v->end < 0) {
- v->end += zlen;
- if (v->end < 0) {
- v->end = 0;
- } else if (v->end >= zlen) {
- v->end = zlen;
- } else {
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- v->end += MB_METACHARLEN(z + v->end);
- } else {
- v->end++;
- }
-#else
- v->end++;
-#endif
- }
- }
- else if (v->end > zlen)
- v->end = zlen;
-
- vlen = strlen(val);
- /* Characters preceding start index +
- characters of what is assigned +
- characters following end index */
- newsize = v->start + vlen + (zlen - v->end);
-
- /* Does new size differ? */
- if (newsize != zlen || v->pm->gsu.s->setfn != strsetfn) {
- x = (char *) zalloc(newsize + 1);
- strncpy(x, z, v->start);
- strcpy(x + v->start, val);
- strcat(x + v->start, z + v->end);
- v->pm->gsu.s->setfn(v->pm, x);
- } else {
- Param pm = v->pm;
- /* Size doesn't change, can limit actions to only
- * overwriting bytes in already allocated string */
- strncpy(z + v->start, val, vlen);
- /* Implement remainder of strsetfn */
- if (!(pm->node.flags & PM_HASHELEM) &&
- ((pm->node.flags & PM_NAMEDDIR) ||
- isset(AUTONAMEDIRS))) {
- pm->node.flags |= PM_NAMEDDIR;
- adduserdir(pm->node.nam, z, 0, 0);
- }
- }
- zsfree(val);
- }
- break;
- case PM_INTEGER:
- if (val) {
- zlong ival;
- if (flags & ASSPM_ENV_IMPORT) {
- char *ptr;
- ival = zstrtol_underscore(val, &ptr, 0, 1);
- } else
- ival = mathevali(val);
- v->pm->gsu.i->setfn(v->pm, ival);
- if ((v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) &&
- !v->pm->width)
- v->pm->width = strlen(val);
- zsfree(val);
- }
- if (!v->pm->base && lastbase != -1)
- v->pm->base = lastbase;
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- if (val) {
- mnumber mn;
- if (flags & ASSPM_ENV_IMPORT) {
- char *ptr;
- mn.type = MN_FLOAT;
- mn.u.d = strtod(val, &ptr);
- } else
- mn = matheval(val);
- v->pm->gsu.f->setfn(v->pm, (mn.type & MN_FLOAT) ? mn.u.d :
- (double)mn.u.l);
- if ((v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) &&
- !v->pm->width)
- v->pm->width = strlen(val);
- zsfree(val);
- }
- break;
- case PM_ARRAY:
- {
- char **ss = (char **) zalloc(2 * sizeof(char *));
-
- ss[0] = val;
- ss[1] = NULL;
- setarrvalue(v, ss);
- }
- break;
- case PM_HASHED:
- {
- if (foundparam == NULL)
- {
- zerr("%s: attempt to set associative array to scalar",
- v->pm->node.nam);
- zsfree(val);
- return;
- }
- else
- foundparam->gsu.s->setfn(foundparam, val);
- }
- break;
- }
- if ((!v->pm->env && !(v->pm->node.flags & PM_EXPORTED) &&
- !(isset(ALLEXPORT) && !(v->pm->node.flags & PM_HASHELEM))) ||
- (v->pm->node.flags & PM_ARRAY) || v->pm->ename)
- return;
- export_param(v->pm);
-}
-
-/**/
-void
-setnumvalue(Value v, mnumber val)
-{
- char buf[BDIGBUFSIZE], *p;
-
- if (unset(EXECOPT))
- return;
- if (v->pm->node.flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->node.nam);
- return;
- }
- if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerr("%s: restricted", v->pm->node.nam);
- return;
- }
- switch (PM_TYPE(v->pm->node.flags)) {
- case PM_SCALAR:
- case PM_ARRAY:
- if ((val.type & MN_INTEGER) || outputradix) {
- if (!(val.type & MN_INTEGER))
- val.u.l = (zlong) val.u.d;
- p = convbase_underscore(buf, val.u.l, outputradix,
- outputunderscore);
- } else
- p = convfloat_underscore(val.u.d, outputunderscore);
- setstrvalue(v, ztrdup(p));
- break;
- case PM_INTEGER:
- v->pm->gsu.i->setfn(v->pm, (val.type & MN_INTEGER) ? val.u.l :
- (zlong) val.u.d);
- setstrvalue(v, NULL);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- v->pm->gsu.f->setfn(v->pm, (val.type & MN_INTEGER) ?
- (double)val.u.l : val.u.d);
- setstrvalue(v, NULL);
- break;
- }
-}
-
-/**/
-mod_export void
-setarrvalue(Value v, char **val)
-{
- if (unset(EXECOPT))
- return;
- if (v->pm->node.flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->node.nam);
- freearray(val);
- return;
- }
- if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerr("%s: restricted", v->pm->node.nam);
- freearray(val);
- return;
- }
- if (!(PM_TYPE(v->pm->node.flags) & (PM_ARRAY|PM_HASHED))) {
- freearray(val);
- zerr("%s: attempt to assign array value to non-array",
- v->pm->node.nam);
- return;
- }
- if (v->flags & VALFLAG_EMPTY) {
- zerr("%s: assignment to invalid subscript range", v->pm->node.nam);
- freearray(val);
- return;
- }
-
- if (v->start == 0 && v->end == -1) {
- if (PM_TYPE(v->pm->node.flags) == PM_HASHED)
- arrhashsetfn(v->pm, val, 0);
- else
- v->pm->gsu.a->setfn(v->pm, val);
- } else if (v->start == -1 && v->end == 0 &&
- PM_TYPE(v->pm->node.flags) == PM_HASHED) {
- arrhashsetfn(v->pm, val, ASSPM_AUGMENT);
- } else if ((PM_TYPE(v->pm->node.flags) == PM_HASHED)) {
- freearray(val);
- zerr("%s: attempt to set slice of associative array",
- v->pm->node.nam);
- return;
- } else {
- char **const old = v->pm->gsu.a->getfn(v->pm);
- char **new;
- char **p, **q, **r; /* index variables */
- const int pre_assignment_length = arrlen(old);
- int post_assignment_length;
- int i;
-
- q = old;
-
- if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) {
- if (v->start > 0)
- v->start--;
- v->end--;
- }
- if (v->start < 0) {
- v->start += pre_assignment_length;
- if (v->start < 0)
- v->start = 0;
- }
- if (v->end < 0) {
- v->end += pre_assignment_length + 1;
- if (v->end < 0)
- v->end = 0;
- }
- if (v->end < v->start)
- v->end = v->start;
-
- post_assignment_length = v->start + arrlen(val);
- if (v->end < pre_assignment_length) {
- /*
- * Allocate room for array elements between the end of the slice `v'
- * and the original array's end.
- */
- post_assignment_length += pre_assignment_length - v->end;
- }
-
- if (pre_assignment_length == post_assignment_length
- && v->pm->gsu.a->setfn == arrsetfn
- /* ... and isn't something that arrsetfn() treats specially */
- && 0 == (v->pm->node.flags & (PM_SPECIAL|PM_UNIQUE))
- && NULL == v->pm->ename)
- {
- /* v->start is 0-based */
- p = old + v->start;
- for (r = val; *r;) {
- /* Free previous string */
- zsfree(*p);
- /* Give away ownership of the string */
- *p++ = *r++;
- }
- } else {
- /* arr+=( ... )
- * arr[${#arr}+x,...]=( ... ) */
- if (post_assignment_length > pre_assignment_length &&
- pre_assignment_length <= v->start &&
- pre_assignment_length > 0 &&
- v->pm->gsu.a->setfn == arrsetfn)
- {
- p = new = (char **) zrealloc(old, sizeof(char *)
- * (post_assignment_length + 1));
-
- p += pre_assignment_length; /* after old elements */
-
- /* Consider 1 < 0, case for a=( 1 ); a[1,..] =
- * 1 < 1, case for a=( 1 ); a[2,..] = */
- if (pre_assignment_length < v->start) {
- for (i = pre_assignment_length; i < v->start; i++) {
- *p++ = ztrdup("");
- }
- }
-
- for (r = val; *r;) {
- /* Give away ownership of the string */
- *p++ = *r++;
- }
-
- /* v->end doesn't matter:
- * a=( 1 2 ); a[4,100]=( a b ); echo "${(q@)a}"
- * 1 2 '' a b */
- *p = NULL;
-
- v->pm->u.arr = NULL;
- v->pm->gsu.a->setfn(v->pm, new);
- } else {
- p = new = (char **) zalloc(sizeof(char *)
- * (post_assignment_length + 1));
- for (i = 0; i < v->start; i++)
- *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup("");
- for (r = val; *r;) {
- /* Give away ownership of the string */
- *p++ = *r++;
- }
- if (v->end < pre_assignment_length)
- for (q = old + v->end; *q;)
- *p++ = ztrdup(*q++);
- *p = NULL;
-
- v->pm->gsu.a->setfn(v->pm, new);
- }
-
- DPUTS2(p - new != post_assignment_length, "setarrvalue: wrong allocation: %d 1= %lu",
- post_assignment_length, (unsigned long)(p - new));
- }
-
- /* Ownership of all strings has been
- * given away, can plainly free */
- free(val);
- }
-}
-
-/* Retrieve an integer parameter */
-
-/**/
-mod_export zlong
-getiparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!(v = getvalue(&vbuf, &s, 1)))
- return 0;
- return getintvalue(v);
-}
-
-/* Retrieve a numerical parameter, either integer or floating */
-
-/**/
-mnumber
-getnparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!(v = getvalue(&vbuf, &s, 1))) {
- mnumber mn;
- mn.type = MN_INTEGER;
- mn.u.l = 0;
- return mn;
- }
- return getnumvalue(v);
-}
-
-/* Retrieve a scalar (string) parameter */
-
-/**/
-mod_export char *
-getsparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!(v = getvalue(&vbuf, &s, 0)))
- return NULL;
- return getstrvalue(v);
-}
-
-/**/
-mod_export char *
-getsparam_u(char *s)
-{
- if ((s = getsparam(s)))
- return unmetafy(s, NULL);
- return s;
-}
-
-/* Retrieve an array parameter */
-
-/**/
-mod_export char **
-getaparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) &&
- PM_TYPE(v->pm->node.flags) == PM_ARRAY)
- return v->pm->gsu.a->getfn(v->pm);
- return NULL;
-}
-
-/* Retrieve an assoc array parameter as an array */
-
-/**/
-mod_export char **
-gethparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) &&
- PM_TYPE(v->pm->node.flags) == PM_HASHED)
- return paramvalarr(v->pm->gsu.h->getfn(v->pm), SCANPM_WANTVALS);
- return NULL;
-}
-
-/* Retrieve the keys of an assoc array parameter as an array */
-
-/**/
-mod_export char **
-gethkparam(char *s)
-{
- struct value vbuf;
- Value v;
-
- if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) &&
- PM_TYPE(v->pm->node.flags) == PM_HASHED)
- return paramvalarr(v->pm->gsu.h->getfn(v->pm), SCANPM_WANTKEYS);
- return NULL;
-}
-
-/*
- * Function behind WARNCREATEGLOBAL and WARNNESTEDVAR option.
- *
- * For WARNNESTEDVAR:
- * Called when the variable is created.
- * Apply heuristics to see if this variable was just created
- * globally but in a local context.
- *
- * For WARNNESTEDVAR:
- * Called when the variable already exists and is set.
- * Apply heuristics to see if this variable is setting
- * a variable that was created in a less nested function
- * or globally.
- */
-
-/**/
-static void
-check_warn_pm(Param pm, const char *pmtype, int created,
- int may_warn_about_nested_vars)
-{
- Funcstack i;
-
- if (!may_warn_about_nested_vars && !created)
- return;
-
- if (created && isset(WARNCREATEGLOBAL)) {
- if (locallevel <= forklevel || pm->level != 0)
- return;
- } else if (!created && isset(WARNNESTEDVAR)) {
- if (pm->level >= locallevel)
- return;
- } else
- return;
-
- if (pm->node.flags & PM_SPECIAL)
- return;
-
- for (i = funcstack; i; i = i->prev) {
- if (i->tp == FS_FUNC) {
- char *msg;
- DPUTS(!i->name, "funcstack entry with no name");
- msg = created ?
- "%s parameter %s created globally in function %s" :
- "%s parameter %s set in enclosing scope in function %s";
- zwarn(msg, pmtype, pm->node.nam, i->name);
- break;
- }
- }
-}
-
-/**/
-mod_export Param
-assignsparam(char *s, char *val, int flags)
-{
- struct value vbuf;
- Value v;
- char *t = s;
- char *ss, *copy, *var;
- size_t lvar;
- mnumber lhs, rhs;
- int sstart, created = 0;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s);
- zsfree(val);
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- queue_signals();
- if ((ss = strchr(s, '['))) {
- *ss = '\0';
- if (!(v = getvalue(&vbuf, &s, 1))) {
- createparam(t, PM_ARRAY);
- created = 1;
- } else {
- if (v->pm->node.flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->node.nam);
- *ss = '[';
- zsfree(val);
- unqueue_signals();
- return NULL;
- }
- /*
- * Parameter defined here is a temporary bogus one.
- * Don't warn about anything.
- */
- flags &= ~ASSPM_WARN;
- }
- *ss = '[';
- v = NULL;
- } else {
- if (!(v = getvalue(&vbuf, &s, 1))) {
- createparam(t, PM_SCALAR);
- created = 1;
- } else if ((((v->pm->node.flags & PM_ARRAY) && !(flags & ASSPM_AUGMENT)) ||
- (v->pm->node.flags & PM_HASHED)) &&
- !(v->pm->node.flags & (PM_SPECIAL|PM_TIED)) &&
- unset(KSHARRAYS)) {
- unsetparam(t);
- createparam(t, PM_SCALAR);
- /* not regarded as a new creation */
- v = NULL;
- }
- }
- if (!v && !(v = getvalue(&vbuf, &t, 1))) {
- unqueue_signals();
- zsfree(val);
- /* errflag |= ERRFLAG_ERROR; */
- return NULL;
- }
- if (flags & ASSPM_WARN)
- check_warn_pm(v->pm, "scalar", created, 1);
- if (flags & ASSPM_AUGMENT) {
- if (v->start == 0 && v->end == -1) {
- switch (PM_TYPE(v->pm->node.flags)) {
- case PM_SCALAR:
- v->start = INT_MAX; /* just append to scalar value */
- break;
- case PM_INTEGER:
- case PM_EFLOAT:
- case PM_FFLOAT:
- rhs = matheval(val);
- lhs = getnumvalue(v);
- if (lhs.type == MN_FLOAT) {
- if ((rhs.type) == MN_FLOAT)
- lhs.u.d = lhs.u.d + rhs.u.d;
- else
- lhs.u.d = lhs.u.d + (double)rhs.u.l;
- } else {
- if ((rhs.type) == MN_INTEGER)
- lhs.u.l = lhs.u.l + rhs.u.l;
- else
- lhs.u.l = lhs.u.l + (zlong)rhs.u.d;
- }
- setnumvalue(v, lhs);
- unqueue_signals();
- zsfree(val);
- return v->pm; /* avoid later setstrvalue() call */
- case PM_ARRAY:
- if (unset(KSHARRAYS)) {
- v->start = arrlen(v->pm->gsu.a->getfn(v->pm));
- v->end = v->start + 1;
- } else {
- /* ksh appends scalar to first element */
- v->end = 1;
- goto kshappend;
- }
- break;
- }
- } else {
- switch (PM_TYPE(v->pm->node.flags)) {
- case PM_SCALAR:
- if (v->end > 0)
- v->start = v->end;
- else
- v->start = v->end = strlen(v->pm->gsu.s->getfn(v->pm)) +
- v->end + 1;
- break;
- case PM_INTEGER:
- case PM_EFLOAT:
- case PM_FFLOAT:
- unqueue_signals();
- zerr("attempt to add to slice of a numeric variable");
- zsfree(val);
- return NULL;
- case PM_ARRAY:
- kshappend:
- /* treat slice as the end element */
- v->start = sstart = v->end > 0 ? v->end - 1 : v->end;
- v->isarr = 0;
- var = getstrvalue(v);
- v->start = sstart;
- copy = val;
- lvar = strlen(var);
- val = (char *)zalloc(lvar + strlen(val) + 1);
- strcpy(val, var);
- strcpy(val + lvar, copy);
- zsfree(copy);
- break;
- }
- }
- }
-
- assignstrvalue(v, val, flags);
- unqueue_signals();
- return v->pm;
-}
-
-/**/
-mod_export Param
-setsparam(char *s, char *val)
-{
- return assignsparam(s, val, ASSPM_WARN);
-}
-
-/**/
-mod_export Param
-assignaparam(char *s, char **val, int flags)
-{
- struct value vbuf;
- Value v;
- char *t = s;
- char *ss;
- int created = 0;
- int may_warn_about_nested_vars = 1;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s);
- freearray(val);
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- queue_signals();
- if ((ss = strchr(s, '['))) {
- *ss = '\0';
- if (!(v = getvalue(&vbuf, &s, 1))) {
- createparam(t, PM_ARRAY);
- created = 1;
- } else {
- may_warn_about_nested_vars = 0;
- }
- *ss = '[';
- if (v && PM_TYPE(v->pm->node.flags) == PM_HASHED) {
- unqueue_signals();
- zerr("%s: attempt to set slice of associative array",
- v->pm->node.nam);
- freearray(val);
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- v = NULL;
- } else {
- if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) {
- createparam(t, PM_ARRAY);
- created = 1;
- } else if (!(PM_TYPE(v->pm->node.flags) & (PM_ARRAY|PM_HASHED)) &&
- !(v->pm->node.flags & (PM_SPECIAL|PM_TIED))) {
- int uniq = v->pm->node.flags & PM_UNIQUE;
- if (flags & ASSPM_AUGMENT) {
- /* insert old value at the beginning of the val array */
- char **new;
- int lv = arrlen(val);
-
- new = (char **) zalloc(sizeof(char *) * (lv + 2));
- *new = ztrdup(getstrvalue(v));
- memcpy(new+1, val, sizeof(char *) * (lv + 1));
- free(val);
- val = new;
- }
- unsetparam(t);
- createparam(t, PM_ARRAY | uniq);
- v = NULL;
- }
- }
- if (!v)
- if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
- unqueue_signals();
- freearray(val);
- /* errflag |= ERRFLAG_ERROR; */
- return NULL;
- }
-
- if (flags & ASSPM_WARN)
- check_warn_pm(v->pm, "array", created, may_warn_about_nested_vars);
-
- /*
- * At this point, we may have array entries consisting of
- * - a Marker element --- normally allocated array entry but
- * with just Marker char and null
- * - an array index element --- as normal for associative array,
- * but non-standard for normal array which we handle now.
- * - a value for the indexed element.
- * This only applies if the flag ASSPM_KEY_VALUE is passed in,
- * indicating prefork() detected this syntax.
- *
- * For associative arrays we just junk the Marker elements.
- */
- if (flags & ASSPM_KEY_VALUE) {
- char **aptr;
- if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) {
- /*
- * This is an ordinary array with key / value pairs.
- */
- int maxlen, origlen, nextind;
- char **fullval, **origptr;
- zlong *subscripts = (zlong *)zhalloc(arrlen(val) * sizeof(zlong));
- zlong *iptr = subscripts;
- if (flags & ASSPM_AUGMENT) {
- origptr = v->pm->gsu.a->getfn(v->pm);
- maxlen = origlen = arrlen(origptr);
- } else {
- maxlen = origlen = 0;
- origptr = NULL;
- }
- nextind = 0;
- for (aptr = val; *aptr; ) {
- if (**aptr == Marker) {
- *iptr = mathevali(*++aptr);
- if (*iptr < 0 ||
- (!isset(KSHARRAYS) && *iptr == 0)) {
- unqueue_signals();
- zerr("bad subscript for direct array assignment: %s", *aptr);
- freearray(val);
- return NULL;
- }
- if (!isset(KSHARRAYS))
- --*iptr;
- nextind = *iptr + 1;
- ++iptr;
- aptr += 2;
- } else {
- ++nextind;
- ++aptr;
- }
- if (nextind > maxlen)
- maxlen = nextind;
- }
- fullval = zshcalloc((maxlen+1) * sizeof(char *));
- if (!fullval) {
- zerr("array too large");
- freearray(val);
- return NULL;
- }
- fullval[maxlen] = NULL;
- if (flags & ASSPM_AUGMENT) {
- char **srcptr = origptr;
- for (aptr = fullval; aptr <= fullval + origlen; aptr++) {
- *aptr = ztrdup(*srcptr);
- srcptr++;
- }
- }
- iptr = subscripts;
- nextind = 0;
- for (aptr = val; *aptr; ++aptr) {
- char *old;
- if (**aptr == Marker) {
- int augment = ((*aptr)[1] == '+');
- zsfree(*aptr);
- zsfree(*++aptr); /* Index, no longer needed */
- old = fullval[*iptr];
- if (augment && old) {
- fullval[*iptr] = bicat(old, *++aptr);
- zsfree(*aptr);
- } else {
- fullval[*iptr] = *++aptr;
- }
- nextind = *iptr + 1;
- ++iptr;
- } else {
- old = fullval[nextind];
- fullval[nextind] = *aptr;
- ++nextind;
- }
- if (old)
- zsfree(old);
- /* aptr now on value in both cases */
- }
- if (*aptr) { /* Shouldn't be possible */
- DPUTS(1, "Extra element in key / value array");
- zsfree(*aptr);
- }
- free(val);
- for (aptr = fullval; aptr < fullval + maxlen; aptr++) {
- /*
- * Remember we don't have sparse arrays but and they're null
- * terminated --- so any value we don't set has to be an
- * empty string.
- */
- if (!*aptr)
- *aptr = ztrdup("");
- }
- setarrvalue(v, fullval);
- unqueue_signals();
- return v->pm;
- } else if (PM_TYPE(v->pm->node.flags & PM_HASHED)) {
- /*
- * We strictly enforce [key]=value syntax for associative
- * arrays. Marker can only indicate a Marker / key / value
- * triad; it cannot be there by accident.
- *
- * It's too inefficient to strip Markers here, and they
- * can't be there in the other form --- so just ignore
- * them willy nilly lower down.
- */
- for (aptr = val; *aptr; aptr += 3) {
- if (**aptr != Marker) {
- unqueue_signals();
- freearray(val);
- zerr("bad [key]=value syntax for associative array");
- return NULL;
- }
- }
- } else {
- unqueue_signals();
- freearray(val);
- zerr("invalid use of [key]=value assignment syntax");
- return NULL;
- }
- }
-
- if (flags & ASSPM_AUGMENT) {
- if (v->start == 0 && v->end == -1) {
- if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) {
- v->start = arrlen(v->pm->gsu.a->getfn(v->pm));
- v->end = v->start + 1;
- } else if (PM_TYPE(v->pm->node.flags) & PM_HASHED)
- v->start = -1, v->end = 0;
- } else {
- if (v->end > 0)
- v->start = v->end--;
- else if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) {
- v->end = arrlen(v->pm->gsu.a->getfn(v->pm)) + v->end;
- v->start = v->end + 1;
- }
- }
- }
-
- setarrvalue(v, val);
- unqueue_signals();
- return v->pm;
-}
-
-
-/**/
-mod_export Param
-setaparam(char *s, char **aval)
-{
- return assignaparam(s, aval, ASSPM_WARN);
-}
-
-/**/
-mod_export Param
-sethparam(char *s, char **val)
-{
- struct value vbuf;
- Value v;
- char *t = s;
- int checkcreate = 0;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s);
- freearray(val);
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- if (strchr(s, '[')) {
- freearray(val);
- zerr("nested associative arrays not yet supported");
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- if (unset(EXECOPT))
- return NULL;
- queue_signals();
- if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) {
- createparam(t, PM_HASHED);
- checkcreate = 1;
- } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED)) {
- if (!(v->pm->node.flags & PM_SPECIAL)) {
- unsetparam(t);
- /* no WARNCREATEGLOBAL check here as parameter already existed */
- createparam(t, PM_HASHED);
- v = NULL;
- } else {
- zerr("%s: can't change type of a special parameter", t);
- unqueue_signals();
- return NULL;
- }
- }
- if (!v)
- if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
- unqueue_signals();
- /* errflag |= ERRFLAG_ERROR; */
- return NULL;
- }
- check_warn_pm(v->pm, "associative array", checkcreate, 1);
- setarrvalue(v, val);
- unqueue_signals();
- return v->pm;
-}
-
-
-/*
- * Set a generic shell number, floating point or integer.
- * Option to warn on setting.
- */
-
-/**/
-mod_export Param
-assignnparam(char *s, mnumber val, int flags)
-{
- struct value vbuf;
- Value v;
- char *t = s, *ss;
- Param pm;
- int was_unset = 0;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s);
- errflag |= ERRFLAG_ERROR;
- return NULL;
- }
- if (unset(EXECOPT))
- return NULL;
- queue_signals();
- ss = strchr(s, '[');
- v = getvalue(&vbuf, &s, 1);
- if (v && (v->pm->node.flags & (PM_ARRAY|PM_HASHED)) &&
- !(v->pm->node.flags & (PM_SPECIAL|PM_TIED)) &&
- /*
- * not sure what KSHARRAYS has got to do with this...
- * copied this from assignsparam().
- */
- unset(KSHARRAYS) && !ss) {
- unsetparam_pm(v->pm, 0, 1);
- was_unset = 1;
- s = t;
- v = NULL;
- }
- if (!v) {
- /* s has been updated by getvalue, so check again */
- ss = strchr(s, '[');
- if (ss)
- *ss = '\0';
- pm = createparam(t, ss ? PM_ARRAY :
- isset(POSIXIDENTIFIERS) ? PM_SCALAR :
- (val.type & MN_INTEGER) ? PM_INTEGER : PM_FFLOAT);
- if (!pm)
- pm = (Param) paramtab->getnode(paramtab, t);
- DPUTS(!pm, "BUG: parameter not created");
- if (ss) {
- *ss = '[';
- } else if (val.type & MN_INTEGER) {
- pm->base = outputradix;
- }
- if (!(v = getvalue(&vbuf, &t, 1))) {
- DPUTS(!v, "BUG: value not found for new parameter");
- /* errflag |= ERRFLAG_ERROR; */
- unqueue_signals();
- return NULL;
- }
- if (flags & ASSPM_WARN)
- check_warn_pm(v->pm, "numeric", !was_unset, 1);
- } else {
- if (flags & ASSPM_WARN)
- check_warn_pm(v->pm, "numeric", 0, 1);
- }
- setnumvalue(v, val);
- unqueue_signals();
- return v->pm;
-}
-
-/*
- * Set a generic shell number, floating point or integer.
- * Warn on setting based on option.
- */
-
-/**/
-mod_export Param
-setnparam(char *s, mnumber val)
-{
- return assignnparam(s, val, ASSPM_WARN);
-}
-
-/* Simplified interface to assignnparam */
-
-/**/
-mod_export Param
-assigniparam(char *s, zlong val, int flags)
-{
- mnumber mnval;
- mnval.type = MN_INTEGER;
- mnval.u.l = val;
- return assignnparam(s, mnval, flags);
-}
-
-/* Simplified interface to setnparam */
-
-/**/
-mod_export Param
-setiparam(char *s, zlong val)
-{
- mnumber mnval;
- mnval.type = MN_INTEGER;
- mnval.u.l = val;
- return assignnparam(s, mnval, ASSPM_WARN);
-}
-
-/*
- * Set an integer parameter without forcing creation of an integer type.
- * This is useful if the integer is going to be set to a parmaeter which
- * would usually be scalar but may not exist.
- */
-
-/**/
-mod_export Param
-setiparam_no_convert(char *s, zlong val)
-{
- /*
- * If the target is already an integer, thisgets converted
- * back. Low technology rules.
- */
- char buf[BDIGBUFSIZE];
- convbase(buf, val, 10);
- return assignsparam(s, ztrdup(buf), ASSPM_WARN);
-}
-
-/* Unset a parameter */
-
-/**/
-mod_export void
-unsetparam(char *s)
-{
- Param pm;
-
- queue_signals();
- if ((pm = (Param) (paramtab == realparamtab ?
- /* getnode2() to avoid autoloading */
- paramtab->getnode2(paramtab, s) :
- paramtab->getnode(paramtab, s))))
- unsetparam_pm(pm, 0, 1);
- unqueue_signals();
-}
-
-/* Unset a parameter
- *
- * altflag: if true, don't remove pm->ename from the environment
- * exp: See stdunsetfn()
- */
-
-/**/
-mod_export int
-unsetparam_pm(Param pm, int altflag, int exp)
-{
- Param oldpm, altpm;
- char *altremove;
-
- if ((pm->node.flags & PM_READONLY) && pm->level <= locallevel) {
- zerr("read-only variable: %s", pm->node.nam);
- return 1;
- }
- if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
- zerr("%s: restricted", pm->node.nam);
- return 1;
- }
-
- if (pm->ename && !altflag)
- altremove = ztrdup(pm->ename);
- else
- altremove = NULL;
-
- if (!(pm->node.flags & PM_UNSET))
- pm->gsu.s->unsetfn(pm, exp);
- if (pm->env)
- delenv(pm);
-
- /* remove it under its alternate name if necessary */
- if (altremove) {
- altpm = (Param) paramtab->getnode(paramtab, altremove);
- /* tied parameters are at the same local level as each other */
- oldpm = NULL;
- while (altpm && altpm->level > pm->level) {
- /* param under alternate name hidden by a local */
- oldpm = altpm;
- altpm = altpm->old;
- }
- if (altpm) {
- if (oldpm && !altpm->level) {
- oldpm->old = NULL;
- /* fudge things so removenode isn't called */
- altpm->level = 1;
- }
- unsetparam_pm(altpm, 1, exp);
- }
-
- zsfree(altremove);
- }
-
- /*
- * If this was a local variable, we need to keep the old
- * struct so that it is resurrected at the right level.
- * This is partly because when an array/scalar value is set
- * and the parameter used to be the other sort, unsetparam()
- * is called. Beyond that, there is an ambiguity: should
- * foo() { local bar; unset bar; } make the global bar
- * available or not? The following makes the answer "no".
- *
- * Some specials, such as those used in zle, still need removing
- * from the parameter table; they have the PM_REMOVABLE flag.
- */
- if ((pm->level && locallevel >= pm->level) ||
- (pm->node.flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL)
- return 0;
-
- /* remove parameter node from table */
- paramtab->removenode(paramtab, pm->node.nam);
-
- if (pm->old) {
- oldpm = pm->old;
- paramtab->addnode(paramtab, oldpm->node.nam, oldpm);
- if ((PM_TYPE(oldpm->node.flags) == PM_SCALAR) &&
- !(pm->node.flags & PM_HASHELEM) &&
- (oldpm->node.flags & PM_NAMEDDIR) &&
- oldpm->gsu.s == &stdscalar_gsu)
- adduserdir(oldpm->node.nam, oldpm->u.str, 0, 0);
- if (oldpm->node.flags & PM_EXPORTED) {
- /*
- * Re-export the old value which we removed in typeset_single().
- * I don't think we need to test for ALL_EXPORT here, since if
- * it was used to export the parameter originally the parameter
- * should still have the PM_EXPORTED flag.
- */
- export_param(oldpm);
- }
- }
-
- paramtab->freenode(&pm->node); /* free parameter node */
-
- return 0;
-}
-
-/* Standard function to unset a parameter. This is mostly delegated to *
- * the specific set function.
- *
- * This could usefully be made type-specific, but then we need
- * to be more careful when calling the unset method directly.
- *
- * The "exp"licit parameter should be nonzero for assignments and the
- * unset command, and zero for implicit unset (e.g., end of scope).
- * Currently this is used only by some modules.
- */
-
-/**/
-mod_export void
-stdunsetfn(Param pm, UNUSED(int exp))
-{
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- if (pm->gsu.s->setfn)
- pm->gsu.s->setfn(pm, NULL);
- break;
-
- case PM_ARRAY:
- if (pm->gsu.a->setfn)
- pm->gsu.a->setfn(pm, NULL);
- break;
-
- case PM_HASHED:
- if (pm->gsu.h->setfn)
- pm->gsu.h->setfn(pm, NULL);
- break;
-
- default:
- if (!(pm->node.flags & PM_SPECIAL))
- pm->u.str = NULL;
- break;
- }
- if ((pm->node.flags & (PM_SPECIAL|PM_TIED)) == PM_TIED) {
- if (pm->ename) {
- zsfree(pm->ename);
- pm->ename = NULL;
- }
- pm->node.flags &= ~PM_TIED;
- }
- pm->node.flags |= PM_UNSET;
-}
-
-/* Function to get value of an integer parameter */
-
-/**/
-mod_export zlong
-intgetfn(Param pm)
-{
- return pm->u.val;
-}
-
-/* Function to set value of an integer parameter */
-
-/**/
-static void
-intsetfn(Param pm, zlong x)
-{
- pm->u.val = x;
-}
-
-/* Function to get value of a floating point parameter */
-
-/**/
-static double
-floatgetfn(Param pm)
-{
- return pm->u.dval;
-}
-
-/* Function to set value of an integer parameter */
-
-/**/
-static void
-floatsetfn(Param pm, double x)
-{
- pm->u.dval = x;
-}
-
-/* Function to get value of a scalar (string) parameter */
-
-/**/
-mod_export char *
-strgetfn(Param pm)
-{
- return pm->u.str ? pm->u.str : (char *) hcalloc(1);
-}
-
-/* Function to set value of a scalar (string) parameter */
-
-/**/
-mod_export void
-strsetfn(Param pm, char *x)
-{
- zsfree(pm->u.str);
- pm->u.str = x;
- if (!(pm->node.flags & PM_HASHELEM) &&
- ((pm->node.flags & PM_NAMEDDIR) || isset(AUTONAMEDIRS))) {
- pm->node.flags |= PM_NAMEDDIR;
- adduserdir(pm->node.nam, x, 0, 0);
- }
- /* If you update this function, you may need to update the
- * `Implement remainder of strsetfn' block in assignstrvalue(). */
-}
-
-/* Function to get value of an array parameter */
-
-static char *nullarray = NULL;
-
-/**/
-char **
-arrgetfn(Param pm)
-{
- return pm->u.arr ? pm->u.arr : &nullarray;
-}
-
-/* Function to set value of an array parameter */
-
-/**/
-mod_export void
-arrsetfn(Param pm, char **x)
-{
- if (pm->u.arr && pm->u.arr != x)
- freearray(pm->u.arr);
- if (pm->node.flags & PM_UNIQUE)
- uniqarray(x);
- pm->u.arr = x;
- /* Arrays tied to colon-arrays may need to fix the environment */
- if (pm->ename && x)
- arrfixenv(pm->ename, x);
- /* If you extend this function, update the list of conditions in
- * setarrvalue(). */
-}
-
-/* Function to get value of an association parameter */
-
-/**/
-mod_export HashTable
-hashgetfn(Param pm)
-{
- return pm->u.hash;
-}
-
-/* Function to set value of an association parameter */
-
-/**/
-mod_export void
-hashsetfn(Param pm, HashTable x)
-{
- if (pm->u.hash && pm->u.hash != x)
- deleteparamtable(pm->u.hash);
- pm->u.hash = x;
-}
-
-/* Function to dispose of setting of an unsettable hash */
-
-/**/
-mod_export void
-nullsethashfn(UNUSED(Param pm), HashTable x)
-{
- deleteparamtable(x);
-}
-
-/* Function to set value of an association parameter using key/value pairs */
-
-/**/
-static void
-arrhashsetfn(Param pm, char **val, int flags)
-{
- /* Best not to shortcut this by using the existing hash table, *
- * since that could cause trouble for special hashes. This way, *
- * it's up to pm->gsu.h->setfn() what to do. */
- int alen = 0;
- HashTable opmtab = paramtab, ht = 0;
- char **aptr;
- Value v = (Value) hcalloc(sizeof *v);
- v->end = -1;
-
- for (aptr = val; *aptr; ++aptr) {
- if (**aptr != Marker)
- ++alen;
- }
-
- if (alen % 2) {
- freearray(val);
- zerr("bad set of key/value pairs for associative array");
- return;
- }
- if (flags & ASSPM_AUGMENT) {
- ht = paramtab = pm->gsu.h->getfn(pm);
- }
- if (alen && (!(flags & ASSPM_AUGMENT) || !paramtab)) {
- ht = paramtab = newparamtable(17, pm->node.nam);
- }
- for (aptr = val; *aptr; ) {
- int eltflags = 0;
- if (**aptr == Marker) {
- /* Either all elements have Marker or none. Checked in caller. */
- if ((*aptr)[1] == '+') {
- /* Actually, assignstrvalue currently doesn't handle this... */
- eltflags = ASSPM_AUGMENT;
- /* ...so we'll use the trick from setsparam(). */
- v->start = INT_MAX;
- } else {
- v->start = 0;
- }
- v->end = -1;
- zsfree(*aptr++);
- }
- /* The parameter name is ztrdup'd... */
- v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET);
- /*
- * createparam() doesn't return anything if the parameter
- * already existed.
- */
- if (!v->pm)
- v->pm = (Param) paramtab->getnode(paramtab, *aptr);
- zsfree(*aptr++);
- /* ...but we can use the value without copying. */
- assignstrvalue(v, *aptr++, eltflags);
- }
- paramtab = opmtab;
- pm->gsu.h->setfn(pm, ht);
- free(val); /* not freearray() */
-}
-
-/*
- * These functions are used as the set function for special parameters that
- * cannot be set by the user. The set is incomplete as the only such
- * parameters are scalar and integer.
- */
-
-/**/
-mod_export void
-nullstrsetfn(UNUSED(Param pm), char *x)
-{
- zsfree(x);
-}
-
-/**/
-mod_export void
-nullintsetfn(UNUSED(Param pm), UNUSED(zlong x))
-{}
-
-/**/
-mod_export void
-nullunsetfn(UNUSED(Param pm), UNUSED(int exp))
-{}
-
-
-/* Function to get value of generic special integer *
- * parameter. data is pointer to global variable *
- * containing the integer value. */
-
-/**/
-mod_export zlong
-intvargetfn(Param pm)
-{
- return *pm->u.valptr;
-}
-
-/* Function to set value of generic special integer *
- * parameter. data is pointer to global variable *
- * where the value is to be stored. */
-
-/**/
-mod_export void
-intvarsetfn(Param pm, zlong x)
-{
- *pm->u.valptr = x;
-}
-
-/* Function to set value of any ZLE-related integer *
- * parameter. data is pointer to global variable *
- * where the value is to be stored. */
-
-/**/
-void
-zlevarsetfn(Param pm, zlong x)
-{
- zlong *p = pm->u.valptr;
-
- *p = x;
- if (p == &zterm_lines || p == &zterm_columns)
- adjustwinsize(2 + (p == &zterm_columns));
-}
-
-
-/* Implements gsu_integer.unsetfn for ZLE_RPROMPT_INDENT; see stdunsetfn() */
-
-static void
-rprompt_indent_unsetfn(Param pm, int exp)
-{
- stdunsetfn(pm, exp);
- rprompt_indent = 1; /* Keep this in sync with init_term() */
-}
-
-/* Function to set value of generic special scalar *
- * parameter. data is pointer to a character pointer *
- * representing the scalar (string). */
-
-/**/
-mod_export void
-strvarsetfn(Param pm, char *x)
-{
- char **q = ((char **)pm->u.data);
-
- zsfree(*q);
- *q = x;
-}
-
-/* Function to get value of generic special scalar *
- * parameter. data is pointer to a character pointer *
- * representing the scalar (string). */
-
-/**/
-mod_export char *
-strvargetfn(Param pm)
-{
- char *s = *((char **)pm->u.data);
-
- if (!s)
- return hcalloc(1);
- return s;
-}
-
-/* Function to get value of generic special array *
- * parameter. data is a pointer to the pointer to *
- * a pointer (a pointer to a variable length array *
- * of pointers). */
-
-/**/
-mod_export char **
-arrvargetfn(Param pm)
-{
- char **arrptr = *((char ***)pm->u.data);
-
- return arrptr ? arrptr : &nullarray;
-}
-
-/* Function to set value of generic special array parameter. *
- * data is pointer to a variable length array of pointers which *
- * represents this array of scalars (strings). If pm->ename is *
- * non NULL, then it is a colon separated environment variable *
- * version of this array which will need to be updated. */
-
-/**/
-mod_export void
-arrvarsetfn(Param pm, char **x)
-{
- char ***dptr = (char ***)pm->u.data;
-
- if (*dptr != x)
- freearray(*dptr);
- if (pm->node.flags & PM_UNIQUE)
- uniqarray(x);
- /*
- * Special tied arrays point to variables accessible in other
- * ways which need to be set to NULL. We can't do this
- * with user tied variables since we can leak memory.
- */
- if ((pm->node.flags & PM_SPECIAL) && !x)
- *dptr = mkarray(NULL);
- else
- *dptr = x;
- if (pm->ename) {
- if (x)
- arrfixenv(pm->ename, x);
- else if (*dptr == path)
- pathchecked = path;
- }
-}
-
-/**/
-char *
-colonarrgetfn(Param pm)
-{
- char ***dptr = (char ***)pm->u.data;
- return *dptr ? zjoin(*dptr, ':', 1) : "";
-}
-
-/**/
-void
-colonarrsetfn(Param pm, char *x)
-{
- char ***dptr = (char ***)pm->u.data;
- /*
- * We have to make sure this is never NULL, since that
- * can cause problems.
- */
- if (*dptr)
- freearray(*dptr);
- if (x)
- *dptr = colonsplit(x, pm->node.flags & PM_UNIQUE);
- else
- *dptr = mkarray(NULL);
- arrfixenv(pm->node.nam, *dptr);
- zsfree(x);
-}
-
-/**/
-char *
-tiedarrgetfn(Param pm)
-{
- struct tieddata *dptr = (struct tieddata *)pm->u.data;
- return *dptr->arrptr ? zjoin(*dptr->arrptr, STOUC(dptr->joinchar), 1) : "";
-}
-
-/**/
-void
-tiedarrsetfn(Param pm, char *x)
-{
- struct tieddata *dptr = (struct tieddata *)pm->u.data;
-
- if (*dptr->arrptr)
- freearray(*dptr->arrptr);
- if (x) {
- char sepbuf[3];
- if (imeta(dptr->joinchar))
- {
- sepbuf[0] = Meta;
- sepbuf[1] = dptr->joinchar ^ 32;
- sepbuf[2] = '\0';
- }
- else
- {
- sepbuf[0] = dptr->joinchar;
- sepbuf[1] = '\0';
- }
- *dptr->arrptr = sepsplit(x, sepbuf, 0, 0);
- if (pm->node.flags & PM_UNIQUE)
- uniqarray(*dptr->arrptr);
- zsfree(x);
- } else
- *dptr->arrptr = NULL;
- if (pm->ename)
- arrfixenv(pm->node.nam, *dptr->arrptr);
-}
-
-/**/
-void
-tiedarrunsetfn(Param pm, UNUSED(int exp))
-{
- /*
- * Special unset function because we allocated a struct tieddata
- * in typeset_single to hold the special data which we now
- * need to delete.
- */
- pm->gsu.s->setfn(pm, NULL);
- zfree(pm->u.data, sizeof(struct tieddata));
- /* paranoia -- shouldn't need these, but in case we reuse the struct... */
- pm->u.data = NULL;
- zsfree(pm->ename);
- pm->ename = NULL;
- pm->node.flags &= ~PM_TIED;
- pm->node.flags |= PM_UNSET;
-}
-
-/**/
-static void
-simple_arrayuniq(char **x, int freeok)
-{
- char **t, **p = x;
- char *hole = "";
-
- /* Find duplicates and replace them with holes */
- while (*++p)
- for (t = x; t < p; t++)
- if (*t != hole && !strcmp(*p, *t)) {
- if (freeok)
- zsfree(*p);
- *p = hole;
- break;
- }
- /* Swap non-holes into holes in optimal jumps */
- for (p = t = x; *t != NULL; t++) {
- if (*t == hole) {
- while (*p == hole)
- ++p;
- if ((*t = *p) != NULL)
- *p++ = hole;
- } else if (p == t)
- p++;
- }
- /* Erase all the remaining holes, just in case */
- while (++t < p)
- *t = NULL;
-}
-
-/**/
-static void
-arrayuniq_freenode(HashNode hn)
-{
- (void)hn;
-}
-
-/**/
-HashTable
-newuniqtable(zlong size)
-{
- HashTable ht = newhashtable((int)size, "arrayuniq", NULL);
- /* ??? error checking */
-
- ht->hash = hasher;
- ht->emptytable = emptyhashtable;
- ht->filltable = NULL;
- ht->cmpnodes = strcmp;
- ht->addnode = addhashnode;
- ht->getnode = gethashnode2;
- ht->getnode2 = gethashnode2;
- ht->removenode = removehashnode;
- ht->disablenode = disablehashnode;
- ht->enablenode = enablehashnode;
- ht->freenode = arrayuniq_freenode;
- ht->printnode = NULL;
-
- return ht;
-}
-
-/**/
-static void
-arrayuniq(char **x, int freeok)
-{
- char **it, **write_it;
- zlong array_size = arrlen(x);
- HashTable ht;
-
- if (array_size == 0)
- return;
- if (array_size < 10 || !(ht = newuniqtable(array_size + 1))) {
- /* fallback to simpler routine */
- simple_arrayuniq(x, freeok);
- return;
- }
-
- for (it = x, write_it = x; *it;) {
- if (! gethashnode2(ht, *it)) {
- HashNode new_node = zhalloc(sizeof(struct hashnode));
- if (!new_node) {
- /* Oops, out of heap memory, no way to recover */
- zerr("out of memory in arrayuniq");
- break;
- }
- (void) addhashnode2(ht, *it, new_node);
- *write_it = *it;
- if (it != write_it)
- *it = NULL;
- ++write_it;
- }
- else {
- if (freeok)
- zsfree(*it);
- *it = NULL;
- }
- ++it;
- }
-
- deletehashtable(ht);
-}
-
-/**/
-void
-uniqarray(char **x)
-{
- if (!x || !*x)
- return;
- arrayuniq(x, !zheapptr(*x));
-}
-
-/**/
-void
-zhuniqarray(char **x)
-{
- if (!x || !*x)
- return;
- arrayuniq(x, 0);
-}
-
-/* Function to get value of special parameter `#' and `ARGC' */
-
-/**/
-zlong
-poundgetfn(UNUSED(Param pm))
-{
- return arrlen(pparams);
-}
-
-/* Function to get value for special parameter `RANDOM' */
-
-/**/
-zlong
-randomgetfn(UNUSED(Param pm))
-{
- return rand() & 0x7fff;
-}
-
-/* Function to set value of special parameter `RANDOM' */
-
-/**/
-void
-randomsetfn(UNUSED(Param pm), zlong v)
-{
- srand((unsigned int)v);
-}
-
-/* Function to get value for special parameter `SECONDS' */
-
-/**/
-zlong
-intsecondsgetfn(UNUSED(Param pm))
-{
- struct timeval now;
- struct timezone dummy_tz;
-
- gettimeofday(&now, &dummy_tz);
-
- return (zlong)(now.tv_sec - shtimer.tv_sec -
- (now.tv_usec < shtimer.tv_usec ? 1 : 0));
-}
-
-/* Function to set value of special parameter `SECONDS' */
-
-/**/
-void
-intsecondssetfn(UNUSED(Param pm), zlong x)
-{
- struct timeval now;
- struct timezone dummy_tz;
- zlong diff;
-
- gettimeofday(&now, &dummy_tz);
- diff = (zlong)now.tv_sec - x;
- shtimer.tv_sec = diff;
- if ((zlong)shtimer.tv_sec != diff)
- zwarn("SECONDS truncated on assignment");
- shtimer.tv_usec = now.tv_usec;
-}
-
-/**/
-double
-floatsecondsgetfn(UNUSED(Param pm))
-{
- struct timeval now;
- struct timezone dummy_tz;
-
- gettimeofday(&now, &dummy_tz);
-
- return (double)(now.tv_sec - shtimer.tv_sec) +
- (double)(now.tv_usec - shtimer.tv_usec) / 1000000.0;
-}
-
-/**/
-void
-floatsecondssetfn(UNUSED(Param pm), double x)
-{
- struct timeval now;
- struct timezone dummy_tz;
-
- gettimeofday(&now, &dummy_tz);
- shtimer.tv_sec = now.tv_sec - (zlong)x;
- shtimer.tv_usec = now.tv_usec - (zlong)((x - (zlong)x) * 1000000.0);
-}
-
-/**/
-double
-getrawseconds(void)
-{
- return (double)shtimer.tv_sec + (double)shtimer.tv_usec / 1000000.0;
-}
-
-/**/
-void
-setrawseconds(double x)
-{
- shtimer.tv_sec = (zlong)x;
- shtimer.tv_usec = (zlong)((x - (zlong)x) * 1000000.0);
-}
-
-/**/
-int
-setsecondstype(Param pm, int on, int off)
-{
- int newflags = (pm->node.flags | on) & ~off;
- int tp = PM_TYPE(newflags);
- /* Only one of the numeric types is allowed. */
- if (tp == PM_EFLOAT || tp == PM_FFLOAT)
- {
- pm->gsu.f = &floatseconds_gsu;
- }
- else if (tp == PM_INTEGER)
- {
- pm->gsu.i = &intseconds_gsu;
- }
- else
- return 1;
- pm->node.flags = newflags;
- return 0;
-}
-
-/* Function to get value for special parameter `USERNAME' */
-
-/**/
-char *
-usernamegetfn(UNUSED(Param pm))
-{
- return get_username();
-}
-
-/* Function to set value of special parameter `USERNAME' */
-
-/**/
-void
-usernamesetfn(UNUSED(Param pm), char *x)
-{
-#if defined(HAVE_SETUID) && defined(HAVE_GETPWNAM)
- struct passwd *pswd;
-
- if (x && (pswd = getpwnam(x)) && (pswd->pw_uid != cached_uid)) {
-# ifdef USE_INITGROUPS
- initgroups(x, pswd->pw_gid);
-# endif
- if (setgid(pswd->pw_gid))
- zwarn("failed to change group ID: %e", errno);
- else if (setuid(pswd->pw_uid))
- zwarn("failed to change user ID: %e", errno);
- else {
- zsfree(cached_username);
- cached_username = ztrdup(pswd->pw_name);
- cached_uid = pswd->pw_uid;
- }
- }
-#endif /* HAVE_SETUID && HAVE_GETPWNAM */
- zsfree(x);
-}
-
-/* Function to get value for special parameter `UID' */
-
-/**/
-zlong
-uidgetfn(UNUSED(Param pm))
-{
- return getuid();
-}
-
-/* Function to set value of special parameter `UID' */
-
-/**/
-void
-uidsetfn(UNUSED(Param pm), zlong x)
-{
-#ifdef HAVE_SETUID
- if (setuid((uid_t)x))
- zerr("failed to change user ID: %e", errno);
-#endif
-}
-
-/* Function to get value for special parameter `EUID' */
-
-/**/
-zlong
-euidgetfn(UNUSED(Param pm))
-{
- return geteuid();
-}
-
-/* Function to set value of special parameter `EUID' */
-
-/**/
-void
-euidsetfn(UNUSED(Param pm), zlong x)
-{
-#ifdef HAVE_SETEUID
- if (seteuid((uid_t)x))
- zerr("failed to change effective user ID: %e", errno);
-#endif
-}
-
-/* Function to get value for special parameter `GID' */
-
-/**/
-zlong
-gidgetfn(UNUSED(Param pm))
-{
- return getgid();
-}
-
-/* Function to set value of special parameter `GID' */
-
-/**/
-void
-gidsetfn(UNUSED(Param pm), zlong x)
-{
-#ifdef HAVE_SETUID
- if (setgid((gid_t)x))
- zerr("failed to change group ID: %e", errno);
-#endif
-}
-
-/* Function to get value for special parameter `EGID' */
-
-/**/
-zlong
-egidgetfn(UNUSED(Param pm))
-{
- return getegid();
-}
-
-/* Function to set value of special parameter `EGID' */
-
-/**/
-void
-egidsetfn(UNUSED(Param pm), zlong x)
-{
-#ifdef HAVE_SETEUID
- if (setegid((gid_t)x))
- zerr("failed to change effective group ID: %e", errno);
-#endif
-}
-
-/**/
-zlong
-ttyidlegetfn(UNUSED(Param pm))
-{
- struct stat ttystat;
-
- if (SHTTY == -1 || fstat(SHTTY, &ttystat))
- return -1;
- return time(NULL) - ttystat.st_atime;
-}
-
-/* Function to get value for special parameter `IFS' */
-
-/**/
-char *
-ifsgetfn(UNUSED(Param pm))
-{
- return ifs;
-}
-
-/* Function to set value of special parameter `IFS' */
-
-/**/
-void
-ifssetfn(UNUSED(Param pm), char *x)
-{
- zsfree(ifs);
- ifs = x;
- inittyptab();
-}
-
-/* Functions to set value of special parameters `LANG' and `LC_*' */
-
-#ifdef USE_LOCALE
-static struct localename {
- char *name;
- int category;
-} lc_names[] = {
-#ifdef LC_COLLATE
- {"LC_COLLATE", LC_COLLATE},
-#endif
-#ifdef LC_CTYPE
- {"LC_CTYPE", LC_CTYPE},
-#endif
-#ifdef LC_MESSAGES
- {"LC_MESSAGES", LC_MESSAGES},
-#endif
-#ifdef LC_NUMERIC
- {"LC_NUMERIC", LC_NUMERIC},
-#endif
-#ifdef LC_TIME
- {"LC_TIME", LC_TIME},
-#endif
- {NULL, 0}
-};
-
-/**/
-static void
-setlang(char *x)
-{
- struct localename *ln;
- char *x2;
-
- if ((x2 = getsparam_u("LC_ALL")) && *x2)
- return;
-
- /*
- * Set the global locale to the value passed, but override
- * this with any non-empty definitions for specific
- * categories.
- *
- * We only use non-empty definitions because empty values aren't
- * valid as locales; when passed to setlocale() they mean "use the
- * environment variable", but if that's what we're setting the value
- * from this is meaningless. So just all $LANG to show through in
- * that case.
- */
- setlocale(LC_ALL, x ? unmeta(x) : "");
- queue_signals();
- for (ln = lc_names; ln->name; ln++)
- if ((x = getsparam_u(ln->name)) && *x)
- setlocale(ln->category, x);
- unqueue_signals();
-}
-
-/**/
-void
-lc_allsetfn(Param pm, char *x)
-{
- strsetfn(pm, x);
- /*
- * Treat an empty LC_ALL the same as an unset one,
- * namely by using LANG as the default locale but overriding
- * that with any LC_* that are set.
- */
- if (!x || !*x) {
- x = getsparam_u("LANG");
- if (x && *x) {
- queue_signals();
- setlang(x);
- unqueue_signals();
- }
- }
- else
- setlocale(LC_ALL, unmeta(x));
-}
-
-/**/
-void
-langsetfn(Param pm, char *x)
-{
- strsetfn(pm, x);
- setlang(unmeta(x));
-}
-
-/**/
-void
-lcsetfn(Param pm, char *x)
-{
- char *x2;
- struct localename *ln;
-
- strsetfn(pm, x);
- if ((x2 = getsparam("LC_ALL")) && *x2)
- return;
- queue_signals();
- /* Treat empty LC_* the same as unset. */
- if (!x || !*x)
- x = getsparam("LANG");
-
- /*
- * If we've got no non-empty string at this
- * point (after checking $LANG, too),
- * we shouldn't bother setting anything.
- */
- if (x && *x) {
- for (ln = lc_names; ln->name; ln++)
- if (!strcmp(ln->name, pm->node.nam))
- setlocale(ln->category, unmeta(x));
- }
- unqueue_signals();
-}
-#endif /* USE_LOCALE */
-
-/* Function to set value for special parameter `0' */
-
-/**/
-static void
-argzerosetfn(UNUSED(Param pm), char *x)
-{
- if (x) {
- if (isset(POSIXARGZERO))
- zerr("read-only variable: 0");
- else {
- zsfree(argzero);
- argzero = ztrdup(x);
- }
- zsfree(x);
- }
-}
-
-/* Function to get value for special parameter `0' */
-
-/**/
-static char *
-argzerogetfn(UNUSED(Param pm))
-{
- if (isset(POSIXARGZERO))
- return posixzero;
- return argzero;
-}
-
-/* Function to get value for special parameter `HISTSIZE' */
-
-/**/
-zlong
-histsizegetfn(UNUSED(Param pm))
-{
- return histsiz;
-}
-
-/* Function to set value of special parameter `HISTSIZE' */
-
-/**/
-void
-histsizesetfn(UNUSED(Param pm), zlong v)
-{
- if ((histsiz = v) < 1)
- histsiz = 1;
- resizehistents();
-}
-
-/* Function to get value for special parameter `SAVEHIST' */
-
-/**/
-zlong
-savehistsizegetfn(UNUSED(Param pm))
-{
- return savehistsiz;
-}
-
-/* Function to set value of special parameter `SAVEHIST' */
-
-/**/
-void
-savehistsizesetfn(UNUSED(Param pm), zlong v)
-{
- if ((savehistsiz = v) < 0)
- savehistsiz = 0;
-}
-
-/* Function to set value for special parameter `ERRNO' */
-
-/**/
-void
-errnosetfn(UNUSED(Param pm), zlong x)
-{
- errno = (int)x;
- if ((zlong)errno != x)
- zwarn("errno truncated on assignment");
-}
-
-/* Function to get value for special parameter `ERRNO' */
-
-/**/
-zlong
-errnogetfn(UNUSED(Param pm))
-{
- return errno;
-}
-
-/* Function to get value for special parameter `KEYBOARD_HACK' */
-
-/**/
-char *
-keyboardhackgetfn(UNUSED(Param pm))
-{
- static char buf[2];
-
- buf[0] = keyboardhackchar;
- buf[1] = '\0';
- return buf;
-}
-
-
-/* Function to set value of special parameter `KEYBOARD_HACK' */
-
-/**/
-void
-keyboardhacksetfn(UNUSED(Param pm), char *x)
-{
- if (x) {
- int len, i;
-
- unmetafy(x, &len);
- if (len > 1) {
- len = 1;
- zwarn("Only one KEYBOARD_HACK character can be defined"); /* could be changed if needed */
- }
- for (i = 0; i < len; i++) {
- if (!isascii(STOUC(x[i]))) {
- zwarn("KEYBOARD_HACK can only contain ASCII characters");
- return;
- }
- }
- keyboardhackchar = len ? STOUC(x[0]) : '\0';
- free(x);
- } else
- keyboardhackchar = '\0';
-}
-
-/* Function to get value for special parameter `histchar' */
-
-/**/
-char *
-histcharsgetfn(UNUSED(Param pm))
-{
- static char buf[4];
-
- buf[0] = bangchar;
- buf[1] = hatchar;
- buf[2] = hashchar;
- buf[3] = '\0';
- return buf;
-}
-
-/* Function to set value of special parameter `histchar' */
-
-/**/
-void
-histcharssetfn(UNUSED(Param pm), char *x)
-{
- if (x) {
- int len, i;
-
- unmetafy(x, &len);
- if (len > 3)
- len = 3;
- for (i = 0; i < len; i++) {
- if (!isascii(STOUC(x[i]))) {
- zwarn("HISTCHARS can only contain ASCII characters");
- return;
- }
- }
- bangchar = len ? STOUC(x[0]) : '\0';
- hatchar = len > 1 ? STOUC(x[1]) : '\0';
- hashchar = len > 2 ? STOUC(x[2]) : '\0';
- free(x);
- } else {
- bangchar = '!';
- hashchar = '#';
- hatchar = '^';
- }
- inittyptab();
-}
-
-/* Function to get value for special parameter `HOME' */
-
-/**/
-char *
-homegetfn(UNUSED(Param pm))
-{
- return home;
-}
-
-/* Function to set value of special parameter `HOME' */
-
-/**/
-void
-homesetfn(UNUSED(Param pm), char *x)
-{
- zsfree(home);
- if (x && isset(CHASELINKS) && (home = xsymlink(x, 0)))
- zsfree(x);
- else
- home = x ? x : ztrdup("");
- finddir(NULL);
-}
-
-/* Function to get value for special parameter `WORDCHARS' */
-
-/**/
-char *
-wordcharsgetfn(UNUSED(Param pm))
-{
- return wordchars;
-}
-
-/* Function to set value of special parameter `WORDCHARS' */
-
-/**/
-void
-wordcharssetfn(UNUSED(Param pm), char *x)
-{
- zsfree(wordchars);
- wordchars = x;
- inittyptab();
-}
-
-/* Function to get value for special parameter `_' */
-
-/**/
-char *
-underscoregetfn(UNUSED(Param pm))
-{
- char *u = dupstring(zunderscore);
-
- untokenize(u);
- return u;
-}
-
-/* Function used when we need to reinitialise the terminal */
-
-static void
-term_reinit_from_pm(void)
-{
- /* If non-interactive, delay setting up term till we need it. */
- if (unset(INTERACTIVE) || !*term)
- termflags |= TERM_UNKNOWN;
- else
- init_term();
-}
-
-/* Function to get value for special parameter `TERM' */
-
-/**/
-char *
-termgetfn(UNUSED(Param pm))
-{
- return term;
-}
-
-/* Function to set value of special parameter `TERM' */
-
-/**/
-void
-termsetfn(UNUSED(Param pm), char *x)
-{
- zsfree(term);
- term = x ? x : ztrdup("");
- term_reinit_from_pm();
-}
-
-/* Function to get value of special parameter `TERMINFO' */
-
-/**/
-char *
-terminfogetfn(UNUSED(Param pm))
-{
- return zsh_terminfo ? zsh_terminfo : dupstring("");
-}
-
-/* Function to set value of special parameter `TERMINFO' */
-
-/**/
-void
-terminfosetfn(Param pm, char *x)
-{
- zsfree(zsh_terminfo);
- zsh_terminfo = x;
-
- /*
- * terminfo relies on the value being exported before
- * we reinitialise the terminal. This is a bit inefficient.
- */
- if ((pm->node.flags & PM_EXPORTED) && x)
- addenv(pm, x);
-
- term_reinit_from_pm();
-}
-
-/* Function to get value of special parameter `TERMINFO_DIRS' */
-
-/**/
-char *
-terminfodirsgetfn(UNUSED(Param pm))
-{
- return zsh_terminfodirs ? zsh_terminfodirs : dupstring("");
-}
-
-/* Function to set value of special parameter `TERMINFO_DIRS' */
-
-/**/
-void
-terminfodirssetfn(Param pm, char *x)
-{
- zsfree(zsh_terminfodirs);
- zsh_terminfodirs = x;
-
- /*
- * terminfo relies on the value being exported before
- * we reinitialise the terminal. This is a bit inefficient.
- */
- if ((pm->node.flags & PM_EXPORTED) && x)
- addenv(pm, x);
-
- term_reinit_from_pm();
-}
-/* Function to get value for special parameter `pipestatus' */
-
-/**/
-static char **
-pipestatgetfn(UNUSED(Param pm))
-{
- char **x = (char **) zhalloc((numpipestats + 1) * sizeof(char *));
- char buf[DIGBUFSIZE], **p;
- int *q, i;
-
- for (p = x, q = pipestats, i = numpipestats; i--; p++, q++) {
- sprintf(buf, "%d", *q);
- *p = dupstring(buf);
- }
- *p = NULL;
-
- return x;
-}
-
-/* Function to get value for special parameter `pipestatus' */
-
-/**/
-static void
-pipestatsetfn(UNUSED(Param pm), char **x)
-{
- if (x) {
- int i;
-
- for (i = 0; *x && i < MAX_PIPESTATS; i++, x++)
- pipestats[i] = atoi(*x);
- numpipestats = i;
- }
- else
- numpipestats = 0;
-}
-
-/**/
-void
-arrfixenv(char *s, char **t)
-{
- Param pm;
- int joinchar;
-
- if (t == path)
- cmdnamtab->emptytable(cmdnamtab);
-
- pm = (Param) paramtab->getnode(paramtab, s);
-
- /*
- * Only one level of a parameter can be exported. Unless
- * ALLEXPORT is set, this must be global.
- */
-
- if (pm->node.flags & PM_HASHELEM)
- return;
-
- if (isset(ALLEXPORT))
- pm->node.flags |= PM_EXPORTED;
-
- /*
- * Do not "fix" parameters that were not exported
- */
-
- if (!(pm->node.flags & PM_EXPORTED))
- return;
-
- if (pm->node.flags & PM_TIED)
- joinchar = STOUC(((struct tieddata *)pm->u.data)->joinchar);
- else
- joinchar = ':';
-
- addenv(pm, t ? zjoin(t, joinchar, 1) : "");
-}
-
-
-/**/
-int
-zputenv(char *str)
-{
- DPUTS(!str, "Attempt to put null string into environment.");
-#ifdef USE_SET_UNSET_ENV
- /*
- * If we are using unsetenv() to remove values from the
- * environment, which is the safe thing to do, we
- * need to use setenv() to put them there in the first place.
- * Unfortunately this is a slightly different interface
- * from what zputenv() assumes.
- */
- char *ptr;
- int ret;
-
- for (ptr = str; *ptr && STOUC(*ptr) < 128 && *ptr != '='; ptr++)
- ;
- if (STOUC(*ptr) >= 128) {
- /*
- * Environment variables not in the portable character
- * set are non-standard and we don't really know of
- * a use for them.
- *
- * We'll disable until someone complains.
- */
- return 1;
- } else if (*ptr) {
- *ptr = '\0';
- ret = setenv(str, ptr+1, 1);
- *ptr = '=';
- } else {
- /* safety first */
- DPUTS(1, "bad environment string");
- ret = setenv(str, ptr, 1);
- }
- return ret;
-#else
-#ifdef HAVE_PUTENV
- return putenv(str);
-#else
- char **ep;
- int num_env;
-
-
- /* First check if there is already an environment *
- * variable matching string `name'. */
- if (findenv(str, &num_env)) {
- environ[num_env] = str;
- } else {
- /* Else we have to make room and add it */
- num_env = arrlen(environ);
- environ = (char **) zrealloc(environ, (sizeof(char *)) * (num_env + 2));
-
- /* Now add it at the end */
- ep = environ + num_env;
- *ep = str;
- *(ep + 1) = NULL;
- }
- return 0;
-#endif
-#endif
-}
-
-/**/
-#ifndef USE_SET_UNSET_ENV
-/**/
-static int
-findenv(char *name, int *pos)
-{
- char **ep, *eq;
- int nlen;
-
-
- eq = strchr(name, '=');
- nlen = eq ? eq - name : (int)strlen(name);
- for (ep = environ; *ep; ep++)
- if (!strncmp (*ep, name, nlen) && *((*ep)+nlen) == '=') {
- if (pos)
- *pos = ep - environ;
- return 1;
- }
-
- return 0;
-}
-/**/
-#endif
-
-/* Given *name = "foo", it searches the environment for string *
- * "foo=bar", and returns a pointer to the beginning of "bar" */
-
-/**/
-mod_export char *
-zgetenv(char *name)
-{
-#ifdef HAVE_GETENV
- return getenv(name);
-#else
- char **ep, *s, *t;
-
- for (ep = environ; *ep; ep++) {
- for (s = *ep, t = name; *s && *s == *t; s++, t++);
- if (*s == '=' && !*t)
- return s + 1;
- }
- return NULL;
-#endif
-}
-
-/**/
-static void
-copyenvstr(char *s, char *value, int flags)
-{
- while (*s++) {
- if ((*s = *value++) == Meta)
- *s = *value++ ^ 32;
- if (flags & PM_LOWER)
- *s = tulower(*s);
- else if (flags & PM_UPPER)
- *s = tuupper(*s);
- }
-}
-
-/**/
-void
-addenv(Param pm, char *value)
-{
- char *newenv = 0;
-#ifndef USE_SET_UNSET_ENV
- char *oldenv = 0, *env = 0;
- int pos;
-
- /*
- * First check if there is already an environment
- * variable matching string `name'.
- */
- if (findenv(pm->node.nam, &pos))
- oldenv = environ[pos];
-#endif
-
- newenv = mkenvstr(pm->node.nam, value, pm->node.flags);
- if (zputenv(newenv)) {
- zsfree(newenv);
- pm->env = NULL;
- return;
- }
-#ifdef USE_SET_UNSET_ENV
- /*
- * If we are using setenv/unsetenv to manage the environment,
- * we simply store the string we created in pm->env since
- * memory management of the environment is handled entirely
- * by the system.
- *
- * TODO: is this good enough to fix problem cases from
- * the other branch? If so, we don't actually need to
- * store pm->env at all, just a flag that the value was set.
- */
- if (pm->env)
- zsfree(pm->env);
- pm->env = newenv;
- pm->node.flags |= PM_EXPORTED;
-#else
- /*
- * Under Cygwin we must use putenv() to maintain consistency.
- * Unfortunately, current version (1.1.2) copies argument and may
- * silently reuse existing environment string. This tries to
- * check for both cases
- */
- if (findenv(pm->node.nam, &pos)) {
- env = environ[pos];
- if (env != oldenv)
- zsfree(oldenv);
- if (env != newenv)
- zsfree(newenv);
- pm->node.flags |= PM_EXPORTED;
- pm->env = env;
- return;
- }
-
- DPUTS(1, "addenv should never reach the end");
- pm->env = NULL;
-#endif
-}
-
-
-/* Given strings *name = "foo", *value = "bar", *
- * return a new string *str = "foo=bar". */
-
-/**/
-static char *
-mkenvstr(char *name, char *value, int flags)
-{
- char *str, *s = value;
- int len_name, len_value = 0;
-
- len_name = strlen(name);
- if (s)
- while (*s && (*s++ != Meta || *s++ != 32))
- len_value++;
- s = str = (char *) zalloc(len_name + len_value + 2);
- strcpy(s, name);
- s += len_name;
- *s = '=';
- if (value)
- copyenvstr(s, value, flags);
- else
- *++s = '\0';
- return str;
-}
-
-/* Given *name = "foo", *value = "bar", add the *
- * string "foo=bar" to the environment. Return a *
- * pointer to the location of this new environment *
- * string. */
-
-
-#ifndef USE_SET_UNSET_ENV
-/**/
-void
-delenvvalue(char *x)
-{
- char **ep;
-
- for (ep = environ; *ep; ep++) {
- if (*ep == x)
- break;
- }
- if (*ep) {
- for (; (ep[0] = ep[1]); ep++);
- }
- zsfree(x);
-}
-#endif
-
-
-/* Delete a pointer from the list of pointers to environment *
- * variables by shifting all the other pointers up one slot. */
-
-/**/
-void
-delenv(Param pm)
-{
-#ifdef USE_SET_UNSET_ENV
- unsetenv(pm->node.nam);
- zsfree(pm->env);
-#else
- delenvvalue(pm->env);
-#endif
- pm->env = NULL;
- /*
- * Note we don't remove PM_EXPORT from the flags. This
- * may be asking for trouble but we need to know later
- * if we restore this parameter to its old value.
- */
-}
-
-/*
- * Guts of convbase: this version can return the number of digits
- * sans any base discriminator.
- */
-
-/**/
-void
-convbase_ptr(char *s, zlong v, int base, int *ndigits)
-{
- int digs = 0;
- zulong x;
-
- if (v < 0)
- *s++ = '-', v = -v;
- if (base >= -1 && base <= 1)
- base = -10;
-
- if (base > 0) {
- if (isset(CBASES) && base == 16)
- sprintf(s, "0x");
- else if (isset(CBASES) && base == 8 && isset(OCTALZEROES))
- sprintf(s, "0");
- else if (base != 10)
- sprintf(s, "%d#", base);
- else
- *s = 0;
- s += strlen(s);
- } else
- base = -base;
- for (x = v; x; digs++)
- x /= base;
- if (!digs)
- digs = 1;
- if (ndigits)
- *ndigits = digs;
- s[digs--] = '\0';
- x = v;
- while (digs >= 0) {
- int dig = x % base;
-
- s[digs--] = (dig < 10) ? '0' + dig : dig - 10 + 'A';
- x /= base;
- }
-}
-
-/*
- * Basic conversion of integer to a string given a base.
- * If 0 base is 10.
- * If negative no base discriminator is output.
- */
-
-/**/
-mod_export void
-convbase(char *s, zlong v, int base)
-{
- convbase_ptr(s, v, base, NULL);
-}
-
-/*
- * Add underscores to converted integer for readability with given spacing.
- * s is as for convbase: at least BDIGBUFSIZE.
- * If underscores were added, returned value with underscores comes from
- * heap, else the returned value is s.
- */
-
-/**/
-char *
-convbase_underscore(char *s, zlong v, int base, int underscore)
-{
- char *retptr, *sptr, *dptr;
- int ndigits, nunderscore, mod, len;
-
- convbase_ptr(s, v, base, &ndigits);
-
- if (underscore <= 0)
- return s;
-
- nunderscore = (ndigits - 1) / underscore;
- if (!nunderscore)
- return s;
- len = strlen(s);
- retptr = zhalloc(len + nunderscore + 1);
- mod = 0;
- memcpy(retptr, s, len - ndigits);
- sptr = s + len;
- dptr = retptr + len + nunderscore;
- /* copy the null */
- *dptr-- = *sptr--;
- for (;;) {
- *dptr = *sptr;
- if (!--ndigits)
- break;
- dptr--;
- sptr--;
- if (++mod == underscore) {
- mod = 0;
- *dptr-- = '_';
- }
- }
-
- return retptr;
-}
-
-/*
- * Convert a floating point value for output.
- * Unlike convbase(), this has its own internal storage and returns
- * a value from the heap.
- */
-
-/**/
-char *
-convfloat(double dval, int digits, int flags, FILE *fout)
-{
- char fmt[] = "%.*e";
- char *prev_locale, *ret;
-
- /*
- * The difficulty with the buffer size is that a %f conversion
- * prints all digits before the decimal point: with 64 bit doubles,
- * that's around 310. We can't check without doing some quite
- * serious floating point operations we'd like to avoid.
- * Then we are liable to get all the digits
- * we asked for after the decimal point, or we should at least
- * bargain for it. So we just allocate 512 + digits. This
- * should work until somebody decides on 128-bit doubles.
- */
- if (!(flags & (PM_EFLOAT|PM_FFLOAT))) {
- /*
- * Conversion from a floating point expression without using
- * a variable. The best bet in this case just seems to be
- * to use the general %g format with something like the maximum
- * double precision.
- */
- fmt[3] = 'g';
- if (!digits)
- digits = 17;
- } else {
- if (flags & PM_FFLOAT)
- fmt[3] = 'f';
- if (digits <= 0)
- digits = 10;
- if (flags & PM_EFLOAT) {
- /*
- * Here, we are given the number of significant figures, but
- * %e wants the number of decimal places (unlike %g)
- */
- digits--;
- }
- }
-#ifdef USE_LOCALE
- prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
- setlocale(LC_NUMERIC, "POSIX");
-#endif
- if (fout) {
- fprintf(fout, fmt, digits, dval);
- ret = NULL;
- } else {
- VARARR(char, buf, 512 + digits);
- if (isinf(dval))
- ret = dupstring((dval < 0.0) ? "-Inf" : "Inf");
- else if (isnan(dval))
- ret = dupstring("NaN");
- else {
- sprintf(buf, fmt, digits, dval);
- if (!strchr(buf, 'e') && !strchr(buf, '.'))
- strcat(buf, ".");
- ret = dupstring(buf);
- }
- }
-#ifdef USE_LOCALE
- if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
-#endif
- return ret;
-}
-
-/*
- * convert float to string with basic options but inserting underscores
- * for readability.
- */
-
-/**/
-char *convfloat_underscore(double dval, int underscore)
-{
- int ndigits_int = 0, ndigits_frac = 0, nunderscore, len;
- char *s, *retptr, *sptr, *dptr;
-
- s = convfloat(dval, 0, 0, NULL);
- if (underscore <= 0)
- return s;
-
- /*
- * Count the number of digits before and after the decimal point, if any.
- */
- sptr = s;
- if (*sptr == '-')
- sptr++;
- while (idigit(*sptr)) {
- ndigits_int++;
- sptr++;
- }
- if (*sptr == '.') {
- sptr++;
- while (idigit(*sptr)) {
- ndigits_frac++;
- sptr++;
- }
- }
-
- /*
- * Work out how many underscores to insert --- remember we
- * put them in integer and fractional parts separately.
- */
- nunderscore = (ndigits_int-1) / underscore + (ndigits_frac-1) / underscore;
- if (!nunderscore)
- return s;
- len = strlen(s);
- dptr = retptr = zhalloc(len + nunderscore + 1);
-
- /*
- * Insert underscores in integer part.
- * Grouping starts from the point in both directions.
- */
- sptr = s;
- if (*sptr == '-')
- *dptr++ = *sptr++;
- while (ndigits_int) {
- *dptr++ = *sptr++;
- if (--ndigits_int && !(ndigits_int % underscore))
- *dptr++ = '_';
- }
- if (ndigits_frac) {
- /*
- * Insert underscores in the fractional part.
- */
- int mod = 0;
- /* decimal point, we already checked */
- *dptr++ = *sptr++;
- while (ndigits_frac) {
- *dptr++ = *sptr++;
- mod++;
- if (--ndigits_frac && mod == underscore) {
- *dptr++ = '_';
- mod = 0;
- }
- }
- }
- /* Copy exponent and anything else up to null */
- while ((*dptr++ = *sptr++))
- ;
- return retptr;
-}
-
-/* Start a parameter scope */
-
-/**/
-mod_export void
-startparamscope(void)
-{
- locallevel++;
-}
-
-/* End a parameter scope: delete the parameters local to the scope. */
-
-/**/
-mod_export void
-endparamscope(void)
-{
- queue_signals();
- locallevel--;
- /* This pops anything from a higher locallevel */
- saveandpophiststack(0, HFILE_USE_OPTIONS);
- scanhashtable(paramtab, 0, 0, 0, scanendscope, 0);
- unqueue_signals();
-}
-
-/**/
-static void
-scanendscope(HashNode hn, UNUSED(int flags))
-{
- Param pm = (Param)hn;
- if (pm->level > locallevel) {
- if ((pm->node.flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL) {
- /*
- * Removable specials are normal in that they can be removed
- * to reveal an ordinary parameter beneath. Here we handle
- * non-removable specials, which were made local by stealth
- * (see newspecial code in typeset_single()). In fact the
- * visible pm is always the same struct; the pm->old is
- * just a place holder for old data and flags.
- */
- Param tpm = pm->old;
-
- if (!strcmp(pm->node.nam, "SECONDS"))
- {
- setsecondstype(pm, PM_TYPE(tpm->node.flags), PM_TYPE(pm->node.flags));
- /*
- * We restore SECONDS by restoring its raw internal value
- * that we cached off into tpm->u.dval.
- */
- setrawseconds(tpm->u.dval);
- tpm->node.flags |= PM_NORESTORE;
- }
- DPUTS(!tpm || PM_TYPE(pm->node.flags) != PM_TYPE(tpm->node.flags) ||
- !(tpm->node.flags & PM_SPECIAL),
- "BUG: in restoring scope of special parameter");
- pm->old = tpm->old;
- pm->node.flags = (tpm->node.flags & ~PM_NORESTORE);
- pm->level = tpm->level;
- pm->base = tpm->base;
- pm->width = tpm->width;
- if (pm->env)
- delenv(pm);
-
- if (!(tpm->node.flags & (PM_NORESTORE|PM_READONLY)))
- switch (PM_TYPE(pm->node.flags)) {
- case PM_SCALAR:
- pm->gsu.s->setfn(pm, tpm->u.str);
- break;
- case PM_INTEGER:
- pm->gsu.i->setfn(pm, tpm->u.val);
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- pm->gsu.f->setfn(pm, tpm->u.dval);
- break;
- case PM_ARRAY:
- pm->gsu.a->setfn(pm, tpm->u.arr);
- break;
- case PM_HASHED:
- pm->gsu.h->setfn(pm, tpm->u.hash);
- break;
- }
- zfree(tpm, sizeof(*tpm));
-
- if (pm->node.flags & PM_EXPORTED)
- export_param(pm);
- } else
- unsetparam_pm(pm, 0, 0);
- }
-}
-
-
-/**********************************/
-/* Parameter Hash Table Functions */
-/**********************************/
-
-/**/
-void
-freeparamnode(HashNode hn)
-{
- Param pm = (Param) hn;
-
- /* The second argument of unsetfn() is used by modules to
- * differentiate "exp"licit unset from implicit unset, as when
- * a parameter is going out of scope. It's not clear which
- * of these applies here, but passing 1 has always worked.
- */
- if (delunset)
- pm->gsu.s->unsetfn(pm, 1);
- zsfree(pm->node.nam);
- /* If this variable was tied by the user, ename was ztrdup'd */
- if (pm->node.flags & PM_TIED)
- zsfree(pm->ename);
- zfree(pm, sizeof(struct param));
-}
-
-/* Print a parameter */
-
-enum paramtypes_flags {
- PMTF_USE_BASE = (1<<0),
- PMTF_USE_WIDTH = (1<<1),
- PMTF_TEST_LEVEL = (1<<2)
-};
-
-struct paramtypes {
- int binflag; /* The relevant PM_FLAG(S) */
- const char *string; /* String for verbose output */
- int typeflag; /* Flag for typeset -? */
- int flags; /* The enum above */
-};
-
-static const struct paramtypes pmtypes[] = {
- { PM_AUTOLOAD, "undefined", 0, 0},
- { PM_INTEGER, "integer", 'i', PMTF_USE_BASE},
- { PM_EFLOAT, "float", 'E', 0},
- { PM_FFLOAT, "float", 'F', 0},
- { PM_ARRAY, "array", 'a', 0},
- { PM_HASHED, "association", 'A', 0},
- { 0, "local", 0, PMTF_TEST_LEVEL},
- { PM_LEFT, "left justified", 'L', PMTF_USE_WIDTH},
- { PM_RIGHT_B, "right justified", 'R', PMTF_USE_WIDTH},
- { PM_RIGHT_Z, "zero filled", 'Z', PMTF_USE_WIDTH},
- { PM_LOWER, "lowercase", 'l', 0},
- { PM_UPPER, "uppercase", 'u', 0},
- { PM_READONLY, "readonly", 'r', 0},
- { PM_TAGGED, "tagged", 't', 0},
- { PM_EXPORTED, "exported", 'x', 0}
-};
-
-#define PMTYPES_SIZE ((int)(sizeof(pmtypes)/sizeof(struct paramtypes)))
-
-static void
-printparamvalue(Param p, int printflags)
-{
- char *t, **u;
-
- if (!(printflags & PRINT_KV_PAIR))
- putchar('=');
-
- /* How the value is displayed depends *
- * on the type of the parameter */
- switch (PM_TYPE(p->node.flags)) {
- case PM_SCALAR:
- /* string: simple output */
- if (p->gsu.s->getfn && (t = p->gsu.s->getfn(p)))
- quotedzputs(t, stdout);
- break;
- case PM_INTEGER:
- /* integer */
-#ifdef ZSH_64_BIT_TYPE
- fputs(output64(p->gsu.i->getfn(p)), stdout);
-#else
- printf("%ld", p->gsu.i->getfn(p));
-#endif
- break;
- case PM_EFLOAT:
- case PM_FFLOAT:
- /* float */
- convfloat(p->gsu.f->getfn(p), p->base, p->node.flags, stdout);
- break;
- case PM_ARRAY:
- /* array */
- if (!(printflags & PRINT_KV_PAIR)) {
- putchar('(');
- if (!(printflags & PRINT_LINE))
- putchar(' ');
- }
- u = p->gsu.a->getfn(p);
- if(*u) {
- if (printflags & PRINT_LINE) {
- if (printflags & PRINT_KV_PAIR)
- printf(" ");
- else
- printf("\n ");
- }
- quotedzputs(*u++, stdout);
- while (*u) {
- if (printflags & PRINT_LINE)
- printf("\n ");
- else
- putchar(' ');
- quotedzputs(*u++, stdout);
- }
- if ((printflags & (PRINT_LINE|PRINT_KV_PAIR)) == PRINT_LINE)
- putchar('\n');
- }
- if (!(printflags & PRINT_KV_PAIR)) {
- if (!(printflags & PRINT_LINE))
- putchar(' ');
- putchar(')');
- }
- break;
- case PM_HASHED:
- /* association */
- {
- HashTable ht;
- int found = 0;
- if (!(printflags & PRINT_KV_PAIR)) {
- putchar('(');
- if (!(printflags & PRINT_LINE))
- putchar(' ');
- }
- ht = p->gsu.h->getfn(p);
- if (ht)
- found = scanhashtable(ht, 1, 0, PM_UNSET,
- ht->printnode, PRINT_KV_PAIR |
- (printflags & PRINT_LINE));
- if (!(printflags & PRINT_KV_PAIR)) {
- if (found && (printflags & PRINT_LINE))
- putchar('\n');
- putchar(')');
- }
- }
- break;
- }
- if ((printflags & (PRINT_KV_PAIR|PRINT_LINE)) == PRINT_KV_PAIR)
- putchar(' ');
- else if (!(printflags & PRINT_KV_PAIR))
- putchar('\n');
-}
-
-/**/
-mod_export void
-printparamnode(HashNode hn, int printflags)
-{
- Param p = (Param) hn;
-
- if (p->node.flags & PM_UNSET) {
- if (isset(POSIXBUILTINS) && (p->node.flags & PM_READONLY) &&
- (printflags & PRINT_TYPESET))
- {
- /*
- * Special POSIX rules: show the parameter as readonly
- * even though it's unset, but with no value.
- */
- printflags |= PRINT_NAMEONLY;
- }
- else if (p->node.flags & PM_EXPORTED)
- printflags |= PRINT_NAMEONLY;
- else
- return;
- }
- if (p->node.flags & PM_AUTOLOAD)
- printflags |= PRINT_NAMEONLY;
-
- if (printflags & PRINT_TYPESET) {
- if ((p->node.flags & (PM_READONLY|PM_SPECIAL)) ==
- (PM_READONLY|PM_SPECIAL) ||
- (p->node.flags & PM_AUTOLOAD)) {
- /*
- * It's not possible to restore the state of
- * these, so don't output.
- */
- return;
- }
- if (locallevel && p->level >= locallevel) {
- printf("typeset "); /* printf("local "); */
- } else if ((p->node.flags & PM_EXPORTED) &&
- !(p->node.flags & (PM_ARRAY|PM_HASHED))) {
- printf("export ");
- } else if (locallevel) {
- printf("typeset -g ");
- } else
- printf("typeset ");
- }
-
- /* Print the attributes of the parameter */
- if (printflags & (PRINT_TYPE|PRINT_TYPESET)) {
- int doneminus = 0, i;
- const struct paramtypes *pmptr;
-
- for (pmptr = pmtypes, i = 0; i < PMTYPES_SIZE; i++, pmptr++) {
- int doprint = 0;
- if (pmptr->flags & PMTF_TEST_LEVEL) {
- if (p->level)
- doprint = 1;
- } else if ((pmptr->binflag != PM_EXPORTED || p->level ||
- (p->node.flags & (PM_LOCAL|PM_ARRAY|PM_HASHED))) &&
- (p->node.flags & pmptr->binflag))
- doprint = 1;
-
- if (doprint) {
- if (printflags & PRINT_TYPESET) {
- if (pmptr->typeflag) {
- if (!doneminus) {
- putchar('-');
- doneminus = 1;
- }
- putchar(pmptr->typeflag);
- }
- } else
- printf("%s ", pmptr->string);
- if ((pmptr->flags & PMTF_USE_BASE) && p->base) {
- printf("%d ", p->base);
- doneminus = 0;
- }
- if ((pmptr->flags & PMTF_USE_WIDTH) && p->width) {
- printf("%d ", p->width);
- doneminus = 0;
- }
- }
- }
- if (doneminus)
- putchar(' ');
- }
-
- if ((printflags & PRINT_NAMEONLY) ||
- ((p->node.flags & PM_HIDEVAL) && !(printflags & PRINT_INCLUDEVALUE))) {
- zputs(p->node.nam, stdout);
- putchar('\n');
- } else {
- if (printflags & PRINT_KV_PAIR) {
- if (printflags & PRINT_LINE)
- printf("\n ");
- putchar('[');
- }
- quotedzputs(p->node.nam, stdout);
- if (printflags & PRINT_KV_PAIR)
- printf("]=");
-
- printparamvalue(p, printflags);
- }
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/parse.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/parse.c
deleted file mode 100644
index 83383f10..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/parse.c
+++ /dev/null
@@ -1,3977 +0,0 @@
-/*
- * parse.c - parser
- *
- * 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 "parse.pro"
-
-/* != 0 if we are about to read a command word */
-
-/**/
-mod_export int incmdpos;
-
-/**/
-int aliasspaceflag;
-
-/* != 0 if we are in the middle of a [[ ... ]] */
-
-/**/
-mod_export int incond;
-
-/* != 0 if we are after a redirection (for ctxtlex only) */
-
-/**/
-mod_export int inredir;
-
-/*
- * 1 if we are about to read a case pattern
- * -1 if we are not quite sure
- * 0 otherwise
- */
-
-/**/
-int incasepat;
-
-/* != 0 if we just read a newline */
-
-/**/
-int isnewlin;
-
-/* != 0 if we are after a for keyword */
-
-/**/
-int infor;
-
-/* != 0 if we are after a repeat keyword; if it's nonzero it's a 1-based index
- * of the current token from the last-seen command position */
-
-/**/
-int inrepeat_; /* trailing underscore because of name clash with Zle/zle_vi.c */
-
-/* != 0 if parsing arguments of typeset etc. */
-
-/**/
-mod_export int intypeset;
-
-/* list of here-documents */
-
-/**/
-struct heredocs *hdocs;
-
-
-#define YYERROR(O) { tok = LEXERR; ecused = (O); return 0; }
-#define YYERRORV(O) { tok = LEXERR; ecused = (O); return; }
-#define COND_ERROR(X,Y) \
- do { \
- zwarn(X,Y); \
- herrflush(); \
- if (noerrs != 2) \
- errflag |= ERRFLAG_ERROR; \
- YYERROR(ecused) \
- } while(0)
-
-
-/*
- * Word code.
- *
- * The parser now produces word code, reducing memory consumption compared
- * to the nested structs we had before.
- *
- * Word code layout:
- *
- * WC_END
- * - end of program code
- *
- * WC_LIST
- * - data contains type (sync, ...)
- * - followed by code for this list
- * - if not (type & Z_END), followed by next WC_LIST
- *
- * WC_SUBLIST
- * - data contains type (&&, ||, END) and flags (coprog, not)
- * - followed by code for sublist
- * - if not (type == END), followed by next WC_SUBLIST
- *
- * WC_PIPE
- * - data contains type (end, mid) and LINENO
- * - if not (type == END), followed by offset to next WC_PIPE
- * - followed by command
- * - if not (type == END), followed by next WC_PIPE
- *
- * WC_REDIR
- * - must precede command-code (or WC_ASSIGN)
- * - data contains type (<, >, ...)
- * - followed by fd1 and name from struct redir
- * - for the extended form {var}>... where the fd is assigned
- * to var, there is an extra item to contain var
- *
- * WC_ASSIGN
- * - data contains type (scalar, array) and number of array-elements
- * - followed by name and value
- * Note variant for WC_TYPESET assignments: WC_ASSIGN_INC indicates
- * a name with no equals, not an =+ which isn't valid here.
- *
- * WC_SIMPLE
- * - data contains the number of arguments (plus command)
- * - followed by strings
- *
- * WC_TYPESET
- * Variant of WC_SIMPLE used when TYPESET reserved word found.
- * - data contains the number of string arguments (plus command)
- * - followed by strings
- * - followed by number of assignments
- * - followed by assignments if non-zero number.
- *
- * WC_SUBSH
- * - data unused
- * - followed by list
- *
- * WC_CURSH
- * - data unused
- * - followed by list
- *
- * WC_TIMED
- * - data contains type (followed by pipe or not)
- * - if (type == PIPE), followed by pipe
- *
- * WC_FUNCDEF
- * - data contains offset to after body
- * - followed by number of names
- * - followed by names
- * - followed by offset to first string
- * - followed by length of string table
- * - followed by number of patterns for body
- * - followed by codes for body
- * - followed by strings for body
- *
- * WC_FOR
- * - data contains type (list, ...) and offset to after body
- * - if (type == COND), followed by init, cond, advance expressions
- * - else if (type == PPARAM), followed by param name
- * - else if (type == LIST), followed by param name, num strings, strings
- * - followed by body
- *
- * WC_SELECT
- * - data contains type (list, ...) and offset to after body
- * - if (type == PPARAM), followed by param name
- * - else if (type == LIST), followed by param name, num strings, strings
- * - followed by body
- *
- * WC_WHILE
- * - data contains type (while, until) and offset to after body
- * - followed by condition
- * - followed by body
- *
- * WC_REPEAT
- * - data contains offset to after body
- * - followed by number-string
- * - followed by body
- *
- * WC_CASE
- * - first CASE is always of type HEAD, data contains offset to esac
- * - after that CASEs of type OR (;;), AND (;&) and TESTAND (;|),
- * data is offset to next case
- * - each OR/AND/TESTAND case is followed by pattern, pattern-number, list
- *
- * WC_IF
- * - first IF is of type HEAD, data contains offset to fi
- * - after that IFs of type IF, ELIF, ELSE, data is offset to next
- * - each non-HEAD is followed by condition (only IF, ELIF) and body
- *
- * WC_COND
- * - data contains type
- * - if (type == AND/OR), data contains offset to after this one,
- * followed by two CONDs
- * - else if (type == NOT), followed by COND
- * - else if (type == MOD), followed by name and strings
- * - else if (type == MODI), followed by name, left, right
- * - else if (type == STR[N]EQ), followed by left, right, pattern-number
- * - else if (has two args) followed by left, right
- * - else followed by string
- *
- * WC_ARITH
- * - followed by string (there's only one)
- *
- * WC_AUTOFN
- * - only used by the autoload builtin
- *
- * Lists and sublists may also be simplified, indicated by the presence
- * of the Z_SIMPLE or WC_SUBLIST_SIMPLE flags. In this case they are only
- * followed by a slot containing the line number, not by a WC_SUBLIST or
- * WC_PIPE, respectively. The real advantage of simplified lists and
- * sublists is that they can be executed faster, see exec.c. In the
- * parser, the test if a list can be simplified is done quite simply
- * by passing a int* around which gets set to non-zero if the thing
- * just parsed is `cmplx', i.e. may need to be run by forking or
- * some such.
- *
- * In each of the above, strings are encoded as one word code. For empty
- * strings this is the bit pattern 11x, the lowest bit is non-zero if the
- * string contains tokens and zero otherwise (this is true for the other
- * ways to encode strings, too). For short strings (one to three
- * characters), this is the marker 01x with the 24 bits above that
- * containing the characters. Longer strings are encoded as the offset
- * into the strs character array stored in the eprog struct shifted by
- * two and ored with the bit pattern 0x.
- * The ecstrcode() function that adds the code for a string uses a simple
- * binary tree of strings already added so that long strings are encoded
- * only once.
- *
- * Note also that in the eprog struct the pattern, code, and string
- * arrays all point to the same memory block.
- *
- *
- * To make things even faster in future versions, we could not only
- * test if the strings contain tokens, but instead what kind of
- * expansions need to be done on strings. In the execution code we
- * could then use these flags for a specialized version of prefork()
- * to avoid a lot of string parsing and some more string duplication.
- */
-
-/**/
-int eclen, ecused, ecnpats;
-/**/
-Wordcode ecbuf;
-/**/
-Eccstr ecstrs;
-/**/
-int ecsoffs, ecssub, ecnfunc;
-
-#define EC_INIT_SIZE 256
-#define EC_DOUBLE_THRESHOLD 32768
-#define EC_INCREMENT 1024
-
-/* save parse context */
-
-/**/
-void
-parse_context_save(struct parse_stack *ps, int toplevel)
-{
- (void)toplevel;
-
- ps->incmdpos = incmdpos;
- ps->aliasspaceflag = aliasspaceflag;
- ps->incond = incond;
- ps->inredir = inredir;
- ps->incasepat = incasepat;
- ps->isnewlin = isnewlin;
- ps->infor = infor;
- ps->inrepeat_ = inrepeat_;
- ps->intypeset = intypeset;
-
- ps->hdocs = hdocs;
- ps->eclen = eclen;
- ps->ecused = ecused;
- ps->ecnpats = ecnpats;
- ps->ecbuf = ecbuf;
- ps->ecstrs = ecstrs;
- ps->ecsoffs = ecsoffs;
- ps->ecssub = ecssub;
- ps->ecnfunc = ecnfunc;
- ecbuf = NULL;
- hdocs = NULL;
-}
-
-/* restore parse context */
-
-/**/
-void
-parse_context_restore(const struct parse_stack *ps, int toplevel)
-{
- (void)toplevel;
-
- if (ecbuf)
- zfree(ecbuf, eclen);
-
- incmdpos = ps->incmdpos;
- aliasspaceflag = ps->aliasspaceflag;
- incond = ps->incond;
- inredir = ps->inredir;
- incasepat = ps->incasepat;
- isnewlin = ps->isnewlin;
- infor = ps->infor;
- inrepeat_ = ps->inrepeat_;
- intypeset = ps->intypeset;
-
- hdocs = ps->hdocs;
- eclen = ps->eclen;
- ecused = ps->ecused;
- ecnpats = ps->ecnpats;
- ecbuf = ps->ecbuf;
- ecstrs = ps->ecstrs;
- ecsoffs = ps->ecsoffs;
- ecssub = ps->ecssub;
- ecnfunc = ps->ecnfunc;
-
- errflag &= ~ERRFLAG_ERROR;
-}
-
-/* Adjust pointers in here-doc structs. */
-
-static void
-ecadjusthere(int p, int d)
-{
- struct heredocs *h;
-
- for (h = hdocs; h; h = h->next)
- if (h->pc >= p)
- h->pc += d;
-}
-
-/* Insert n free code-slots at position p. */
-
-static void
-ecispace(int p, int n)
-{
- int m;
-
- if ((eclen - ecused) < n) {
- int a = (eclen < EC_DOUBLE_THRESHOLD ? eclen : EC_INCREMENT);
-
- if (n > a) a = n;
-
- ecbuf = (Wordcode) zrealloc((char *) ecbuf, (eclen + a) * sizeof(wordcode));
- eclen += a;
- }
- if ((m = ecused - p) > 0)
- memmove(ecbuf + p + n, ecbuf + p, m * sizeof(wordcode));
- ecused += n;
- ecadjusthere(p, n);
-}
-
-/* Add one wordcode. */
-
-static int
-ecadd(wordcode c)
-{
- if ((eclen - ecused) < 1) {
- int a = (eclen < EC_DOUBLE_THRESHOLD ? eclen : EC_INCREMENT);
-
- ecbuf = (Wordcode) zrealloc((char *) ecbuf, (eclen + a) * sizeof(wordcode));
- eclen += a;
- }
- ecbuf[ecused] = c;
-
- return ecused++;
-}
-
-/* Delete a wordcode. */
-
-static void
-ecdel(int p)
-{
- int n = ecused - p - 1;
-
- if (n > 0)
- memmove(ecbuf + p, ecbuf + p + 1, n * sizeof(wordcode));
- ecused--;
- ecadjusthere(p, -1);
-}
-
-/* Build the wordcode for a string. */
-
-static wordcode
-ecstrcode(char *s)
-{
- int l, t;
-
- unsigned val = hasher(s);
-
- if ((l = strlen(s) + 1) && l <= 4) {
- t = has_token(s);
- wordcode c = (t ? 3 : 2);
- switch (l) {
- case 4: c |= ((wordcode) STOUC(s[2])) << 19;
- case 3: c |= ((wordcode) STOUC(s[1])) << 11;
- case 2: c |= ((wordcode) STOUC(s[0])) << 3; break;
- case 1: c = (t ? 7 : 6); break;
- }
- return c;
- } else {
- Eccstr p, *pp;
- int cmp;
-
- for (pp = &ecstrs; (p = *pp); ) {
- if (!(cmp = p->nfunc - ecnfunc) && !(cmp = (((signed)p->hashval) - ((signed)val))) && !(cmp = strcmp(p->str, s))) {
- return p->offs;
- }
- pp = (cmp < 0 ? &(p->left) : &(p->right));
- }
-
- t = has_token(s);
-
- p = *pp = (Eccstr) zhalloc(sizeof(*p));
- p->left = p->right = 0;
- p->offs = ((ecsoffs - ecssub) << 2) | (t ? 1 : 0);
- p->aoffs = ecsoffs;
- p->str = s;
- p->nfunc = ecnfunc;
- p->hashval = val;
- ecsoffs += l;
-
- return p->offs;
- }
-}
-
-#define ecstr(S) ecadd(ecstrcode(S))
-
-#define par_save_list(C) \
- do { \
- int eu = ecused; \
- par_list(C); \
- if (eu == ecused) ecadd(WCB_END()); \
- } while (0)
-#define par_save_list1(C) \
- do { \
- int eu = ecused; \
- par_list1(C); \
- if (eu == ecused) ecadd(WCB_END()); \
- } while (0)
-
-
-/**/
-mod_export void
-init_parse_status(void)
-{
- /*
- * These variables are currently declared by the parser, so we
- * initialise them here. Possibly they are more naturally declared
- * by the lexical anaylser; however, as they are used for signalling
- * between the two it's a bit ambiguous. We clear them when
- * using the lexical analyser for strings as well as here.
- */
- incasepat = incond = inredir = infor = intypeset = 0;
- inrepeat_ = 0;
- incmdpos = 1;
-}
-
-/* Initialise wordcode buffer. */
-
-/**/
-void
-init_parse(void)
-{
- queue_signals();
-
- if (ecbuf) zfree(ecbuf, eclen);
-
- ecbuf = (Wordcode) zalloc((eclen = EC_INIT_SIZE) * sizeof(wordcode));
- ecused = 0;
- ecstrs = NULL;
- ecsoffs = ecnpats = 0;
- ecssub = 0;
- ecnfunc = 0;
-
- init_parse_status();
-
- unqueue_signals();
-}
-
-/* Build eprog. */
-
-/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */
-
-static void
-copy_ecstr(Eccstr s, char *p)
-{
- while (s) {
- memcpy(p + s->aoffs, s->str, strlen(s->str) + 1);
- copy_ecstr(s->left, p);
- s = s->right;
- }
-}
-
-static Eprog
-bld_eprog(int heap)
-{
- Eprog ret;
- int l;
-
- queue_signals();
-
- ecadd(WCB_END());
-
- ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret));
- ret->len = ((ecnpats * sizeof(Patprog)) +
- (ecused * sizeof(wordcode)) +
- ecsoffs);
- ret->npats = ecnpats;
- ret->nref = heap ? -1 : 1;
- ret->pats = heap ? (Patprog *) zhalloc(ret->len) :
- (Patprog *) zshcalloc(ret->len);
- ret->prog = (Wordcode) (ret->pats + ecnpats);
- ret->strs = (char *) (ret->prog + ecused);
- ret->shf = NULL;
- ret->flags = heap ? EF_HEAP : EF_REAL;
- ret->dump = NULL;
- for (l = 0; l < ecnpats; l++)
- ret->pats[l] = dummy_patprog1;
- memcpy(ret->prog, ecbuf, ecused * sizeof(wordcode));
- copy_ecstr(ecstrs, ret->strs);
-
- zfree(ecbuf, eclen);
- ecbuf = NULL;
-
- unqueue_signals();
-
- return ret;
-}
-
-/**/
-mod_export int
-empty_eprog(Eprog p)
-{
- return (!p || !p->prog || *p->prog == WCB_END());
-}
-
-static void
-clear_hdocs(void)
-{
- struct heredocs *p, *n;
-
- for (p = hdocs; p; p = n) {
- n = p->next;
- zfree(p, sizeof(struct heredocs));
- }
- hdocs = NULL;
-}
-
-/*
- * event : ENDINPUT
- * | SEPER
- * | sublist [ SEPER | AMPER | AMPERBANG ]
- *
- * cmdsubst indicates our event is part of a command-style
- * substitution terminated by the token indicationg, usual closing
- * parenthesis. In other cases endtok is ENDINPUT.
- */
-
-/**/
-Eprog
-parse_event(int endtok)
-{
- tok = ENDINPUT;
- incmdpos = 1;
- aliasspaceflag = 0;
- zshlex();
- init_parse();
-
- if (!par_event(endtok)) {
- clear_hdocs();
- return NULL;
- }
- if (endtok != ENDINPUT) {
- /* don't need to build an eprog for this */
- return &dummy_eprog;
- }
- return bld_eprog(1);
-}
-
-/**/
-int
-par_event(int endtok)
-{
- int r = 0, p, c = 0;
-
- while (tok == SEPER) {
- if (isnewlin > 0 && endtok == ENDINPUT)
- return 0;
- zshlex();
- }
- if (tok == ENDINPUT)
- return 0;
- if (tok == endtok)
- return 1;
-
- p = ecadd(0);
-
- if (par_sublist(&c)) {
- if (tok == ENDINPUT || tok == endtok) {
- set_list_code(p, Z_SYNC, c);
- r = 1;
- } else if (tok == SEPER) {
- set_list_code(p, Z_SYNC, c);
- if (isnewlin <= 0 || endtok != ENDINPUT)
- zshlex();
- r = 1;
- } else if (tok == AMPER) {
- set_list_code(p, Z_ASYNC, c);
- zshlex();
- r = 1;
- } else if (tok == AMPERBANG) {
- set_list_code(p, (Z_ASYNC | Z_DISOWN), c);
- zshlex();
- r = 1;
- }
- }
- if (!r) {
- tok = LEXERR;
- if (errflag) {
- yyerror(0);
- ecused--;
- return 0;
- }
- yyerror(1);
- herrflush();
- if (noerrs != 2)
- errflag |= ERRFLAG_ERROR;
- ecused--;
- return 0;
- } else {
- int oec = ecused;
-
- if (!par_event(endtok)) {
- ecused = oec;
- ecbuf[p] |= wc_bdata(Z_END);
- return errflag ? 0 : 1;
- }
- }
- return 1;
-}
-
-/**/
-mod_export Eprog
-parse_list(void)
-{
- int c = 0;
-
- tok = ENDINPUT;
- init_parse();
- zshlex();
- par_list(&c);
- if (tok != ENDINPUT) {
- clear_hdocs();
- tok = LEXERR;
- yyerror(0);
- return NULL;
- }
- return bld_eprog(1);
-}
-
-/*
- * This entry point is only used for bin_test, our attempt to
- * provide compatibility with /bin/[ and /bin/test. Hence
- * at this point condlex should always be set to testlex.
- */
-
-/**/
-mod_export Eprog
-parse_cond(void)
-{
- init_parse();
-
- if (!par_cond()) {
- clear_hdocs();
- return NULL;
- }
- return bld_eprog(1);
-}
-
-/* This adds a list wordcode. The important bit about this is that it also
- * tries to optimise this to a Z_SIMPLE list code. */
-
-/**/
-static void
-set_list_code(int p, int type, int cmplx)
-{
- if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
- WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) {
- int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE);
- ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p);
- ecdel(p + 1);
- if (ispipe)
- ecbuf[p + 1] = WC_PIPE_LINENO(ecbuf[p + 1]);
- } else
- ecbuf[p] = WCB_LIST(type, 0);
-}
-
-/* The same for sublists. */
-
-/**/
-static void
-set_sublist_code(int p, int type, int flags, int skip, int cmplx)
-{
- if (cmplx)
- ecbuf[p] = WCB_SUBLIST(type, flags, skip);
- else {
- ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip);
- ecbuf[p + 1] = WC_PIPE_LINENO(ecbuf[p + 1]);
- }
-}
-
-/*
- * list : { SEPER } [ sublist [ { SEPER | AMPER | AMPERBANG } list ] ]
- */
-
-/**/
-static void
-par_list(int *cmplx)
-{
- int p, lp = -1, c;
-
- rec:
-
- while (tok == SEPER)
- zshlex();
-
- p = ecadd(0);
- c = 0;
-
- if (par_sublist(&c)) {
- *cmplx |= c;
- if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
- if (tok != SEPER)
- *cmplx = 1;
- set_list_code(p, ((tok == SEPER) ? Z_SYNC :
- (tok == AMPER) ? Z_ASYNC :
- (Z_ASYNC | Z_DISOWN)), c);
- incmdpos = 1;
- do {
- zshlex();
- } while (tok == SEPER);
- lp = p;
- goto rec;
- } else
- set_list_code(p, (Z_SYNC | Z_END), c);
- } else {
- ecused--;
- if (lp >= 0)
- ecbuf[lp] |= wc_bdata(Z_END);
- }
-}
-
-/**/
-static void
-par_list1(int *cmplx)
-{
- int p = ecadd(0), c = 0;
-
- if (par_sublist(&c)) {
- set_list_code(p, (Z_SYNC | Z_END), c);
- *cmplx |= c;
- } else
- ecused--;
-}
-
-/*
- * sublist : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ]
- */
-
-/**/
-static int
-par_sublist(int *cmplx)
-{
- int f, p, c = 0;
-
- p = ecadd(0);
-
- if ((f = par_sublist2(&c)) != -1) {
- int e = ecused;
-
- *cmplx |= c;
- if (tok == DBAR || tok == DAMPER) {
- enum lextok qtok = tok;
- int sl;
-
- cmdpush(tok == DBAR ? CS_CMDOR : CS_CMDAND);
- zshlex();
- while (tok == SEPER)
- zshlex();
- sl = par_sublist(cmplx);
- set_sublist_code(p, (sl ? (qtok == DBAR ?
- WC_SUBLIST_OR : WC_SUBLIST_AND) :
- WC_SUBLIST_END),
- f, (e - 1 - p), c);
- cmdpop();
- } else {
- if (tok == AMPER || tok == AMPERBANG) {
- c = 1;
- *cmplx |= c;
- }
- set_sublist_code(p, WC_SUBLIST_END, f, (e - 1 - p), c);
- }
- return 1;
- } else {
- ecused--;
- return 0;
- }
-}
-
-/*
- * sublist2 : [ COPROC | BANG ] pline
- */
-
-/**/
-static int
-par_sublist2(int *cmplx)
-{
- int f = 0;
-
- if (tok == COPROC) {
- *cmplx = 1;
- f |= WC_SUBLIST_COPROC;
- zshlex();
- } else if (tok == BANG) {
- *cmplx = 1;
- f |= WC_SUBLIST_NOT;
- zshlex();
- }
- if (!par_pline(cmplx) && !f)
- return -1;
-
- return f;
-}
-
-/*
- * pline : cmd [ ( BAR | BARAMP ) { SEPER } pline ]
- */
-
-/**/
-static int
-par_pline(int *cmplx)
-{
- int p;
- zlong line = toklineno;
-
- p = ecadd(0);
-
- if (!par_cmd(cmplx, 0)) {
- ecused--;
- return 0;
- }
- if (tok == BAR) {
- *cmplx = 1;
- cmdpush(CS_PIPE);
- zshlex();
- while (tok == SEPER)
- zshlex();
- ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
- ecispace(p + 1, 1);
- ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(cmplx)) {
- tok = LEXERR;
- }
- cmdpop();
- return 1;
- } else if (tok == BARAMP) {
- int r;
-
- for (r = p + 1; wc_code(ecbuf[r]) == WC_REDIR;
- r += WC_REDIR_WORDS(ecbuf[r]));
-
- ecispace(r, 3);
- ecbuf[r] = WCB_REDIR(REDIR_MERGEOUT);
- ecbuf[r + 1] = 2;
- ecbuf[r + 2] = ecstrcode("1");
-
- *cmplx = 1;
- cmdpush(CS_ERRPIPE);
- zshlex();
- while (tok == SEPER)
- zshlex();
- ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
- ecispace(p + 1, 1);
- ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(cmplx)) {
- tok = LEXERR;
- }
- cmdpop();
- return 1;
- } else {
- ecbuf[p] = WCB_PIPE(WC_PIPE_END, (line >= 0 ? line + 1 : 0));
- return 1;
- }
-}
-
-/*
- * cmd : { redir } ( for | case | if | while | repeat |
- * subsh | funcdef | time | dinbrack | dinpar | simple ) { redir }
- *
- * zsh_construct is passed through to par_subsh(), q.v.
- */
-
-/**/
-static int
-par_cmd(int *cmplx, int zsh_construct)
-{
- int r, nr = 0;
-
- r = ecused;
-
- if (IS_REDIROP(tok)) {
- *cmplx = 1;
- while (IS_REDIROP(tok)) {
- nr += par_redir(&r, NULL);
- }
- }
- switch (tok) {
- case FOR:
- cmdpush(CS_FOR);
- par_for(cmplx);
- cmdpop();
- break;
- case FOREACH:
- cmdpush(CS_FOREACH);
- par_for(cmplx);
- cmdpop();
- break;
- case SELECT:
- *cmplx = 1;
- cmdpush(CS_SELECT);
- par_for(cmplx);
- cmdpop();
- break;
- case CASE:
- cmdpush(CS_CASE);
- par_case(cmplx);
- cmdpop();
- break;
- case IF:
- par_if(cmplx);
- break;
- case WHILE:
- cmdpush(CS_WHILE);
- par_while(cmplx);
- cmdpop();
- break;
- case UNTIL:
- cmdpush(CS_UNTIL);
- par_while(cmplx);
- cmdpop();
- break;
- case REPEAT:
- cmdpush(CS_REPEAT);
- par_repeat(cmplx);
- cmdpop();
- break;
- case INPAR:
- *cmplx = 1;
- cmdpush(CS_SUBSH);
- par_subsh(cmplx, zsh_construct);
- cmdpop();
- break;
- case INBRACE:
- cmdpush(CS_CURSH);
- par_subsh(cmplx, zsh_construct);
- cmdpop();
- break;
- case FUNC:
- cmdpush(CS_FUNCDEF);
- par_funcdef(cmplx);
- cmdpop();
- break;
- case DINBRACK:
- cmdpush(CS_COND);
- par_dinbrack();
- cmdpop();
- break;
- case DINPAR:
- ecadd(WCB_ARITH());
- ecstr(tokstr);
- zshlex();
- break;
- case TIME:
- {
- static int inpartime = 0;
-
- if (!inpartime) {
- *cmplx = 1;
- inpartime = 1;
- par_time();
- inpartime = 0;
- break;
- }
- }
- tok = STRING;
- /* fall through */
- default:
- {
- int sr;
-
- if (!(sr = par_simple(cmplx, nr))) {
- if (!nr)
- return 0;
- } else {
- /* Take account of redirections */
- if (sr > 1) {
- *cmplx = 1;
- r += sr - 1;
- }
- }
- }
- break;
- }
- if (IS_REDIROP(tok)) {
- *cmplx = 1;
- while (IS_REDIROP(tok))
- (void)par_redir(&r, NULL);
- }
- incmdpos = 1;
- incasepat = 0;
- incond = 0;
- intypeset = 0;
- return 1;
-}
-
-/*
- * for : ( FOR DINPAR expr SEMI expr SEMI expr DOUTPAR |
- * ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR ) )
- * { SEPER } ( DO list DONE | INBRACE list OUTBRACE | list ZEND | list1 )
- */
-
-/**/
-static void
-par_for(int *cmplx)
-{
- int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT);
- int type;
-
- p = ecadd(0);
-
- incmdpos = 0;
- infor = tok == FOR ? 2 : 0;
- zshlex();
- if (tok == DINPAR) {
- zshlex();
- if (tok != DINPAR)
- YYERRORV(oecused);
- ecstr(tokstr);
- zshlex();
- if (tok != DINPAR)
- YYERRORV(oecused);
- ecstr(tokstr);
- zshlex();
- if (tok != DOUTPAR)
- YYERRORV(oecused);
- ecstr(tokstr);
- infor = 0;
- incmdpos = 1;
- zshlex();
- type = WC_FOR_COND;
- } else {
- int np = 0, n, posix_in, ona = noaliases, onc = nocorrect;
- infor = 0;
- if (tok != STRING || !isident(tokstr))
- YYERRORV(oecused);
- if (!sel)
- np = ecadd(0);
- n = 0;
- incmdpos = 1;
- noaliases = nocorrect = 1;
- for (;;) {
- n++;
- ecstr(tokstr);
- zshlex();
- if (tok != STRING || !strcmp(tokstr, "in") || sel)
- break;
- if (!isident(tokstr) || errflag)
- {
- noaliases = ona;
- nocorrect = onc;
- YYERRORV(oecused);
- }
- }
- noaliases = ona;
- nocorrect = onc;
- if (!sel)
- ecbuf[np] = n;
- posix_in = isnewlin;
- while (isnewlin)
- zshlex();
- if (tok == STRING && !strcmp(tokstr, "in")) {
- incmdpos = 0;
- zshlex();
- np = ecadd(0);
- n = par_wordlist();
- if (tok != SEPER)
- YYERRORV(oecused);
- ecbuf[np] = n;
- type = (sel ? WC_SELECT_LIST : WC_FOR_LIST);
- } else if (!posix_in && tok == INPAR) {
- incmdpos = 0;
- zshlex();
- np = ecadd(0);
- n = par_nl_wordlist();
- if (tok != OUTPAR)
- YYERRORV(oecused);
- ecbuf[np] = n;
- incmdpos = 1;
- zshlex();
- type = (sel ? WC_SELECT_LIST : WC_FOR_LIST);
- } else
- type = (sel ? WC_SELECT_PPARAM : WC_FOR_PPARAM);
- }
- incmdpos = 1;
- while (tok == SEPER)
- zshlex();
- if (tok == DOLOOP) {
- zshlex();
- par_save_list(cmplx);
- if (tok != DONE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (tok == INBRACE) {
- zshlex();
- par_save_list(cmplx);
- if (tok != OUTBRACE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (csh || isset(CSHJUNKIELOOPS)) {
- par_save_list(cmplx);
- if (tok != ZEND)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (unset(SHORTLOOPS)) {
- YYERRORV(oecused);
- } else
- par_save_list1(cmplx);
-
- ecbuf[p] = (sel ?
- WCB_SELECT(type, ecused - 1 - p) :
- WCB_FOR(type, ecused - 1 - p));
-}
-
-/*
- * case : CASE STRING { SEPER } ( "in" | INBRACE )
- { { SEPER } STRING { BAR STRING } OUTPAR
- list [ DSEMI | SEMIAMP | SEMIBAR ] }
- { SEPER } ( "esac" | OUTBRACE )
- */
-
-/**/
-static void
-par_case(int *cmplx)
-{
- int oecused = ecused, brflag, p, pp, palts, type, nalts;
- int ona, onc;
-
- p = ecadd(0);
-
- incmdpos = 0;
- zshlex();
- if (tok != STRING)
- YYERRORV(oecused);
- ecstr(tokstr);
-
- incmdpos = 1;
- ona = noaliases;
- onc = nocorrect;
- noaliases = nocorrect = 1;
- zshlex();
- while (tok == SEPER)
- zshlex();
- if (!(tok == STRING && !strcmp(tokstr, "in")) && tok != INBRACE)
- {
- noaliases = ona;
- nocorrect = onc;
- YYERRORV(oecused);
- }
- brflag = (tok == INBRACE);
- incasepat = 1;
- incmdpos = 0;
- noaliases = ona;
- nocorrect = onc;
- zshlex();
-
- for (;;) {
- char *str;
- int skip_zshlex;
-
- while (tok == SEPER)
- zshlex();
- if (tok == OUTBRACE)
- break;
- if (tok == INPAR)
- zshlex();
- if (tok == BAR) {
- str = dupstring("");
- skip_zshlex = 1;
- } else {
- if (tok != STRING)
- YYERRORV(oecused);
- if (!strcmp(tokstr, "esac"))
- break;
- str = dupstring(tokstr);
- skip_zshlex = 0;
- }
- type = WC_CASE_OR;
- pp = ecadd(0);
- palts = ecadd(0);
- nalts = 0;
- /*
- * Hack here.
- *
- * [Pause for astonished hubbub to subside.]
- *
- * The next token we get may be
- * - ")" or "|" if we're looking at an honest-to-god
- * "case" pattern, either because there's no opening
- * parenthesis, or because SH_GLOB is set and we
- * managed to grab an initial "(" to mark the start
- * of the case pattern.
- * - Something else --- we don't care what --- because
- * we're parsing a complete "(...)" as a complete
- * zsh pattern. In that case, we treat this as a
- * single instance of a case pattern but we pretend
- * we're doing proper case parsing --- in which the
- * parentheses and bar are in different words from
- * the string, so may be separated by whitespace.
- * So we quietly massage the whitespace and hope
- * no one noticed. This is horrible, but it's
- * unfortunately too difficult to combine traditional
- * zsh patterns with a properly parsed case pattern
- * without generating incompatibilities which aren't
- * all that popular (I've discovered).
- * - We can also end up with something other than ")" or "|"
- * just because we're looking at garbage.
- *
- * Because of the second case, what happens next might
- * be the start of the command after the pattern, so we
- * need to treat it as in command position. Luckily
- * this doesn't affect our ability to match a | or ) as
- * these are valid on command lines.
- */
- incasepat = -1;
- incmdpos = 1;
- if (!skip_zshlex)
- zshlex();
- for (;;) {
- if (tok == OUTPAR) {
- ecstr(str);
- ecadd(ecnpats++);
- nalts++;
-
- incasepat = 0;
- incmdpos = 1;
- zshlex();
- break;
- } else if (tok == BAR) {
- ecstr(str);
- ecadd(ecnpats++);
- nalts++;
-
- incasepat = 1;
- incmdpos = 0;
- } else {
- if (!nalts && str[0] == Inpar) {
- int pct = 0, sl;
- char *s;
-
- for (s = str; *s; s++) {
- if (*s == Inpar)
- pct++;
- if (!pct)
- break;
- if (pct == 1) {
- if (*s == Bar || *s == Inpar)
- while (iblank(s[1]))
- chuck(s+1);
- if (*s == Bar || *s == Outpar)
- while (iblank(s[-1]) &&
- (s < str + 1 || s[-2] != Meta))
- chuck(--s);
- }
- if (*s == Outpar)
- pct--;
- }
- if (*s || pct || s == str)
- YYERRORV(oecused);
- /* Simplify pattern by removing surrounding (...) */
- sl = strlen(str);
- DPUTS(*str != Inpar || str[sl - 1] != Outpar,
- "BUG: strange case pattern");
- str[sl - 1] = '\0';
- chuck(str);
- ecstr(str);
- ecadd(ecnpats++);
- nalts++;
- break;
- }
- YYERRORV(oecused);
- }
-
- zshlex();
- switch (tok) {
- case STRING:
- /* Normal case */
- str = dupstring(tokstr);
- zshlex();
- break;
-
- case OUTPAR:
- case BAR:
- /* Empty string */
- str = dupstring("");
- break;
-
- default:
- /* Oops. */
- YYERRORV(oecused);
- break;
- }
- }
- incasepat = 0;
- par_save_list(cmplx);
- if (tok == SEMIAMP)
- type = WC_CASE_AND;
- else if (tok == SEMIBAR)
- type = WC_CASE_TESTAND;
- ecbuf[pp] = WCB_CASE(type, ecused - 1 - pp);
- ecbuf[palts] = nalts;
- if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag))
- break;
- if (tok != DSEMI && tok != SEMIAMP && tok != SEMIBAR)
- YYERRORV(oecused);
- incasepat = 1;
- incmdpos = 0;
- zshlex();
- }
- incmdpos = 1;
- incasepat = 0;
- zshlex();
-
- ecbuf[p] = WCB_CASE(WC_CASE_HEAD, ecused - 1 - p);
-}
-
-/*
- * if : { ( IF | ELIF ) { SEPER } ( INPAR list OUTPAR | list )
- { SEPER } ( THEN list | INBRACE list OUTBRACE | list1 ) }
- [ FI | ELSE list FI | ELSE { SEPER } INBRACE list OUTBRACE ]
- (you get the idea...?)
- */
-
-/**/
-static void
-par_if(int *cmplx)
-{
- int oecused = ecused, p, pp, type, usebrace = 0;
- enum lextok xtok;
- unsigned char nc;
-
- p = ecadd(0);
-
- for (;;) {
- xtok = tok;
- cmdpush(xtok == IF ? CS_IF : CS_ELIF);
- if (xtok == FI) {
- incmdpos = 0;
- zshlex();
- break;
- }
- zshlex();
- if (xtok == ELSE)
- break;
- while (tok == SEPER)
- zshlex();
- if (!(xtok == IF || xtok == ELIF)) {
- cmdpop();
- YYERRORV(oecused);
- }
- pp = ecadd(0);
- type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF);
- par_save_list(cmplx);
- incmdpos = 1;
- if (tok == ENDINPUT) {
- cmdpop();
- YYERRORV(oecused);
- }
- while (tok == SEPER)
- zshlex();
- xtok = FI;
- nc = cmdstack[cmdsp - 1] == CS_IF ? CS_IFTHEN : CS_ELIFTHEN;
- if (tok == THEN) {
- usebrace = 0;
- cmdpop();
- cmdpush(nc);
- zshlex();
- par_save_list(cmplx);
- ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
- incmdpos = 1;
- cmdpop();
- } else if (tok == INBRACE) {
- usebrace = 1;
- cmdpop();
- cmdpush(nc);
- zshlex();
- par_save_list(cmplx);
- if (tok != OUTBRACE) {
- cmdpop();
- YYERRORV(oecused);
- }
- ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
- /* command word (else) allowed to follow immediately */
- zshlex();
- incmdpos = 1;
- if (tok == SEPER)
- break;
- cmdpop();
- } else if (unset(SHORTLOOPS)) {
- cmdpop();
- YYERRORV(oecused);
- } else {
- cmdpop();
- cmdpush(nc);
- par_save_list1(cmplx);
- ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
- incmdpos = 1;
- break;
- }
- }
- cmdpop();
- if (xtok == ELSE || tok == ELSE) {
- pp = ecadd(0);
- cmdpush(CS_ELSE);
- while (tok == SEPER)
- zshlex();
- if (tok == INBRACE && usebrace) {
- zshlex();
- par_save_list(cmplx);
- if (tok != OUTBRACE) {
- cmdpop();
- YYERRORV(oecused);
- }
- } else {
- par_save_list(cmplx);
- if (tok != FI) {
- cmdpop();
- YYERRORV(oecused);
- }
- }
- incmdpos = 0;
- ecbuf[pp] = WCB_IF(WC_IF_ELSE, ecused - 1 - pp);
- zshlex();
- cmdpop();
- }
- ecbuf[p] = WCB_IF(WC_IF_HEAD, ecused - 1 - p);
-}
-
-/*
- * while : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER }
- ( DO list DONE | INBRACE list OUTBRACE | list ZEND )
- */
-
-/**/
-static void
-par_while(int *cmplx)
-{
- int oecused = ecused, p;
- int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE);
-
- p = ecadd(0);
- zshlex();
- par_save_list(cmplx);
- incmdpos = 1;
- while (tok == SEPER)
- zshlex();
- if (tok == DOLOOP) {
- zshlex();
- par_save_list(cmplx);
- if (tok != DONE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (tok == INBRACE) {
- zshlex();
- par_save_list(cmplx);
- if (tok != OUTBRACE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(cmplx);
- if (tok != ZEND)
- YYERRORV(oecused);
- zshlex();
- } else if (unset(SHORTLOOPS)) {
- YYERRORV(oecused);
- } else
- par_save_list1(cmplx);
-
- ecbuf[p] = WCB_WHILE(type, ecused - 1 - p);
-}
-
-/*
- * repeat : REPEAT STRING { SEPER } ( DO list DONE | list1 )
- */
-
-/**/
-static void
-par_repeat(int *cmplx)
-{
- /* ### what to do about inrepeat_ here? */
- int oecused = ecused, p;
-
- p = ecadd(0);
-
- incmdpos = 0;
- zshlex();
- if (tok != STRING)
- YYERRORV(oecused);
- ecstr(tokstr);
- incmdpos = 1;
- zshlex();
- while (tok == SEPER)
- zshlex();
- if (tok == DOLOOP) {
- zshlex();
- par_save_list(cmplx);
- if (tok != DONE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (tok == INBRACE) {
- zshlex();
- par_save_list(cmplx);
- if (tok != OUTBRACE)
- YYERRORV(oecused);
- incmdpos = 0;
- zshlex();
- } else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(cmplx);
- if (tok != ZEND)
- YYERRORV(oecused);
- zshlex();
- } else if (unset(SHORTLOOPS)) {
- YYERRORV(oecused);
- } else
- par_save_list1(cmplx);
-
- ecbuf[p] = WCB_REPEAT(ecused - 1 - p);
-}
-
-/*
- * subsh : INPAR list OUTPAR |
- * INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ]
- *
- * With zsh_construct non-zero, we're doing a zsh special in which
- * the following token is not considered in command position. This
- * is used for arguments of anonymous functions.
- */
-
-/**/
-static void
-par_subsh(int *cmplx, int zsh_construct)
-{
- enum lextok otok = tok;
- int oecused = ecused, p, pp;
-
- p = ecadd(0);
- /* Extra word only needed for always block */
- pp = ecadd(0);
- zshlex();
- par_list(cmplx);
- ecadd(WCB_END());
- if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE))
- YYERRORV(oecused);
- incmdpos = !zsh_construct;
- zshlex();
-
- /* Optional always block. No intervening SEPERs allowed. */
- if (otok == INBRACE && tok == STRING && !strcmp(tokstr, "always")) {
- ecbuf[pp] = WCB_TRY(ecused - 1 - pp);
- incmdpos = 1;
- do {
- zshlex();
- } while (tok == SEPER);
-
- if (tok != INBRACE)
- YYERRORV(oecused);
- cmdpop();
- cmdpush(CS_ALWAYS);
-
- zshlex();
- par_save_list(cmplx);
- while (tok == SEPER)
- zshlex();
-
- incmdpos = 1;
-
- if (tok != OUTBRACE)
- YYERRORV(oecused);
- zshlex();
- ecbuf[p] = WCB_TRY(ecused - 1 - p);
- } else {
- ecbuf[p] = (otok == INPAR ? WCB_SUBSH(ecused - 1 - p) :
- WCB_CURSH(ecused - 1 - p));
- }
-}
-
-/*
- * funcdef : FUNCTION wordlist [ INOUTPAR ] { SEPER }
- * ( list1 | INBRACE list OUTBRACE )
- */
-
-/**/
-static void
-par_funcdef(int *cmplx)
-{
- int oecused = ecused, num = 0, onp, p, c = 0;
- int so, oecssub = ecssub;
- zlong oldlineno = lineno;
-
- lineno = 0;
- nocorrect = 1;
- incmdpos = 0;
- zshlex();
-
- p = ecadd(0);
- ecadd(0);
-
- while (tok == STRING) {
- if ((*tokstr == Inbrace || *tokstr == '{') &&
- !tokstr[1]) {
- tok = INBRACE;
- break;
- }
- ecstr(tokstr);
- num++;
- zshlex();
- }
- ecadd(0);
- ecadd(0);
- ecadd(0);
-
- nocorrect = 0;
- incmdpos = 1;
- if (tok == INOUTPAR)
- zshlex();
- while (tok == SEPER)
- zshlex();
-
- ecnfunc++;
- ecssub = so = ecsoffs;
- onp = ecnpats;
- ecnpats = 0;
-
- if (tok == INBRACE) {
- zshlex();
- par_list(&c);
- if (tok != OUTBRACE) {
- lineno += oldlineno;
- ecnpats = onp;
- ecssub = oecssub;
- YYERRORV(oecused);
- }
- if (num == 0) {
- /* Anonymous function, possibly with arguments */
- incmdpos = 0;
- }
- zshlex();
- } else if (unset(SHORTLOOPS)) {
- lineno += oldlineno;
- ecnpats = onp;
- ecssub = oecssub;
- YYERRORV(oecused);
- } else
- par_list1(&c);
-
- ecadd(WCB_END());
- ecbuf[p + num + 2] = so - oecssub;
- ecbuf[p + num + 3] = ecsoffs - so;
- ecbuf[p + num + 4] = ecnpats;
- ecbuf[p + 1] = num;
-
- ecnpats = onp;
- ecssub = oecssub;
- ecnfunc++;
-
- ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
-
- if (num == 0) {
- /* Unnamed function */
- int parg = ecadd(0);
- ecadd(0);
- while (tok == STRING) {
- ecstr(tokstr);
- num++;
- zshlex();
- }
- if (num > 0)
- *cmplx = 1;
- ecbuf[parg] = ecused - parg; /*?*/
- ecbuf[parg+1] = num;
- }
- lineno += oldlineno;
-}
-
-/*
- * time : TIME sublist2
- */
-
-/**/
-static void
-par_time(void)
-{
- int p, f, c = 0;
-
- zshlex();
-
- p = ecadd(0);
- ecadd(0);
- if ((f = par_sublist2(&c)) < 0) {
- ecused--;
- ecbuf[p] = WCB_TIMED(WC_TIMED_EMPTY);
- } else {
- ecbuf[p] = WCB_TIMED(WC_TIMED_PIPE);
- set_sublist_code(p + 1, WC_SUBLIST_END, f, ecused - 2 - p, c);
- }
-}
-
-/*
- * dinbrack : DINBRACK cond DOUTBRACK
- */
-
-/**/
-static void
-par_dinbrack(void)
-{
- int oecused = ecused;
-
- incond = 1;
- incmdpos = 0;
- zshlex();
- par_cond();
- if (tok != DOUTBRACK)
- YYERRORV(oecused);
- incond = 0;
- incmdpos = 1;
- zshlex();
-}
-
-/*
- * simple : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH }
- { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir }
- [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ]
- *
- * Returns 0 if no code, else 1 plus the number of code words
- * used up by redirections.
- */
-
-/**/
-static int
-par_simple(int *cmplx, int nr)
-{
- int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
- int c = *cmplx, nrediradd, assignments = 0, ppost = 0, is_typeset = 0;
- char *hasalias = input_hasalias();
- wordcode postassigns = 0;
-
- r = ecused;
- for (;;) {
- if (tok == NOCORRECT) {
- *cmplx = c = 1;
- nocorrect = 1;
- } else if (tok == ENVSTRING) {
- char *ptr, *name, *str;
-
- name = tokstr;
- for (ptr = tokstr;
- *ptr && *ptr != Inbrack && *ptr != '=' && *ptr != '+';
- ptr++);
- if (*ptr == Inbrack) skipparens(Inbrack, Outbrack, &ptr);
- if (*ptr == '+') {
- *ptr++ = '\0';
- ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0));
- } else
- ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_NEW, 0));
-
- if (*ptr == '=') {
- *ptr = '\0';
- str = ptr + 1;
- } else
- equalsplit(tokstr, &str);
- for (ptr = str; *ptr; ptr++) {
- /*
- * We can't treat this as "simple" if it contains
- * expansions that require process subsitution, since then
- * we need process handling.
- */
- if (ptr[1] == Inpar &&
- (*ptr == Equals || *ptr == Inang || *ptr == OutangProc)) {
- *cmplx = 1;
- break;
- }
- }
- ecstr(name);
- ecstr(str);
- isnull = 0;
- assignments = 1;
- } else if (tok == ENVARRAY) {
- int oldcmdpos = incmdpos, n, type2;
-
- /*
- * We consider array setting cmplx because it can
- * contain process substitutions, which need a valid job.
- */
- *cmplx = c = 1;
- p = ecadd(0);
- incmdpos = 0;
- if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') {
- tokstr[type2] = '\0';
- type2 = WC_ASSIGN_INC;
- } else
- type2 = WC_ASSIGN_NEW;
- ecstr(tokstr);
- cmdpush(CS_ARRAY);
- zshlex();
- n = par_nl_wordlist();
- ecbuf[p] = WCB_ASSIGN(WC_ASSIGN_ARRAY, type2, n);
- cmdpop();
- if (tok != OUTPAR)
- YYERROR(oecused);
- incmdpos = oldcmdpos;
- isnull = 0;
- assignments = 1;
- } else if (IS_REDIROP(tok)) {
- *cmplx = c = 1;
- nr += par_redir(&r, NULL);
- continue;
- } else
- break;
- zshlex();
- if (!hasalias)
- hasalias = input_hasalias();
- }
- if (tok == AMPER || tok == AMPERBANG)
- YYERROR(oecused);
-
- p = ecadd(WCB_SIMPLE(0));
-
- for (;;) {
- if (tok == STRING || tok == TYPESET) {
- int redir_var = 0;
-
- *cmplx = 1;
- incmdpos = 0;
-
- if (tok == TYPESET)
- intypeset = is_typeset = 1;
-
- if (!isset(IGNOREBRACES) && *tokstr == Inbrace)
- {
- /* Look for redirs of the form {var}>file etc. */
- char *eptr = tokstr + strlen(tokstr) - 1;
- char *ptr = eptr;
-
- if (*ptr == Outbrace && ptr > tokstr + 1)
- {
- if (itype_end(tokstr+1, IIDENT, 0) >= ptr)
- {
- char *toksave = tokstr;
- char *idstring = dupstrpfx(tokstr+1, eptr-tokstr-1);
- redir_var = 1;
- zshlex();
- if (!hasalias)
- hasalias = input_hasalias();
-
- if (IS_REDIROP(tok) && tokfd == -1)
- {
- *cmplx = c = 1;
- nrediradd = par_redir(&r, idstring);
- p += nrediradd;
- sr += nrediradd;
- }
- else
- {
- ecstr(toksave);
- argc++;
- }
- }
- }
- }
-
- if (!redir_var)
- {
- if (postassigns) {
- /*
- * We're in the variable part of a typeset,
- * but this doesn't have an assignment.
- * We'll parse it as if it does, but mark
- * it specially with WC_ASSIGN_INC.
- */
- postassigns++;
- ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_INC, 0));
- ecstr(tokstr);
- ecstr(""); /* TBD can possibly optimise out */
- } else {
- ecstr(tokstr);
- argc++;
- }
- zshlex();
- if (!hasalias)
- hasalias = input_hasalias();
- }
- } else if (IS_REDIROP(tok)) {
- *cmplx = c = 1;
- nrediradd = par_redir(&r, NULL);
- p += nrediradd;
- if (ppost)
- ppost += nrediradd;
- sr += nrediradd;
- } else if (tok == ENVSTRING) {
- char *ptr, *name, *str;
-
- if (!postassigns++)
- ppost = ecadd(0);
-
- name = tokstr;
- for (ptr = tokstr; *ptr && *ptr != Inbrack && *ptr != '=' && *ptr != '+';
- ptr++);
- if (*ptr == Inbrack) skipparens(Inbrack, Outbrack, &ptr);
- ecadd(WCB_ASSIGN(WC_ASSIGN_SCALAR, WC_ASSIGN_NEW, 0));
-
- if (*ptr == '=') {
- *ptr = '\0';
- str = ptr + 1;
- } else
- equalsplit(tokstr, &str);
- ecstr(name);
- ecstr(str);
- zshlex();
- if (!hasalias)
- hasalias = input_hasalias();
- } else if (tok == ENVARRAY) {
- int n, parr;
-
- if (!postassigns++)
- ppost = ecadd(0);
-
- parr = ecadd(0);
- ecstr(tokstr);
- cmdpush(CS_ARRAY);
- /*
- * Careful here: this must be the typeset case,
- * but we need to tell the lexer not to look
- * for assignments until we've finished the
- * present one.
- */
- intypeset = 0;
- zshlex();
- n = par_nl_wordlist();
- ecbuf[parr] = WCB_ASSIGN(WC_ASSIGN_ARRAY, WC_ASSIGN_NEW, n);
- cmdpop();
- intypeset = 1;
- if (tok != OUTPAR)
- YYERROR(oecused);
- zshlex();
- } else if (tok == INOUTPAR) {
- zlong oldlineno = lineno;
- int onp, so, oecssub = ecssub;
-
- /* Error if too many function definitions at once */
- if (!isset(MULTIFUNCDEF) && argc > 1)
- YYERROR(oecused);
- /* Error if preceding assignments */
- if (assignments || postassigns)
- YYERROR(oecused);
- if (hasalias && !isset(ALIASFUNCDEF) && argc &&
- hasalias != input_hasalias()) {
- zwarn("defining function based on alias `%s'", hasalias);
- YYERROR(oecused);
- }
-
- *cmplx = c;
- lineno = 0;
- incmdpos = 1;
- cmdpush(CS_FUNCDEF);
- zshlex();
- while (tok == SEPER)
- zshlex();
-
- ecispace(p + 1, 1);
- ecbuf[p + 1] = argc;
- ecadd(0);
- ecadd(0);
- ecadd(0);
-
- ecnfunc++;
- ecssub = so = ecsoffs;
- onp = ecnpats;
- ecnpats = 0;
-
- if (tok == INBRACE) {
- int c = 0;
-
- zshlex();
- par_list(&c);
- if (tok != OUTBRACE) {
- cmdpop();
- lineno += oldlineno;
- ecnpats = onp;
- ecssub = oecssub;
- YYERROR(oecused);
- }
- if (argc == 0) {
- /* Anonymous function, possibly with arguments */
- incmdpos = 0;
- }
- zshlex();
- } else {
- int ll, sl, c = 0;
-
- ll = ecadd(0);
- sl = ecadd(0);
- (void)ecadd(WCB_PIPE(WC_PIPE_END, 0));
-
- if (!par_cmd(&c, argc == 0)) {
- cmdpop();
- YYERROR(oecused);
- }
- if (argc == 0) {
- /*
- * Anonymous function, possibly with arguments.
- * N.B. for cmplx structures in particular
- * ( ... ) we rely on lower level code doing this
- * to get the immediately following word (the
- * first token after the ")" has already been
- * read).
- */
- incmdpos = 0;
- }
-
- set_sublist_code(sl, WC_SUBLIST_END, 0, ecused - 1 - sl, c);
- set_list_code(ll, (Z_SYNC | Z_END), c);
- }
- cmdpop();
-
- ecadd(WCB_END());
- ecbuf[p + argc + 2] = so - oecssub;
- ecbuf[p + argc + 3] = ecsoffs - so;
- ecbuf[p + argc + 4] = ecnpats;
-
- ecnpats = onp;
- ecssub = oecssub;
- ecnfunc++;
-
- ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
-
- if (argc == 0) {
- /* Unnamed function */
- int parg = ecadd(0);
- ecadd(0);
- while (tok == STRING || IS_REDIROP(tok)) {
- if (tok == STRING)
- {
- ecstr(tokstr);
- argc++;
- zshlex();
- } else {
- *cmplx = c = 1;
- nrediradd = par_redir(&r, NULL);
- p += nrediradd;
- if (ppost)
- ppost += nrediradd;
- sr += nrediradd;
- parg += nrediradd;
- }
- }
- if (argc > 0)
- *cmplx = 1;
- ecbuf[parg] = ecused - parg; /*?*/
- ecbuf[parg+1] = argc;
- }
- lineno += oldlineno;
-
- isfunc = 1;
- isnull = 0;
- break;
- } else
- break;
- isnull = 0;
- }
- if (isnull && !(sr + nr)) {
- ecused = p;
- return 0;
- }
- incmdpos = 1;
- intypeset = 0;
-
- if (!isfunc) {
- if (is_typeset) {
- ecbuf[p] = WCB_TYPESET(argc);
- if (postassigns)
- ecbuf[ppost] = postassigns;
- else
- ecadd(0);
- } else
- ecbuf[p] = WCB_SIMPLE(argc);
- }
-
- return sr + 1;
-}
-
-/*
- * redir : ( OUTANG | ... | TRINANG ) STRING
- *
- * Return number of code words required for redirection
- */
-
-static int redirtab[TRINANG - OUTANG + 1] = {
- REDIR_WRITE,
- REDIR_WRITENOW,
- REDIR_APP,
- REDIR_APPNOW,
- REDIR_READ,
- REDIR_READWRITE,
- REDIR_HEREDOC,
- REDIR_HEREDOCDASH,
- REDIR_MERGEIN,
- REDIR_MERGEOUT,
- REDIR_ERRWRITE,
- REDIR_ERRWRITENOW,
- REDIR_ERRAPP,
- REDIR_ERRAPPNOW,
- REDIR_HERESTR,
-};
-
-/**/
-static int
-par_redir(int *rp, char *idstring)
-{
- int r = *rp, type, fd1, oldcmdpos, oldnc, ncodes;
- char *name;
-
- oldcmdpos = incmdpos;
- incmdpos = 0;
- oldnc = nocorrect;
- if (tok != INANG && tok != INOUTANG)
- nocorrect = 1;
- type = redirtab[tok - OUTANG];
- fd1 = tokfd;
- zshlex();
- if (tok != STRING && tok != ENVSTRING)
- YYERROR(ecused);
- incmdpos = oldcmdpos;
- nocorrect = oldnc;
-
- /* assign default fd */
- if (fd1 == -1)
- fd1 = IS_READFD(type) ? 0 : 1;
-
- name = tokstr;
-
- switch (type) {
- case REDIR_HEREDOC:
- case REDIR_HEREDOCDASH: {
- /* <<[-] name */
- struct heredocs **hd;
- int htype = type;
-
- /*
- * Add two here for the string to remember the HERE
- * terminator in raw and munged form.
- */
- if (idstring)
- {
- type |= REDIR_VARID_MASK;
- ncodes = 6;
- }
- else
- ncodes = 5;
-
- /* If we ever to change the number of codes, we have to change
- * the definition of WC_REDIR_WORDS. */
- ecispace(r, ncodes);
- *rp = r + ncodes;
- ecbuf[r] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK);
- ecbuf[r + 1] = fd1;
-
- /*
- * r + 2: the HERE string we recover
- * r + 3: the HERE document terminator, raw
- * r + 4: the HERE document terminator, munged
- */
- if (idstring)
- ecbuf[r + 5] = ecstrcode(idstring);
-
- for (hd = &hdocs; *hd; hd = &(*hd)->next)
- ;
- *hd = zalloc(sizeof(struct heredocs));
- (*hd)->next = NULL;
- (*hd)->type = htype;
- (*hd)->pc = r;
- (*hd)->str = tokstr;
-
- zshlex();
- return ncodes;
- }
- case REDIR_WRITE:
- case REDIR_WRITENOW:
- if (tokstr[0] == OutangProc && tokstr[1] == Inpar)
- /* > >(...) */
- type = REDIR_OUTPIPE;
- else if (tokstr[0] == Inang && tokstr[1] == Inpar)
- YYERROR(ecused);
- break;
- case REDIR_READ:
- if (tokstr[0] == Inang && tokstr[1] == Inpar)
- /* < <(...) */
- type = REDIR_INPIPE;
- else if (tokstr[0] == OutangProc && tokstr[1] == Inpar)
- YYERROR(ecused);
- break;
- case REDIR_READWRITE:
- if ((tokstr[0] == Inang || tokstr[0] == OutangProc) &&
- tokstr[1] == Inpar)
- type = tokstr[0] == Inang ? REDIR_INPIPE : REDIR_OUTPIPE;
- break;
- }
- zshlex();
-
- /* If we ever to change the number of codes, we have to change
- * the definition of WC_REDIR_WORDS. */
- if (idstring)
- {
- type |= REDIR_VARID_MASK;
- ncodes = 4;
- }
- else
- ncodes = 3;
-
- ecispace(r, ncodes);
- *rp = r + ncodes;
- ecbuf[r] = WCB_REDIR(type);
- ecbuf[r + 1] = fd1;
- ecbuf[r + 2] = ecstrcode(name);
- if (idstring)
- ecbuf[r + 3] = ecstrcode(idstring);
-
- return ncodes;
-}
-
-/**/
-void
-setheredoc(int pc, int type, char *str, char *termstr, char *munged_termstr)
-{
- ecbuf[pc] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK);
- ecbuf[pc + 2] = ecstrcode(str);
- ecbuf[pc + 3] = ecstrcode(termstr);
- ecbuf[pc + 4] = ecstrcode(munged_termstr);
-}
-
-/*
- * wordlist : { STRING }
- */
-
-/**/
-static int
-par_wordlist(void)
-{
- int num = 0;
- while (tok == STRING) {
- ecstr(tokstr);
- num++;
- zshlex();
- }
- return num;
-}
-
-/*
- * nl_wordlist : { STRING | SEPER }
- */
-
-/**/
-static int
-par_nl_wordlist(void)
-{
- int num = 0;
-
- while (tok == STRING || tok == SEPER) {
- if (tok != SEPER) {
- ecstr(tokstr);
- num++;
- }
- zshlex();
- }
- return num;
-}
-
-/*
- * condlex is zshlex for normal parsing, but is altered to allow
- * the test builtin to use par_cond.
- */
-
-/**/
-void (*condlex) _((void)) = zshlex;
-
-/*
- * cond : cond_1 { SEPER } [ DBAR { SEPER } cond ]
- */
-
-#define COND_SEP() (tok == SEPER && condlex != testlex && *zshlextext != ';')
-
-/**/
-static int
-par_cond(void)
-{
- int p = ecused, r;
-
- r = par_cond_1();
- while (COND_SEP())
- condlex();
- if (tok == DBAR) {
- condlex();
- while (COND_SEP())
- condlex();
- ecispace(p, 1);
- par_cond();
- ecbuf[p] = WCB_COND(COND_OR, ecused - 1 - p);
- return 1;
- }
- return r;
-}
-
-/*
- * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ]
- */
-
-/**/
-static int
-par_cond_1(void)
-{
- int r, p = ecused;
-
- r = par_cond_2();
- while (COND_SEP())
- condlex();
- if (tok == DAMPER) {
- condlex();
- while (COND_SEP())
- condlex();
- ecispace(p, 1);
- par_cond_1();
- ecbuf[p] = WCB_COND(COND_AND, ecused - 1 - p);
- return 1;
- }
- return r;
-}
-
-/*
- * Return 1 if condition matches. This also works for non-elided options.
- *
- * input is test string, may begin - or Dash.
- * cond is condition following the -.
- */
-static int check_cond(const char *input, const char *cond)
-{
- if (!IS_DASH(input[0]))
- return 0;
- return !strcmp(input + 1, cond);
-}
-
-/*
- * cond_2 : BANG cond_2
- | INPAR { SEPER } cond_2 { SEPER } OUTPAR
- | STRING STRING STRING
- | STRING STRING
- | STRING ( INANG | OUTANG ) STRING
- */
-
-/**/
-static int
-par_cond_2(void)
-{
- char *s1, *s2, *s3;
- int dble = 0;
- int n_testargs = (condlex == testlex) ? arrlen(testargs) + 1 : 0;
-
- if (n_testargs) {
- /* See the description of test in POSIX 1003.2 */
- if (tok == NULLTOK)
- /* no arguments: false */
- return par_cond_double(dupstring("-n"), dupstring(""));
- if (n_testargs == 1) {
- /* one argument: [ foo ] is equivalent to [ -n foo ] */
- s1 = tokstr;
- condlex();
- /* ksh behavior: [ -t ] means [ -t 1 ]; bash disagrees */
- if (unset(POSIXBUILTINS) && check_cond(s1, "t"))
- return par_cond_double(s1, dupstring("1"));
- return par_cond_double(dupstring("-n"), s1);
- }
- if (n_testargs > 2) {
- /* three arguments: if the second argument is a binary operator, *
- * perform that binary test on the first and the third argument */
- if (!strcmp(*testargs, "=") ||
- !strcmp(*testargs, "==") ||
- !strcmp(*testargs, "!=") ||
- (IS_DASH(**testargs) && get_cond_num(*testargs + 1) >= 0)) {
- s1 = tokstr;
- condlex();
- s2 = tokstr;
- condlex();
- s3 = tokstr;
- condlex();
- return par_cond_triple(s1, s2, s3);
- }
- }
- /*
- * We fall through here on any non-numeric infix operator
- * or any other time there are at least two arguments.
- */
- } else
- while (COND_SEP())
- condlex();
- if (tok == BANG) {
- /*
- * In "test" compatibility mode, "! -a ..." and "! -o ..."
- * are treated as "[string] [and] ..." and "[string] [or] ...".
- */
- if (!(n_testargs > 1 && (check_cond(*testargs, "a") ||
- check_cond(*testargs, "o"))))
- {
- condlex();
- ecadd(WCB_COND(COND_NOT, 0));
- return par_cond_2();
- }
- }
- if (tok == INPAR) {
- int r;
-
- condlex();
- while (COND_SEP())
- condlex();
- r = par_cond();
- while (COND_SEP())
- condlex();
- if (tok != OUTPAR)
- YYERROR(ecused);
- condlex();
- return r;
- }
- s1 = tokstr;
- dble = (s1 && IS_DASH(*s1)
- && (!n_testargs
- || strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
- && !s1[2]);
- if (tok != STRING) {
- /* Check first argument for [[ STRING ]] re-interpretation */
- if (s1 /* tok != DOUTBRACK && tok != DAMPER && tok != DBAR */
- && tok != LEXERR && (!dble || n_testargs)) {
- do condlex(); while (COND_SEP());
- return par_cond_double(dupstring("-n"), s1);
- } else
- YYERROR(ecused);
- }
- condlex();
- if (n_testargs == 2 && tok != STRING && tokstr && IS_DASH(s1[0])) {
- /*
- * Something like "test -z" followed by a token.
- * We'll turn the token into a string (we've also
- * checked it does have a string representation).
- */
- tok = STRING;
- } else
- while (COND_SEP())
- condlex();
- if (tok == INANG || tok == OUTANG) {
- enum lextok xtok = tok;
- do condlex(); while (COND_SEP());
- if (tok != STRING)
- YYERROR(ecused);
- s3 = tokstr;
- do condlex(); while (COND_SEP());
- ecadd(WCB_COND((xtok == INANG ? COND_STRLT : COND_STRGTR), 0));
- ecstr(s1);
- ecstr(s3);
- return 1;
- }
- if (tok != STRING) {
- /*
- * Check second argument in case semantics e.g. [ = -a = ]
- * mean we have to go back and fix up the first one
- */
- if (tok != LEXERR) {
- if (!dble || n_testargs)
- return par_cond_double(dupstring("-n"), s1);
- else
- return par_cond_multi(s1, newlinklist());
- } else
- YYERROR(ecused);
- }
- s2 = tokstr;
- if (!n_testargs)
- dble = (s2 && IS_DASH(*s2) && !s2[2]);
- incond++; /* parentheses do globbing */
- do condlex(); while (COND_SEP());
- incond--; /* parentheses do grouping */
- if (tok == STRING && !dble) {
- s3 = tokstr;
- do condlex(); while (COND_SEP());
- if (tok == STRING) {
- LinkList l = newlinklist();
-
- addlinknode(l, s2);
- addlinknode(l, s3);
-
- while (tok == STRING) {
- addlinknode(l, tokstr);
- do condlex(); while (COND_SEP());
- }
- return par_cond_multi(s1, l);
- } else
- return par_cond_triple(s1, s2, s3);
- } else
- return par_cond_double(s1, s2);
-}
-
-/**/
-static int
-par_cond_double(char *a, char *b)
-{
- if (!IS_DASH(a[0]) || !a[1])
- COND_ERROR("parse error: condition expected: %s", a);
- else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
- ecadd(WCB_COND(a[1], 0));
- ecstr(b);
- } else {
- ecadd(WCB_COND(COND_MOD, 1));
- ecstr(a);
- ecstr(b);
- }
- return 1;
-}
-
-/**/
-static int
-get_cond_num(char *tst)
-{
- static char *condstrs[] =
- {
- "nt", "ot", "ef", "eq", "ne", "lt", "gt", "le", "ge", NULL
- };
- int t0;
-
- for (t0 = 0; condstrs[t0]; t0++)
- if (!strcmp(condstrs[t0], tst))
- return t0;
- return -1;
-}
-
-/**/
-static int
-par_cond_triple(char *a, char *b, char *c)
-{
- int t0;
-
- if ((b[0] == Equals || b[0] == '=') && !b[1]) {
- ecadd(WCB_COND(COND_STREQ, 0));
- ecstr(a);
- ecstr(c);
- ecadd(ecnpats++);
- } else if ((b[0] == Equals || b[0] == '=') &&
- (b[1] == Equals || b[1] == '=') && !b[2]) {
- ecadd(WCB_COND(COND_STRDEQ, 0));
- ecstr(a);
- ecstr(c);
- ecadd(ecnpats++);
- } else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
- ecadd(WCB_COND(COND_STRNEQ, 0));
- ecstr(a);
- ecstr(c);
- ecadd(ecnpats++);
- } else if ((b[0] == Equals || b[0] == '=') &&
- (b[1] == '~' || b[1] == Tilde) && !b[2]) {
- /* We become an implicit COND_MODI but do not provide the first
- * item, it's skipped */
- ecadd(WCB_COND(COND_REGEX, 0));
- ecstr(a);
- ecstr(c);
- } else if (IS_DASH(b[0])) {
- if ((t0 = get_cond_num(b + 1)) > -1) {
- ecadd(WCB_COND(t0 + COND_NT, 0));
- ecstr(a);
- ecstr(c);
- } else {
- ecadd(WCB_COND(COND_MODI, 0));
- ecstr(b);
- ecstr(a);
- ecstr(c);
- }
- } else if (IS_DASH(a[0]) && a[1]) {
- ecadd(WCB_COND(COND_MOD, 2));
- ecstr(a);
- ecstr(b);
- ecstr(c);
- } else
- COND_ERROR("condition expected: %s", b);
-
- return 1;
-}
-
-/**/
-static int
-par_cond_multi(char *a, LinkList l)
-{
- if (!IS_DASH(a[0]) || !a[1])
- COND_ERROR("condition expected: %s", a);
- else {
- LinkNode n;
-
- ecadd(WCB_COND(COND_MOD, countlinknodes(l)));
- ecstr(a);
- for (n = firstnode(l); n; incnode(n))
- ecstr((char *) getdata(n));
- }
- return 1;
-}
-
-/**/
-static void
-yyerror(int noerr)
-{
- int t0;
- char *t;
-
- if ((t = dupstring(zshlextext)))
- untokenize(t);
-
- for (t0 = 0; t0 != 20; t0++)
- if (!t || !t[t0] || t[t0] == '\n')
- break;
- if (!(histdone & HISTFLAG_NOEXEC) && !(errflag & ERRFLAG_INT)) {
- if (t0 == 20)
- zwarn("parse error near `%l...'", t, 20);
- else if (t0)
- zwarn("parse error near `%l'", t, t0);
- else
- zwarn("parse error");
- }
- if (!noerr && noerrs != 2)
- errflag |= ERRFLAG_ERROR;
-}
-
-/*
- * Duplicate a programme list, on the heap if heap is 1, else
- * in permanent storage.
- *
- * Be careful in case p is the Eprog for a function which will
- * later be autoloaded. The shf element of the returned Eprog
- * must be set appropriately by the caller. (Normally we create
- * the Eprog in this case by using mkautofn.)
- */
-
-/**/
-mod_export Eprog
-dupeprog(Eprog p, int heap)
-{
- Eprog r;
- int i;
- Patprog *pp;
-
- if (p == &dummy_eprog)
- return p;
-
- r = (heap ? (Eprog) zhalloc(sizeof(*r)) : (Eprog) zalloc(sizeof(*r)));
- r->flags = (heap ? EF_HEAP : EF_REAL) | (p->flags & EF_RUN);
- r->dump = NULL;
- r->len = p->len;
- r->npats = p->npats;
- /*
- * If Eprog is on the heap, reference count is not valid.
- * Otherwise, initialise reference count to 1 so that a freeeprog()
- * will delete it if it is not in use.
- */
- r->nref = heap ? -1 : 1;
- pp = r->pats = (heap ? (Patprog *) hcalloc(r->len) :
- (Patprog *) zshcalloc(r->len));
- r->prog = (Wordcode) (r->pats + r->npats);
- r->strs = ((char *) r->prog) + (p->strs - ((char *) p->prog));
- memcpy(r->prog, p->prog, r->len - (p->npats * sizeof(Patprog)));
- r->shf = NULL;
-
- for (i = r->npats; i--; pp++)
- *pp = dummy_patprog1;
-
- return r;
-}
-
-
-/*
- * Pair of functions to mark an Eprog as in use, and to delete it
- * when it is no longer in use, by means of the reference count in
- * then nref element.
- *
- * If nref is negative, the Eprog is on the heap and is never freed.
- */
-
-/* Increase the reference count of an Eprog so it won't be deleted. */
-
-/**/
-mod_export void
-useeprog(Eprog p)
-{
- if (p && p != &dummy_eprog && p->nref >= 0)
- p->nref++;
-}
-
-/* Free an Eprog if we have finished with it */
-
-/**/
-mod_export void
-freeeprog(Eprog p)
-{
- int i;
- Patprog *pp;
-
- if (p && p != &dummy_eprog) {
- /* paranoia */
- DPUTS(p->nref > 0 && (p->flags & EF_HEAP), "Heap EPROG has nref > 0");
- DPUTS(p->nref < 0 && !(p->flags & EF_HEAP), "Real EPROG has nref < 0");
- DPUTS(p->nref < -1, "Uninitialised EPROG nref");
-#ifdef MAX_FUNCTION_DEPTH
- DPUTS(zsh_funcnest >=0 && p->nref > zsh_funcnest + 10,
- "Overlarge EPROG nref");
-#endif
- if (p->nref > 0 && !--p->nref) {
- for (i = p->npats, pp = p->pats; i--; pp++)
- freepatprog(*pp);
- if (p->dump) {
- decrdumpcount(p->dump);
- zfree(p->pats, p->npats * sizeof(Patprog));
- } else
- zfree(p->pats, p->len);
- zfree(p, sizeof(*p));
- }
- }
-}
-
-/**/
-char *
-ecgetstr(Estate s, int dup, int *tokflag)
-{
- static char buf[4];
- wordcode c = *s->pc++;
- char *r;
-
- if (c == 6 || c == 7)
- r = "";
- else if (c & 2) {
- buf[0] = (char) ((c >> 3) & 0xff);
- buf[1] = (char) ((c >> 11) & 0xff);
- buf[2] = (char) ((c >> 19) & 0xff);
- buf[3] = '\0';
- r = dupstring(buf);
- dup = EC_NODUP;
- } else {
- r = s->strs + (c >> 2);
- }
- if (tokflag)
- *tokflag = (c & 1);
-
- /*** Since function dump files are mapped read-only, avoiding to
- * to duplicate strings when they don't contain tokens may fail
- * when one of the many utility functions happens to write to
- * one of the strings (without really modifying it).
- * If that happens to you and you don't feel like debugging it,
- * just change the line below to:
- *
- * return (dup ? dupstring(r) : r);
- */
-
- return ((dup == EC_DUP || (dup && (c & 1))) ? dupstring(r) : r);
-}
-
-/**/
-char *
-ecrawstr(Eprog p, Wordcode pc, int *tokflag)
-{
- static char buf[4];
- wordcode c = *pc;
-
- if (c == 6 || c == 7) {
- if (tokflag)
- *tokflag = (c & 1);
- return "";
- } else if (c & 2) {
- buf[0] = (char) ((c >> 3) & 0xff);
- buf[1] = (char) ((c >> 11) & 0xff);
- buf[2] = (char) ((c >> 19) & 0xff);
- buf[3] = '\0';
- if (tokflag)
- *tokflag = (c & 1);
- return buf;
- } else {
- if (tokflag)
- *tokflag = (c & 1);
- return p->strs + (c >> 2);
- }
-}
-
-/**/
-char **
-ecgetarr(Estate s, int num, int dup, int *tokflag)
-{
- char **ret, **rp;
- int tf = 0, tmp = 0;
-
- ret = rp = (char **) zhalloc((num + 1) * sizeof(char *));
-
- while (num--) {
- *rp++ = ecgetstr(s, dup, &tmp);
- tf |= tmp;
- }
- *rp = NULL;
- if (tokflag)
- *tokflag = tf;
-
- return ret;
-}
-
-/**/
-LinkList
-ecgetlist(Estate s, int num, int dup, int *tokflag)
-{
- if (num) {
- LinkList ret;
- int i, tf = 0, tmp = 0;
-
- ret = newsizedlist(num);
- for (i = 0; i < num; i++) {
- setsizednode(ret, i, ecgetstr(s, dup, &tmp));
- tf |= tmp;
- }
- if (tokflag)
- *tokflag = tf;
- return ret;
- }
- if (tokflag)
- *tokflag = 0;
- return NULL;
-}
-
-/**/
-LinkList
-ecgetredirs(Estate s)
-{
- LinkList ret = newlinklist();
- wordcode code = *s->pc++;
-
- while (wc_code(code) == WC_REDIR) {
- Redir r = (Redir) zhalloc(sizeof(*r));
-
- r->type = WC_REDIR_TYPE(code);
- r->fd1 = *s->pc++;
- r->name = ecgetstr(s, EC_DUP, NULL);
- if (WC_REDIR_FROM_HEREDOC(code)) {
- r->flags = REDIRF_FROM_HEREDOC;
- r->here_terminator = ecgetstr(s, EC_DUP, NULL);
- r->munged_here_terminator = ecgetstr(s, EC_DUP, NULL);
- } else {
- r->flags = 0;
- r->here_terminator = NULL;
- r->munged_here_terminator = NULL;
- }
- if (WC_REDIR_VARID(code))
- r->varid = ecgetstr(s, EC_DUP, NULL);
- else
- r->varid = NULL;
-
- addlinknode(ret, r);
-
- code = *s->pc++;
- }
- s->pc--;
-
- return ret;
-}
-
-/*
- * Copy the consecutive set of redirections in the state at s.
- * Return NULL if none, else an Eprog consisting only of the
- * redirections from permanently allocated memory.
- *
- * s is left in the state ready for whatever follows the redirections.
- */
-
-/**/
-Eprog
-eccopyredirs(Estate s)
-{
- Wordcode pc = s->pc;
- wordcode code = *pc;
- int ncode, ncodes = 0, r;
-
- if (wc_code(code) != WC_REDIR)
- return NULL;
-
- init_parse();
-
- while (wc_code(code) == WC_REDIR) {
-#ifdef DEBUG
- int type = WC_REDIR_TYPE(code);
-#endif
-
- DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH,
- "unexpanded here document");
-
- if (WC_REDIR_FROM_HEREDOC(code))
- ncode = 5;
- else
- ncode = 3;
- if (WC_REDIR_VARID(code))
- ncode++;
- pc += ncode;
- ncodes += ncode;
- code = *pc;
- }
- r = ecused;
- ecispace(r, ncodes);
-
- code = *s->pc;
- while (wc_code(code) == WC_REDIR) {
- s->pc++;
-
- ecbuf[r++] = code;
- /* fd1 */
- ecbuf[r++] = *s->pc++;
- /* name or HERE string */
- /* No DUP needed as we'll copy into Eprog immediately below */
- ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
- if (WC_REDIR_FROM_HEREDOC(code))
- {
- /* terminator, raw */
- ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
- /* terminator, munged */
- ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
- }
- if (WC_REDIR_VARID(code))
- ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
-
- code = *s->pc;
- }
-
- /* bld_eprog() appends a useful WC_END marker */
- return bld_eprog(0);
-}
-
-/**/
-mod_export struct eprog dummy_eprog;
-
-static wordcode dummy_eprog_code;
-
-/**/
-void
-init_eprog(void)
-{
- dummy_eprog_code = WCB_END();
- dummy_eprog.len = sizeof(wordcode);
- dummy_eprog.prog = &dummy_eprog_code;
- dummy_eprog.strs = NULL;
-}
-
-/* Code for function dump files.
- *
- * Dump files consist of a header and the function bodies (the wordcode
- * plus the string table) and that twice: once for the byte-order of the
- * host the file was created on and once for the other byte-order. The
- * header describes where the beginning of the `other' version is and it
- * is up to the shell reading the file to decide which version it needs.
- * This is done by checking if the first word is FD_MAGIC (then the
- * shell reading the file has the same byte order as the one that created
- * the file) or if it is FD_OMAGIC, then the `other' version has to be
- * read.
- * The header is the magic number, a word containing the flags (if the
- * file should be mapped or read and if this header is the `other' one),
- * the version string in a field of 40 characters and the descriptions
- * for the functions in the dump file.
- *
- * NOTES:
- * - This layout has to be kept; everything after it may be changed.
- * - When incompatible changes are made, the FD_MAGIC and FD_OMAGIC
- * numbers have to be changed.
- *
- * Each description consists of a struct fdhead followed by the name,
- * aligned to sizeof(wordcode) (i.e. 4 bytes).
- */
-
-#include "version.h"
-
-#define FD_EXT ".zwc"
-#define FD_MINMAP 4096
-
-#define FD_PRELEN 12
-#define FD_MAGIC 0x04050607
-#define FD_OMAGIC 0x07060504
-
-#define FDF_MAP 1
-#define FDF_OTHER 2
-
-typedef struct fdhead *FDHead;
-
-struct fdhead {
- wordcode start; /* offset to function definition */
- wordcode len; /* length of wordcode/strings */
- wordcode npats; /* number of patterns needed */
- wordcode strs; /* offset to strings */
- wordcode hlen; /* header length (incl. name) */
- wordcode flags; /* flags and offset to name tail */
-};
-
-#define fdheaderlen(f) (((Wordcode) (f))[FD_PRELEN])
-
-#define fdmagic(f) (((Wordcode) (f))[0])
-#define fdsetbyte(f,i,v) \
- ((((unsigned char *) (((Wordcode) (f)) + 1))[i]) = ((unsigned char) (v)))
-#define fdbyte(f,i) ((wordcode) (((unsigned char *) (((Wordcode) (f)) + 1))[i]))
-#define fdflags(f) fdbyte(f, 0)
-#define fdsetflags(f,v) fdsetbyte(f, 0, v)
-#define fdother(f) (fdbyte(f, 1) + (fdbyte(f, 2) << 8) + (fdbyte(f, 3) << 16))
-#define fdsetother(f, o) \
- do { \
- fdsetbyte(f, 1, ((o) & 0xff)); \
- fdsetbyte(f, 2, (((o) >> 8) & 0xff)); \
- fdsetbyte(f, 3, (((o) >> 16) & 0xff)); \
- } while (0)
-#define fdversion(f) ((char *) ((f) + 2))
-
-#define firstfdhead(f) ((FDHead) (((Wordcode) (f)) + FD_PRELEN))
-#define nextfdhead(f) ((FDHead) (((Wordcode) (f)) + (f)->hlen))
-
-#define fdhflags(f) (((FDHead) (f))->flags)
-#define fdhtail(f) (((FDHead) (f))->flags >> 2)
-#define fdhbldflags(f,t) ((f) | ((t) << 2))
-
-#define FDHF_KSHLOAD 1
-#define FDHF_ZSHLOAD 2
-
-#define fdname(f) ((char *) (((FDHead) (f)) + 1))
-
-/* This is used when building wordcode files. */
-
-typedef struct wcfunc *WCFunc;
-
-struct wcfunc {
- char *name;
- Eprog prog;
- int flags;
-};
-
-/* Try to find the description for the given function name. */
-
-static FDHead
-dump_find_func(Wordcode h, char *name)
-{
- FDHead n, e = (FDHead) (h + fdheaderlen(h));
-
- for (n = firstfdhead(h); n < e; n = nextfdhead(n))
- if (!strcmp(name, fdname(n) + fdhtail(n)))
- return n;
-
- return NULL;
-}
-
-/**/
-int
-bin_zcompile(char *nam, char **args, Options ops, UNUSED(int func))
-{
- int map, flags, ret;
- char *dump;
-
- if ((OPT_ISSET(ops,'k') && OPT_ISSET(ops,'z')) ||
- (OPT_ISSET(ops,'R') && OPT_ISSET(ops,'M')) ||
- (OPT_ISSET(ops,'c') &&
- (OPT_ISSET(ops,'U') || OPT_ISSET(ops,'k') || OPT_ISSET(ops,'z'))) ||
- (!(OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) && OPT_ISSET(ops,'m'))) {
- zwarnnam(nam, "illegal combination of options");
- return 1;
- }
- if ((OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) && isset(KSHAUTOLOAD))
- zwarnnam(nam, "functions will use zsh style autoloading");
-
- flags = (OPT_ISSET(ops,'k') ? FDHF_KSHLOAD :
- (OPT_ISSET(ops,'z') ? FDHF_ZSHLOAD : 0));
-
- if (OPT_ISSET(ops,'t')) {
- Wordcode f;
-
- if (!*args) {
- zwarnnam(nam, "too few arguments");
- return 1;
- }
- if (!(f = load_dump_header(nam, (strsfx(FD_EXT, *args) ? *args :
- dyncat(*args, FD_EXT)), 1)))
- return 1;
-
- if (args[1]) {
- for (args++; *args; args++)
- if (!dump_find_func(f, *args))
- return 1;
- return 0;
- } else {
- FDHead h, e = (FDHead) (f + fdheaderlen(f));
-
- printf("zwc file (%s) for zsh-%s\n",
- ((fdflags(f) & FDF_MAP) ? "mapped" : "read"), fdversion(f));
- for (h = firstfdhead(f); h < e; h = nextfdhead(h))
- printf("%s\n", fdname(h));
- return 0;
- }
- }
- if (!*args) {
- zwarnnam(nam, "too few arguments");
- return 1;
- }
- map = (OPT_ISSET(ops,'M') ? 2 : (OPT_ISSET(ops,'R') ? 0 : 1));
-
- if (!args[1] && !(OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a'))) {
- queue_signals();
- ret = build_dump(nam, dyncat(*args, FD_EXT), args, OPT_ISSET(ops,'U'),
- map, flags);
- unqueue_signals();
- return ret;
- }
- dump = (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT));
-
- queue_signals();
- ret = ((OPT_ISSET(ops,'c') || OPT_ISSET(ops,'a')) ?
- build_cur_dump(nam, dump, args + 1, OPT_ISSET(ops,'m'), map,
- (OPT_ISSET(ops,'c') ? 1 : 0) |
- (OPT_ISSET(ops,'a') ? 2 : 0)) :
- build_dump(nam, dump, args + 1, OPT_ISSET(ops,'U'), map, flags));
- unqueue_signals();
-
- return ret;
-}
-
-/* Load the header of a dump file. Returns NULL if the file isn't a
- * valid dump file. */
-
-/**/
-static Wordcode
-load_dump_header(char *nam, char *name, int err)
-{
- int fd, v = 1;
- wordcode buf[FD_PRELEN + 1];
-
- if ((fd = open(name, O_RDONLY)) < 0) {
- if (err)
- zwarnnam(nam, "can't open zwc file: %s", name);
- return NULL;
- }
- if (read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
- ((FD_PRELEN + 1) * sizeof(wordcode)) ||
- (v = (fdmagic(buf) != FD_MAGIC && fdmagic(buf) != FD_OMAGIC)) ||
- strcmp(fdversion(buf), ZSH_VERSION)) {
- if (err) {
- if (!v) {
- zwarnnam(nam, "zwc file has wrong version (zsh-%s): %s",
- fdversion(buf), name);
- } else
- zwarnnam(nam, "invalid zwc file: %s" , name);
- }
- close(fd);
- return NULL;
- } else {
- int len;
- Wordcode head;
-
- if (fdmagic(buf) == FD_MAGIC) {
- len = fdheaderlen(buf) * sizeof(wordcode);
- head = (Wordcode) zhalloc(len);
- }
- else {
- int o = fdother(buf);
-
- if (lseek(fd, o, 0) == -1 ||
- read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
- ((FD_PRELEN + 1) * sizeof(wordcode))) {
- zwarnnam(nam, "invalid zwc file: %s" , name);
- close(fd);
- return NULL;
- }
- len = fdheaderlen(buf) * sizeof(wordcode);
- head = (Wordcode) zhalloc(len);
- }
- memcpy(head, buf, (FD_PRELEN + 1) * sizeof(wordcode));
-
- len -= (FD_PRELEN + 1) * sizeof(wordcode);
- if (read(fd, head + (FD_PRELEN + 1), len) != len) {
- close(fd);
- zwarnnam(nam, "invalid zwc file: %s" , name);
- return NULL;
- }
- close(fd);
- return head;
- }
-}
-
-/* Swap the bytes in a wordcode. */
-
-static void
-fdswap(Wordcode p, int n)
-{
- wordcode c;
-
- for (; n--; p++) {
- c = *p;
- *p = (((c & 0xff) << 24) |
- ((c & 0xff00) << 8) |
- ((c & 0xff0000) >> 8) |
- ((c & 0xff000000) >> 24));
- }
-}
-
-/* Write a dump file. */
-
-static void
-write_dump(int dfd, LinkList progs, int map, int hlen, int tlen)
-{
- LinkNode node;
- WCFunc wcf;
- int other = 0, ohlen, tmp;
- wordcode pre[FD_PRELEN];
- char *tail, *n;
- struct fdhead head;
- Eprog prog;
-
- if (map == 1)
- map = (tlen >= FD_MINMAP);
-
- memset(pre, 0, sizeof(wordcode) * FD_PRELEN);
-
- for (ohlen = hlen; ; hlen = ohlen) {
- fdmagic(pre) = (other ? FD_OMAGIC : FD_MAGIC);
- fdsetflags(pre, ((map ? FDF_MAP : 0) | other));
- fdsetother(pre, tlen);
- strcpy(fdversion(pre), ZSH_VERSION);
- write_loop(dfd, (char *)pre, FD_PRELEN * sizeof(wordcode));
-
- for (node = firstnode(progs); node; incnode(node)) {
- wcf = (WCFunc) getdata(node);
- n = wcf->name;
- prog = wcf->prog;
- head.start = hlen;
- hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
- sizeof(wordcode) - 1) / sizeof(wordcode);
- head.len = prog->len - (prog->npats * sizeof(Patprog));
- head.npats = prog->npats;
- head.strs = prog->strs - ((char *) prog->prog);
- head.hlen = (sizeof(struct fdhead) / sizeof(wordcode)) +
- (strlen(n) + sizeof(wordcode)) / sizeof(wordcode);
- if ((tail = strrchr(n, '/')))
- tail++;
- else
- tail = n;
- head.flags = fdhbldflags(wcf->flags, (tail - n));
- if (other)
- fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
- write_loop(dfd, (char *)&head, sizeof(head));
- tmp = strlen(n) + 1;
- write_loop(dfd, n, tmp);
- if ((tmp &= (sizeof(wordcode) - 1)))
- write_loop(dfd, (char *)&head, sizeof(wordcode) - tmp);
- }
- for (node = firstnode(progs); node; incnode(node)) {
- prog = ((WCFunc) getdata(node))->prog;
- tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
- sizeof(wordcode) - 1) / sizeof(wordcode);
- if (other)
- fdswap(prog->prog, (((Wordcode) prog->strs) - prog->prog));
- write_loop(dfd, (char *)prog->prog, tmp * sizeof(wordcode));
- }
- if (other)
- break;
- other = FDF_OTHER;
- }
-}
-
-/**/
-static int
-build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
-{
- int dfd, fd, hlen, tlen, flen, ona = noaliases;
- LinkList progs;
- char *file;
- Eprog prog;
- WCFunc wcf;
-
- if (!strsfx(FD_EXT, dump))
- dump = dyncat(dump, FD_EXT);
-
- unlink(dump);
- if ((dfd = open(dump, O_WRONLY|O_CREAT, 0444)) < 0) {
- zwarnnam(nam, "can't write zwc file: %s", dump);
- return 1;
- }
- progs = newlinklist();
- noaliases = ali;
-
- for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
- struct stat st;
-
- if (check_cond(*files, "k")) {
- flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
- continue;
- } else if (check_cond(*files, "z")) {
- flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
- continue;
- }
- if ((fd = open(*files, O_RDONLY)) < 0 ||
- fstat(fd, &st) != 0 || !S_ISREG(st.st_mode) ||
- (flen = lseek(fd, 0, 2)) == -1) {
- if (fd >= 0)
- close(fd);
- close(dfd);
- zwarnnam(nam, "can't open file: %s", *files);
- noaliases = ona;
- unlink(dump);
- return 1;
- }
- file = (char *) zalloc(flen + 1);
- file[flen] = '\0';
- lseek(fd, 0, 0);
- if (read(fd, file, flen) != flen) {
- close(fd);
- close(dfd);
- zfree(file, flen);
- zwarnnam(nam, "can't read file: %s", *files);
- noaliases = ona;
- unlink(dump);
- return 1;
- }
- close(fd);
- file = metafy(file, flen, META_REALLOC);
-
- if (!(prog = parse_string(file, 1)) || errflag) {
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- zfree(file, flen);
- zwarnnam(nam, "can't read file: %s", *files);
- noaliases = ona;
- unlink(dump);
- return 1;
- }
- zfree(file, flen);
-
- wcf = (WCFunc) zhalloc(sizeof(*wcf));
- wcf->name = *files;
- wcf->prog = prog;
- wcf->flags = ((prog->flags & EF_RUN) ? FDHF_KSHLOAD : flags);
- addlinknode(progs, wcf);
-
- flen = (strlen(*files) + sizeof(wordcode)) / sizeof(wordcode);
- hlen += (sizeof(struct fdhead) / sizeof(wordcode)) + flen;
-
- tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
- sizeof(wordcode) - 1) / sizeof(wordcode);
- }
- noaliases = ona;
-
- tlen = (tlen + hlen) * sizeof(wordcode);
-
- write_dump(dfd, progs, map, hlen, tlen);
-
- close(dfd);
-
- return 0;
-}
-
-static int
-cur_add_func(char *nam, Shfunc shf, LinkList names, LinkList progs,
- int *hlen, int *tlen, int what)
-{
- Eprog prog;
- WCFunc wcf;
-
- if (shf->node.flags & PM_UNDEFINED) {
- int ona = noaliases;
-
- if (!(what & 2)) {
- zwarnnam(nam, "function is not loaded: %s", shf->node.nam);
- return 1;
- }
- noaliases = (shf->node.flags & PM_UNALIASED);
- if (!(prog = getfpfunc(shf->node.nam, NULL, NULL, NULL, 0)) ||
- prog == &dummy_eprog) {
- noaliases = ona;
- zwarnnam(nam, "can't load function: %s", shf->node.nam);
- return 1;
- }
- if (prog->dump)
- prog = dupeprog(prog, 1);
- noaliases = ona;
- } else {
- if (!(what & 1)) {
- zwarnnam(nam, "function is already loaded: %s", shf->node.nam);
- return 1;
- }
- prog = dupeprog(shf->funcdef, 1);
- }
- wcf = (WCFunc) zhalloc(sizeof(*wcf));
- wcf->name = shf->node.nam;
- wcf->prog = prog;
- wcf->flags = ((prog->flags & EF_RUN) ? FDHF_KSHLOAD : FDHF_ZSHLOAD);
- addlinknode(progs, wcf);
- addlinknode(names, shf->node.nam);
-
- *hlen += ((sizeof(struct fdhead) / sizeof(wordcode)) +
- ((strlen(shf->node.nam) + sizeof(wordcode)) / sizeof(wordcode)));
- *tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
- sizeof(wordcode) - 1) / sizeof(wordcode);
-
- return 0;
-}
-
-/**/
-static int
-build_cur_dump(char *nam, char *dump, char **names, int match, int map,
- int what)
-{
- int dfd, hlen, tlen;
- LinkList progs, lnames;
- Shfunc shf = NULL;
-
- if (!strsfx(FD_EXT, dump))
- dump = dyncat(dump, FD_EXT);
-
- unlink(dump);
- if ((dfd = open(dump, O_WRONLY|O_CREAT, 0444)) < 0) {
- zwarnnam(nam, "can't write zwc file: %s", dump);
- return 1;
- }
- progs = newlinklist();
- lnames = newlinklist();
-
- hlen = FD_PRELEN;
- tlen = 0;
-
- if (!*names) {
- int i;
- HashNode hn;
-
- for (i = 0; i < shfunctab->hsize; i++)
- for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
- if (cur_add_func(nam, (Shfunc) hn, lnames, progs,
- &hlen, &tlen, what)) {
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- unlink(dump);
- return 1;
- }
- } else if (match) {
- char *pat;
- Patprog pprog;
- int i;
- HashNode hn;
-
- for (; *names; names++) {
- tokenize(pat = dupstring(*names));
- /* Signal-safe here, caller queues signals */
- if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) {
- zwarnnam(nam, "bad pattern: %s", *names);
- close(dfd);
- unlink(dump);
- return 1;
- }
- for (i = 0; i < shfunctab->hsize; i++)
- for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
- if (!linknodebydatum(lnames, hn->nam) &&
- pattry(pprog, hn->nam) &&
- cur_add_func(nam, (Shfunc) hn, lnames, progs,
- &hlen, &tlen, what)) {
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- unlink(dump);
- return 1;
- }
- }
- } else {
- for (; *names; names++) {
- if (errflag ||
- !(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
- zwarnnam(nam, "unknown function: %s", *names);
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- unlink(dump);
- return 1;
- }
- if (cur_add_func(nam, shf, lnames, progs, &hlen, &tlen, what)) {
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- unlink(dump);
- return 1;
- }
- }
- }
- if (empty(progs)) {
- zwarnnam(nam, "no functions");
- errflag &= ~ERRFLAG_ERROR;
- close(dfd);
- unlink(dump);
- return 1;
- }
- tlen = (tlen + hlen) * sizeof(wordcode);
-
- write_dump(dfd, progs, map, hlen, tlen);
-
- close(dfd);
-
- return 0;
-}
-
-/**/
-#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
-
-#include
-
-/**/
-#if defined(MAP_SHARED) && defined(PROT_READ)
-
-/**/
-#define USE_MMAP 1
-
-/**/
-#endif
-/**/
-#endif
-
-/**/
-#ifdef USE_MMAP
-
-/* List of dump files mapped. */
-
-static FuncDump dumps;
-
-/**/
-static int
-zwcstat(char *filename, struct stat *buf)
-{
- if (stat(filename, buf)) {
-#ifdef HAVE_FSTAT
- FuncDump f;
-
- for (f = dumps; f; f = f->next) {
- if (!strncmp(filename, f->filename, strlen(f->filename)) &&
- !fstat(f->fd, buf))
- return 0;
- }
-#endif
- return 1;
- } else return 0;
-}
-
-/* Load a dump file (i.e. map it). */
-
-static void
-load_dump_file(char *dump, struct stat *sbuf, int other, int len)
-{
- FuncDump d;
- Wordcode addr;
- int fd, off, mlen;
-
- if (other) {
- static size_t pgsz = 0;
-
- if (!pgsz) {
-
-#ifdef _SC_PAGESIZE
- pgsz = sysconf(_SC_PAGESIZE); /* SVR4 */
-#else
-# ifdef _SC_PAGE_SIZE
- pgsz = sysconf(_SC_PAGE_SIZE); /* HPUX */
-# else
- pgsz = getpagesize();
-# endif
-#endif
-
- pgsz--;
- }
- off = len & ~pgsz;
- mlen = len + (len - off);
- } else {
- off = 0;
- mlen = len;
- }
- if ((fd = open(dump, O_RDONLY)) < 0)
- return;
-
- fd = movefd(fd);
- if (fd == -1)
- return;
-
- if ((addr = (Wordcode) mmap(NULL, mlen, PROT_READ, MAP_SHARED, fd, off)) ==
- ((Wordcode) -1)) {
- close(fd);
- return;
- }
- d = (FuncDump) zalloc(sizeof(*d));
- d->next = dumps;
- dumps = d;
- d->dev = sbuf->st_dev;
- d->ino = sbuf->st_ino;
- d->fd = fd;
-#ifdef FD_CLOEXEC
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-#endif
- d->map = addr + (other ? (len - off) / sizeof(wordcode) : 0);
- d->addr = addr;
- d->len = len;
- d->count = 0;
- d->filename = ztrdup(dump);
-}
-
-#else
-
-#define zwcstat(f, b) (!!stat(f, b))
-
-/**/
-#endif
-
-/* Try to load a function from one of the possible wordcode files for it.
- * The first argument is a element of $fpath, the second one is the name
- * of the function searched and the last one is the possible name for the
- * uncompiled function file (/). */
-
-/**/
-Eprog
-try_dump_file(char *path, char *name, char *file, int *ksh, int test_only)
-{
- Eprog prog;
- struct stat std, stc, stn;
- int rd, rc, rn;
- char *dig, *wc;
-
- if (strsfx(FD_EXT, path)) {
- queue_signals();
- prog = check_dump_file(path, NULL, name, ksh, test_only);
- unqueue_signals();
- return prog;
- }
- dig = dyncat(path, FD_EXT);
- wc = dyncat(file, FD_EXT);
-
- rd = zwcstat(dig, &std);
- rc = stat(wc, &stc);
- rn = stat(file, &stn);
-
- /* See if there is a digest file for the directory, it is younger than
- * both the uncompiled function file and its compiled version (or they
- * don't exist) and the digest file contains the definition for the
- * function. */
- queue_signals();
- if (!rd &&
- (rc || std.st_mtime >= stc.st_mtime) &&
- (rn || std.st_mtime >= stn.st_mtime) &&
- (prog = check_dump_file(dig, &std, name, ksh, test_only))) {
- unqueue_signals();
- return prog;
- }
- /* No digest file. Now look for the per-function compiled file. */
- if (!rc &&
- (rn || stc.st_mtime >= stn.st_mtime) &&
- (prog = check_dump_file(wc, &stc, name, ksh, test_only))) {
- unqueue_signals();
- return prog;
- }
- /* No compiled file for the function. The caller (getfpfunc() will
- * check if the directory contains the uncompiled file for it. */
- unqueue_signals();
- return NULL;
-}
-
-/* Almost the same, but for sourced files. */
-
-/**/
-Eprog
-try_source_file(char *file)
-{
- Eprog prog;
- struct stat stc, stn;
- int rc, rn;
- char *wc, *tail;
-
- if ((tail = strrchr(file, '/')))
- tail++;
- else
- tail = file;
-
- if (strsfx(FD_EXT, file)) {
- queue_signals();
- prog = check_dump_file(file, NULL, tail, NULL, 0);
- unqueue_signals();
- return prog;
- }
- wc = dyncat(file, FD_EXT);
-
- rc = stat(wc, &stc);
- rn = stat(file, &stn);
-
- queue_signals();
- if (!rc && (rn || stc.st_mtime >= stn.st_mtime) &&
- (prog = check_dump_file(wc, &stc, tail, NULL, 0))) {
- unqueue_signals();
- return prog;
- }
- unqueue_signals();
- return NULL;
-}
-
-/* See if `file' names a wordcode dump file and that contains the
- * definition for the function `name'. If so, return an eprog for it. */
-
-/**/
-static Eprog
-check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh,
- int test_only)
-{
- int isrec = 0;
- Wordcode d;
- FDHead h;
- FuncDump f;
- struct stat lsbuf;
-
- if (!sbuf) {
- if (zwcstat(file, &lsbuf))
- return NULL;
- sbuf = &lsbuf;
- }
-
-#ifdef USE_MMAP
-
- rec:
-
-#endif
-
- d = NULL;
-
-#ifdef USE_MMAP
-
- for (f = dumps; f; f = f->next)
- if (f->dev == sbuf->st_dev && f->ino == sbuf->st_ino) {
- d = f->map;
- break;
- }
-
-#else
-
- f = NULL;
-
-#endif
-
- if (!f && (isrec || !(d = load_dump_header(NULL, file, 0))))
- return NULL;
-
- if ((h = dump_find_func(d, name))) {
- /* Found the name. If the file is already mapped, return the eprog,
- * otherwise map it and just go up. */
- if (test_only)
- {
- /* This is all we need. Just return dummy. */
- return &dummy_eprog;
- }
-
-#ifdef USE_MMAP
-
- if (f) {
- Eprog prog = (Eprog) zalloc(sizeof(*prog));
- Patprog *pp;
- int np;
-
- prog->flags = EF_MAP;
- prog->len = h->len;
- prog->npats = np = h->npats;
- prog->nref = 1; /* allocated from permanent storage */
- prog->pats = pp = (Patprog *) zalloc(np * sizeof(Patprog));
- prog->prog = f->map + h->start;
- prog->strs = ((char *) prog->prog) + h->strs;
- prog->shf = NULL;
- prog->dump = f;
-
- incrdumpcount(f);
-
- while (np--)
- *pp++ = dummy_patprog1;
-
- if (ksh)
- *ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
- ((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
-
- return prog;
- } else if (fdflags(d) & FDF_MAP) {
- load_dump_file(file, sbuf, (fdflags(d) & FDF_OTHER), fdother(d));
- isrec = 1;
- goto rec;
- } else
-
-#endif
-
- {
- Eprog prog;
- Patprog *pp;
- int np, fd, po = h->npats * sizeof(Patprog);
-
- if ((fd = open(file, O_RDONLY)) < 0 ||
- lseek(fd, ((h->start * sizeof(wordcode)) +
- ((fdflags(d) & FDF_OTHER) ? fdother(d) : 0)), 0) < 0) {
- if (fd >= 0)
- close(fd);
- return NULL;
- }
- d = (Wordcode) zalloc(h->len + po);
-
- if (read(fd, ((char *) d) + po, h->len) != (int)h->len) {
- close(fd);
- zfree(d, h->len);
-
- return NULL;
- }
- close(fd);
-
- prog = (Eprog) zalloc(sizeof(*prog));
-
- prog->flags = EF_REAL;
- prog->len = h->len + po;
- prog->npats = np = h->npats;
- prog->nref = 1; /* allocated from permanent storage */
- prog->pats = pp = (Patprog *) d;
- prog->prog = (Wordcode) (((char *) d) + po);
- prog->strs = ((char *) prog->prog) + h->strs;
- prog->shf = NULL;
- prog->dump = f;
-
- while (np--)
- *pp++ = dummy_patprog1;
-
- if (ksh)
- *ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
- ((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
-
- return prog;
- }
- }
- return NULL;
-}
-
-#ifdef USE_MMAP
-
-/* Increment the reference counter for a dump file. */
-
-/**/
-void
-incrdumpcount(FuncDump f)
-{
- f->count++;
-}
-
-/**/
-static void
-freedump(FuncDump f)
-{
- munmap((void *) f->addr, f->len);
- zclose(f->fd);
- zsfree(f->filename);
- zfree(f, sizeof(*f));
-}
-
-/* Decrement the reference counter for a dump file. If zero, unmap the file. */
-
-/**/
-void
-decrdumpcount(FuncDump f)
-{
- f->count--;
- if (!f->count) {
- FuncDump p, q;
-
- for (q = NULL, p = dumps; p && p != f; q = p, p = p->next);
- if (p) {
- if (q)
- q->next = p->next;
- else
- dumps = p->next;
- freedump(f);
- }
- }
-}
-
-#ifndef FD_CLOEXEC
-/**/
-mod_export void
-closedumps(void)
-{
- while (dumps) {
- FuncDump p = dumps->next;
- freedump(dumps);
- dumps = p;
- }
-}
-#endif
-
-#else
-
-void
-incrdumpcount(FuncDump f)
-{
-}
-
-void
-decrdumpcount(FuncDump f)
-{
-}
-
-#ifndef FD_CLOEXEC
-/**/
-mod_export void
-closedumps(void)
-{
-}
-#endif
-
-#endif
-
-/**/
-int
-dump_autoload(char *nam, char *file, int on, Options ops, int func)
-{
- Wordcode h;
- FDHead n, e;
- Shfunc shf;
- int ret = 0;
-
- if (!strsfx(FD_EXT, file))
- file = dyncat(file, FD_EXT);
-
- if (!(h = load_dump_header(nam, file, 1)))
- return 1;
-
- for (n = firstfdhead(h), e = (FDHead) (h + fdheaderlen(h)); n < e;
- n = nextfdhead(n)) {
- shf = (Shfunc) zshcalloc(sizeof *shf);
- shf->node.flags = on;
- shf->funcdef = mkautofn(shf);
- shf->sticky = NULL;
- shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf);
- if (OPT_ISSET(ops,'X') && eval_autoload(shf, shf->node.nam, ops, func))
- ret = 1;
- }
- return ret;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/pattern.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/pattern.c
deleted file mode 100644
index 737f5cdc..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/pattern.c
+++ /dev/null
@@ -1,4336 +0,0 @@
-/*
- * pattern.c - pattern matching
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1999 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.
- *
- * Pattern matching code derived from the regexp library by Henry
- * Spencer, which has the following copyright.
- *
- * Copyright (c) 1986 by University of Toronto.
- * Written by Henry Spencer. Not derived from licensed software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to redistribute it freely,
- * subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of
- * this software, no matter how awful, even if they arise
- * from defects in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * Eagle-eyed readers will notice this is an altered version. Incredibly
- * sharp-eyed readers might even find bits that weren't altered.
- *
- *
- * And I experienced a sense that, like certain regular
- * expressions, seemed to match the day from beginning to end, so
- * that I did not need to identify the parenthesised subexpression
- * that told of dawn, nor the group of characters that indicated
- * the moment when my grandfather returned home with news of
- * Swann's departure for Paris; and the whole length of the month
- * of May, as if matched by a closure, fitted into the buffer of my
- * life with no sign of overflowing, turning the days, like a
- * procession of insects that could consist of this or that
- * species, into a random and unstructured repetition of different
- * sequences, anchored from the first day of the month to the last
- * in the same fashion as the weeks when I knew I would not see
- * Gilberte and would search in vain for any occurrences of the
- * string in the avenue of hawthorns by Tansonville, without my
- * having to delimit explicitly the start or finish of the pattern.
- *
- * M. Proust, "In Search of Lost Files",
- * bk I, "The Walk by Bourne's Place".
- */
-
-#include "zsh.mdh"
-
-/*
- * The following union is used mostly for alignment purposes.
- * Normal nodes are longs, while certain nodes take a char * as an argument;
- * here we make sure that they both work out to the same length.
- * The compiled regexp we construct consists of upats stuck together;
- * anything else to be added (strings, numbers) is stuck after and
- * then aligned to a whole number of upat units.
- *
- * Note also that offsets are in terms of the sizes of these things.
- */
-union upat {
- long l;
- unsigned char *p;
-};
-
-typedef union upat *Upat;
-
-#include "pattern.pro"
-
-/* Number of active parenthesized expressions allowed in backreferencing */
-#define NSUBEXP 9
-
-/* definition number opnd? meaning */
-#define P_END 0x00 /* no End of program. */
-#define P_EXCSYNC 0x01 /* no Test if following exclude already failed */
-#define P_EXCEND 0x02 /* no Test if exclude matched orig branch */
-#define P_BACK 0x03 /* no Match "", "next" ptr points backward. */
-#define P_EXACTLY 0x04 /* lstr Match this string. */
-#define P_NOTHING 0x05 /* no Match empty string. */
-#define P_ONEHASH 0x06 /* node Match this (simple) thing 0 or more times. */
-#define P_TWOHASH 0x07 /* node Match this (simple) thing 1 or more times. */
-#define P_GFLAGS 0x08 /* long Match nothing and set globbing flags */
-#define P_ISSTART 0x09 /* no Match start of string. */
-#define P_ISEND 0x0a /* no Match end of string. */
-#define P_COUNTSTART 0x0b /* no Initialise P_COUNT */
-#define P_COUNT 0x0c /* 3*long uc* node Match a number of repetitions */
-/* numbered so we can test bit 5 for a branch */
-#define P_BRANCH 0x20 /* node Match this alternative, or the next... */
-#define P_WBRANCH 0x21 /* uc* node P_BRANCH, but match at least 1 char */
-/* excludes are also branches, but have bit 4 set, too */
-#define P_EXCLUDE 0x30 /* uc* node Exclude this from previous branch */
-#define P_EXCLUDP 0x31 /* uc* node Exclude, using full file path so far */
-/* numbered so we can test bit 6 so as not to match initial '.' */
-#define P_ANY 0x40 /* no Match any one character. */
-#define P_ANYOF 0x41 /* str Match any character in this string. */
-#define P_ANYBUT 0x42 /* str Match any character not in this string. */
-#define P_STAR 0x43 /* no Match any set of characters. */
-#define P_NUMRNG 0x44 /* zr, zr Match a numeric range. */
-#define P_NUMFROM 0x45 /* zr Match a number >= X */
-#define P_NUMTO 0x46 /* zr Match a number <= X */
-#define P_NUMANY 0x47 /* no Match any set of decimal digits */
-/* spaces left for P_OPEN+n,... for backreferences */
-#define P_OPEN 0x80 /* no Mark this point in input as start of n. */
-#define P_CLOSE 0x90 /* no Analogous to OPEN. */
-/*
- * no no argument
- * zr the range type zrange_t: may be zlong or unsigned long
- * char a single char
- * uc* a pointer to unsigned char, used at run time and initialised
- * to NULL.
- * str null-terminated, metafied string
- * lstr length as long then string, not null-terminated, unmetafied.
- */
-
-/*
- * Notes on usage:
- * P_WBRANCH: This works like a branch and is used in complex closures,
- * to ensure we don't succeed on a zero-length match of the pattern,
- * since that would cause an infinite loop. We do this by recording
- * the positions where we have already tried to match. See the
- * P_WBRANCH test in patmatch().
- *
- * P_ANY, P_ANYOF: the operand is a null terminated
- * string. Normal characters match as expected. Characters
- * in the range Meta+PP_ALPHA..Meta+PP_UNKWN do the appropriate
- * Posix range tests. This relies on imeta returning true for these
- * characters. We treat unknown POSIX ranges as never matching.
- * PP_RANGE means the next two (possibly metafied) characters form
- * the limits of a range to test; it's too much like hard work to
- * expand the range.
- *
- * P_EXCLUDE, P_EXCSYNC, PEXCEND: P_EXCLUDE appears in the pattern like
- * P_BRANCH, but applies to the immediately preceding branch. The code in
- * the corresponding branch is followed by a P_EXCSYNC, which simply
- * acts as a marker that a P_EXCLUDE comes next. The P_EXCLUDE
- * has a pointer to char embeded in it, which works
- * like P_WBRANCH: if we get to the P_EXCSYNC, and we already matched
- * up to the same position, fail. Thus we are forced to backtrack
- * on closures in the P_BRANCH if the first attempt was excluded.
- * Corresponding to P_EXCSYNC in the original branch, there is a
- * P_EXCEND in the exclusion. If we get to this point, and we did
- * *not* match in the original branch, the exclusion itself fails,
- * otherwise it succeeds since we know the tail already matches,
- * so P_EXCEND is the end of the exclusion test.
- * The whole sorry mess looks like this, where the upper lines
- * show the linkage of the branches, and the lower shows the linkage
- * of their pattern arguments.
- *
- * --------------------- ----------------------
- * ^ v ^ v
- * ( :apat-> :excpat-> ) tail
- * ^
- * | |
- * --------------------------------------
- *
- * P_EXCLUDP: this behaves exactly like P_EXCLUDE, with the sole exception
- * that we prepend the path so far to the exclude pattern. This is
- * for top level file globs, e.g. ** / *.c~*foo.c
- * ^ I had to leave this space
- * P_NUM*: zl is a zlong if that is 64-bit, else an unsigned long.
- *
- * P_COUNTSTART, P_COUNT: a P_COUNTSTART flags the start of a quantified
- * closure (#cN,M) and is used to initialise the count. Executing
- * the pattern leads back to the P_COUNT, while the next links of the
- * P_COUNTSTART and P_COUNT lead to the tail of the pattern:
- *
- * ----------------
- * v ^
- * pattern tail
- * v v ^
- * ------------------------
- */
-
-#define P_OP(p) ((p)->l & 0xff)
-#define P_NEXT(p) ((p)->l >> 8)
-#define P_OPERAND(p) ((p) + 1)
-#define P_ISBRANCH(p) ((p)->l & 0x20)
-#define P_ISEXCLUDE(p) (((p)->l & 0x30) == 0x30)
-#define P_NOTDOT(p) ((p)->l & 0x40)
-
-/* Specific to lstr type, i.e. P_EXACTLY. */
-#define P_LS_LEN(p) ((p)[1].l) /* can be used as lvalue */
-#define P_LS_STR(p) ((char *)((p) + 2))
-
-/* Specific to P_COUNT: arguments as offset in nodes from operator */
-#define P_CT_CURRENT (1) /* Current count */
-#define P_CT_MIN (2) /* Minimum count */
-#define P_CT_MAX (3) /* Maximum count, -1 for none */
-#define P_CT_PTR (4) /* Pointer to last match start */
-#define P_CT_OPERAND (5) /* Operand of P_COUNT */
-
-/* Flags needed when pattern is executed */
-#define P_SIMPLE 0x01 /* Simple enough to be #/## operand. */
-#define P_HSTART 0x02 /* Starts with # or ##'d pattern. */
-#define P_PURESTR 0x04 /* Can be matched with a strcmp */
-
-#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
-typedef zlong zrange_t;
-#define ZRANGE_T_IS_SIGNED (1)
-#define ZRANGE_MAX ZLONG_MAX
-#else
-typedef unsigned long zrange_t;
-#define ZRANGE_MAX ULONG_MAX
-#endif
-
-#ifdef MULTIBYTE_SUPPORT
-/*
- * Handle a byte that's not part of a valid character.
- *
- * This range in Unicode is recommended for purposes of this
- * kind as it corresponds to invalid characters.
- *
- * Note that this strictly only works if wchar_t represents
- * Unicode code points, which isn't necessarily true; however,
- * converting an invalid character into an unknown format is
- * a bit tricky...
- */
-#define WCHAR_INVALID(ch) \
- ((wchar_t) (0xDC00 + STOUC(ch)))
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Array of characters corresponding to zpc_chars enum, which it must match.
- */
-static const char zpc_chars[ZPC_COUNT] = {
- '/', '\0', Bar, Outpar, Tilde, Inpar, Quest, Star, Inbrack, Inang,
- Hat, Pound, Bnullkeep, Quest, Star, '+', Bang, '!', '@'
-};
-
-/*
- * Corresponding strings used in enable/disable -p.
- * NULL means no way of turning this on or off.
- */
-/**/
-mod_export const char *zpc_strings[ZPC_COUNT] = {
- NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<",
- "^", "#", NULL, "?(", "*(", "+(", "!(", "\\!(", "@("
-};
-
-/*
- * Corresponding array of pattern disables as set by the user
- * using "disable -p".
- */
-/**/
-mod_export char zpc_disables[ZPC_COUNT];
-
-/*
- * Stack of saved (compressed) zpc_disables for function scope.
- */
-
-static struct zpc_disables_save *zpc_disables_stack;
-
-/*
- * Characters which terminate a simple string (ZPC_COUNT) or
- * an entire pattern segment (the first ZPC_SEG_COUNT).
- * Each entry is either the corresponding character in zpc_chars
- * or Marker which is guaranteed not to match a character in a
- * pattern we are compiling.
- *
- * The complete list indicates characters that are special, so e.g.
- * (testchar == special[ZPC_TILDE]) succeeds only if testchar is a Tilde
- * *and* Tilde is currently special.
- */
-
-/**/
-char zpc_special[ZPC_COUNT];
-
-/* Default size for pattern buffer */
-#define P_DEF_ALLOC 256
-
-/* Flags used in compilation */
-static char *patstart, *patparse; /* input pointers */
-static int patnpar; /* () count */
-static char *patcode; /* point of code emission */
-static long patsize; /* size of code */
-static char *patout; /* start of code emission string */
-static long patalloc; /* size allocated for same */
-
-/* Flags used in both compilation and execution */
-static int patflags; /* flags passed down to patcompile */
-static int patglobflags; /* globbing flags & approx */
-
-/*
- * Increment pointer to metafied multibyte string.
- */
-#ifdef MULTIBYTE_SUPPORT
-typedef wint_t patint_t;
-
-#define PEOF WEOF
-
-#define METACHARINC(x) ((void)metacharinc(&x))
-
-/*
- * TODO: the shiftstate isn't well handled; we don't guarantee
- * to maintain it properly between characters. If we don't
- * need it we should use mbtowc() instead.
- */
-static mbstate_t shiftstate;
-
-/*
- * Multibyte version: it's (almost) as easy to return the
- * value as not, so do so since we sometimes need it..
- */
-static wchar_t
-metacharinc(char **x)
-{
- char *inptr = *x;
- char inchar;
- size_t ret = MB_INVALID;
- wchar_t wc;
-
- /*
- * Cheat if the top bit isn't set. This is second-guessing
- * the library, but we know for sure that if the character
- * set doesn't have the property that all bytes with the 8th
- * bit clear are single characters then we are stuffed.
- */
- if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*inptr) & 0x80))
- {
- if (itok(*inptr))
- inchar = ztokens[*inptr++ - Pound];
- else if (*inptr == Meta) {
- inptr++;
- inchar = *inptr++ ^ 32;
- } else {
- inchar = *inptr++;
- }
- *x = inptr;
- return (wchar_t)STOUC(inchar);
- }
-
- while (*inptr) {
- if (itok(*inptr))
- inchar = ztokens[*inptr++ - Pound];
- else if (*inptr == Meta) {
- inptr++;
- inchar = *inptr++ ^ 32;
- } else {
- inchar = *inptr++;
- }
- ret = mbrtowc(&wc, &inchar, 1, &shiftstate);
-
- if (ret == MB_INVALID)
- break;
- if (ret == MB_INCOMPLETE)
- continue;
- *x = inptr;
- return wc;
- }
-
- /* Error. */
- /* Reset the shift state for next time. */
- memset(&shiftstate, 0, sizeof(shiftstate));
- return WCHAR_INVALID(*(*x)++);
-}
-
-#else
-typedef int patint_t;
-
-#define PEOF EOF
-
-#define METACHARINC(x) ((void)((x) += (*(x) == Meta) ? 2 : 1))
-#endif
-
-/*
- * Return unmetafied char from string (x is any char *).
- * Used with MULTIBYTE_SUPPORT if the GF_MULTIBYTE is not
- * in effect.
- */
-#define UNMETA(x) (*(x) == Meta ? (x)[1] ^ 32 : *(x))
-
-/* Add n more characters, ensuring there is enough space. */
-
-enum {
- PA_NOALIGN = 1,
- PA_UNMETA = 2
-};
-
-/**/
-static void
-patadd(char *add, int ch, long n, int paflags)
-{
- /* Make sure everything gets aligned unless we get PA_NOALIGN. */
- long newpatsize = patsize + n;
- if (!(paflags & PA_NOALIGN))
- newpatsize = (newpatsize + sizeof(union upat) - 1) &
- ~(sizeof(union upat) - 1);
- if (patalloc < newpatsize) {
- long newpatalloc =
- 2*(newpatsize > patalloc ? newpatsize : patalloc);
- patout = (char *)zrealloc((char *)patout, newpatalloc);
- patcode = patout + patsize;
- patalloc = newpatalloc;
- }
- patsize = newpatsize;
- if (add) {
- if (paflags & PA_UNMETA) {
- /*
- * Unmetafy and untokenize the string as we go.
- * The Meta characters in add aren't counted in n.
- */
- while (n--) {
- if (itok(*add))
- *patcode++ = ztokens[*add++ - Pound];
- else if (*add == Meta) {
- add++;
- *patcode++ = *add++ ^ 32;
- } else {
- *patcode++ = *add++;
- }
- }
- } else {
- while (n--)
- *patcode++ = *add++;
- }
- } else
- *patcode++ = ch;
- patcode = patout + patsize;
-}
-
-static long rn_offs;
-/* operates on pointers to union upat, returns a pointer */
-#define PATNEXT(p) ((rn_offs = P_NEXT(p)) ? \
- (P_OP(p) == P_BACK) ? \
- ((p)-rn_offs) : ((p)+rn_offs) : NULL)
-
-/*
- * Set up zpc_special with characters that end a string segment.
- * "Marker" cannot occur in the pattern we are compiling so
- * is used to mark "invalid".
- */
-static void
-patcompcharsset(void)
-{
- char *spp, *disp;
- int i;
-
- /* Initialise enabled special characters */
- memcpy(zpc_special, zpc_chars, ZPC_COUNT);
- /* Apply user disables from disable -p */
- for (i = 0, spp = zpc_special, disp = zpc_disables;
- i < ZPC_COUNT;
- i++, spp++, disp++) {
- if (*disp)
- *spp = Marker;
- }
-
- if (!isset(EXTENDEDGLOB)) {
- /* Extended glob characters are not active */
- zpc_special[ZPC_TILDE] = zpc_special[ZPC_HAT] =
- zpc_special[ZPC_HASH] = Marker;
- }
- if (!isset(KSHGLOB)) {
- /*
- * Ksh glob characters are not active.
- * * and ? are shared with normal globbing, but for their
- * use here we are looking for a following Inpar.
- */
- zpc_special[ZPC_KSH_QUEST] = zpc_special[ZPC_KSH_STAR] =
- zpc_special[ZPC_KSH_PLUS] = zpc_special[ZPC_KSH_BANG] =
- zpc_special[ZPC_KSH_BANG2] = zpc_special[ZPC_KSH_AT] = Marker;
- }
- /*
- * Note that if we are using KSHGLOB, then we test for a following
- * Inpar, not zpc_special[ZPC_INPAR]: the latter makes an Inpar on
- * its own active. The zpc_special[ZPC_KSH_*] followed by any old Inpar
- * discriminate ksh globbing.
- */
- if (isset(SHGLOB)) {
- /*
- * Grouping and numeric ranges are not valid.
- * We do allow alternation, however; it's needed for
- * "case". This may not be entirely consistent.
- *
- * Don't disable Outpar: we may need to match the end of KSHGLOB
- * parentheses and it would be difficult to tell them apart.
- */
- zpc_special[ZPC_INPAR] = zpc_special[ZPC_INANG] = Marker;
- }
-}
-
-/* Called before parsing a set of file matchs to initialize flags */
-
-/**/
-void
-patcompstart(void)
-{
- patcompcharsset();
- if (isset(CASEGLOB))
- patglobflags = 0;
- else
- patglobflags = GF_IGNCASE;
- if (isset(MULTIBYTE))
- patglobflags |= GF_MULTIBYTE;
-}
-
-/*
- * Top level pattern compilation subroutine
- * exp is a null-terminated, metafied string.
- * inflags is an or of some PAT_* flags.
- * endexp, if non-null, is set to a pointer to the end of the
- * part of exp which was compiled. This is used when
- * compiling patterns for directories which must be
- * matched recursively.
- */
-
-/**/
-mod_export Patprog
-patcompile(char *exp, int inflags, char **endexp)
-{
- int flags = 0;
- long len = 0;
- long startoff;
- Upat pscan;
- char *lng, *strp = NULL;
- Patprog p;
-
- queue_signals();
-
- startoff = sizeof(struct patprog);
- /* Ensure alignment of start of program string */
- startoff = (startoff + sizeof(union upat) - 1) & ~(sizeof(union upat) - 1);
-
- /* Allocate reasonable sized chunk if none, reduce size if too big */
- if (patalloc != P_DEF_ALLOC)
- patout = (char *)zrealloc(patout, patalloc = P_DEF_ALLOC);
- patcode = patout + startoff;
- patsize = patcode - patout;
- patstart = patparse = exp;
- /*
- * Note global patnpar numbers parentheses 1..9, while patnpar
- * in struct is actual count of parentheses.
- */
- patnpar = 1;
- patflags = inflags & ~(PAT_PURES|PAT_HAS_EXCLUDP);
-
- if (!(patflags & PAT_FILE)) {
- patcompcharsset();
- zpc_special[ZPC_SLASH] = Marker;
- remnulargs(patparse);
- if (isset(MULTIBYTE))
- patglobflags = GF_MULTIBYTE;
- else
- patglobflags = 0;
- }
- if (patflags & PAT_LCMATCHUC)
- patglobflags |= GF_LCMATCHUC;
- /*
- * Have to be set now, since they get updated during compilation.
- */
- ((Patprog)patout)->globflags = patglobflags;
-
- if (!(patflags & PAT_ANY)) {
- /* Look for a really pure string, with no tokens at all. */
- if (!(patglobflags & ~GF_MULTIBYTE)
-#ifdef __CYGWIN__
- /*
- * If the OS treats files case-insensitively and we
- * are looking at files, we don't need to use pattern
- * matching to find the file.
- */
- || (!(patglobflags & ~GF_IGNCASE) && (patflags & PAT_FILE))
-#endif
- )
- {
- /*
- * Waah! I wish I understood this.
- * Empty metafied strings have an initial Nularg.
- * This never corresponds to a real character in
- * a glob pattern or string, so skip it.
- */
- if (*exp == Nularg)
- exp++;
- for (strp = exp; *strp &&
- (!(patflags & PAT_FILE) || *strp != '/') && !itok(*strp);
- strp++)
- ;
- }
- if (!strp || (*strp && *strp != '/')) {
- /* No, do normal compilation. */
- strp = NULL;
- if (patcompswitch(0, &flags) == 0) {
- unqueue_signals();
- return NULL;
- }
- } else {
- /*
- * Yes, copy the string, and skip compilation altogether.
- * Null terminate for the benefit of globbing.
- * Leave metafied both for globbing and for our own
- * efficiency.
- */
- patparse = strp;
- len = strp - exp;
- patadd(exp, 0, len + 1, 0);
- patout[startoff + len] = '\0';
- patflags |= PAT_PURES;
- }
- }
-
- /* end of compilation: safe to use pointers */
- p = (Patprog)patout;
- p->startoff = startoff;
- p->patstartch = '\0';
- p->globend = patglobflags;
- p->flags = patflags;
- p->mustoff = 0;
- p->size = patsize;
- p->patmlen = len;
- p->patnpar = patnpar-1;
-
- if (!strp) {
- pscan = (Upat)(patout + startoff);
-
- if (!(patflags & PAT_ANY) && P_OP(PATNEXT(pscan)) == P_END) {
- /* only one top level choice */
- pscan = P_OPERAND(pscan);
-
- if (flags & P_PURESTR) {
- /*
- * The pattern can be matched with a simple strncmp/strcmp.
- * Careful in case we've overwritten the node for the next ptr.
- */
- char *dst = patout + startoff;
- Upat next;
- p->flags |= PAT_PURES;
- for (; pscan; pscan = next) {
- next = PATNEXT(pscan);
- if (P_OP(pscan) == P_EXACTLY) {
- char *opnd = P_LS_STR(pscan), *mtest;
- long oplen = P_LS_LEN(pscan), ilen;
- int nmeta = 0;
- /*
- * Unfortunately we unmetafied the string
- * and we need to put any metacharacters
- * back now we know it's a pure string.
- * This shouldn't happen too often, it's
- * just that there are some cases such
- * as . and .. in files where we really
- * need a pure string even if there are
- * pattern characters flying around.
- */
- for (mtest = opnd, ilen = oplen; ilen;
- mtest++, ilen--)
- if (imeta(*mtest))
- nmeta++;
- if (nmeta) {
- patadd(NULL, 0, nmeta, 0);
- p = (Patprog)patout;
- opnd = dupstring_wlen(opnd, oplen);
- dst = patout + startoff;
- }
-
- while (oplen--) {
- if (imeta(*opnd)) {
- *dst++ = Meta;
- *dst++ = *opnd++ ^ 32;
- } else {
- *dst++ = *opnd++;
- }
- }
- /* Only one string in a PAT_PURES, so now done. */
- break;
- }
- }
- p->size = dst - patout;
- /* patmlen is really strlen. We don't need a null. */
- p->patmlen = p->size - startoff;
- } else {
- /* starting point info */
- if (P_OP(pscan) == P_EXACTLY && !p->globflags &&
- P_LS_LEN(pscan))
- p->patstartch = *P_LS_STR(pscan);
- /*
- * Find the longest literal string in something expensive.
- * This is itself not all that cheap if we have
- * case-insensitive matching or approximation, so don't.
- */
- if ((flags & P_HSTART) && !p->globflags) {
- lng = NULL;
- len = 0;
- for (; pscan; pscan = PATNEXT(pscan))
- if (P_OP(pscan) == P_EXACTLY &&
- P_LS_LEN(pscan) >= len) {
- lng = P_LS_STR(pscan);
- len = P_LS_LEN(pscan);
- }
- if (lng) {
- p->mustoff = lng - patout;
- p->patmlen = len;
- }
- }
- }
- }
- }
-
- /*
- * The pattern was compiled in a fixed buffer: unless told otherwise,
- * we stick the compiled pattern on the heap. This is necessary
- * for files where we will often be compiling multiple segments at once.
- * But if we get the ZDUP flag we always put it in zalloc()ed memory.
- */
- if (patflags & PAT_ZDUP) {
- Patprog newp = (Patprog)zalloc(patsize);
- memcpy((char *)newp, (char *)p, patsize);
- p = newp;
- } else if (!(patflags & PAT_STATIC)) {
- Patprog newp = (Patprog)zhalloc(patsize);
- memcpy((char *)newp, (char *)p, patsize);
- p = newp;
- }
-
- if (endexp)
- *endexp = patparse;
-
- unqueue_signals();
- return p;
-}
-
-/*
- * Main body or parenthesized subexpression in pattern
- * Parenthesis (and any ksh_glob gubbins) will have been removed.
- */
-
-/**/
-static long
-patcompswitch(int paren, int *flagp)
-{
- long starter, br, ender, excsync = 0;
- int parno = 0;
- int flags, gfchanged = 0;
- long savglobflags = (long)patglobflags;
- Upat ptr;
-
- *flagp = 0;
-
- if (paren && (patglobflags & GF_BACKREF) && patnpar <= NSUBEXP) {
- /*
- * parenthesized: make an open node.
- * We can only refer to the first nine parentheses.
- * For any others, we just use P_OPEN on its own; there's
- * no gain in arbitrarily limiting the number of parentheses.
- */
- parno = patnpar++;
- starter = patnode(P_OPEN + parno);
- } else
- starter = 0;
-
- br = patnode(P_BRANCH);
- if (!patcompbranch(&flags, paren))
- return 0;
- if (patglobflags != (int)savglobflags)
- gfchanged++;
- if (starter)
- pattail(starter, br);
- else
- starter = br;
-
- *flagp |= flags & (P_HSTART|P_PURESTR);
-
- while (*patparse == zpc_chars[ZPC_BAR] ||
- (*patparse == zpc_special[ZPC_TILDE] &&
- (patparse[1] == '/' ||
- !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) {
- int tilde = *patparse++ == zpc_special[ZPC_TILDE];
- long gfnode = 0, newbr;
-
- *flagp &= ~P_PURESTR;
-
- if (tilde) {
- union upat up;
- /* excsync remembers the P_EXCSYNC node before a chain of
- * exclusions: all point back to this. only the
- * original (non-excluded) branch gets a trailing P_EXCSYNC.
- */
- if (!excsync) {
- excsync = patnode(P_EXCSYNC);
- patoptail(br, excsync);
- }
- /*
- * By default, approximations are turned off in exclusions:
- * we need to do this here as otherwise the code compiling
- * the exclusion doesn't know if the flags have really
- * changed if the error count gets restored.
- */
- patglobflags &= ~0xff;
- if (!(patflags & PAT_FILET) || paren) {
- br = patnode(P_EXCLUDE);
- } else {
- /*
- * At top level (paren == 0) in a file glob !(patflags
- * &PAT_FILET) do the exclusion prepending the file path
- * so far. We need to flag this to avoid unnecessarily
- * copying the path.
- */
- br = patnode(P_EXCLUDP);
- patflags |= PAT_HAS_EXCLUDP;
- }
- up.p = NULL;
- patadd((char *)&up, 0, sizeof(up), 0);
- /* / is not treated as special if we are at top level */
- if (!paren && zpc_special[ZPC_SLASH] == '/') {
- tilde++;
- zpc_special[ZPC_SLASH] = Marker;
- }
- } else {
- excsync = 0;
- br = patnode(P_BRANCH);
- /*
- * The position of the following statements means globflags
- * set in the main branch carry over to the exclusion.
- */
- if (!paren) {
- patglobflags = 0;
- if (((Patprog)patout)->globflags) {
- /*
- * If at top level, we need to reinitialize flags to zero,
- * since (#i)foo|bar only applies to foo and we stuck
- * the #i into the global flags.
- * We could have done it so that they only got set in the
- * first branch, but it's quite convenient having any
- * global flags set in the header and not buried in the
- * pattern. (Or maybe it isn't and we should
- * forget this bit and always stick in an explicit GFLAGS
- * statement instead of using the header.)
- * Also, this can't happen for file globs where there are
- * no top-level |'s.
- *
- * No gfchanged, as nothing to follow branch at top
- * level.
- */
- union upat up;
- gfnode = patnode(P_GFLAGS);
- up.l = patglobflags;
- patadd((char *)&up, 0, sizeof(union upat), 0);
- }
- } else {
- patglobflags = (int)savglobflags;
- }
- }
- newbr = patcompbranch(&flags, paren);
- if (tilde == 2) {
- /* restore special treatment of / */
- zpc_special[ZPC_SLASH] = '/';
- }
- if (!newbr)
- return 0;
- if (gfnode)
- pattail(gfnode, newbr);
- if (!tilde && patglobflags != (int)savglobflags)
- gfchanged++;
- pattail(starter, br);
- if (excsync)
- patoptail(br, patnode(P_EXCEND));
- *flagp |= flags & P_HSTART;
- }
-
- /*
- * Make a closing node, hooking it to the end.
- * Note that we can't optimize P_NOTHING out here, since another
- * branch at that point would indicate the current choices continue,
- * which they don't.
- */
- ender = patnode(paren ? parno ? P_CLOSE+parno : P_NOTHING : P_END);
- pattail(starter, ender);
-
- /*
- * Hook the tails of the branches to the closing node,
- * except for exclusions which terminate where they are.
- */
- for (ptr = (Upat)patout + starter; ptr; ptr = PATNEXT(ptr))
- if (!P_ISEXCLUDE(ptr))
- patoptail(ptr-(Upat)patout, ender);
-
- /* check for proper termination */
- if ((paren && *patparse++ != Outpar) ||
- (!paren && *patparse &&
- !((patflags & PAT_FILE) && *patparse == '/')))
- return 0;
-
- if (paren && gfchanged) {
- /*
- * Restore old values of flags when leaving parentheses.
- * gfchanged detects a change in any branch (except exclusions
- * which are separate), since we need to emit this even if
- * a later branch happened to put the flags back.
- */
- pattail(ender, patnode(P_GFLAGS));
- patglobflags = (int)savglobflags;
- patadd((char *)&savglobflags, 0, sizeof(long), 0);
- }
-
- return starter;
-}
-
-/*
- * Compile something ended by Bar, Outpar, Tilde, or end of string.
- * Note the BRANCH or EXCLUDE tag must already have been omitted:
- * this returns the position of the operand of that.
- */
-
-/**/
-static long
-patcompbranch(int *flagp, int paren)
-{
- long chain, latest = 0, starter;
- int flags = 0;
-
- *flagp = P_PURESTR;
-
- starter = chain = 0;
- while (!memchr(zpc_special, *patparse, ZPC_SEG_COUNT) ||
- (*patparse == zpc_special[ZPC_TILDE] && patparse[1] != '/' &&
- memchr(zpc_special, patparse[1], ZPC_SEG_COUNT))) {
- if ((*patparse == zpc_special[ZPC_INPAR] &&
- patparse[1] == zpc_special[ZPC_HASH]) ||
- (*patparse == zpc_special[ZPC_KSH_AT] && patparse[1] == Inpar &&
- patparse[2] == zpc_special[ZPC_HASH])) {
- /* Globbing flags. */
- char *pp1 = patparse;
- int oldglobflags = patglobflags, ignore;
- long assert;
- patparse += (*patparse == '@') ? 3 : 2;
- if (!patgetglobflags(&patparse, &assert, &ignore))
- return 0;
- if (!ignore) {
- if (assert) {
- /*
- * Start/end assertion looking like flags, but
- * actually handled as a normal node
- */
- latest = patnode(assert);
- flags = 0;
- } else {
- if (pp1 == patstart) {
- /* Right at start of pattern, the simplest case.
- * Put them into the flags and don't emit anything.
- */
- ((Patprog)patout)->globflags = patglobflags;
- continue;
- } else if (!*patparse) {
- /* Right at the end, so just leave the flags for
- * the next Patprog in the chain to pick up.
- */
- break;
- }
- /*
- * Otherwise, we have to stick them in as a pattern
- * matching nothing.
- */
- if (oldglobflags != patglobflags) {
- /* Flags changed */
- union upat up;
- latest = patnode(P_GFLAGS);
- up.l = patglobflags;
- patadd((char *)&up, 0, sizeof(union upat), 0);
- } else {
- /* No effect. */
- continue;
- }
- }
- } else if (!*patparse)
- break;
- else
- continue;
- } else if (*patparse == zpc_special[ZPC_HAT]) {
- /*
- * ^pat: anything but pat. For proper backtracking,
- * etc., we turn this into (*~pat), except without the
- * parentheses.
- */
- patparse++;
- latest = patcompnot(0, &flags);
- } else
- latest = patcomppiece(&flags, paren);
- if (!latest)
- return 0;
- if (!starter)
- starter = latest;
- if (!(flags & P_PURESTR))
- *flagp &= ~P_PURESTR;
- if (!chain)
- *flagp |= flags & P_HSTART;
- else
- pattail(chain, latest);
- chain = latest;
- }
- /* check if there was nothing in the loop, i.e. () */
- if (!chain)
- starter = patnode(P_NOTHING);
-
- return starter;
-}
-
-/* get glob flags, return 1 for success, 0 for failure */
-
-/**/
-int
-patgetglobflags(char **strp, long *assertp, int *ignore)
-{
- char *nptr, *ptr = *strp;
- zlong ret;
-
- *assertp = 0;
- *ignore = 1;
- /* (#X): assumes we are still positioned on the first X */
- for (; *ptr && *ptr != Outpar; ptr++) {
- if (*ptr == 'q') {
- /* Glob qualifiers, ignored in pattern code */
- while (*ptr && *ptr != Outpar)
- ptr++;
- break;
- } else {
- *ignore = 0;
- switch (*ptr) {
- case 'a':
- /* Approximate matching, max no. of errors follows */
- ret = zstrtol(++ptr, &nptr, 10);
- /*
- * We can't have more than 254, because we need 255 to
- * mark 254 errors in wbranch and exclude sync strings
- * (hypothetically --- hope no-one tries it).
- */
- if (ret < 0 || ret > 254 || ptr == nptr)
- return 0;
- patglobflags = (patglobflags & ~0xff) | (ret & 0xff);
- ptr = nptr-1;
- break;
-
- case 'l':
- /* Lowercase in pattern matches lower or upper in target */
- patglobflags = (patglobflags & ~GF_IGNCASE) | GF_LCMATCHUC;
- break;
-
- case 'i':
- /* Fully case insensitive */
- patglobflags = (patglobflags & ~GF_LCMATCHUC) | GF_IGNCASE;
- break;
-
- case 'I':
- /* Restore case sensitivity */
- patglobflags &= ~(GF_LCMATCHUC|GF_IGNCASE);
- break;
-
- case 'b':
- /* Make backreferences */
- patglobflags |= GF_BACKREF;
- break;
-
- case 'B':
- /* Don't make backreferences */
- patglobflags &= ~GF_BACKREF;
- break;
-
- case 'm':
- /* Make references to complete match */
- patglobflags |= GF_MATCHREF;
- break;
-
- case 'M':
- /* Don't */
- patglobflags &= ~GF_MATCHREF;
- break;
-
- case 's':
- *assertp = P_ISSTART;
- break;
-
- case 'e':
- *assertp = P_ISEND;
- break;
-
- case 'u':
- patglobflags |= GF_MULTIBYTE;
- break;
-
- case 'U':
- patglobflags &= ~GF_MULTIBYTE;
- break;
-
- default:
- return 0;
- }
- }
- }
- if (*ptr != Outpar)
- return 0;
- /* Start/end assertions must appear on their own. */
- if (*assertp && (*strp)[1] != Outpar)
- return 0;
- *strp = ptr + 1;
- return 1;
-}
-
-
-static const char *colon_stuffs[] = {
- "alpha", "alnum", "ascii", "blank", "cntrl", "digit", "graph",
- "lower", "print", "punct", "space", "upper", "xdigit", "IDENT",
- "IFS", "IFSSPACE", "WORD", "INCOMPLETE", "INVALID", NULL
-};
-
-/*
- * Handle the guts of a [:stuff:] character class element.
- * start is the beginning of "stuff" and len is its length.
- * This code is exported for the benefit of completion matching.
- */
-
-/**/
-mod_export int
-range_type(char *start, int len)
-{
- const char **csp;
-
- for (csp = colon_stuffs; *csp; csp++) {
- if (strlen(*csp) == len && !strncmp(start, *csp, len))
- return (csp - colon_stuffs) + PP_FIRST;
- }
-
- return PP_UNKWN;
-}
-
-
-/*
- * Convert the contents of a [...] or [^...] expression (just the
- * ... part) back into a string. This is used by compfiles -p/-P
- * for some reason. The compiled form (a metafied string) is
- * passed in rangestr.
- *
- * If outstr is non-NULL the compiled form is placed there. It
- * must be sufficiently long. A terminating NULL is appended.
- *
- * Return the length required, not including the terminating NULL.
- *
- * TODO: this is non-multibyte for now. It will need to be defined
- * appropriately with MULTIBYTE_SUPPORT when the completion matching
- * code catches up.
- */
-
-/**/
-mod_export int
-pattern_range_to_string(char *rangestr, char *outstr)
-{
- int len = 0;
-
- while (*rangestr) {
- if (imeta(STOUC(*rangestr))) {
- int swtype = STOUC(*rangestr) - STOUC(Meta);
-
- if (swtype == 0) {
- /* Ordindary metafied character */
- if (outstr)
- {
- *outstr++ = Meta;
- *outstr++ = rangestr[1] ^ 32;
- }
- len += 2;
- rangestr += 2;
- } else if (swtype == PP_RANGE) {
- /* X-Y range */
- int i;
-
- for (i = 0; i < 2; i++) {
- if (*rangestr == Meta) {
- if (outstr) {
- *outstr++ = Meta;
- *outstr++ = rangestr[1];
- }
- len += 2;
- rangestr += 2;
- } else {
- if (outstr)
- *outstr++ = *rangestr;
- len++;
- rangestr++;
- }
-
- if (i == 0) {
- if (outstr)
- *outstr++ = '-';
- len++;
- }
- }
- } else if (swtype >= PP_FIRST && swtype <= PP_LAST) {
- /* [:stuff:]; we need to output [: and :] */
- const char *found = colon_stuffs[swtype - PP_FIRST];
- int newlen = strlen(found);
- if (outstr) {
- strcpy(outstr, "[:");
- outstr += 2;
- memcpy(outstr, found, newlen);
- outstr += newlen;
- strcpy(outstr, ":]");
- outstr += 2;
- }
- len += newlen + 4;
- rangestr++;
- } else {
- /* shouldn't happen */
- DPUTS(1, "BUG: unknown PP_ code in pattern range");
- rangestr++;
- }
- } else {
- /* ordinary character, guaranteed no Meta handling needed */
- if (outstr)
- *outstr++ = *rangestr;
- len++;
- rangestr++;
- }
- }
-
- if (outstr)
- *outstr = '\0';
- return len;
-}
-
-/*
- * compile a chunk such as a literal string or a [...] followed
- * by a possible hash operator
- */
-
-/**/
-static long
-patcomppiece(int *flagp, int paren)
-{
- long starter = 0, next, op, opnd;
- int flags, flags2, kshchar, len, ch, patch, nmeta;
- int hash, count;
- union upat up;
- char *nptr, *str0, *ptr, *patprev;
- zrange_t from, to;
- char *charstart;
-
- flags = 0;
- str0 = patprev = patparse;
- for (;;) {
- /*
- * Check if we have a string. First, we need to make sure
- * the string doesn't introduce a ksh-like parenthesized expression.
- */
- kshchar = '\0';
- if (*patparse && patparse[1] == Inpar) {
- if (*patparse == zpc_special[ZPC_KSH_PLUS])
- kshchar = STOUC('+');
- else if (*patparse == zpc_special[ZPC_KSH_BANG])
- kshchar = STOUC('!');
- else if (*patparse == zpc_special[ZPC_KSH_BANG2])
- kshchar = STOUC('!');
- else if (*patparse == zpc_special[ZPC_KSH_AT])
- kshchar = STOUC('@');
- else if (*patparse == zpc_special[ZPC_KSH_STAR])
- kshchar = STOUC('*');
- else if (*patparse == zpc_special[ZPC_KSH_QUEST])
- kshchar = STOUC('?');
- }
-
- /*
- * If '(' is disabled as a pattern char, allow ')' as
- * an ordinary string character if there are no parentheses to
- * close. Don't allow it otherwise, it changes the syntax.
- */
- if (zpc_special[ZPC_INPAR] != Marker || *patparse != Outpar ||
- paren) {
- /*
- * End of string (or no string at all) if ksh-type parentheses,
- * or special character, unless that character is a tilde and
- * the character following is an end-of-segment character. Thus
- * tildes are not special if there is nothing following to
- * be excluded.
- *
- * Don't look for X()-style kshglobs at this point; we've
- * checked above for the case with parentheses and we don't
- * want to match without parentheses.
- */
- if (kshchar ||
- (memchr(zpc_special, *patparse, ZPC_NO_KSH_GLOB) &&
- (*patparse != zpc_special[ZPC_TILDE] ||
- patparse[1] == '/' ||
- !memchr(zpc_special, patparse[1], ZPC_SEG_COUNT)))) {
- break;
- }
- }
-
- /* Remember the previous character for backtracking */
- patprev = patparse;
- METACHARINC(patparse);
- }
-
- if (patparse > str0) {
- long slen = patparse - str0;
- int morelen;
-
- /* Ordinary string: cancel kshchar lookahead */
- kshchar = '\0';
- /*
- * Assume it matches a simple string until we find otherwise.
- */
- flags |= P_PURESTR;
- DPUTS(patparse == str0, "BUG: matched nothing in patcomppiece.");
- /* more than one character matched? */
- morelen = (patprev > str0);
- /*
- * If we have more than one character, a following hash
- * or (#c...) only applies to the last, so backtrack one character.
- */
- if ((*patparse == zpc_special[ZPC_HASH] ||
- (*patparse == zpc_special[ZPC_INPAR] &&
- patparse[1] == zpc_special[ZPC_HASH] &&
- patparse[2] == 'c') ||
- (*patparse == zpc_special[ZPC_KSH_AT] &&
- patparse[1] == Inpar &&
- patparse[2] == zpc_special[ZPC_HASH] &&
- patparse[3] == 'c')) && morelen)
- patparse = patprev;
- /*
- * If len is 1, we can't have an active # following, so doesn't
- * matter that we don't make X in `XX#' simple.
- */
- if (!morelen)
- flags |= P_SIMPLE;
- starter = patnode(P_EXACTLY);
-
- /* Get length of string without metafication. */
- nmeta = 0;
- /* inherited from domatch, but why, exactly? */
- if (*str0 == Nularg)
- str0++;
- for (ptr = str0; ptr < patparse; ptr++) {
- if (*ptr == Meta) {
- nmeta++;
- ptr++;
- }
- }
- slen = (patparse - str0) - nmeta;
- /* First add length, which is a long */
- patadd((char *)&slen, 0, sizeof(long), 0);
- /*
- * Then the string, not null terminated.
- * Unmetafy and untokenize; pass the final length,
- * which is what we need to allocate, i.e. not including
- * a count for each Meta in the string.
- */
- patadd(str0, 0, slen, PA_UNMETA);
- nptr = P_LS_STR((Upat)patout + starter);
- /*
- * It's much simpler to turn off pure string mode for
- * any case-insensitive or approximate matching; usually,
- * that is correct, or they wouldn't have been turned on.
- * However, we need to make sure we match a "." or ".."
- * in a file name as a pure string. There's a minor bug
- * that this will also apply to something like
- * ..(#a1).. (i.e. the (#a1) has no effect), but if you're
- * going to write funny patterns, you get no sympathy from me.
- */
- if (patglobflags &
-#ifdef __CYGWIN__
- /*
- * As above: don't use pattern matching for files
- * just because of case insensitivity if file system
- * is known to be case insensitive.
- *
- * This is known to be necessary in at least one case:
- * if "mount -c /" is in effect, so that drives appear
- * directly under / instead of the usual /cygdrive, they
- * aren't shown by readdir(). So it's vital we don't use
- * globbing to find "/c", since that'll fail.
- */
- ((patflags & PAT_FILE) ?
- (0xFF|GF_LCMATCHUC) :
- (0xFF|GF_LCMATCHUC|GF_IGNCASE))
-#else
- (0xFF|GF_LCMATCHUC|GF_IGNCASE)
-#endif
- ) {
- if (!(patflags & PAT_FILE))
- flags &= ~P_PURESTR;
- else if (!(nptr[0] == '.' &&
- (slen == 1 || (nptr[1] == '.' && slen == 2))))
- flags &= ~P_PURESTR;
- }
- } else {
- if (kshchar)
- patparse++;
-
- patch = *patparse;
- METACHARINC(patparse);
- switch(patch) {
- case Quest:
- DPUTS(zpc_special[ZPC_QUEST] == Marker,
- "Treating '?' as pattern character although disabled");
- flags |= P_SIMPLE;
- starter = patnode(P_ANY);
- break;
- case Star:
- DPUTS(zpc_special[ZPC_STAR] == Marker,
- "Treating '*' as pattern character although disabled");
- /* kshchar is used as a sign that we can't have #'s. */
- kshchar = -1;
- starter = patnode(P_STAR);
- break;
- case Inbrack:
- DPUTS(zpc_special[ZPC_INBRACK] == Marker,
- "Treating '[' as pattern character although disabled");
- flags |= P_SIMPLE;
- if (*patparse == Hat || *patparse == Bang) {
- patparse++;
- starter = patnode(P_ANYBUT);
- } else
- starter = patnode(P_ANYOF);
- /*
- * []...] means match a "]" or other included characters.
- * However, to be a bit helpful and for compatibility
- * with other shells, don't take in that sense if
- * there's no further "]". That's still imperfect,
- * but it's all we can do --- we're required to
- * treat [$var]*[$var]with empty var as [ ... ]
- * containing "]*[".
- */
- if (*patparse == Outbrack && strchr(patparse+1, Outbrack)) {
- patparse++;
- patadd(NULL, ']', 1, PA_NOALIGN);
- }
- while (*patparse && *patparse != Outbrack) {
- /* Meta is not a token */
- if (*patparse == Inbrack && patparse[1] == ':' &&
- (nptr = strchr(patparse+2, ':')) &&
- nptr[1] == Outbrack) {
- /* Posix range. */
- patparse += 2;
- len = nptr - patparse;
- ch = range_type(patparse, len);
- patparse = nptr + 2;
- if (ch != PP_UNKWN)
- patadd(NULL, STOUC(Meta) + ch, 1, PA_NOALIGN);
- continue;
- }
- charstart = patparse;
- METACHARINC(patparse);
-
- if (*patparse == Dash && patparse[1] &&
- patparse[1] != Outbrack) {
- patadd(NULL, STOUC(Meta)+PP_RANGE, 1, PA_NOALIGN);
- if (itok(*charstart)) {
- patadd(0, STOUC(ztokens[*charstart - Pound]), 1,
- PA_NOALIGN);
- } else {
- patadd(charstart, 0, patparse-charstart, PA_NOALIGN);
- }
- charstart = ++patparse; /* skip Dash token */
- METACHARINC(patparse);
- }
- if (itok(*charstart)) {
- patadd(0, STOUC(ztokens[*charstart - Pound]), 1,
- PA_NOALIGN);
- } else {
- patadd(charstart, 0, patparse-charstart, PA_NOALIGN);
- }
- }
- if (*patparse != Outbrack)
- return 0;
- patparse++;
- /* terminate null string and fix alignment */
- patadd(NULL, 0, 1, 0);
- break;
- case Inpar:
- DPUTS(!kshchar && zpc_special[ZPC_INPAR] == Marker,
- "Treating '(' as pattern character although disabled");
- DPUTS(isset(SHGLOB) && !kshchar,
- "Treating bare '(' as pattern character with SHGLOB");
- if (kshchar == '!') {
- /* This is nasty, we should really either handle all
- * kshglobbing below or here. But most of the
- * others look like non-ksh patterns, while this one
- * doesn't, so we handle it here and leave the rest.
- * We treat it like an extendedglob ^, except that
- * it goes into parentheses.
- *
- * If we did do kshglob here, we could support
- * the old behaviour that things like !(foo)##
- * work, but it makes the code more complicated at
- * the expense of allowing the user to do things
- * they shouldn't.
- */
- if (!(starter = patcompnot(1, &flags2)))
- return 0;
- } else if (!(starter = patcompswitch(1, &flags2)))
- return 0;
- flags |= flags2 & P_HSTART;
- break;
- case Inang:
- /* Numeric glob */
- DPUTS(zpc_special[ZPC_INANG] == Marker,
- "Treating '<' as pattern character although disabled");
- DPUTS(isset(SHGLOB), "Treating <..> as numeric range with SHGLOB");
- len = 0; /* beginning present 1, end present 2 */
- if (idigit(*patparse)) {
- from = (zrange_t) zstrtol((char *)patparse,
- (char **)&nptr, 10);
- patparse = nptr;
- len |= 1;
- }
- DPUTS(!IS_DASH(*patparse), "BUG: - missing from numeric glob");
- patparse++;
- if (idigit(*patparse)) {
- to = (zrange_t) zstrtol((char *)patparse,
- (char **)&nptr, 10);
- patparse = nptr;
- len |= 2;
- }
- if (*patparse != Outang)
- return 0;
- patparse++;
- switch(len) {
- case 3:
- starter = patnode(P_NUMRNG);
- patadd((char *)&from, 0, sizeof(from), 0);
- patadd((char *)&to, 0, sizeof(to), 0);
- break;
- case 2:
- starter = patnode(P_NUMTO);
- patadd((char *)&to, 0, sizeof(to), 0);
- break;
- case 1:
- starter = patnode(P_NUMFROM);
- patadd((char *)&from, 0, sizeof(from), 0);
- break;
- case 0:
- starter = patnode(P_NUMANY);
- break;
- }
- /* This can't be simple, because it isn't.
- * Mention in manual that matching digits with [...]
- * is more efficient.
- */
- break;
- case Pound:
- DPUTS(zpc_special[ZPC_HASH] == Marker,
- "Treating '#' as pattern character although disabled");
- DPUTS(!isset(EXTENDEDGLOB), "BUG: # not treated as string");
- /*
- * A hash here is an error; it should follow something
- * repeatable.
- */
- return 0;
- break;
- case Bnullkeep:
- /*
- * Marker for restoring a backslash in output:
- * does not match a character.
- */
- next = patcomppiece(flagp, paren);
- /*
- * Can't match a pure string since we need to do this
- * as multiple chunks.
- */
- *flagp &= ~P_PURESTR;
- return next;
- break;
-#ifdef DEBUG
- default:
- dputs("BUG: character not handled in patcomppiece");
- return 0;
- break;
-#endif
- }
- }
-
- count = 0;
- if (!(hash = (*patparse == zpc_special[ZPC_HASH])) &&
- !(count = ((*patparse == zpc_special[ZPC_INPAR] &&
- patparse[1] == zpc_special[ZPC_HASH] &&
- patparse[2] == 'c') ||
- (*patparse == zpc_special[ZPC_KSH_AT] &&
- patparse[1] == Inpar &&
- patparse[2] == zpc_special[ZPC_HASH] &&
- patparse[3] == 'c'))) &&
- (kshchar <= 0 || kshchar == '@' || kshchar == '!')) {
- *flagp = flags;
- return starter;
- }
-
- /* too much at once doesn't currently work */
- if (kshchar && (hash || count))
- return 0;
-
- if (kshchar == '*') {
- op = P_ONEHASH;
- *flagp = P_HSTART;
- } else if (kshchar == '+') {
- op = P_TWOHASH;
- *flagp = P_HSTART;
- } else if (kshchar == '?') {
- op = 0;
- *flagp = 0;
- } else if (count) {
- op = P_COUNT;
- patparse += 3;
- *flagp = P_HSTART;
- } else if (*++patparse == zpc_special[ZPC_HASH]) {
- op = P_TWOHASH;
- patparse++;
- *flagp = P_HSTART;
- } else {
- op = P_ONEHASH;
- *flagp = P_HSTART;
- }
-
- /*
- * Note optimizations with pointers into P_NOTHING branches: some
- * should logically point to next node after current piece.
- *
- * Backtracking is also encoded in a slightly obscure way: the
- * code emitted ensures we test the non-empty branch of complex
- * patterns before the empty branch on each repetition. Hence
- * each time we fail on a non-empty branch, we try the empty branch,
- * which is equivalent to backtracking.
- */
- if (op == P_COUNT) {
- /* (#cN,M) */
- union upat countargs[P_CT_OPERAND];
- char *opp = patparse;
-
- countargs[0].l = P_COUNT;
- countargs[P_CT_CURRENT].l = 0L;
- countargs[P_CT_MIN].l = (long)zstrtol(patparse, &patparse, 10);
- if (patparse == opp) {
- /* missing number treated as zero */
- countargs[P_CT_MIN].l = 0L;
- }
- if (*patparse != ',' && *patparse != Comma) {
- /* either max = min or error */
- if (*patparse != Outpar)
- return 0;
- countargs[P_CT_MAX].l = countargs[P_CT_MIN].l;
- } else {
- opp = ++patparse;
- countargs[P_CT_MAX].l = (long)zstrtol(patparse, &patparse, 10);
- if (*patparse != Outpar)
- return 0;
- if (patparse == opp) {
- /* missing number treated as infinity: record as -1 */
- countargs[P_CT_MAX].l = -1L;
- }
- }
- patparse++;
- countargs[P_CT_PTR].p = NULL;
- /* Mark this chain as a min/max count... */
- patinsert(P_COUNTSTART, starter, (char *)countargs, sizeof(countargs));
- /*
- * The next of the operand is a loop back to the P_COUNT. This is
- * how we get recursion for the count. We don't loop back to
- * the P_COUNTSTART; that's used for initialising the count
- * and saving and restoring the count for any enclosing use
- * of the match.
- */
- opnd = P_OPERAND(starter) + P_CT_OPERAND;
- pattail(opnd, patnode(P_BACK));
- pattail(opnd, P_OPERAND(starter));
- /*
- * The next of the counter operators is what follows the
- * closure.
- * This handles matching of the tail.
- */
- next = patnode(P_NOTHING);
- pattail(starter, next);
- pattail(P_OPERAND(starter), next);
- } else if ((flags & P_SIMPLE) && (op == P_ONEHASH || op == P_TWOHASH) &&
- P_OP((Upat)patout+starter) == P_ANY) {
- /* Optimize ?# to *. Silly thing to do, since who would use
- * use ?# ? But it makes the later code shorter.
- */
- Upat uptr = (Upat)patout + starter;
- if (op == P_TWOHASH) {
- /* ?## becomes ?* */
- uptr->l = (uptr->l & ~0xff) | P_ANY;
- pattail(starter, patnode(P_STAR));
- } else {
- uptr->l = (uptr->l & ~0xff) | P_STAR;
- }
- } else if ((flags & P_SIMPLE) && op && !(patglobflags & 0xff)) {
- /* Simplify, but not if we need to look for approximations. */
- patinsert(op, starter, NULL, 0);
- } else if (op == P_ONEHASH) {
- /* Emit x# as (x&|), where & means "self". */
- up.p = NULL;
- patinsert(P_WBRANCH, starter, (char *)&up, sizeof(up));
- /* Either x */
- patoptail(starter, patnode(P_BACK)); /* and loop */
- patoptail(starter, starter); /* back */
- pattail(starter, patnode(P_BRANCH)); /* or */
- pattail(starter, patnode(P_NOTHING)); /* null. */
- } else if (op == P_TWOHASH) {
- /* Emit x## as x(&|) where & means "self". */
- next = patnode(P_WBRANCH); /* Either */
- up.p = NULL;
- patadd((char *)&up, 0, sizeof(up), 0);
- pattail(starter, next);
- pattail(patnode(P_BACK), starter); /* loop back */
- pattail(next, patnode(P_BRANCH)); /* or */
- pattail(starter, patnode(P_NOTHING)); /* null. */
- } else if (kshchar == '?') {
- /* Emit ?(x) as (x|) */
- patinsert(P_BRANCH, starter, NULL, 0); /* Either x */
- pattail(starter, patnode(P_BRANCH)); /* or */
- next = patnode(P_NOTHING); /* null */
- pattail(starter, next);
- patoptail(starter, next);
- }
- if (*patparse == zpc_special[ZPC_HASH])
- return 0;
-
- return starter;
-}
-
-/*
- * Turn a ^foo (paren = 0) or !(foo) (paren = 1) into *~foo with
- * parentheses if necessary. As you see, that's really quite easy.
- */
-
-/**/
-static long
-patcompnot(int paren, int *flagsp)
-{
- union upat up;
- long excsync, br, excl, n, starter;
- int dummy;
-
- /* Here, we're matching a star at the start. */
- *flagsp = P_HSTART;
-
- starter = patnode(P_BRANCH);
- br = patnode(P_STAR);
- excsync = patnode(P_EXCSYNC);
- pattail(br, excsync);
- pattail(starter, excl = patnode(P_EXCLUDE));
- up.p = NULL;
- patadd((char *)&up, 0, sizeof(up), 0);
- if (!(br = (paren ? patcompswitch(1, &dummy) : patcompbranch(&dummy, 0))))
- return 0;
- pattail(br, patnode(P_EXCEND));
- n = patnode(P_NOTHING); /* just so much easier */
- pattail(excsync, n);
- pattail(excl, n);
-
- return starter;
-}
-
-/* Emit a node */
-
-/**/
-static long
-patnode(long op)
-{
- long starter = (Upat)patcode - (Upat)patout;
- union upat up;
-
- up.l = op;
- patadd((char *)&up, 0, sizeof(union upat), 0);
- return starter;
-}
-
-/*
- * insert an operator in front of an already emitted operand:
- * we relocate the operand. there had better be nothing else after.
- */
-
-/**/
-static void
-patinsert(long op, int opnd, char *xtra, int sz)
-{
- char *src, *dst, *opdst;
- union upat buf, *lptr;
-
- buf.l = 0;
- patadd((char *)&buf, 0, sizeof(buf), 0);
- if (sz)
- patadd(xtra, 0, sz, 0);
- src = patcode - sizeof(union upat) - sz;
- dst = patcode;
- opdst = patout + opnd * sizeof(union upat);
- while (src > opdst)
- *--dst = *--src;
-
- /* A cast can't be an lvalue */
- lptr = (Upat)opdst;
- lptr->l = op;
- opdst += sizeof(union upat);
- while (sz--)
- *opdst++ = *xtra++;
-}
-
-/* set the 'next' pointer at the end of a node chain */
-
-/**/
-static void
-pattail(long p, long val)
-{
- Upat scan, temp;
- long offset;
-
- scan = (Upat)patout + p;
- for (;;) {
- if (!(temp = PATNEXT(scan)))
- break;
- scan = temp;
- }
-
- offset = (P_OP(scan) == P_BACK)
- ? (scan - (Upat)patout) - val : val - (scan - (Upat)patout);
-
- scan->l |= offset << 8;
-}
-
-/* do pattail, but on operand of first argument; nop if operandless */
-
-/**/
-static void
-patoptail(long p, long val)
-{
- Upat ptr = (Upat)patout + p;
- int op = P_OP(ptr);
- if (!p || !P_ISBRANCH(ptr))
- return;
- if (op == P_BRANCH)
- pattail(P_OPERAND(p), val);
- else
- pattail(P_OPERAND(p) + 1, val);
-}
-
-
-/*
- * Run a pattern.
- */
-struct rpat {
- char *patinstart; /* Start of input string */
- char *patinend; /* End of input string */
- char *patinput; /* String input pointer */
- char *patinpath; /* Full path for use with ~ exclusions */
- int patinlen; /* Length of last successful match.
- * Includes count of Meta characters.
- */
-
- char *patbeginp[NSUBEXP]; /* Pointer to backref beginnings */
- char *patendp[NSUBEXP]; /* Pointer to backref ends */
- int parsfound; /* parentheses (with backrefs) found */
-
- int globdots; /* Glob initial dots? */
-};
-
-static struct rpat pattrystate;
-
-#define patinstart (pattrystate.patinstart)
-#define patinend (pattrystate.patinend)
-#define patinput (pattrystate.patinput)
-#define patinpath (pattrystate.patinpath)
-#define patinlen (pattrystate.patinlen)
-#define patbeginp (pattrystate.patbeginp)
-#define patendp (pattrystate.patendp)
-#define parsfound (pattrystate.parsfound)
-#define globdots (pattrystate.globdots)
-
-
-/*
- * Character functions operating on unmetafied strings.
- */
-#ifdef MULTIBYTE_SUPPORT
-
-/* Get a character from the start point in a string */
-#define CHARREF(x, y) charref((x), (y), (int *)NULL)
-static wchar_t
-charref(char *x, char *y, int *zmb_ind)
-{
- wchar_t wc;
- size_t ret;
-
- if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*x) & 0x80))
- return (wchar_t) STOUC(*x);
-
- ret = mbrtowc(&wc, x, y-x, &shiftstate);
-
- if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- /* Error. */
- /* Reset the shift state for next time. */
- memset(&shiftstate, 0, sizeof(shiftstate));
- if (zmb_ind)
- *zmb_ind = (ret == MB_INVALID) ? ZMB_INVALID : ZMB_INCOMPLETE;
- return WCHAR_INVALID(*x);
- }
-
- if (zmb_ind)
- *zmb_ind = ZMB_VALID;
- return wc;
-}
-
-/* Get a pointer to the next character */
-#define CHARNEXT(x, y) charnext((x), (y))
-static char *
-charnext(char *x, char *y)
-{
- wchar_t wc;
- size_t ret;
-
- if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*x) & 0x80))
- return x + 1;
-
- ret = mbrtowc(&wc, x, y-x, &shiftstate);
-
- if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- /* Error. Treat as single byte. */
- /* Reset the shift state for next time. */
- memset(&shiftstate, 0, sizeof(shiftstate));
- return x + 1;
- }
-
- /* Nulls here are normal characters */
- return x + (ret ? ret : 1);
-}
-
-/* Increment a pointer past the current character. */
-#define CHARINC(x, y) ((x) = charnext((x), (y)))
-
-
-/* Get a character and increment */
-#define CHARREFINC(x, y, z) charrefinc(&(x), (y), (z))
-static wchar_t
-charrefinc(char **x, char *y, int *z)
-{
- wchar_t wc;
- size_t ret;
-
- if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(**x) & 0x80))
- return (wchar_t) STOUC(*(*x)++);
-
- ret = mbrtowc(&wc, *x, y-*x, &shiftstate);
-
- if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- /* Error. Treat as single byte, but flag. */
- *z = 1;
- /* Reset the shift state for next time. */
- memset(&shiftstate, 0, sizeof(shiftstate));
- return WCHAR_INVALID(*(*x)++);
- }
-
- /* Nulls here are normal characters */
- *x += ret ? ret : 1;
-
- return wc;
-}
-
-
-/*
- * Counter the number of characters between two pointers, smaller first
- *
- * This is used when setting values in parameters, so we obey
- * the MULTIBYTE option (even if it's been overridden locally).
- */
-#define CHARSUB(x,y) charsub(x, y)
-static ptrdiff_t
-charsub(char *x, char *y)
-{
- ptrdiff_t res = 0;
- size_t ret;
- wchar_t wc;
-
- if (!isset(MULTIBYTE))
- return y - x;
-
- while (x < y) {
- ret = mbrtowc(&wc, x, y-x, &shiftstate);
-
- if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- /* Error. Treat remainder as single characters */
- return res + (y - x);
- }
-
- /* Treat nulls as normal characters */
- if (!ret)
- ret = 1;
- res++;
- x += ret;
- }
-
- return res;
-}
-
-#else /* no MULTIBYTE_SUPPORT */
-
-/* Get a character from the start point in a string */
-#define CHARREF(x, y) (STOUC(*(x)))
-/* Get a pointer to the next character */
-#define CHARNEXT(x, y) ((x)+1)
-/* Increment a pointer past the current character. */
-#define CHARINC(x, y) ((x)++)
-/* Get a character and increment */
-#define CHARREFINC(x, y, z) (STOUC(*(x)++))
-/* Counter the number of characters between two pointers, smaller first */
-#define CHARSUB(x,y) ((y) - (x))
-
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * The following need to be accessed in the globbing scanner for
- * a multi-component file path. See horror story in glob.c.
- */
-/**/
-int errsfound; /* Total error count so far */
-
-/**/
-int forceerrs; /* Forced maximum error count */
-
-/**/
-void
-pattrystart(void)
-{
- forceerrs = -1;
- errsfound = 0;
-}
-
-/*
- * Fix up string length stuff.
- *
- * If we call patallocstr() with "force" to set things up early, it's
- * done there, else it's done in pattryrefs(). The reason for the
- * difference is in the latter case we may not be relying on
- * patallocstr() having an effect.
- */
-
-/**/
-static void
-patmungestring(char **string, int *stringlen, int *unmetalenin)
-{
- /*
- * Special signalling of empty tokenised string.
- */
- if (*stringlen > 0 && **string == Nularg) {
- (*string)++;
- /*
- * If we don't have an unmetafied length
- * and need it (we may not) we'll get it later.
- */
- if (*unmetalenin > 0)
- (*unmetalenin)--;
- if (*stringlen > 0)
- (*stringlen)--;
- }
-
- /* Ensure we have a metafied length */
- if (*stringlen < 0)
- *stringlen = strlen(*string);
-}
-
-/*
- * Allocate memeory for pattern match. Note this is specific to use
- * of pattern *and* trial string.
- *
- * Unmetafy a trial string for use in pattern matching, if needed.
- *
- * If it is needed, returns a heap allocated string; if not needed,
- * returns NULL.
- *
- * prog is the pattern to be executed.
- * string is the metafied trial string.
- * stringlen is it's length; it will be calculated if it's negative
- * (this is a simple strlen()).
- * unmetalen is the unmetafied length of the string, may be -1.
- * force is 1 if we always unmetafy: this is useful if we are going
- * to try again with different versions of the string. If this is
- * called from pattryrefs() we don't force unmetafication as it won't
- * be optimal. This option should be used if the resulting
- * patstralloc is going to be passed to pattrylen() / pattryrefs().
- * In patstralloc (supplied by caller, must last until last pattry is done)
- * unmetalen is the unmetafied length of the string; it will be
- * calculated if the input value is negative.
- * unmetalenp is the umetafied length of a path segment preceeding
- * the trial string needed for file mananagement; it is calculated as
- * needed so does not need to be initialised.
- * alloced is the memory allocated on the heap --- same as return value from
- * function.
- */
-/**/
-mod_export
-char *patallocstr(Patprog prog, char *string, int stringlen, int unmetalen,
- int force, Patstralloc patstralloc)
-{
- int needfullpath;
-
- if (force)
- patmungestring(&string, &stringlen, &unmetalen);
-
- /*
- * For a top-level ~-exclusion, we will need the full
- * path to exclude, so copy the path so far and append the
- * current test string.
- */
- needfullpath = (prog->flags & PAT_HAS_EXCLUDP) && pathpos;
-
- /* Get the length of the full string when unmetafied. */
- if (unmetalen < 0)
- patstralloc->unmetalen = ztrsub(string + stringlen, string);
- else
- patstralloc->unmetalen = unmetalen;
- if (needfullpath) {
- patstralloc->unmetalenp = ztrsub(pathbuf + pathpos, pathbuf);
- if (!patstralloc->unmetalenp)
- needfullpath = 0;
- } else
- patstralloc->unmetalenp = 0;
- /* Initialise cache area */
- patstralloc->progstrunmeta = NULL;
- patstralloc->progstrunmetalen = 0;
-
- DPUTS(needfullpath && (prog->flags & (PAT_PURES|PAT_ANY)),
- "rum sort of file exclusion");
- /*
- * Partly for efficiency, and partly for the convenience of
- * globbing, we don't unmetafy pure string patterns, and
- * there's no reason to if the pattern is just a *.
- */
- if (force ||
- (!(prog->flags & (PAT_PURES|PAT_ANY))
- && (needfullpath || patstralloc->unmetalen != stringlen))) {
- /*
- * We need to copy if we need to prepend the path so far
- * (in which case we copy both chunks), or if we have
- * Meta characters.
- */
- char *dst, *ptr;
- int i, icopy, ncopy;
-
- dst = patstralloc->alloced =
- zhalloc(patstralloc->unmetalen + patstralloc->unmetalenp);
-
- if (needfullpath) {
- /* loop twice, copy path buffer first time */
- ptr = pathbuf;
- ncopy = patstralloc->unmetalenp;
- } else {
- /* just loop once, copy string with unmetafication */
- ptr = string;
- ncopy = patstralloc->unmetalen;
- }
- for (icopy = 0; icopy < 2; icopy++) {
- for (i = 0; i < ncopy; i++) {
- if (*ptr == Meta) {
- ptr++;
- *dst++ = *ptr++ ^ 32;
- } else {
- *dst++ = *ptr++;
- }
- }
- if (!needfullpath)
- break;
- /* next time append test string to path so far */
- ptr = string;
- ncopy = patstralloc->unmetalen;
- }
- }
- else
- {
- patstralloc->alloced = NULL;
- }
-
- return patstralloc->alloced;
-}
-
-
-/*
- * Test prog against null-terminated, metafied string.
- */
-
-/**/
-mod_export int
-pattry(Patprog prog, char *string)
-{
- return pattryrefs(prog, string, -1, -1, NULL, 0, NULL, NULL, NULL);
-}
-
-/*
- * Test prog against string of given length, no null termination
- * but still metafied at this point. offset gives an offset
- * to include in reported match indices
- */
-
-/**/
-mod_export int
-pattrylen(Patprog prog, char *string, int len, int unmetalen,
- Patstralloc patstralloc, int offset)
-{
- return pattryrefs(prog, string, len, unmetalen, patstralloc, offset,
- NULL, NULL, NULL);
-}
-
-/*
- * Test prog against string with given lengths. The input
- * string is metafied; stringlen is the raw string length, and
- * unmetalen the number of characters in the original string (some
- * of which may now be metafied). Either value may be -1
- * to indicate a null-terminated string which will be counted. Note
- * there may be a severe penalty for this if a lot of matching is done
- * on one string.
- *
- * If patstralloc is not NULL it is used to optimise unmetafication
- * of a trial string that may be passed (or any substring may be passed) to
- * pattryrefs multiple times or the same pattern (N.B. so patstralloc
- * depends on both prog *and* the trial string). This should only be
- * done if there is no path prefix (pathpos == 0) as otherwise the path
- * buffer and unmetafied string may not match. To do this,
- * patallocstr() is callled (use force = 1 to ensure it is alway
- * unmetafied); paststralloc points to existing storage. Memory is
- * on the heap.
- *
- * patstralloc->alloced and patstralloc->unmetalen contain the
- * unmetafied string and its length. In that case, the rules for the
- * earlier arguments change:
- * - string is an unmetafied string
- * - stringlen is its unmetafied (i.e. actual) length
- * - unmetalenin is not used.
- * string and stringlen may refer to arbitrary substrings of
- * patstralloc->alloced without any internal modification to patstralloc.
- *
- * patoffset is the position in the original string (not seen by
- * the pattern module) at which we are trying to match.
- * This is added in to the positions recorded in patbeginp and patendp
- * when we are looking for substrings. Currently this only happens
- * in the parameter substitution code. It refers to a real character
- * offset, i.e. is already in the form ready for presentation to the
- * general public --- this is necessary as we don't have the
- * information to convert it down here.
- *
- * Note this is a character offset, i.e. a single possibly metafied and
- * possibly multibyte character counts as 1.
- *
- * The last three arguments are used to report the positions for the
- * backreferences. On entry, *nump should contain the maximum number
- * of positions to report. In this case the match, mbegin, mend
- * arrays are not altered.
- *
- * If nump is NULL but endp is not NULL, then *endp is set to the
- * end position of the match, taking into account patinstart.
- */
-
-/**/
-mod_export int
-pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
- Patstralloc patstralloc, int patoffset,
- int *nump, int *begp, int *endp)
-{
- int i, maxnpos = 0, ret;
- int origlen;
- char **sp, **ep, *ptr;
- char *progstr = (char *)prog + prog->startoff;
- struct patstralloc patstralloc_struct;
-
- if (nump) {
- maxnpos = *nump;
- *nump = 0;
- }
-
- if (!patstralloc)
- patmungestring(&string, &stringlen, &unmetalenin);
- origlen = stringlen;
-
- if (patstralloc) {
- DPUTS(!patstralloc->alloced,
- "External unmetafy didn't actually unmetafy.");
- DPUTS(patstralloc->unmetalenp,
- "Ooh-err: pathpos with external unmetafy. I have bad vibes.");
- patinpath = NULL;
- patinstart = string;
- /* stringlen is unmetafied length; unmetalenin is ignored */
- } else {
- patstralloc = &patstralloc_struct;
- if (patallocstr(prog, string, stringlen, unmetalenin, 0, patstralloc)) {
- patinstart = patstralloc->alloced + patstralloc->unmetalenp;
- stringlen = patstralloc->unmetalen;
- } else
- patinstart = string;
- if (patstralloc->unmetalenp)
- patinpath = patstralloc->alloced;
- else
- patinpath = NULL;
- }
-
- patflags = prog->flags;
- patinend = patinstart + stringlen;
- /*
- * From now on we do not require NULL termination of
- * the test string. There should also be no more references
- * to the variable string.
- */
-
- if (prog->flags & (PAT_PURES|PAT_ANY)) {
- /*
- * Either we are testing against a pure string,
- * or we can match anything at all.
- */
- int pstrlen;
- char *pstr;
- if (patstralloc->alloced)
- {
- /*
- * Unmetafied; we need pattern sring that's also unmetafied.
- * We'll cache it in the patstralloc structure.
- * Note it's on the heap.
- */
- if (!patstralloc->progstrunmeta)
- {
- patstralloc->progstrunmeta =
- dupstrpfx(progstr, (int)prog->patmlen);
- unmetafy(patstralloc->progstrunmeta,
- &patstralloc->progstrunmetalen);
- }
- pstr = patstralloc->progstrunmeta;
- pstrlen = patstralloc->progstrunmetalen;
- }
- else
- {
- /* Metafied. */
- pstr = progstr;
- pstrlen = (int)prog->patmlen;
- }
- if (prog->flags & PAT_ANY) {
- /*
- * Optimisation for a single "*": always matches
- * (except for no_glob_dots, see below).
- */
- ret = 1;
- } else {
- /*
- * Testing a pure string. See if initial
- * components match.
- */
- int lendiff = stringlen - pstrlen;
- if (lendiff < 0) {
- /* No, the pattern string is too long. */
- ret = 0;
- } else if (!memcmp(pstr, patinstart, pstrlen)) {
- /*
- * Initial component matches. Matches either
- * if lengths are the same or we are not anchored
- * to the end of the string.
- */
- ret = !lendiff || (prog->flags & PAT_NOANCH);
- } else {
- /* No match. */
- ret = 0;
- }
- }
- if (ret) {
- /*
- * For files, we won't match initial "."s unless
- * glob_dots is set.
- */
- if ((prog->flags & PAT_NOGLD) && *patinstart == '.') {
- ret = 0;
- } else {
- /*
- * Remember the length in case used for ${..#..} etc.
- * In this case, we didn't unmetafy the pattern string
- * In the orignal structure, but it might be unmetafied
- * for use with an unmetafied test string.
- */
- patinlen = pstrlen;
- /* if matching files, must update globbing flags */
- patglobflags = prog->globend;
-
- if ((patglobflags & GF_MATCHREF) &&
- !(patflags & PAT_FILE)) {
- char *str;
- int mlen;
-
- if (patstralloc->alloced) {
- /*
- * Unmetafied: pstrlen contains unmetafied
- * length in bytes.
- */
- str = metafy(patinstart, pstrlen, META_DUP);
- mlen = CHARSUB(patinstart, patinstart + pstrlen);
- } else {
- str = ztrduppfx(patinstart, patinlen);
- /*
- * Count the characters. We're not using CHARSUB()
- * because the string is still metafied.
- */
- MB_METACHARINIT();
- mlen = MB_METASTRLEN2END(patinstart, 0,
- patinstart + patinlen);
- }
-
- setsparam("MATCH", str);
- setiparam("MBEGIN",
- (zlong)(patoffset + !isset(KSHARRAYS)));
- setiparam("MEND",
- (zlong)(mlen + patoffset +
- !isset(KSHARRAYS) - 1));
- }
- }
- }
- } else {
- /*
- * Test for a `must match' string, unless we're scanning for a match
- * in which case we don't need to do this each time.
- */
- ret = 1;
- if (!(prog->flags & PAT_SCAN) && prog->mustoff)
- {
- char *testptr; /* start pointer into test string */
- char *teststop; /* last point from which we can match */
- char *patptr = (char *)prog + prog->mustoff;
- int patlen = prog->patmlen;
- int found = 0;
-
- if (patlen > stringlen) {
- /* Too long, can't match. */
- ret = 0;
- } else {
- teststop = patinend - patlen;
-
- for (testptr = patinstart; testptr <= teststop; testptr++)
- {
- if (!memcmp(testptr, patptr, patlen)) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- ret = 0;
- }
- }
- if (!ret)
- return 0;
-
- patglobflags = prog->globflags;
- if (!(patflags & PAT_FILE)) {
- forceerrs = -1;
- errsfound = 0;
- }
- globdots = !(patflags & PAT_NOGLD);
- parsfound = 0;
-
- patinput = patinstart;
-
- if (patmatch((Upat)progstr)) {
- /*
- * we were lazy and didn't save the globflags if an exclusion
- * failed, so set it now
- */
- patglobflags = prog->globend;
-
- /*
- * Record length of successful match, including Meta
- * characters. Do it here so that patmatchlen() can return
- * it even if we delete the pattern strings.
- */
- patinlen = patinput - patinstart;
- /*
- * Optimization: if we didn't find any Meta characters
- * to begin with, we don't need to look for them now.
- *
- * For patstralloc pased in, we want the unmetafied length.
- */
- if (patstralloc == &patstralloc_struct &&
- patstralloc->unmetalen != origlen) {
- for (ptr = patinstart; ptr < patinput; ptr++)
- if (imeta(*ptr))
- patinlen++;
- }
-
- /*
- * Should we clear backreferences and matches on a failed
- * match?
- */
- if ((patglobflags & GF_MATCHREF) && !(patflags & PAT_FILE)) {
- /*
- * m flag: for global match. This carries no overhead
- * in the pattern matching part.
- *
- * Remember the test pattern is already unmetafied.
- */
- char *str;
- int mlen = CHARSUB(patinstart, patinput);
-
- str = metafy(patinstart, patinput - patinstart, META_DUP);
- setsparam("MATCH", str);
- setiparam("MBEGIN", (zlong)(patoffset + !isset(KSHARRAYS)));
- setiparam("MEND",
- (zlong)(mlen + patoffset +
- !isset(KSHARRAYS) - 1));
- }
- if (prog->patnpar && nump) {
- /*
- * b flag: for backreferences using parentheses. Reported
- * directly.
- */
- *nump = prog->patnpar;
-
- sp = patbeginp;
- ep = patendp;
-
- for (i = 0; i < prog->patnpar && i < maxnpos; i++) {
- if (parsfound & (1 << i)) {
- if (begp)
- *begp++ = CHARSUB(patinstart, *sp) + patoffset;
- if (endp)
- *endp++ = CHARSUB(patinstart, *ep) + patoffset
- - 1;
- } else {
- if (begp)
- *begp++ = -1;
- if (endp)
- *endp++ = -1;
- }
-
- sp++;
- ep++;
- }
- } else if (prog->patnpar && !(patflags & PAT_FILE)) {
- /*
- * b flag: for backreferences using parentheses.
- */
- int palen = prog->patnpar+1;
- char **matcharr, **mbeginarr, **mendarr;
- char numbuf[DIGBUFSIZE];
-
- matcharr = zshcalloc(palen*sizeof(char *));
- mbeginarr = zshcalloc(palen*sizeof(char *));
- mendarr = zshcalloc(palen*sizeof(char *));
-
- sp = patbeginp;
- ep = patendp;
-
- for (i = 0; i < prog->patnpar; i++) {
- if (parsfound & (1 << i)) {
- matcharr[i] = metafy(*sp, *ep - *sp, META_DUP);
- /*
- * mbegin and mend give indexes into the string
- * in the standard notation, i.e. respecting
- * KSHARRAYS, and with the end index giving
- * the last character, not one beyond.
- * For example, foo=foo; [[ $foo = (f)oo ]] gives
- * (without KSHARRAYS) indexes 1 and 1, which
- * corresponds to indexing as ${foo[1,1]}.
- */
- sprintf(numbuf, "%ld",
- (long)(CHARSUB(patinstart, *sp) +
- patoffset +
- !isset(KSHARRAYS)));
- mbeginarr[i] = ztrdup(numbuf);
- sprintf(numbuf, "%ld",
- (long)(CHARSUB(patinstart, *ep) +
- patoffset +
- !isset(KSHARRAYS) - 1));
- mendarr[i] = ztrdup(numbuf);
- } else {
- /* Pattern wasn't set: either it was in an
- * unmatched branch, or a hashed parenthesis
- * that didn't match at all.
- */
- matcharr[i] = ztrdup("");
- mbeginarr[i] = ztrdup("-1");
- mendarr[i] = ztrdup("-1");
- }
- sp++;
- ep++;
- }
- setaparam("match", matcharr);
- setaparam("mbegin", mbeginarr);
- setaparam("mend", mendarr);
- }
-
- if (!nump && endp) {
- /*
- * We just need the overall end position.
- */
- *endp = CHARSUB(patinstart, patinput) + patoffset;
- }
-
- ret = 1;
- } else
- ret = 0;
- }
-
- return ret;
-}
-
-/*
- * Return length of previous succesful match. This is
- * in metafied bytes, i.e. includes a count of Meta characters,
- * unless the match was done on an unmetafied string using
- * a patstralloc stuct, in which case it, too is unmetafed.
- * Unusual and futile attempt at modular encapsulation.
- */
-
-/**/
-int
-patmatchlen(void)
-{
- return patinlen;
-}
-
-/*
- * Match literal characters with case insensitivity test: the first
- * comes from the input string, the second the current pattern.
- */
-#ifdef MULTIBYTE_SUPPORT
-#define ISUPPER(x) iswupper(x)
-#define ISLOWER(x) iswlower(x)
-#define TOUPPER(x) towupper(x)
-#define TOLOWER(x) towlower(x)
-#define ISDIGIT(x) iswdigit(x)
-#else
-#define ISUPPER(x) isupper(x)
-#define ISLOWER(x) islower(x)
-#define TOUPPER(x) toupper(x)
-#define TOLOWER(x) tolower(x)
-#define ISDIGIT(x) idigit(x)
-#endif
-#define CHARMATCH(chin, chpa) (chin == chpa || \
- ((patglobflags & GF_IGNCASE) ? \
- ((ISUPPER(chin) ? TOLOWER(chin) : chin) == \
- (ISUPPER(chpa) ? TOLOWER(chpa) : chpa)) : \
- (patglobflags & GF_LCMATCHUC) ? \
- (ISLOWER(chpa) && TOUPPER(chpa) == chin) : 0))
-
-/*
- * The same but caching an expression from the first argument,
- * Requires local charmatch_cache definition.
- */
-#define CHARMATCH_EXPR(expr, chpa) \
- (charmatch_cache = (expr), CHARMATCH(charmatch_cache, chpa))
-
-/*
- * exactpos is used to remember how far down an exact string we have
- * matched, if we are doing approximation and can therefore redo from
- * the same point; we never need to otherwise.
- *
- * exactend is a pointer to the end of the string, which isn't
- * null-terminated.
- */
-static char *exactpos, *exactend;
-
-/*
- * Main matching routine.
- *
- * Testing the tail end of a match is usually done by recursion, but
- * we try to eliminate that in favour of looping for simple cases.
- */
-
-/**/
-static int
-patmatch(Upat prog)
-{
- /* Current and next nodes */
- Upat scan = prog, next, opnd;
- char *start, *save, *chrop, *chrend, *compend;
- int savglobflags, op, no, min, fail = 0, saverrsfound;
- zrange_t from, to, comp;
- patint_t nextch;
- int q = queue_signal_level();
-
- /*
- * To avoid overhead of saving state if there are no queued signals
- * waiting, we pierce the signals.h veil and examine queue state.
- */
-#define check_for_signals() do if (queue_front != queue_rear) { \
- int savpatflags = patflags, savpatglobflags = patglobflags; \
- char *savexactpos = exactpos, *savexactend = exactend; \
- struct rpat savpattrystate = pattrystate; \
- dont_queue_signals(); \
- restore_queue_signals(q); \
- exactpos = savexactpos; \
- exactend = savexactend; \
- patflags = savpatflags; \
- patglobflags = savpatglobflags; \
- pattrystate = savpattrystate; \
- } while (0)
-
- check_for_signals();
-
- while (scan && !errflag) {
- next = PATNEXT(scan);
-
- if (!globdots && P_NOTDOT(scan) && patinput == patinstart &&
- patinput < patinend && *patinput == '.')
- return 0;
-
- switch (P_OP(scan)) {
- case P_ANY:
- if (patinput == patinend)
- fail = 1;
- else
- CHARINC(patinput, patinend);
- break;
- case P_EXACTLY:
- /*
- * acts as nothing if *chrop is null: this is used by
- * approx code.
- */
- if (exactpos) {
- chrop = exactpos;
- chrend = exactend;
- } else {
- chrop = P_LS_STR(scan);
- chrend = chrop + P_LS_LEN(scan);
- }
- exactpos = NULL;
- while (chrop < chrend && patinput < patinend) {
- char *savpatinput = patinput;
- char *savchrop = chrop;
- int badin = 0, badpa = 0;
- /*
- * Care with character matching:
- * We do need to convert the character to wide
- * representation if possible, because we may need
- * to do case transformation. However, we should
- * be careful in case one, but not the other, wasn't
- * representable in the current locale---in that
- * case they don't match even if the returned
- * values (one properly converted, one raw) are
- * the same.
- */
- patint_t chin = CHARREFINC(patinput, patinend, &badin);
- patint_t chpa = CHARREFINC(chrop, chrend, &badpa);
- if (!CHARMATCH(chin, chpa) || badin != badpa) {
- fail = 1;
- patinput = savpatinput;
- chrop = savchrop;
- break;
- }
- }
- if (chrop < chrend) {
- exactpos = chrop;
- exactend = chrend;
- fail = 1;
- }
- break;
- case P_ANYOF:
- case P_ANYBUT:
- if (patinput == patinend)
- fail = 1;
- else {
-#ifdef MULTIBYTE_SUPPORT
- int zmb_ind;
- wchar_t cr = charref(patinput, patinend, &zmb_ind);
- char *scanop = (char *)P_OPERAND(scan);
- if (patglobflags & GF_MULTIBYTE) {
- if (mb_patmatchrange(scanop, cr, zmb_ind, NULL, NULL) ^
- (P_OP(scan) == P_ANYOF))
- fail = 1;
- else
- CHARINC(patinput, patinend);
- } else if (patmatchrange(scanop, (int)cr, NULL, NULL) ^
- (P_OP(scan) == P_ANYOF))
- fail = 1;
- else
- CHARINC(patinput, patinend);
-#else
- if (patmatchrange((char *)P_OPERAND(scan),
- CHARREF(patinput, patinend), NULL, NULL) ^
- (P_OP(scan) == P_ANYOF))
- fail = 1;
- else
- CHARINC(patinput, patinend);
-#endif
- }
- break;
- case P_NUMRNG:
- case P_NUMFROM:
- case P_NUMTO:
- /*
- * To do this properly, we really have to treat numbers as
- * closures: that's so things like <1-1000>33 will
- * match 633 (they didn't up to 3.1.6). To avoid making this
- * too inefficient, we see if there's an exact match next:
- * if there is, and it's not a digit, we return 1 after
- * the first attempt.
- */
- op = P_OP(scan);
- start = (char *)P_OPERAND(scan);
- from = to = 0;
- if (op != P_NUMTO) {
-#ifdef ZSH_64_BIT_TYPE
- /* We can't rely on pointer alignment being good enough. */
- memcpy((char *)&from, start, sizeof(zrange_t));
-#else
- from = *((zrange_t *) start);
-#endif
- start += sizeof(zrange_t);
- }
- if (op != P_NUMFROM) {
-#ifdef ZSH_64_BIT_TYPE
- memcpy((char *)&to, start, sizeof(zrange_t));
-#else
- to = *((zrange_t *) start);
-#endif
- }
- start = compend = patinput;
- comp = 0;
- while (patinput < patinend && idigit(*patinput)) {
- int out_of_range = 0;
- int digit = *patinput - '0';
- if (comp > ZRANGE_MAX / (zlong)10) {
- out_of_range = 1;
- } else {
- zrange_t c10 = comp ? comp * 10 : 0;
- if (ZRANGE_MAX - c10 < digit) {
- out_of_range = 1;
- } else {
- comp = c10;
- comp += digit;
- }
- }
- patinput++;
- compend++;
-
- if (out_of_range ||
- (comp & ((zrange_t)1 << (sizeof(comp)*8 -
-#ifdef ZRANGE_T_IS_SIGNED
- 2
-#else
- 1
-#endif
- )))) {
- /*
- * Out of range (allowing for signedness, which
- * we need if we are using zlongs).
- * This is as far as we can go.
- * If we're doing a range "from", skip all the
- * remaining numbers. Otherwise, we can't
- * match beyond the previous point anyway.
- * Leave the pointer to the last calculated
- * position (compend) where it was before.
- */
- if (op == P_NUMFROM) {
- while (patinput < patinend && idigit(*patinput))
- patinput++;
- }
- }
- }
- save = patinput;
- no = 0;
- while (patinput > start) {
- /* if already too small, no power on earth can save it */
- if (comp < from && patinput <= compend)
- break;
- if ((op == P_NUMFROM || comp <= to) && patmatch(next)) {
- return 1;
- }
- if (!no && P_OP(next) == P_EXACTLY &&
- (!P_LS_LEN(next) ||
- !idigit(STOUC(*P_LS_STR(next)))) &&
- !(patglobflags & 0xff))
- return 0;
- patinput = --save;
- no++;
- /*
- * With a range start and an unrepresentable test
- * number, we just back down the test string without
- * changing the number until we get to a representable
- * one.
- */
- if (patinput < compend)
- comp /= 10;
- }
- patinput = start;
- fail = 1;
- break;
- case P_NUMANY:
- /* This is <->: any old set of digits, don't bother comparing */
- start = patinput;
- while (patinput < patinend && idigit(*patinput))
- patinput++;
- save = patinput;
- no = 0;
- while (patinput > start) {
- if (patmatch(next))
- return 1;
- if (!no && P_OP(next) == P_EXACTLY &&
- (!P_LS_LEN(next) ||
- !idigit(*P_LS_STR(next))) &&
- !(patglobflags & 0xff))
- return 0;
- patinput = --save;
- no++;
- }
- patinput = start;
- fail = 1;
- break;
- case P_NOTHING:
- break;
- case P_BACK:
- break;
- case P_GFLAGS:
- patglobflags = P_OPERAND(scan)->l;
- break;
- case P_OPEN:
- case P_OPEN+1:
- case P_OPEN+2:
- case P_OPEN+3:
- case P_OPEN+4:
- case P_OPEN+5:
- case P_OPEN+6:
- case P_OPEN+7:
- case P_OPEN+8:
- case P_OPEN+9:
- no = P_OP(scan) - P_OPEN;
- save = patinput;
-
- if (patmatch(next)) {
- /*
- * Don't set patbeginp if some later invocation of
- * the same parentheses already has.
- */
- if (no && !(parsfound & (1 << (no - 1)))) {
- patbeginp[no-1] = save;
- parsfound |= 1 << (no - 1);
- }
- return 1;
- } else
- return 0;
- break;
- case P_CLOSE:
- case P_CLOSE+1:
- case P_CLOSE+2:
- case P_CLOSE+3:
- case P_CLOSE+4:
- case P_CLOSE+5:
- case P_CLOSE+6:
- case P_CLOSE+7:
- case P_CLOSE+8:
- case P_CLOSE+9:
- no = P_OP(scan) - P_CLOSE;
- save = patinput;
-
- if (patmatch(next)) {
- if (no && !(parsfound & (1 << (no + 15)))) {
- patendp[no-1] = save;
- parsfound |= 1 << (no + 15);
- }
- return 1;
- } else
- return 0;
- break;
- case P_EXCSYNC:
- /* See the P_EXCLUDE code below for where syncptr comes from */
- {
- unsigned char *syncptr;
- Upat after;
- after = P_OPERAND(scan);
- DPUTS(!P_ISEXCLUDE(after),
- "BUG: EXCSYNC not followed by EXCLUDE.");
- DPUTS(!P_OPERAND(after)->p,
- "BUG: EXCSYNC not handled by EXCLUDE");
- syncptr = P_OPERAND(after)->p + (patinput - patinstart);
- /*
- * If we already matched from here, this time we fail.
- * See WBRANCH code for story about error count.
- */
- if (*syncptr && errsfound + 1 >= *syncptr)
- return 0;
- /*
- * Else record that we (possibly) matched this time.
- * No harm if we don't: then the previous test will just
- * short cut the attempted match that is bound to fail.
- * We never try to exclude something that has already
- * failed anyway.
- */
- *syncptr = errsfound + 1;
- }
- break;
- case P_EXCEND:
- /*
- * This is followed by a P_EXCSYNC, but only in the P_EXCLUDE
- * branch. Actually, we don't bother following it: all we
- * need to know is that we successfully matched so far up
- * to the end of the asserted pattern; the endpoint
- * in the target string is nulled out.
- */
- if (!(fail = (patinput < patinend)))
- return 1;
- break;
- case P_BRANCH:
- case P_WBRANCH:
- /* P_EXCLUDE shouldn't occur without a P_BRANCH */
- if (!P_ISBRANCH(next)) {
- /* no choice, avoid recursion */
- DPUTS(P_OP(scan) == P_WBRANCH,
- "BUG: WBRANCH with no alternative.");
- next = P_OPERAND(scan);
- } else {
- do {
- save = patinput;
- savglobflags = patglobflags;
- saverrsfound = errsfound;
- if (P_ISEXCLUDE(next)) {
- /*
- * The strategy is to test the asserted pattern,
- * recording via P_EXCSYNC how far the part to
- * be excluded matched. We then set the
- * length of the test string to that
- * point and see if the exclusion as far as
- * P_EXCEND also matches that string.
- * We need to keep testing the asserted pattern
- * by backtracking, since the first attempt
- * may be excluded while a later attempt may not.
- * For this we keep a pointer just after
- * the P_EXCLUDE which is tested by the P_EXCSYNC
- * to see if we matched there last time, in which
- * case we fail. If there is nothing to backtrack
- * over, that doesn't matter: we should fail anyway.
- * The pointer also tells us where the asserted
- * pattern matched for use by the exclusion.
- *
- * It's hard to allocate space for this
- * beforehand since we may need to do it
- * recursively.
- *
- * P.S. in case you were wondering, this code
- * is horrible.
- */
- Upat syncstrp;
- char *origpatinend;
- unsigned char *oldsyncstr;
- char *matchpt = NULL;
- int ret, savglobdots, matchederrs = 0;
- int savparsfound = parsfound;
- DPUTS(P_OP(scan) == P_WBRANCH,
- "BUG: excluded WBRANCH");
- syncstrp = P_OPERAND(next);
- /*
- * Unlike WBRANCH, each test at the same exclude
- * sync point (due to an external loop) is separate,
- * i.e testing (foo~bar)# is no different from
- * (foo~bar)(foo~bar)... from the exclusion point
- * of view, so we use a different sync string.
- */
- oldsyncstr = syncstrp->p;
- syncstrp->p = (unsigned char *)
- zshcalloc((patinend - patinstart) + 1);
- origpatinend = patinend;
- while ((ret = patmatch(P_OPERAND(scan)))) {
- unsigned char *syncpt;
- char *savpatinstart;
- int savforce = forceerrs;
- int savpatflags = patflags, synclen;
- forceerrs = -1;
- savglobdots = globdots;
- matchederrs = errsfound;
- matchpt = patinput; /* may not be end */
- globdots = 1; /* OK to match . first */
- /* Find the point where the scan
- * matched the part to be excluded: because
- * of backtracking, the one
- * most recently matched will be the first.
- * (Luckily, backtracking is done after all
- * possibilities for approximation have been
- * checked.)
- */
- for (syncpt = syncstrp->p; !*syncpt; syncpt++)
- ;
- synclen = syncpt - syncstrp->p;
- if (patinstart + synclen != patinend) {
- /*
- * Temporarily mark the string as
- * ending at this point.
- */
- DPUTS(patinstart + synclen > matchpt,
- "BUG: EXCSYNC failed");
-
- patinend = patinstart + synclen;
- /*
- * If this isn't really the end of the string,
- * remember this for the (#e) assertion.
- */
- patflags |= PAT_NOTEND;
- }
- savpatinstart = patinstart;
- next = PATNEXT(scan);
- while (next && P_ISEXCLUDE(next)) {
- patinput = save;
- /*
- * turn off approximations in exclusions:
- * note we keep remaining patglobflags
- * set by asserted branch (or previous
- * excluded branches, for consistency).
- */
- patglobflags &= ~0xff;
- errsfound = 0;
- opnd = P_OPERAND(next) + 1;
- if (P_OP(next) == P_EXCLUDP && patinpath) {
- /*
- * Top level exclusion with a file,
- * applies to whole path so add the
- * segments already matched.
- * We copied these in front of the
- * test pattern, so patinend doesn't
- * need moving.
- */
- DPUTS(patinput != patinstart,
- "BUG: not at start excluding path");
- patinput = patinstart = patinpath;
- }
- if (patmatch(opnd)) {
- ret = 0;
- /*
- * Another subtlety: if we exclude the
- * match, any parentheses just found
- * become invalidated.
- */
- parsfound = savparsfound;
- }
- if (patinpath) {
- patinput = savpatinstart +
- (patinput - patinstart);
- patinstart = savpatinstart;
- }
- if (!ret)
- break;
- next = PATNEXT(next);
- }
- /*
- * Restore original end position.
- */
- patinend = origpatinend;
- patflags = savpatflags;
- globdots = savglobdots;
- forceerrs = savforce;
- if (ret)
- break;
- patinput = save;
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- }
- zfree((char *)syncstrp->p,
- (patinend - patinstart) + 1);
- syncstrp->p = oldsyncstr;
- if (ret) {
- patinput = matchpt;
- errsfound = matchederrs;
- return 1;
- }
- while ((scan = PATNEXT(scan)) &&
- P_ISEXCLUDE(scan))
- ;
- } else {
- int ret = 1, pfree = 0;
- Upat ptrp = NULL;
- unsigned char *ptr;
- if (P_OP(scan) == P_WBRANCH) {
- /*
- * This is where we make sure that we are not
- * repeatedly matching zero-length strings in
- * a closure, which would cause an infinite loop,
- * and also remove exponential behaviour in
- * backtracking nested closures.
- * The P_WBRANCH operator leaves a space for a
- * uchar *, initialized to NULL, which is
- * turned into a string the same length as the
- * target string. Every time we match from a
- * particular point in the target string, we
- * stick a 1 at the corresponding point here.
- * If we come round to the same branch again, and
- * there is already a 1, then the test fails.
- */
- opnd = P_OPERAND(scan);
- ptrp = opnd++;
- if (!ptrp->p) {
- ptrp->p = (unsigned char *)
- zshcalloc((patinend - patinstart) + 1);
- pfree = 1;
- }
- ptr = ptrp->p + (patinput - patinstart);
-
- /*
- * Without approximation, this is just a
- * single bit test. With approximation, we
- * need to know how many errors there were
- * last time we made the test. If errsfound
- * is now smaller than it was, hence we can
- * make more approximations in the remaining
- * code, we continue with the test.
- * (This is why the max number of errors is
- * 254, not 255.)
- */
- if (*ptr && errsfound + 1 >= *ptr)
- ret = 0;
- *ptr = errsfound + 1;
- } else
- opnd = P_OPERAND(scan);
- if (ret)
- ret = patmatch(opnd);
- if (pfree) {
- zfree((char *)ptrp->p,
- (patinend - patinstart) + 1);
- ptrp->p = NULL;
- }
- if (ret)
- return 1;
- scan = PATNEXT(scan);
- }
- patinput = save;
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- DPUTS(P_OP(scan) == P_WBRANCH,
- "BUG: WBRANCH not first choice.");
- next = PATNEXT(scan);
- } while (scan && P_ISBRANCH(scan));
- return 0;
- }
- break;
- case P_STAR:
- /* Handle specially for speed, although really P_ONEHASH+P_ANY */
- while (P_OP(next) == P_STAR) {
- /*
- * If there's another * following we can optimise it
- * out. Chains of *'s can give pathologically bad
- * performance.
- */
- scan = next;
- next = PATNEXT(scan);
- }
- /*FALLTHROUGH*/
- case P_ONEHASH:
- case P_TWOHASH:
- /*
- * This is just simple cases, matching one character.
- * With approximations, we still handle * this way, since
- * no approximation is ever necessary, but other closures
- * are handled by the more complicated branching method
- */
- op = P_OP(scan);
- /* Note that no counts possibly metafied characters */
- start = patinput;
- {
- char *lastcharstart;
- /*
- * Array to record the start of characters for
- * backtracking.
- */
- VARARR(char, charstart, patinend-patinput);
- memset(charstart, 0, patinend-patinput);
-
- if (op == P_STAR) {
- for (no = 0; patinput < patinend;
- CHARINC(patinput, patinend))
- {
- charstart[patinput-start] = 1;
- no++;
- }
- /* simple optimization for reasonably common case */
- if (P_OP(next) == P_END)
- return 1;
- } else {
- DPUTS(patglobflags & 0xff,
- "BUG: wrong backtracking with approximation.");
- if (!globdots && P_NOTDOT(P_OPERAND(scan)) &&
- patinput == patinstart && patinput < patinend &&
- CHARREF(patinput, patinend) == ZWC('.'))
- return 0;
- no = patrepeat(P_OPERAND(scan), charstart);
- }
- min = (op == P_TWOHASH) ? 1 : 0;
- /*
- * Lookahead to avoid useless matches. This is not possible
- * with approximation.
- */
- if (P_OP(next) == P_EXACTLY && P_LS_LEN(next) &&
- !(patglobflags & 0xff)) {
- char *nextop = P_LS_STR(next);
-#ifdef MULTIBYTE_SUPPORT
- /* else second argument of CHARREF isn't used */
- int nextlen = P_LS_LEN(next);
-#endif
- /*
- * If that P_EXACTLY is last (common in simple patterns,
- * such as *.c), then it can be only be matched at one
- * point in the test string, so record that.
- */
- if (P_OP(PATNEXT(next)) == P_END &&
- !(patflags & PAT_NOANCH)) {
- int ptlen = patinend - patinput;
- int lenmatch = patinend -
- (min ? CHARNEXT(start, patinend) : start);
- /* Are we in the right range? */
- if (P_LS_LEN(next) > lenmatch ||
- P_LS_LEN(next) < ptlen)
- return 0;
- /* Yes, just position appropriately and test. */
- patinput += ptlen - P_LS_LEN(next);
- /*
- * Here we will need to be careful that patinput is not
- * in the middle of a multibyte character.
- */
- /* Continue loop with P_EXACTLY test. */
- break;
- }
- nextch = CHARREF(nextop, nextop + nextlen);
- } else
- nextch = PEOF;
- savglobflags = patglobflags;
- saverrsfound = errsfound;
- lastcharstart = charstart + (patinput - start);
- if (no >= min) {
- for (;;) {
- patint_t charmatch_cache;
- if (nextch == PEOF ||
- (patinput < patinend &&
- CHARMATCH_EXPR(CHARREF(patinput, patinend),
- nextch))) {
- if (patmatch(next))
- return 1;
- }
- if (--no < min)
- break;
- /* find start of previous full character */
- while (!*--lastcharstart)
- DPUTS(lastcharstart < charstart,
- "lastcharstart invalid");
- patinput = start + (lastcharstart-charstart);
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- }
- }
- }
- /*
- * As with branches, the patmatch(next) stuff for *
- * handles approximation, so we don't need to try
- * anything here.
- */
- return 0;
- case P_ISSTART:
- if (patinput != patinstart || (patflags & PAT_NOTSTART))
- fail = 1;
- break;
- case P_ISEND:
- if (patinput < patinend || (patflags & PAT_NOTEND))
- fail = 1;
- break;
- case P_COUNTSTART:
- {
- /*
- * Save and restore the current count and the
- * start pointer in case the pattern has been
- * executed by a previous repetition of a
- * closure.
- */
- long *curptr = &P_OPERAND(scan)[P_CT_CURRENT].l;
- long savecount = *curptr;
- unsigned char *saveptr = scan[P_CT_PTR].p;
- int ret;
-
- *curptr = 0L;
- ret = patmatch(P_OPERAND(scan));
- *curptr = savecount;
- scan[P_CT_PTR].p = saveptr;
- return ret;
- }
- case P_COUNT:
- {
- /* (#cN,M): execution is relatively straightforward */
- long cur = scan[P_CT_CURRENT].l;
- long min = scan[P_CT_MIN].l;
- long max = scan[P_CT_MAX].l;
-
- if (cur && cur >= min &&
- (unsigned char *)patinput == scan[P_CT_PTR].p) {
- /*
- * Not at the first attempt to match so
- * the previous attempt managed zero length.
- * We can do this indefinitely so there's
- * no point in going on. Simply try to
- * match the remainder of the pattern.
- */
- return patmatch(next);
- }
- scan[P_CT_PTR].p = (unsigned char *)patinput;
-
- if (max < 0 || cur < max) {
- char *patinput_thistime = patinput;
- scan[P_CT_CURRENT].l = cur + 1;
- if (patmatch(scan + P_CT_OPERAND))
- return 1;
- scan[P_CT_CURRENT].l = cur;
- patinput = patinput_thistime;
- }
- if (cur < min)
- return 0;
- return patmatch(next);
- }
- case P_END:
- if (!(fail = (patinput < patinend && !(patflags & PAT_NOANCH))))
- return 1;
- break;
-#ifdef DEBUG
- default:
- dputs("BUG: bad operand in patmatch.");
- return 0;
- break;
-#endif
- }
-
- if (fail) {
- if (errsfound < (patglobflags & 0xff) &&
- (forceerrs == -1 || errsfound < forceerrs)) {
- /*
- * Approximation code. There are four possibilities
- *
- * 1. omit character from input string
- * 2. transpose characters in input and pattern strings
- * 3. omit character in both input and pattern strings
- * 4. omit character from pattern string.
- *
- * which we try in that order.
- *
- * Of these, 2, 3 and 4 require an exact match string
- * (P_EXACTLY) while 1, 2 and 3 require that we not
- * have reached the end of the input string.
- *
- * Note in each case after making the approximation we
- * need to retry the *same* pattern; this is what
- * requires exactpos, a slightly doleful way of
- * communicating with the exact character matcher.
- */
- char *savexact = exactpos;
- save = patinput;
- savglobflags = patglobflags;
- saverrsfound = ++errsfound;
- fail = 0;
-
- DPUTS(P_OP(scan) != P_EXACTLY && exactpos,
- "BUG: non-exact match has set exactpos");
-
- /* Try omitting a character from the input string */
- if (patinput < patinend) {
- CHARINC(patinput, patinend);
- /* If we are not on an exact match, then this is
- * our last gasp effort, so we can optimize out
- * the recursive call.
- */
- if (P_OP(scan) != P_EXACTLY)
- continue;
- if (patmatch(scan))
- return 1;
- }
-
- if (P_OP(scan) == P_EXACTLY) {
- char *nextexact = savexact;
- DPUTS(!savexact,
- "BUG: exact match has not set exactpos");
- CHARINC(nextexact, exactend);
-
- if (save < patinend) {
- char *nextin = save;
- CHARINC(nextin, patinend);
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- exactpos = savexact;
-
- /*
- * Try swapping two characters in patinput and
- * exactpos
- */
- if (save < patinend && nextin < patinend &&
- nextexact < exactend) {
- patint_t cin0 = CHARREF(save, patinend);
- patint_t cpa0 = CHARREF(exactpos, exactend);
- patint_t cin1 = CHARREF(nextin, patinend);
- patint_t cpa1 = CHARREF(nextexact, exactend);
-
- if (CHARMATCH(cin0, cpa1) &&
- CHARMATCH(cin1, cpa0)) {
- patinput = nextin;
- CHARINC(patinput, patinend);
- exactpos = nextexact;
- CHARINC(exactpos, exactend);
- if (patmatch(scan))
- return 1;
-
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- }
- }
-
- /*
- * Try moving up both strings.
- */
- patinput = nextin;
- exactpos = nextexact;
- if (patmatch(scan))
- return 1;
-
- patinput = save;
- patglobflags = savglobflags;
- errsfound = saverrsfound;
- exactpos = savexact;
- }
-
- DPUTS(exactpos == exactend, "approximating too far");
- /*
- * Try moving up the exact match pattern.
- * This must be the last attempt, so just loop
- * instead of calling recursively.
- */
- CHARINC(exactpos, exactend);
- continue;
- }
- }
- exactpos = NULL;
- return 0;
- }
-
- scan = next;
-
- /* Allow handlers to run once per loop */
- check_for_signals();
- }
-
- return 0;
-}
-
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-
-/*
- * See if character ch matches a pattern range specification.
- * The null-terminated specification is in range; the test
- * character is in ch.
- *
- * zmb is one of the enum defined above charref(), for indicating
- * incomplete or invalid multibyte characters.
- *
- * indptr is used by completion matching, which is why this
- * function is exported. If indptr is not NULL we set *indptr
- * to the index of the character in the range string, adjusted
- * in the case of "A-B" ranges such that A would count as its
- * normal index (say IA), B would count as IA + (B-A), and any
- * character within the range as appropriate. We're not strictly
- * guaranteed this fits within a wint_t, but if this is Unicode
- * in 32 bits we have a fair amount of distance left over.
- *
- * mtp is used in the same circumstances. *mtp returns the match type:
- * 0 for a standard character, else the PP_ index. It's not
- * useful if the match failed.
- */
-
-/**/
-mod_export int
-mb_patmatchrange(char *range, wchar_t ch, int zmb_ind, wint_t *indptr, int *mtp)
-{
- wchar_t r1, r2;
-
- if (indptr)
- *indptr = 0;
- /*
- * Careful here: unlike other strings, range is a NULL-terminated,
- * metafied string, because we need to treat the Posix and hyphenated
- * ranges specially.
- */
- while (*range) {
- if (imeta(STOUC(*range))) {
- int swtype = STOUC(*range++) - STOUC(Meta);
- if (mtp)
- *mtp = swtype;
- switch (swtype) {
- case 0:
- /* ordinary metafied character */
- range--;
- if (metacharinc(&range) == ch)
- return 1;
- break;
- case PP_ALPHA:
- if (iswalpha(ch))
- return 1;
- break;
- case PP_ALNUM:
- if (iswalnum(ch))
- return 1;
- break;
- case PP_ASCII:
- if ((ch & ~0x7f) == 0)
- return 1;
- break;
- case PP_BLANK:
-#if !defined(HAVE_ISWBLANK) && !defined(iswblank)
-/*
- * iswblank() is GNU and C99. There's a remote chance that some
- * systems still don't support it (but would support the other ones
- * if MULTIBYTE_SUPPORT is enabled).
- */
-#define iswblank(c) (c == L' ' || c == L'\t')
-#endif
- if (iswblank(ch))
- return 1;
- break;
- case PP_CNTRL:
- if (iswcntrl(ch))
- return 1;
- break;
- case PP_DIGIT:
- if (iswdigit(ch))
- return 1;
- break;
- case PP_GRAPH:
- if (iswgraph(ch))
- return 1;
- break;
- case PP_LOWER:
- if (iswlower(ch))
- return 1;
- break;
- case PP_PRINT:
- if (WC_ISPRINT(ch))
- return 1;
- break;
- case PP_PUNCT:
- if (iswpunct(ch))
- return 1;
- break;
- case PP_SPACE:
- if (iswspace(ch))
- return 1;
- break;
- case PP_UPPER:
- if (iswupper(ch))
- return 1;
- break;
- case PP_XDIGIT:
- if (iswxdigit(ch))
- return 1;
- break;
- case PP_IDENT:
- if (wcsitype(ch, IIDENT))
- return 1;
- break;
- case PP_IFS:
- if (wcsitype(ch, ISEP))
- return 1;
- break;
- case PP_IFSSPACE:
- /* must be ASCII space character */
- if (ch < 128 && iwsep((int)ch))
- return 1;
- break;
- case PP_WORD:
- if (wcsitype(ch, IWORD))
- return 1;
- break;
- case PP_RANGE:
- r1 = metacharinc(&range);
- r2 = metacharinc(&range);
- if (r1 <= ch && ch <= r2) {
- if (indptr)
- *indptr += ch - r1;
- return 1;
- }
- /* Careful not to screw up counting with bogus range */
- if (indptr && r1 < r2) {
- /*
- * This gets incremented again below to get
- * us past the range end. This is correct.
- */
- *indptr += r2 - r1;
- }
- break;
- case PP_INCOMPLETE:
- if (zmb_ind == ZMB_INCOMPLETE)
- return 1;
- break;
- case PP_INVALID:
- if (zmb_ind == ZMB_INVALID)
- return 1;
- break;
- case PP_UNKWN:
- DPUTS(1, "BUG: unknown posix range passed through.\n");
- break;
- default:
- DPUTS(1, "BUG: unknown metacharacter in range.");
- break;
- }
- } else if (metacharinc(&range) == ch) {
- if (mtp)
- *mtp = 0;
- return 1;
- }
- if (indptr)
- (*indptr)++;
- }
- return 0;
-}
-
-
-/*
- * This is effectively the reverse of mb_patmatchrange().
- * Given a range descriptor of the same form, and an index into it,
- * try to determine the character that is matched. If the index
- * points to a [:...:] generic style match, set chr to WEOF and
- * return the type in mtp instead. Return 1 if successful, 0 if
- * there was no corresponding index. Note all pointer arguments
- * must be non-null.
- */
-
-/**/
-mod_export int
-mb_patmatchindex(char *range, wint_t ind, wint_t *chr, int *mtp)
-{
- wchar_t r1, r2, rchr;
- wint_t rdiff;
-
- *chr = WEOF;
- *mtp = 0;
-
- while (*range) {
- if (imeta(STOUC(*range))) {
- int swtype = STOUC(*range++) - STOUC(Meta);
- switch (swtype) {
- case 0:
- range--;
- rchr = metacharinc(&range);
- if (!ind) {
- *chr = (wint_t) rchr;
- return 1;
- }
- break;
-
- case PP_ALPHA:
- case PP_ALNUM:
- case PP_ASCII:
- case PP_BLANK:
- case PP_CNTRL:
- case PP_DIGIT:
- case PP_GRAPH:
- case PP_LOWER:
- case PP_PRINT:
- case PP_PUNCT:
- case PP_SPACE:
- case PP_UPPER:
- case PP_XDIGIT:
- case PP_IDENT:
- case PP_IFS:
- case PP_IFSSPACE:
- case PP_WORD:
- case PP_INCOMPLETE:
- case PP_INVALID:
- if (!ind) {
- *mtp = swtype;
- return 1;
- }
- break;
-
- case PP_RANGE:
- r1 = metacharinc(&range);
- r2 = metacharinc(&range);
- rdiff = (wint_t)r2 - (wint_t)r1;
- if (rdiff >= ind) {
- *chr = (wint_t)r1 + ind;
- return 1;
- }
- /* note the extra decrement to ind below */
- ind -= rdiff;
- break;
- case PP_UNKWN:
- DPUTS(1, "BUG: unknown posix range passed through.\n");
- break;
- default:
- DPUTS(1, "BUG: unknown metacharacter in range.");
- break;
- }
- } else {
- rchr = metacharinc(&range);
- if (!ind) {
- *chr = (wint_t)rchr;
- return 1;
- }
- }
- if (!ind--)
- break;
- }
-
- /* No corresponding index. */
- return 0;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Identical function to mb_patmatchrange() above for single-byte
- * characters.
- */
-
-/**/
-mod_export int
-patmatchrange(char *range, int ch, int *indptr, int *mtp)
-{
- int r1, r2;
-
- if (indptr)
- *indptr = 0;
- /*
- * Careful here: unlike other strings, range is a NULL-terminated,
- * metafied string, because we need to treat the Posix and hyphenated
- * ranges specially.
- */
- for (; *range; range++) {
- if (imeta(STOUC(*range))) {
- int swtype = STOUC(*range) - STOUC(Meta);
- if (mtp)
- *mtp = swtype;
- switch (swtype) {
- case 0:
- if (STOUC(*++range ^ 32) == ch)
- return 1;
- break;
- case PP_ALPHA:
- if (isalpha(ch))
- return 1;
- break;
- case PP_ALNUM:
- if (isalnum(ch))
- return 1;
- break;
- case PP_ASCII:
- if ((ch & ~0x7f) == 0)
- return 1;
- break;
- case PP_BLANK:
-#if !defined(HAVE_ISBLANK) && !defined(isblank)
-/*
- * isblank() is GNU and C99. There's a remote chance that some
- * systems still don't support it.
- */
-#define isblank(c) (c == ' ' || c == '\t')
-#endif
- if (isblank(ch))
- return 1;
- break;
- case PP_CNTRL:
- if (iscntrl(ch))
- return 1;
- break;
- case PP_DIGIT:
- if (isdigit(ch))
- return 1;
- break;
- case PP_GRAPH:
- if (isgraph(ch))
- return 1;
- break;
- case PP_LOWER:
- if (islower(ch))
- return 1;
- break;
- case PP_PRINT:
- if (ZISPRINT(ch))
- return 1;
- break;
- case PP_PUNCT:
- if (ispunct(ch))
- return 1;
- break;
- case PP_SPACE:
- if (isspace(ch))
- return 1;
- break;
- case PP_UPPER:
- if (isupper(ch))
- return 1;
- break;
- case PP_XDIGIT:
- if (isxdigit(ch))
- return 1;
- break;
- case PP_IDENT:
- if (iident(ch))
- return 1;
- break;
- case PP_IFS:
- if (isep(ch))
- return 1;
- break;
- case PP_IFSSPACE:
- if (iwsep(ch))
- return 1;
- break;
- case PP_WORD:
- if (iword(ch))
- return 1;
- break;
- case PP_RANGE:
- range++;
- r1 = STOUC(UNMETA(range));
- METACHARINC(range);
- r2 = STOUC(UNMETA(range));
- if (*range == Meta)
- range++;
- if (r1 <= ch && ch <= r2) {
- if (indptr)
- *indptr += ch - r1;
- return 1;
- }
- if (indptr && r1 < r2)
- *indptr += r2 - r1;
- break;
- case PP_INCOMPLETE:
- case PP_INVALID:
- /* Never true if not in multibyte mode */
- break;
- case PP_UNKWN:
- DPUTS(1, "BUG: unknown posix range passed through.\n");
- break;
- default:
- DPUTS(1, "BUG: unknown metacharacter in range.");
- break;
- }
- } else if (STOUC(*range) == ch) {
- if (mtp)
- *mtp = 0;
- return 1;
- }
- if (indptr)
- (*indptr)++;
- }
- return 0;
-}
-
-
-/**/
-#ifndef MULTIBYTE_SUPPORT
-
-/*
- * Identical function to mb_patmatchindex() above for single-byte
- * characters. Here -1 represents a character that needs a special type.
- *
- * Unlike patmatchrange, we only need this in ZLE, which always
- * uses MULTIBYTE_SUPPORT if compiled in; hence we don't use
- * this function in that case.
- */
-
-/**/
-mod_export int
-patmatchindex(char *range, int ind, int *chr, int *mtp)
-{
- int r1, r2, rdiff, rchr;
-
- *chr = -1;
- *mtp = 0;
-
- for (; *range; range++) {
- if (imeta(STOUC(*range))) {
- int swtype = STOUC(*range) - STOUC(Meta);
- switch (swtype) {
- case 0:
- /* ordinary metafied character */
- rchr = STOUC(*++range) ^ 32;
- if (!ind) {
- *chr = rchr;
- return 1;
- }
- break;
-
- case PP_ALPHA:
- case PP_ALNUM:
- case PP_ASCII:
- case PP_BLANK:
- case PP_CNTRL:
- case PP_DIGIT:
- case PP_GRAPH:
- case PP_LOWER:
- case PP_PRINT:
- case PP_PUNCT:
- case PP_SPACE:
- case PP_UPPER:
- case PP_XDIGIT:
- case PP_IDENT:
- case PP_IFS:
- case PP_IFSSPACE:
- case PP_WORD:
- case PP_INCOMPLETE:
- case PP_INVALID:
- if (!ind) {
- *mtp = swtype;
- return 1;
- }
- break;
-
- case PP_RANGE:
- range++;
- r1 = STOUC(UNMETA(range));
- METACHARINC(range);
- r2 = STOUC(UNMETA(range));
- if (*range == Meta)
- range++;
- rdiff = r2 - r1;
- if (rdiff >= ind) {
- *chr = r1 + ind;
- return 1;
- }
- /* note the extra decrement to ind below */
- ind -= rdiff;
- break;
- case PP_UNKWN:
- DPUTS(1, "BUG: unknown posix range passed through.\n");
- break;
- default:
- DPUTS(1, "BUG: unknown metacharacter in range.");
- break;
- }
- } else {
- if (!ind) {
- *chr = STOUC(*range);
- return 1;
- }
- }
- if (!ind--)
- break;
- }
-
- /* No corresponding index. */
- return 0;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Repeatedly match something simple and say how many times.
- * charstart is an array parallel to that starting at patinput
- * and records the start of (possibly multibyte) characters
- * to aid in later backtracking.
- */
-
-/**/
-static int patrepeat(Upat p, char *charstart)
-{
- int count = 0;
- patint_t tch, charmatch_cache;
- char *scan, *opnd;
-
- scan = patinput;
- opnd = (char *)P_OPERAND(p);
-
- switch(P_OP(p)) {
-#ifdef DEBUG
- case P_ANY:
- dputs("BUG: ?# did not get optimized to *");
- return 0;
- break;
-#endif
- case P_EXACTLY:
- DPUTS(P_LS_LEN(p) != 1, "closure following more than one character");
- tch = CHARREF(P_LS_STR(p), P_LS_STR(p) + P_LS_LEN(p));
- while (scan < patinend &&
- CHARMATCH_EXPR(CHARREF(scan, patinend), tch)) {
- charstart[scan-patinput] = 1;
- count++;
- CHARINC(scan, patinend);
- }
- break;
- case P_ANYOF:
- case P_ANYBUT:
- while (scan < patinend) {
-#ifdef MULTIBYTE_SUPPORT
- int zmb_ind;
- wchar_t cr = charref(scan, patinend, &zmb_ind);
- if (patglobflags & GF_MULTIBYTE) {
- if (mb_patmatchrange(opnd, cr, zmb_ind, NULL, NULL) ^
- (P_OP(p) == P_ANYOF))
- break;
- } else if (patmatchrange(opnd, (int)cr, NULL, NULL) ^
- (P_OP(p) == P_ANYOF))
- break;
-#else
- if (patmatchrange(opnd, CHARREF(scan, patinend), NULL, NULL) ^
- (P_OP(p) == P_ANYOF))
- break;
-#endif
- charstart[scan-patinput] = 1;
- count++;
- CHARINC(scan, patinend);
- }
- break;
-#ifdef DEBUG
- default:
- dputs("BUG: something very strange is happening in patrepeat");
- return 0;
- break;
-#endif
- }
-
- patinput = scan;
- return count;
-}
-
-/* Free a patprog. */
-
-/**/
-mod_export void
-freepatprog(Patprog prog)
-{
- if (prog && prog != dummy_patprog1 && prog != dummy_patprog2)
- zfree(prog, prog->size);
-}
-
-/* Disable or reenable a pattern character */
-
-/**/
-int
-pat_enables(const char *cmd, char **patp, int enable)
-{
- int ret = 0;
- const char **stringp;
- char *disp;
-
- if (!*patp) {
- int done = 0;
- for (stringp = zpc_strings, disp = zpc_disables;
- stringp < zpc_strings + ZPC_COUNT;
- stringp++, disp++) {
- if (!*stringp)
- continue;
- if (enable ? *disp : !*disp)
- continue;
- if (done)
- putc(' ', stdout);
- printf("'%s'", *stringp);
- done = 1;
- }
- if (done)
- putc('\n', stdout);
- return 0;
- }
-
- for (; *patp; patp++) {
- for (stringp = zpc_strings, disp = zpc_disables;
- stringp < zpc_strings + ZPC_COUNT;
- stringp++, disp++) {
- if (*stringp && !strcmp(*stringp, *patp)) {
- *disp = (char)!enable;
- break;
- }
- }
- if (stringp == zpc_strings + ZPC_COUNT) {
- zerrnam(cmd, "invalid pattern: %s", *patp);
- ret = 1;
- }
- }
-
- return ret;
-}
-
-/*
- * Save the current state of pattern disables, returning the saved value.
- */
-
-/**/
-unsigned int
-savepatterndisables(void)
-{
- unsigned int disables, bit;
- char *disp;
-
- disables = 0;
- for (bit = 1, disp = zpc_disables;
- disp < zpc_disables + ZPC_COUNT;
- bit <<= 1, disp++) {
- if (*disp)
- disables |= bit;
- }
- return disables;
-}
-
-/*
- * Function scope saving pattern enables.
- */
-
-/**/
-void
-startpatternscope(void)
-{
- Zpc_disables_save newdis;
-
- newdis = (Zpc_disables_save)zalloc(sizeof(*newdis));
- newdis->next = zpc_disables_stack;
- newdis->disables = savepatterndisables();
-
- zpc_disables_stack = newdis;
-}
-
-/*
- * Restore completely the state of pattern disables.
- */
-
-/**/
-void
-restorepatterndisables(unsigned int disables)
-{
- char *disp;
- unsigned int bit;
-
- for (bit = 1, disp = zpc_disables;
- disp < zpc_disables + ZPC_COUNT;
- bit <<= 1, disp++) {
- if (disables & bit)
- *disp = 1;
- else
- *disp = 0;
- }
-}
-
-/*
- * Function scope to restore pattern enables if localpatterns is turned on.
- */
-
-/**/
-void
-endpatternscope(void)
-{
- Zpc_disables_save olddis;
-
- olddis = zpc_disables_stack;
- zpc_disables_stack = olddis->next;
-
- if (isset(LOCALPATTERNS))
- restorepatterndisables(olddis->disables);
-
- zfree(olddis, sizeof(*olddis));
-}
-
-/* Reinitialise pattern disables */
-
-/**/
-void
-clearpatterndisables(void)
-{
- memset(zpc_disables, 0, ZPC_COUNT);
-}
-
-
-/* Check to see if str is eligible for filename generation. */
-
-/**/
-mod_export int
-haswilds(char *str)
-{
- char *start;
-
- /* `[' and `]' are legal even if bad patterns are usually not. */
- if ((*str == Inbrack || *str == Outbrack) && !str[1])
- return 0;
-
- /* If % is immediately followed by ?, then that ? is *
- * not treated as a wildcard. This is so you don't have *
- * to escape job references such as %?foo. */
- if (str[0] == '%' && str[1] == Quest)
- str[1] = '?';
-
- /*
- * Note that at this point zpc_special has not been set up.
- */
- start = str;
- for (; *str; str++) {
- switch (*str) {
- case Inpar:
- if ((!isset(SHGLOB) && !zpc_disables[ZPC_INPAR]) ||
- (str > start && isset(KSHGLOB) &&
- ((str[-1] == Quest && !zpc_disables[ZPC_KSH_QUEST]) ||
- (str[-1] == Star && !zpc_disables[ZPC_KSH_STAR]) ||
- (str[-1] == '+' && !zpc_disables[ZPC_KSH_PLUS]) ||
- (str[-1] == Bang && !zpc_disables[ZPC_KSH_BANG]) ||
- (str[-1] == '!' && !zpc_disables[ZPC_KSH_BANG2]) ||
- (str[-1] == '@' && !zpc_disables[ZPC_KSH_AT]))))
- return 1;
- break;
-
- case Bar:
- if (!zpc_disables[ZPC_BAR])
- return 1;
- break;
-
- case Star:
- if (!zpc_disables[ZPC_STAR])
- return 1;
- break;
-
- case Inbrack:
- if (!zpc_disables[ZPC_INBRACK])
- return 1;
- break;
-
- case Inang:
- if (!zpc_disables[ZPC_INANG])
- return 1;
- break;
-
- case Quest:
- if (!zpc_disables[ZPC_QUEST])
- return 1;
- break;
-
- case Pound:
- if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH])
- return 1;
- break;
-
- case Hat:
- if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HAT])
- return 1;
- break;
- }
- }
- return 0;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prompt.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prompt.c
deleted file mode 100644
index 959ed8e3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prompt.c
+++ /dev/null
@@ -1,2046 +0,0 @@
-/*
- * prompt.c - construct zsh prompts
- *
- * 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 "prompt.pro"
-
-/* text attribute mask */
-
-/**/
-mod_export unsigned txtattrmask;
-
-/* the command stack for use with %_ in prompts */
-
-/**/
-unsigned char *cmdstack;
-/**/
-int cmdsp;
-
-/* parser states, for %_ */
-
-static char *cmdnames[CS_COUNT] = {
- "for", "while", "repeat", "select",
- "until", "if", "then", "else",
- "elif", "math", "cond", "cmdor",
- "cmdand", "pipe", "errpipe", "foreach",
- "case", "function", "subsh", "cursh",
- "array", "quote", "dquote", "bquote",
- "cmdsubst", "mathsubst", "elif-then", "heredoc",
- "heredocd", "brace", "braceparam", "always",
-};
-
-
-struct buf_vars;
-
-struct buf_vars {
-/* Previous set of prompt variables on the stack. */
-
- struct buf_vars *last;
-
-/* The buffer into which an expanded and metafied prompt is being written, *
- * and its size. */
-
- char *buf;
- int bufspc;
-
-/* bp is the pointer to the current position in the buffer, where the next *
- * character will be added. */
-
- char *bp;
-
-/* Position of the start of the current line in the buffer */
-
- char *bufline;
-
-/* bp1 is an auxiliary pointer into the buffer, which when non-NULL is *
- * moved whenever the buffer is reallocated. It is used when data is *
- * being temporarily held in the buffer. */
-
- char *bp1;
-
-/* The format string, for %-expansion. */
-
- char *fm;
-
-/* Non-zero if truncating the current segment of the buffer. */
-
- int truncwidth;
-
-/* Current level of nesting of %{ / %} sequences. */
-
- int dontcount;
-
-/* Level of %{ / %} surrounding a truncation segment. */
-
- int trunccount;
-
-/* Strings to use for %r and %R (for the spelling prompt). */
-
- char *rstring, *Rstring;
-};
-
-typedef struct buf_vars *Buf_vars;
-
-/* The currently active prompt output variables */
-static Buf_vars bv;
-
-/*
- * Expand path p; maximum is npath segments where 0 means the whole path.
- * If tilde is 1, try and find a named directory to use.
- */
-
-static void
-promptpath(char *p, int npath, int tilde)
-{
- char *modp = p;
- Nameddir nd;
-
- if (tilde && ((nd = finddir(p))))
- modp = tricat("~", nd->node.nam, p + strlen(nd->dir));
-
- if (npath) {
- char *sptr;
- if (npath > 0) {
- for (sptr = modp + strlen(modp); sptr > modp; sptr--) {
- if (*sptr == '/' && !--npath) {
- sptr++;
- break;
- }
- }
- if (*sptr == '/' && sptr[1] && sptr != modp)
- sptr++;
- stradd(sptr);
- } else {
- char cbu;
- for (sptr = modp+1; *sptr; sptr++)
- if (*sptr == '/' && !++npath)
- break;
- cbu = *sptr;
- *sptr = 0;
- stradd(modp);
- *sptr = cbu;
- }
- } else
- stradd(modp);
-
- if (p != modp)
- zsfree(modp);
-}
-
-/*
- * Perform prompt expansion on a string, putting the result in a
- * permanently-allocated string. If ns is non-zero, this string
- * may have embedded Inpar and Outpar, which indicate a toggling
- * between spacing and non-spacing parts of the prompt, and
- * Nularg, which (in a non-spacing sequence) indicates a
- * `glitch' space.
- *
- * txtchangep gives an integer controlling the attributes of
- * the prompt. This is for use in zle to maintain the attributes
- * consistenly. Other parts of the shell should not need to use it.
- */
-
-/**/
-mod_export char *
-promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
-{
- struct buf_vars new_vars;
-
- if(!s)
- return ztrdup("");
-
- if ((termflags & TERM_UNKNOWN) && (unset(INTERACTIVE)))
- init_term();
-
- if (isset(PROMPTSUBST)) {
- int olderr = errflag;
- int oldval = lastval;
-
- s = dupstring(s);
- if (!parsestr(&s))
- singsub(&s);
- /*
- * We don't need the special Nularg hack here and we're
- * going to be using Nularg for other things.
- */
- if (*s == Nularg && s[1] == '\0')
- *s = '\0';
-
- /*
- * Ignore errors and status change in prompt substitution.
- * However, keep any user interrupt error that occurred.
- */
- errflag = olderr | (errflag & ERRFLAG_INT);
- lastval = oldval;
- }
-
- memset(&new_vars, 0, sizeof(new_vars));
- new_vars.last = bv;
- bv = &new_vars;
-
- new_vars.rstring = rs;
- new_vars.Rstring = Rs;
- new_vars.fm = s;
- new_vars.bufspc = 256;
- new_vars.bp = new_vars.bufline = new_vars.buf = zshcalloc(new_vars.bufspc);
- new_vars.bp1 = NULL;
- new_vars.truncwidth = 0;
-
- putpromptchar(1, '\0', txtchangep);
- addbufspc(2);
- if (new_vars.dontcount)
- *new_vars.bp++ = Outpar;
- *new_vars.bp = '\0';
- if (!ns) {
- /* If zero, Inpar, Outpar and Nularg should be removed. */
- for (new_vars.bp = new_vars.buf; *new_vars.bp; ) {
- if (*new_vars.bp == Meta)
- new_vars.bp += 2;
- else if (*new_vars.bp == Inpar || *new_vars.bp == Outpar ||
- *new_vars.bp == Nularg)
- chuck(new_vars.bp);
- else
- new_vars.bp++;
- }
- }
-
- bv = new_vars.last;
-
- return new_vars.buf;
-}
-
-/* Parse the argument for %F and %K */
-static int
-parsecolorchar(int arg, int is_fg)
-{
- if (bv->fm[1] == '{') {
- char *ep;
- bv->fm += 2; /* skip over F{ */
- if ((ep = strchr(bv->fm, '}'))) {
- char oc = *ep, *col, *coll;
- *ep = '\0';
- /* expand the contents of the argument so you can use
- * %v for example */
- coll = col = promptexpand(bv->fm, 0, NULL, NULL, NULL);
- *ep = oc;
- arg = match_colour((const char **)&coll, is_fg, 0);
- free(col);
- bv->fm = ep;
- } else {
- arg = match_colour((const char **)&bv->fm, is_fg, 0);
- if (*bv->fm != '}')
- bv->fm--;
- }
- } else
- arg = match_colour(NULL, 1, arg);
- return arg;
-}
-
-/* Perform %- and !-expansion as required on a section of the prompt. The *
- * section is ended by an instance of endchar. If doprint is 0, the valid *
- * % sequences are merely skipped over, and nothing is stored. */
-
-/**/
-static int
-putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
-{
- char *ss, *hostnam;
- int t0, arg, test, sep, j, numjobs, len;
- struct tm *tm;
- struct timespec ts;
- time_t timet;
- Nameddir nd;
-
- for (; *bv->fm && *bv->fm != endchar; bv->fm++) {
- arg = 0;
- if (*bv->fm == '%' && isset(PROMPTPERCENT)) {
- int minus = 0;
- bv->fm++;
- if (*bv->fm == '-') {
- minus = 1;
- bv->fm++;
- }
- if (idigit(*bv->fm)) {
- arg = zstrtol(bv->fm, &bv->fm, 10);
- if (minus)
- arg *= -1;
- } else if (minus)
- arg = -1;
- if (*bv->fm == '(') {
- int tc, otruncwidth;
-
- if (idigit(*++bv->fm)) {
- arg = zstrtol(bv->fm, &bv->fm, 10);
- } else if (arg < 0) {
- /* negative numbers don't make sense here */
- arg *= -1;
- }
- test = 0;
- ss = pwd;
- switch (tc = *bv->fm) {
- case 'c':
- case '.':
- case '~':
- if ((nd = finddir(ss))) {
- arg--;
- ss += strlen(nd->dir);
- } /*FALLTHROUGH*/
- case '/':
- case 'C':
- /* `/' gives 0, `/any' gives 1, etc. */
- if (*ss && *ss++ == '/' && *ss)
- arg--;
- for (; *ss; ss++)
- if (*ss == '/')
- arg--;
- if (arg <= 0)
- test = 1;
- break;
- case 't':
- case 'T':
- case 'd':
- case 'D':
- case 'w':
- timet = time(NULL);
- tm = localtime(&timet);
- switch (tc) {
- case 't':
- test = (arg == tm->tm_min);
- break;
- case 'T':
- test = (arg == tm->tm_hour);
- break;
- case 'd':
- test = (arg == tm->tm_mday);
- break;
- case 'D':
- test = (arg == tm->tm_mon);
- break;
- case 'w':
- test = (arg == tm->tm_wday);
- break;
- }
- break;
- case '?':
- if (lastval == arg)
- test = 1;
- break;
- case '#':
- if (geteuid() == (uid_t)arg)
- test = 1;
- break;
- case 'g':
- if (getegid() == (gid_t)arg)
- test = 1;
- break;
- case 'j':
- for (numjobs = 0, j = 1; j <= maxjob; j++)
- if (jobtab[j].stat && jobtab[j].procs &&
- !(jobtab[j].stat & STAT_NOPRINT)) numjobs++;
- if (numjobs >= arg)
- test = 1;
- break;
- case 'l':
- *bv->bp = '\0';
- countprompt(bv->bufline, &t0, 0, 0);
- if (minus)
- t0 = zterm_columns - t0;
- if (t0 >= arg)
- test = 1;
- break;
- case 'e':
- {
- Funcstack fsptr = funcstack;
- test = arg;
- while (fsptr && test > 0) {
- test--;
- fsptr = fsptr->prev;
- }
- test = !test;
- }
- break;
- case 'L':
- if (shlvl >= arg)
- test = 1;
- break;
- case 'S':
- if (time(NULL) - shtimer.tv_sec >= arg)
- test = 1;
- break;
- case 'v':
- if (arrlen_ge(psvar, arg))
- test = 1;
- break;
- case 'V':
- if (psvar && *psvar && arrlen_ge(psvar, arg)) {
- if (*psvar[(arg ? arg : 1) - 1])
- test = 1;
- }
- break;
- case '_':
- test = (cmdsp >= arg);
- break;
- case '!':
- test = privasserted();
- break;
- default:
- test = -1;
- break;
- }
- if (!*bv->fm || !(sep = *++bv->fm))
- return 0;
- bv->fm++;
- /* Don't do the current truncation until we get back */
- otruncwidth = bv->truncwidth;
- bv->truncwidth = 0;
- if (!putpromptchar(test == 1 && doprint, sep,
- txtchangep) || !*++bv->fm ||
- !putpromptchar(test == 0 && doprint, ')',
- txtchangep)) {
- bv->truncwidth = otruncwidth;
- return 0;
- }
- bv->truncwidth = otruncwidth;
- continue;
- }
- if (!doprint)
- switch(*bv->fm) {
- case '[':
- while(idigit(*++bv->fm));
- while(*++bv->fm != ']');
- continue;
- case '<':
- while(*++bv->fm != '<');
- continue;
- case '>':
- while(*++bv->fm != '>');
- continue;
- case 'D':
- if(bv->fm[1]=='{')
- while(*++bv->fm != '}');
- continue;
- default:
- continue;
- }
- switch (*bv->fm) {
- case '~':
- promptpath(pwd, arg, 1);
- break;
- case 'd':
- case '/':
- promptpath(pwd, arg, 0);
- break;
- case 'c':
- case '.':
- promptpath(pwd, arg ? arg : 1, 1);
- break;
- case 'C':
- promptpath(pwd, arg ? arg : 1, 0);
- break;
- case 'N':
- promptpath(scriptname ? scriptname : argzero, arg, 0);
- break;
- case 'h':
- case '!':
- addbufspc(DIGBUFSIZE);
- convbase(bv->bp, curhist, 10);
- bv->bp += strlen(bv->bp);
- break;
- case 'j':
- for (numjobs = 0, j = 1; j <= maxjob; j++)
- if (jobtab[j].stat && jobtab[j].procs &&
- !(jobtab[j].stat & STAT_NOPRINT)) numjobs++;
- addbufspc(DIGBUFSIZE);
- sprintf(bv->bp, "%d", numjobs);
- bv->bp += strlen(bv->bp);
- break;
- case 'M':
- queue_signals();
- if ((hostnam = getsparam("HOST")))
- stradd(hostnam);
- unqueue_signals();
- break;
- case 'm':
- if (!arg)
- arg++;
- queue_signals();
- if (!(hostnam = getsparam("HOST"))) {
- unqueue_signals();
- break;
- }
- if (arg < 0) {
- for (ss = hostnam + strlen(hostnam); ss > hostnam; ss--)
- if (ss[-1] == '.' && !++arg)
- break;
- stradd(ss);
- } else {
- for (ss = hostnam; *ss; ss++)
- if (*ss == '.' && !--arg)
- break;
- stradd(*ss ? dupstrpfx(hostnam, ss - hostnam) : hostnam);
- }
- unqueue_signals();
- break;
- case 'S':
- txtchangeset(txtchangep, TXTSTANDOUT, TXTNOSTANDOUT);
- txtset(TXTSTANDOUT);
- tsetcap(TCSTANDOUTBEG, TSC_PROMPT);
- break;
- case 's':
- txtchangeset(txtchangep, TXTNOSTANDOUT, TXTSTANDOUT);
- txtunset(TXTSTANDOUT);
- tsetcap(TCSTANDOUTEND, TSC_PROMPT|TSC_DIRTY);
- break;
- case 'B':
- txtchangeset(txtchangep, TXTBOLDFACE, TXTNOBOLDFACE);
- txtset(TXTBOLDFACE);
- tsetcap(TCBOLDFACEBEG, TSC_PROMPT|TSC_DIRTY);
- break;
- case 'b':
- txtchangeset(txtchangep, TXTNOBOLDFACE, TXTBOLDFACE);
- txtunset(TXTBOLDFACE);
- tsetcap(TCALLATTRSOFF, TSC_PROMPT|TSC_DIRTY);
- break;
- case 'U':
- txtchangeset(txtchangep, TXTUNDERLINE, TXTNOUNDERLINE);
- txtset(TXTUNDERLINE);
- tsetcap(TCUNDERLINEBEG, TSC_PROMPT);
- break;
- case 'u':
- txtchangeset(txtchangep, TXTNOUNDERLINE, TXTUNDERLINE);
- txtunset(TXTUNDERLINE);
- tsetcap(TCUNDERLINEEND, TSC_PROMPT|TSC_DIRTY);
- break;
- case 'F':
- arg = parsecolorchar(arg, 1);
- if (arg >= 0 && !(arg & TXTNOFGCOLOUR)) {
- txtchangeset(txtchangep, arg & TXT_ATTR_FG_ON_MASK,
- TXTNOFGCOLOUR | TXT_ATTR_FG_COL_MASK);
- txtunset(TXT_ATTR_FG_COL_MASK);
- txtset(arg & TXT_ATTR_FG_ON_MASK);
- set_colour_attribute(arg, COL_SEQ_FG, TSC_PROMPT);
- break;
- }
- /* else FALLTHROUGH */
- case 'f':
- txtchangeset(txtchangep, TXTNOFGCOLOUR, TXT_ATTR_FG_ON_MASK);
- txtunset(TXT_ATTR_FG_ON_MASK);
- set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, TSC_PROMPT);
- break;
- case 'K':
- arg = parsecolorchar(arg, 0);
- if (arg >= 0 && !(arg & TXTNOBGCOLOUR)) {
- txtchangeset(txtchangep, arg & TXT_ATTR_BG_ON_MASK,
- TXTNOBGCOLOUR | TXT_ATTR_BG_COL_MASK);
- txtunset(TXT_ATTR_BG_COL_MASK);
- txtset(arg & TXT_ATTR_BG_ON_MASK);
- set_colour_attribute(arg, COL_SEQ_BG, TSC_PROMPT);
- break;
- }
- /* else FALLTHROUGH */
- case 'k':
- txtchangeset(txtchangep, TXTNOBGCOLOUR, TXT_ATTR_BG_ON_MASK);
- txtunset(TXT_ATTR_BG_ON_MASK);
- set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, TSC_PROMPT);
- break;
- case '[':
- if (idigit(*++bv->fm))
- arg = zstrtol(bv->fm, &bv->fm, 10);
- if (!prompttrunc(arg, ']', doprint, endchar, txtchangep))
- return *bv->fm;
- break;
- case '<':
- case '>':
- /* Test (minus) here so -0 means "at the right margin" */
- if (minus) {
- *bv->bp = '\0';
- countprompt(bv->bufline, &t0, 0, 0);
- arg = zterm_columns - t0 + arg;
- if (arg <= 0)
- arg = 1;
- }
- if (!prompttrunc(arg, *bv->fm, doprint, endchar, txtchangep))
- return *bv->fm;
- break;
- case '{': /*}*/
- if (!bv->dontcount++) {
- addbufspc(1);
- *bv->bp++ = Inpar;
- }
- if (arg <= 0)
- break;
- /* else */
- /* FALLTHROUGH */
- case 'G':
- if (arg > 0) {
- addbufspc(arg);
- while (arg--)
- *bv->bp++ = Nularg;
- } else {
- addbufspc(1);
- *bv->bp++ = Nularg;
- }
- break;
- case /*{*/ '}':
- if (bv->trunccount && bv->trunccount >= bv->dontcount)
- return *bv->fm;
- if (bv->dontcount && !--bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Outpar;
- }
- break;
- case 't':
- case '@':
- case 'T':
- case '*':
- case 'w':
- case 'W':
- case 'D':
- {
- char *tmfmt, *dd, *tmbuf = NULL;
-
- switch (*bv->fm) {
- case 'T':
- tmfmt = "%K:%M";
- break;
- case '*':
- tmfmt = "%K:%M:%S";
- break;
- case 'w':
- tmfmt = "%a %f";
- break;
- case 'W':
- tmfmt = "%m/%d/%y";
- break;
- case 'D':
- if (bv->fm[1] == '{' /*}*/) {
- for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}'; ss++)
- if(*ss == '\\' && ss[1])
- ss++;
- dd = tmfmt = tmbuf = zalloc(ss - bv->fm);
- for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}';
- ss++) {
- if(*ss == '\\' && ss[1])
- ss++;
- *dd++ = *ss;
- }
- *dd = 0;
- bv->fm = ss - !*ss;
- if (!*tmfmt) {
- free(tmbuf);
- continue;
- }
- } else
- tmfmt = "%y-%m-%d";
- break;
- default:
- tmfmt = "%l:%M%p";
- break;
- }
- zgettime(&ts);
- tm = localtime(&ts.tv_sec);
- /*
- * Hack because strftime won't say how
- * much space it actually needs. Try to add it
- * a few times until it works. Some formats don't
- * actually have a length, so we could go on for
- * ever.
- */
- for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) {
- addbufspc(t0);
- if ((len = ztrftime(bv->bp, t0, tmfmt, tm, ts.tv_nsec))
- >= 0)
- break;
- }
- /* There is enough room for this because addbufspc(t0)
- * allocates room for t0 * 2 bytes. */
- if (len >= 0)
- metafy(bv->bp, len, META_NOALLOC);
- bv->bp += strlen(bv->bp);
- zsfree(tmbuf);
- break;
- }
- case 'n':
- stradd(get_username());
- break;
- case 'l':
- if (*ttystrname) {
- ss = (strncmp(ttystrname, "/dev/tty", 8) ?
- ttystrname + 5 : ttystrname + 8);
- stradd(ss);
- } else
- stradd("()");
- break;
- case 'y':
- if (*ttystrname) {
- ss = (strncmp(ttystrname, "/dev/", 5) ?
- ttystrname : ttystrname + 5);
- stradd(ss);
- } else
- stradd("()");
- break;
- case 'L':
- addbufspc(DIGBUFSIZE);
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- sprintf(bv->bp, "%lld", shlvl);
-#else
- sprintf(bv->bp, "%ld", (long)shlvl);
-#endif
- bv->bp += strlen(bv->bp);
- break;
- case '?':
- addbufspc(DIGBUFSIZE);
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- sprintf(bv->bp, "%lld", lastval);
-#else
- sprintf(bv->bp, "%ld", (long)lastval);
-#endif
- bv->bp += strlen(bv->bp);
- break;
- case '%':
- case ')':
- addbufspc(1);
- *bv->bp++ = *bv->fm;
- break;
- case '#':
- addbufspc(1);
- *bv->bp++ = privasserted() ? '#' : '%';
- break;
- case 'v':
- if (!arg)
- arg = 1;
- else if (arg < 0)
- arg += arrlen(psvar) + 1;
- if (arg > 0 && arrlen_ge(psvar, arg))
- stradd(psvar[arg - 1]);
- break;
- case 'E':
- tsetcap(TCCLEAREOL, TSC_PROMPT);
- break;
- case '^':
- if (cmdsp) {
- if (arg >= 0) {
- if (arg > cmdsp || arg == 0)
- arg = cmdsp;
- for (t0 = cmdsp - 1; arg--; t0--) {
- stradd(cmdnames[cmdstack[t0]]);
- if (arg) {
- addbufspc(1);
- *bv->bp++=' ';
- }
- }
- } else {
- arg = -arg;
- if (arg > cmdsp)
- arg = cmdsp;
- for (t0 = arg - 1; arg--; t0--) {
- stradd(cmdnames[cmdstack[t0]]);
- if (arg) {
- addbufspc(1);
- *bv->bp++=' ';
- }
- }
- }
- }
- break;
- case '_':
- if (cmdsp) {
- if (arg >= 0) {
- if (arg > cmdsp || arg == 0)
- arg = cmdsp;
- for (t0 = cmdsp - arg; arg--; t0++) {
- stradd(cmdnames[cmdstack[t0]]);
- if (arg) {
- addbufspc(1);
- *bv->bp++=' ';
- }
- }
- } else {
- arg = -arg;
- if (arg > cmdsp)
- arg = cmdsp;
- for (t0 = 0; arg--; t0++) {
- stradd(cmdnames[cmdstack[t0]]);
- if (arg) {
- addbufspc(1);
- *bv->bp++=' ';
- }
- }
- }
- }
- break;
- case 'r':
- if(bv->rstring)
- stradd(bv->rstring);
- break;
- case 'R':
- if(bv->Rstring)
- stradd(bv->Rstring);
- break;
- case 'e':
- {
- int depth = 0;
- Funcstack fsptr = funcstack;
- while (fsptr) {
- depth++;
- fsptr = fsptr->prev;
- }
- addbufspc(DIGBUFSIZE);
- sprintf(bv->bp, "%d", depth);
- bv->bp += strlen(bv->bp);
- break;
- }
- case 'I':
- if (funcstack && funcstack->tp != FS_SOURCE &&
- !IN_EVAL_TRAP()) {
- /*
- * We're in a function or an eval with
- * EVALLINENO. Calculate the line number in
- * the file.
- */
- zlong flineno = lineno + funcstack->flineno;
- /* take account of eval line nos. starting at 1 */
- if (funcstack->tp == FS_EVAL)
- lineno--;
- addbufspc(DIGBUFSIZE);
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- sprintf(bv->bp, "%lld", flineno);
-#else
- sprintf(bv->bp, "%ld", (long)flineno);
-#endif
- bv->bp += strlen(bv->bp);
- break;
- }
- /* else we're in a file and lineno is already correct */
- /* FALLTHROUGH */
- case 'i':
- addbufspc(DIGBUFSIZE);
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- sprintf(bv->bp, "%lld", lineno);
-#else
- sprintf(bv->bp, "%ld", (long)lineno);
-#endif
- bv->bp += strlen(bv->bp);
- break;
- case 'x':
- if (funcstack && funcstack->tp != FS_SOURCE &&
- !IN_EVAL_TRAP())
- promptpath(funcstack->filename ? funcstack->filename : "",
- arg, 0);
- else
- promptpath(scriptfilename ? scriptfilename : argzero,
- arg, 0);
- break;
- case '\0':
- return 0;
- case Meta:
- bv->fm++;
- break;
- }
- } else if(*bv->fm == '!' && isset(PROMPTBANG)) {
- if(doprint) {
- if(bv->fm[1] == '!') {
- bv->fm++;
- addbufspc(1);
- pputc('!');
- } else {
- addbufspc(DIGBUFSIZE);
- convbase(bv->bp, curhist, 10);
- bv->bp += strlen(bv->bp);
- }
- }
- } else {
- char c = *bv->fm == Meta ? *++bv->fm ^ 32 : *bv->fm;
-
- if (doprint) {
- addbufspc(1);
- pputc(c);
- }
- }
- }
-
- return *bv->fm;
-}
-
-/* pputc adds a character to the buffer, metafying. There must *
- * already be space. */
-
-/**/
-static void
-pputc(char c)
-{
- if (imeta(c)) {
- *bv->bp++ = Meta;
- c ^= 32;
- }
- *bv->bp++ = c;
- if (c == '\n' && !bv->dontcount)
- bv->bufline = bv->bp;
-}
-
-/* Make sure there is room for `need' more characters in the buffer. */
-
-/**/
-static void
-addbufspc(int need)
-{
- need *= 2; /* for metafication */
- if((bv->bp - bv->buf) + need > bv->bufspc) {
- int bo = bv->bp - bv->buf;
- int bo1 = bv->bp1 ? bv->bp1 - bv->buf : -1;
- ptrdiff_t bufline_off = bv->bufline ? bv->bufline - bv->buf : -1;
-
- if(need & 255)
- need = (need | 255) + 1;
- bv->buf = realloc(bv->buf, bv->bufspc += need);
- memset(bv->buf + bv->bufspc - need, 0, need);
- bv->bp = bv->buf + bo;
- if(bo1 != -1)
- bv->bp1 = bv->buf + bo1;
- if (bufline_off != -1)
- bv->bufline = bv->buf + bufline_off;
- }
-}
-
-/* stradd() adds a metafied string to the prompt, *
- * in a visible representation. */
-
-/**/
-void
-stradd(char *d)
-{
-#ifdef MULTIBYTE_SUPPORT
- char *ums, *ups;
- int upslen, eol = 0;
- mbstate_t mbs;
-
- memset(&mbs, 0, sizeof mbs);
- ums = ztrdup(d);
- ups = unmetafy(ums, &upslen);
-
- /*
- * We now have a raw string of possibly multibyte characters.
- * Read each character one by one.
- */
- while (upslen > 0) {
- wchar_t cc;
- char *pc;
- size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, ups, upslen, &mbs);
-
- switch (cnt) {
- case MB_INCOMPLETE:
- eol = 1;
- /* FALL THROUGH */
- case MB_INVALID:
- /* Bad character. Take the next byte on its own. */
- pc = nicechar(*ups);
- cnt = 1;
- memset(&mbs, 0, sizeof mbs);
- break;
- case 0:
- cnt = 1;
- /* FALL THROUGH */
- default:
- /* Take full wide character in one go */
- mb_charinit();
- pc = wcs_nicechar(cc, NULL, NULL);
- break;
- }
- /* Keep output as metafied string. */
- addbufspc(strlen(pc));
-
- upslen -= cnt;
- ups += cnt;
-
- /* Put printed representation into the buffer */
- while (*pc)
- *bv->bp++ = *pc++;
- }
-
- free(ums);
-#else
- char *ps, *pc;
- addbufspc(niceztrlen(d));
- /* This loop puts the nice representation of the string into the
- * prompt buffer. */
- for (ps = d; *ps; ps++) {
- for (pc = nicechar(*ps == Meta ? *++ps^32 : *ps); *pc; pc++)
- *bv->bp++ = *pc;
- }
-#endif
-}
-
-/* tsetcap(), among other things, can write a termcap string into the buffer. */
-
-/**/
-mod_export void
-tsetcap(int cap, int flags)
-{
- if (tccan(cap) && !isset(SINGLELINEZLE) &&
- !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
- switch (flags & TSC_OUTPUT_MASK) {
- case TSC_RAW:
- tputs(tcstr[cap], 1, putraw);
- break;
- case 0:
- default:
- tputs(tcstr[cap], 1, putshout);
- break;
- case TSC_PROMPT:
- if (!bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Inpar;
- }
- tputs(tcstr[cap], 1, putstr);
- if (!bv->dontcount) {
- int glitch = 0;
-
- if (cap == TCSTANDOUTBEG || cap == TCSTANDOUTEND)
- glitch = tgetnum("sg");
- else if (cap == TCUNDERLINEBEG || cap == TCUNDERLINEEND)
- glitch = tgetnum("ug");
- if(glitch < 0)
- glitch = 0;
- addbufspc(glitch + 1);
- while(glitch--)
- *bv->bp++ = Nularg;
- *bv->bp++ = Outpar;
- }
- break;
- }
-
- if (flags & TSC_DIRTY) {
- flags &= ~TSC_DIRTY;
- if (txtisset(TXTBOLDFACE) && cap != TCBOLDFACEBEG)
- tsetcap(TCBOLDFACEBEG, flags);
- if (txtisset(TXTSTANDOUT))
- tsetcap(TCSTANDOUTBEG, flags);
- if (txtisset(TXTUNDERLINE))
- tsetcap(TCUNDERLINEBEG, flags);
- if (txtisset(TXTFGCOLOUR))
- set_colour_attribute(txtattrmask, COL_SEQ_FG, TSC_PROMPT);
- if (txtisset(TXTBGCOLOUR))
- set_colour_attribute(txtattrmask, COL_SEQ_BG, TSC_PROMPT);
- }
- }
-}
-
-/**/
-int
-putstr(int d)
-{
- addbufspc(1);
- pputc(d);
- return 0;
-}
-
-/*
- * Count height etc. of a prompt string returned by promptexpand().
- * This depends on the current terminal width, and tabs and
- * newlines require nontrivial processing.
- * Passing `overf' as -1 means to ignore columns (absolute width).
- *
- * If multibyte is enabled, take account of multibyte characters
- * by locating them and finding out their screen width.
- */
-
-/**/
-mod_export void
-countprompt(char *str, int *wp, int *hp, int overf)
-{
- int w = 0, h = 1;
- int s = 1;
-#ifdef MULTIBYTE_SUPPORT
- int wcw, multi = 0;
- char inchar;
- mbstate_t mbs;
- wchar_t wc;
-
- memset(&mbs, 0, sizeof(mbs));
-#endif
-
- for (; *str; str++) {
- if (w > zterm_columns && overf >= 0) {
- w = 0;
- h++;
- }
- /*
- * Input string should be metafied, so tokens in it should
- * be real tokens, even if there are multibyte characters.
- */
- if (*str == Inpar)
- s = 0;
- else if (*str == Outpar)
- s = 1;
- else if (*str == Nularg)
- w++;
- else if (s) {
- if (*str == Meta) {
-#ifdef MULTIBYTE_SUPPORT
- inchar = *++str ^ 32;
-#else
- str++;
-#endif
- } else {
-#ifdef MULTIBYTE_SUPPORT
- /*
- * Don't look for tab or newline in the middle
- * of a multibyte character. Otherwise, we are
- * relying on the character set being an extension
- * of ASCII so it's safe to test a single byte.
- */
- if (!multi) {
-#endif
- if (*str == '\t') {
- w = (w | 7) + 1;
- continue;
- } else if (*str == '\n') {
- w = 0;
- h++;
- continue;
- }
-#ifdef MULTIBYTE_SUPPORT
- }
-
- inchar = *str;
-#endif
- }
-
-#ifdef MULTIBYTE_SUPPORT
- switch (mbrtowc(&wc, &inchar, 1, &mbs)) {
- case MB_INCOMPLETE:
- /* Character is incomplete -- keep looking. */
- multi = 1;
- break;
- case MB_INVALID:
- memset(&mbs, 0, sizeof mbs);
- /* Invalid character: assume single width. */
- multi = 0;
- w++;
- break;
- case 0:
- multi = 0;
- break;
- default:
- /*
- * If the character isn't printable, WCWIDTH() returns
- * -1. We assume width 1.
- */
- wcw = WCWIDTH(wc);
- if (wcw >= 0)
- w += wcw;
- else
- w++;
- multi = 0;
- break;
- }
-#else
- w++;
-#endif
- }
- }
- /*
- * multi may still be set if we were in the middle of the character.
- * This isn't easy to handle generally; just assume there's no
- * output.
- */
- if(w >= zterm_columns && overf >= 0) {
- if (!overf || w > zterm_columns) {
- w = 0;
- h++;
- }
- }
- if(wp)
- *wp = w;
- if(hp)
- *hp = h;
-}
-
-/**/
-static int
-prompttrunc(int arg, int truncchar, int doprint, int endchar,
- unsigned int *txtchangep)
-{
- if (arg > 0) {
- char ch = *bv->fm, *ptr, *truncstr;
- int truncatleft = ch == '<';
- int w = bv->bp - bv->buf;
-
- /*
- * If there is already a truncation active, return so that
- * can be finished, backing up so that the new truncation
- * can be started afterwards.
- */
- if (bv->truncwidth) {
- while (*--bv->fm != '%')
- ;
- bv->fm--;
- return 0;
- }
-
- bv->truncwidth = arg;
- if (*bv->fm != ']')
- bv->fm++;
- while (*bv->fm && *bv->fm != truncchar) {
- if (*bv->fm == '\\' && bv->fm[1])
- ++bv->fm;
- addbufspc(1);
- *bv->bp++ = *bv->fm++;
- }
- if (!*bv->fm)
- return 0;
- if (bv->bp - bv->buf == w && truncchar == ']') {
- addbufspc(1);
- *bv->bp++ = '<';
- }
- ptr = bv->buf + w; /* addbufspc() may have realloc()'d bv->buf */
- /*
- * Now:
- * bv->buf is the start of the output prompt buffer
- * ptr is the start of the truncation string
- * bv->bp is the end of the truncation string
- */
- truncstr = ztrduppfx(ptr, bv->bp - ptr);
-
- bv->bp = ptr;
- w = bv->bp - bv->buf;
- bv->fm++;
- bv->trunccount = bv->dontcount;
- putpromptchar(doprint, endchar, txtchangep);
- bv->trunccount = 0;
- ptr = bv->buf + w; /* putpromptchar() may have realloc()'d */
- *bv->bp = '\0';
- /*
- * Now:
- * ptr is the start of the truncation string and also
- * where we need to start putting any truncated output
- * bv->bp is the end of the string we have just added, which
- * may need truncating.
- */
-
- /*
- * w below is screen width if multibyte support is enabled
- * (note that above it was a raw string pointer difference).
- * It's the full width of the string we may need to truncate.
- *
- * bv->truncwidth has come from the user, so we interpret this
- * as a screen width, too.
- */
- countprompt(ptr, &w, 0, -1);
- if (w > bv->truncwidth) {
- /*
- * We need to truncate. t points to the truncation string
- * -- which is inserted literally, without nice
- * representation. twidth is its printing width, and maxwidth
- * is the amount of the main string that we want to keep.
- * Note that if the truncation string is longer than the
- * truncation length (twidth > bv->truncwidth), the truncation
- * string is used in full.
- */
- char *t = truncstr;
- int fullen = bv->bp - ptr;
- int twidth, maxwidth;
- int ntrunc = strlen(t);
-
- twidth = MB_METASTRWIDTH(t);
- if (twidth < bv->truncwidth) {
- maxwidth = bv->truncwidth - twidth;
- /*
- * It's not safe to assume there are no invisible substrings
- * just because the width is less than the full string
- * length since there may be multibyte characters.
- */
- addbufspc(ntrunc+1);
- /* may have realloc'd */
- ptr = bv->bp - fullen;
-
- if (truncatleft) {
- /*
- * To truncate at the left, selectively copy
- * maxwidth bytes from the main prompt, preceded
- * by the truncation string in full.
- *
- * We're overwriting the string containing the
- * text to be truncated, so copy it. We've
- * just ensured there's sufficient space at the
- * end of the prompt string.
- *
- * Pointer into text to be truncated.
- */
- char *fulltextptr, *fulltext;
- int remw;
-#ifdef MULTIBYTE_SUPPORT
- mbstate_t mbs;
- memset(&mbs, 0, sizeof mbs);
-#endif
-
- fulltextptr = fulltext = ptr + ntrunc;
- memmove(fulltext, ptr, fullen);
- fulltext[fullen] = '\0';
-
- /* Copy the truncstr into place. */
- while (*t)
- *ptr++ = *t++;
-
- /*
- * Find the point in the text at which we should
- * start copying, i.e. when the remaining width
- * is less than or equal to the maximum width.
- */
- remw = w;
- while (remw > maxwidth && *fulltextptr) {
- if (*fulltextptr == Inpar) {
- /*
- * Text marked as invisible: copy
- * regardless, since we don't know what
- * this does. It only affects the width
- * if there are Nularg's present.
- * However, even in that case we
- * can't break the sequence down, so
- * we still loop over the entire group.
- */
- for (;;) {
- *ptr++ = *fulltextptr;
- if (*fulltextptr == '\0' ||
- *fulltextptr++ == Outpar)
- break;
- if (fulltextptr[-1] == Nularg)
- remw--;
- }
- } else {
-#ifdef MULTIBYTE_SUPPORT
- /*
- * Normal text: build up a multibyte character.
- */
- char inchar;
- wchar_t cc;
- int wcw;
-
- /*
- * careful: string is still metafied (we
- * need that because we don't know a
- * priori when to stop and the resulting
- * string must be metafied).
- */
- if (*fulltextptr == Meta)
- inchar = *++fulltextptr ^ 32;
- else
- inchar = *fulltextptr;
- fulltextptr++;
- switch (mbrtowc(&cc, &inchar, 1, &mbs)) {
- case MB_INCOMPLETE:
- /* Incomplete multibyte character. */
- break;
- case MB_INVALID:
- /* Reset invalid state. */
- memset(&mbs, 0, sizeof mbs);
- /* FALL THROUGH */
- case 0:
- /* Assume a single-byte character. */
- remw--;
- break;
- default:
- wcw = WCWIDTH(cc);
- if (wcw >= 0)
- remw -= wcw;
- else
- remw--;
- break;
- }
-#else
- /* Single byte character */
- if (*fulltextptr == Meta)
- fulltextptr++;
- fulltextptr++;
- remw--;
-#endif
- }
- }
-
- /*
- * Now simply copy the rest of the text. Still
- * metafied, so this is easy.
- */
- while (*fulltextptr)
- *ptr++ = *fulltextptr++;
- /* Mark the end of copying */
- bv->bp = ptr;
- } else {
- /*
- * Truncating at the right is easier: just leave
- * enough characters until we have reached the
- * maximum width.
- */
- char *skiptext = ptr;
-#ifdef MULTIBYTE_SUPPORT
- mbstate_t mbs;
- memset(&mbs, 0, sizeof mbs);
-#endif
-
- while (maxwidth > 0 && *skiptext) {
- if (*skiptext == Inpar) {
- /* see comment on left truncation above */
- for (;;) {
- if (*skiptext == '\0' ||
- *skiptext++ == Outpar)
- break;
- if (skiptext[-1] == Nularg)
- maxwidth--;
- }
- } else {
-#ifdef MULTIBYTE_SUPPORT
- char inchar;
- wchar_t cc;
- int wcw;
-
- if (*skiptext == Meta)
- inchar = *++skiptext ^ 32;
- else
- inchar = *skiptext;
- skiptext++;
- switch (mbrtowc(&cc, &inchar, 1, &mbs)) {
- case MB_INCOMPLETE:
- /* Incomplete character. */
- break;
- case MB_INVALID:
- /* Reset invalid state. */
- memset(&mbs, 0, sizeof mbs);
- /* FALL THROUGH */
- case 0:
- /* Assume a single-byte character. */
- maxwidth--;
- break;
- default:
- wcw = WCWIDTH(cc);
- if (wcw >= 0)
- maxwidth -= wcw;
- else
- maxwidth--;
- break;
- }
-#else
- if (*skiptext == Meta)
- skiptext++;
- skiptext++;
- maxwidth--;
-#endif
- }
- }
- /*
- * We don't need the visible text from now on,
- * but we'd better copy any invisible bits.
- * History dictates that these go after the
- * truncation string. This is sensible since
- * they may, for example, turn off an effect which
- * should apply to all text at this point.
- *
- * Copy the truncstr.
- */
- ptr = skiptext;
- while (*t)
- *ptr++ = *t++;
- bv->bp = ptr;
- if (*skiptext) {
- /* Move remaining text so we don't overwrite it */
- memmove(bv->bp, skiptext, strlen(skiptext)+1);
- skiptext = bv->bp;
-
- /*
- * Copy anything we want, updating bv->bp
- */
- while (*skiptext) {
- if (*skiptext == Inpar) {
- for (;;) {
- *bv->bp++ = *skiptext;
- if (*skiptext == Outpar ||
- *skiptext == '\0')
- break;
- skiptext++;
- }
- }
- else
- skiptext++;
- }
- }
- }
- } else {
- /* Just copy truncstr; no other text appears. */
- while (*t)
- *ptr++ = *t++;
- bv->bp = ptr;
- }
- *bv->bp = '\0';
- }
- zsfree(truncstr);
- bv->truncwidth = 0;
- /*
- * We may have returned early from the previous putpromptchar *
- * because we found another truncation following this one. *
- * In that case we need to do the rest now. *
- */
- if (!*bv->fm)
- return 0;
- if (*bv->fm != endchar) {
- bv->fm++;
- /*
- * With bv->truncwidth set to zero, we always reach endchar *
- * (or the terminating NULL) this time round. *
- */
- if (!putpromptchar(doprint, endchar, txtchangep))
- return 0;
- }
- /* Now we have to trick it into matching endchar again */
- bv->fm--;
- } else {
- if (*bv->fm != endchar)
- bv->fm++;
- while(*bv->fm && *bv->fm != truncchar) {
- if (*bv->fm == '\\' && bv->fm[1])
- bv->fm++;
- bv->fm++;
- }
- if (bv->truncwidth || !*bv->fm)
- return 0;
- }
- return 1;
-}
-
-/**/
-void
-cmdpush(int cmdtok)
-{
- if (cmdsp >= 0 && cmdsp < CMDSTACKSZ)
- cmdstack[cmdsp++] = (unsigned char)cmdtok;
-}
-
-/**/
-void
-cmdpop(void)
-{
- if (cmdsp <= 0) {
- DPUTS(1, "BUG: cmdstack empty");
- fflush(stderr);
- } else
- cmdsp--;
-}
-
-
-/*****************************************************************************
- * Utilities dealing with colour and other forms of highlighting.
- *
- * These are shared by prompts and by zle, so it's easiest to have them
- * in the main shell.
- *****************************************************************************/
-
-/* Defines standard ANSI colour names in index order */
-static const char *ansi_colours[] = {
- "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white",
- "default", NULL
-};
-
-/* Defines the available types of highlighting */
-struct highlight {
- const char *name;
- int mask_on;
- int mask_off;
-};
-
-static const struct highlight highlights[] = {
- { "none", 0, TXT_ATTR_ON_MASK },
- { "bold", TXTBOLDFACE, 0 },
- { "standout", TXTSTANDOUT, 0 },
- { "underline", TXTUNDERLINE, 0 },
- { NULL, 0, 0 }
-};
-
-/*
- * Return index of ANSI colour for which *teststrp is an abbreviation.
- * Any non-alphabetic character ends the abbreviation.
- * 8 is the special value for default (note this is *not* the
- * right sequence for default which is typically 9).
- * -1 is failure.
- */
-
-static int
-match_named_colour(const char **teststrp)
-{
- const char *teststr = *teststrp, *end, **cptr;
- int len;
-
- for (end = teststr; ialpha(*end); end++)
- ;
- len = end - teststr;
- *teststrp = end;
-
- for (cptr = ansi_colours; *cptr; cptr++) {
- if (!strncmp(teststr, *cptr, len))
- return cptr - ansi_colours;
- }
-
- return -1;
-}
-
-/*
- * Match just the colour part of a highlight specification.
- * If teststrp is NULL, use the already parsed numeric colour.
- * Return the attributes to set in the attribute variable.
- * Return -1 for out of range. Does not check the character
- * following the colour specification.
- */
-
-/**/
-mod_export int
-match_colour(const char **teststrp, int is_fg, int colour)
-{
- int shft, on, named = 0, tc;
-
- if (teststrp) {
- if ((named = ialpha(**teststrp))) {
- colour = match_named_colour(teststrp);
- if (colour == 8) {
- /* default */
- return is_fg ? TXTNOFGCOLOUR : TXTNOBGCOLOUR;
- }
- }
- else
- colour = (int)zstrtol(*teststrp, (char **)teststrp, 10);
- }
- if (colour < 0 || colour >= 256)
- return -1;
- if (is_fg) {
- shft = TXT_ATTR_FG_COL_SHIFT;
- on = TXTFGCOLOUR;
- tc = TCFGCOLOUR;
- } else {
- shft = TXT_ATTR_BG_COL_SHIFT;
- on = TXTBGCOLOUR;
- tc = TCBGCOLOUR;
- }
- /*
- * Try termcap for numbered characters if posible.
- * Don't for named characters, since our best bet
- * of getting the names right is with ANSI sequences.
- */
- if (!named && tccan(tc)) {
- if (tccolours >= 0 && colour >= tccolours) {
- /*
- * Out of range of termcap colours.
- * Can we assume ANSI colours work?
- */
- if (colour > 7)
- return -1; /* No. */
- } else {
- /*
- * We can handle termcap colours and the number
- * is in range, so use termcap.
- */
- on |= is_fg ? TXT_ATTR_FG_TERMCAP :
- TXT_ATTR_BG_TERMCAP;
- }
- }
- return on | (colour << shft);
-}
-
-/*
- * Match a set of highlights in the given teststr.
- * Set *on_var to reflect the values found.
- */
-
-/**/
-mod_export void
-match_highlight(const char *teststr, int *on_var)
-{
- int found = 1;
-
- *on_var = 0;
- while (found && *teststr) {
- const struct highlight *hl;
-
- found = 0;
- if (strpfx("fg=", teststr) || strpfx("bg=", teststr)) {
- int is_fg = (teststr[0] == 'f'), atr;
-
- teststr += 3;
- atr = match_colour(&teststr, is_fg, 0);
- if (*teststr == ',')
- teststr++;
- else if (*teststr)
- break;
- found = 1;
- /* skip out of range colours but keep scanning attributes */
- if (atr >= 0)
- *on_var |= atr;
- } else {
- for (hl = highlights; hl->name; hl++) {
- if (strpfx(hl->name, teststr)) {
- const char *val = teststr + strlen(hl->name);
-
- if (*val == ',')
- val++;
- else if (*val)
- break;
-
- *on_var |= hl->mask_on;
- *on_var &= ~hl->mask_off;
- teststr = val;
- found = 1;
- }
- }
- }
- }
-}
-
-/*
- * Count or output a string for colour information: used
- * by output_highlight().
- */
-
-static int
-output_colour(int colour, int fg_bg, int use_tc, char *buf)
-{
- int atrlen = 3, len;
- char *ptr = buf;
- if (buf) {
- strcpy(ptr, fg_bg == COL_SEQ_FG ? "fg=" : "bg=");
- ptr += 3;
- }
- /* colour should only be > 7 if using termcap but let's be safe */
- if (use_tc || colour > 7) {
- char digbuf[DIGBUFSIZE];
- sprintf(digbuf, "%d", colour);
- len = strlen(digbuf);
- atrlen += len;
- if (buf)
- strcpy(ptr, digbuf);
- } else {
- len = strlen(ansi_colours[colour]);
- atrlen += len;
- if (buf)
- strcpy(ptr, ansi_colours[colour]);
- }
-
- return atrlen;
-}
-
-/*
- * Count the length needed for outputting highlighting information
- * as a string based on the bits for the attributes.
- *
- * If buf is not NULL, output the strings into the buffer, too.
- * As conventional with strings, the allocated length should be
- * at least the returned value plus 1 for the NUL byte.
- */
-
-/**/
-mod_export int
-output_highlight(int atr, char *buf)
-{
- const struct highlight *hp;
- int atrlen = 0, len;
- char *ptr = buf;
-
- if (atr & TXTFGCOLOUR) {
- len = output_colour(txtchangeget(atr, TXT_ATTR_FG_COL),
- COL_SEQ_FG,
- (atr & TXT_ATTR_FG_TERMCAP),
- ptr);
- atrlen += len;
- if (buf)
- ptr += len;
- }
- if (atr & TXTBGCOLOUR) {
- if (atrlen) {
- atrlen++;
- if (buf) {
- strcpy(ptr, ",");
- ptr++;
- }
- }
- len = output_colour(txtchangeget(atr, TXT_ATTR_BG_COL),
- COL_SEQ_BG,
- (atr & TXT_ATTR_BG_TERMCAP),
- ptr);
- atrlen += len;
- if (buf)
- ptr += len;
- }
- for (hp = highlights; hp->name; hp++) {
- if (hp->mask_on & atr) {
- if (atrlen) {
- atrlen++;
- if (buf) {
- strcpy(ptr, ",");
- ptr++;
- }
- }
- len = strlen(hp->name);
- atrlen += len;
- if (buf) {
- strcpy(ptr, hp->name);
- ptr += len;
- }
- }
- }
-
- if (atrlen == 0) {
- if (buf)
- strcpy(ptr, "none");
- return 4;
- }
- return atrlen;
-}
-
-/* Structure and array for holding special colour terminal sequences */
-
-/* Start of escape sequence for foreground colour */
-#define TC_COL_FG_START "\033[3"
-/* End of escape sequence for foreground colour */
-#define TC_COL_FG_END "m"
-/* Code to reset foreground colour */
-#define TC_COL_FG_DEFAULT "9"
-
-/* Start of escape sequence for background colour */
-#define TC_COL_BG_START "\033[4"
-/* End of escape sequence for background colour */
-#define TC_COL_BG_END "m"
-/* Code to reset background colour */
-#define TC_COL_BG_DEFAULT "9"
-
-struct colour_sequences {
- char *start; /* Escape sequence start */
- char *end; /* Escape sequence terminator */
- char *def; /* Code to reset default colour */
-};
-static struct colour_sequences fg_bg_sequences[2];
-
-/*
- * We need a buffer for colour sequence composition. It may
- * vary depending on the sequences set. However, it's inefficient
- * allocating it separately every time we send a colour sequence,
- * so do it once per refresh.
- */
-static char *colseq_buf;
-
-/*
- * Count how often this has been allocated, for recursive usage.
- */
-static int colseq_buf_allocs;
-
-/**/
-void
-set_default_colour_sequences(void)
-{
- fg_bg_sequences[COL_SEQ_FG].start = ztrdup(TC_COL_FG_START);
- fg_bg_sequences[COL_SEQ_FG].end = ztrdup(TC_COL_FG_END);
- fg_bg_sequences[COL_SEQ_FG].def = ztrdup(TC_COL_FG_DEFAULT);
-
- fg_bg_sequences[COL_SEQ_BG].start = ztrdup(TC_COL_BG_START);
- fg_bg_sequences[COL_SEQ_BG].end = ztrdup(TC_COL_BG_END);
- fg_bg_sequences[COL_SEQ_BG].def = ztrdup(TC_COL_BG_DEFAULT);
-}
-
-static void
-set_colour_code(char *str, char **var)
-{
- char *keyseq;
- int len;
-
- zsfree(*var);
- keyseq = getkeystring(str, &len, GETKEYS_BINDKEY, NULL);
- *var = metafy(keyseq, len, META_DUP);
-}
-
-/* Allocate buffer for colour code composition */
-
-/**/
-mod_export void
-allocate_colour_buffer(void)
-{
- char **atrs;
- int lenfg, lenbg, len;
-
- if (colseq_buf_allocs++)
- return;
-
- atrs = getaparam("zle_highlight");
- if (atrs) {
- for (; *atrs; atrs++) {
- if (strpfx("fg_start_code:", *atrs)) {
- set_colour_code(*atrs + 14, &fg_bg_sequences[COL_SEQ_FG].start);
- } else if (strpfx("fg_default_code:", *atrs)) {
- set_colour_code(*atrs + 16, &fg_bg_sequences[COL_SEQ_FG].def);
- } else if (strpfx("fg_end_code:", *atrs)) {
- set_colour_code(*atrs + 12, &fg_bg_sequences[COL_SEQ_FG].end);
- } else if (strpfx("bg_start_code:", *atrs)) {
- set_colour_code(*atrs + 14, &fg_bg_sequences[COL_SEQ_BG].start);
- } else if (strpfx("bg_default_code:", *atrs)) {
- set_colour_code(*atrs + 16, &fg_bg_sequences[COL_SEQ_BG].def);
- } else if (strpfx("bg_end_code:", *atrs)) {
- set_colour_code(*atrs + 12, &fg_bg_sequences[COL_SEQ_BG].end);
- }
- }
- }
-
- lenfg = strlen(fg_bg_sequences[COL_SEQ_FG].def);
- /* always need 1 character for non-default code */
- if (lenfg < 1)
- lenfg = 1;
- lenfg += strlen(fg_bg_sequences[COL_SEQ_FG].start) +
- strlen(fg_bg_sequences[COL_SEQ_FG].end);
-
- lenbg = strlen(fg_bg_sequences[COL_SEQ_BG].def);
- /* always need 1 character for non-default code */
- if (lenbg < 1)
- lenbg = 1;
- lenbg += strlen(fg_bg_sequences[COL_SEQ_BG].start) +
- strlen(fg_bg_sequences[COL_SEQ_BG].end);
-
- len = lenfg > lenbg ? lenfg : lenbg;
- colseq_buf = (char *)zalloc(len+1);
-}
-
-/* Free the colour buffer previously allocated. */
-
-/**/
-mod_export void
-free_colour_buffer(void)
-{
- if (--colseq_buf_allocs)
- return;
-
- DPUTS(!colseq_buf, "Freeing colour sequence buffer without alloc");
- /* Free buffer for colour code composition */
- free(colseq_buf);
- colseq_buf = NULL;
-}
-
-/*
- * Handle outputting of a colour for prompts or zle.
- * colour is the numeric colour, 0 to 255 (or less if termcap
- * says fewer are supported).
- * fg_bg indicates if we're changing the foreground or background.
- * tc indicates the termcap code to use, if appropriate.
- * def indicates if we're resetting the default colour.
- * use_termcap indicates if we should use termcap to output colours.
- * flags is either 0 or TSC_PROMPT.
- */
-
-/**/
-mod_export void
-set_colour_attribute(int atr, int fg_bg, int flags)
-{
- char *ptr;
- int do_free, is_prompt = (flags & TSC_PROMPT) ? 1 : 0;
- int colour, tc, def, use_termcap;
-
- if (fg_bg == COL_SEQ_FG) {
- colour = txtchangeget(atr, TXT_ATTR_FG_COL);
- tc = TCFGCOLOUR;
- def = txtchangeisset(atr, TXTNOFGCOLOUR);
- use_termcap = txtchangeisset(atr, TXT_ATTR_FG_TERMCAP);
- } else {
- colour = txtchangeget(atr, TXT_ATTR_BG_COL);
- tc = TCBGCOLOUR;
- def = txtchangeisset(atr, TXTNOBGCOLOUR);
- use_termcap = txtchangeisset(atr, TXT_ATTR_BG_TERMCAP);
- }
-
- /*
- * If we're not restoring the default, and either have a
- * colour value that is too large for ANSI, or have been told
- * to use the termcap sequence, try to use the termcap sequence.
- *
- * We have already sanitised the values we allow from the
- * highlighting variables, so much of this shouldn't be
- * necessary at this point, but we might as well be safe.
- */
- if (!def && (colour > 7 || use_termcap)) {
- /*
- * We can if it's available, and either we couldn't get
- * the maximum number of colours, or the colour is in range.
- */
- if (tccan(tc) && (tccolours < 0 || colour < tccolours))
- {
- if (is_prompt)
- {
- if (!bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Inpar;
- }
- tputs(tgoto(tcstr[tc], colour, colour), 1, putstr);
- if (!bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Outpar;
- }
- } else {
- tputs(tgoto(tcstr[tc], colour, colour), 1, putshout);
- }
- /* That worked. */
- return;
- }
- /*
- * Nope, that didn't work.
- * If 0 to 7, assume standard ANSI works, otherwise it won't.
- */
- if (colour > 7)
- return;
- }
-
- if ((do_free = (colseq_buf == NULL))) {
- /* This can happen when moving the cursor in trashzle() */
- allocate_colour_buffer();
- }
-
- strcpy(colseq_buf, fg_bg_sequences[fg_bg].start);
-
- ptr = colseq_buf + strlen(colseq_buf);
- if (def) {
- strcpy(ptr, fg_bg_sequences[fg_bg].def);
- while (*ptr)
- ptr++;
- } else
- *ptr++ = colour + '0';
- strcpy(ptr, fg_bg_sequences[fg_bg].end);
-
- if (is_prompt) {
- if (!bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Inpar;
- }
- tputs(colseq_buf, 1, putstr);
- if (!bv->dontcount) {
- addbufspc(1);
- *bv->bp++ = Outpar;
- }
- } else
- tputs(colseq_buf, 1, putshout);
-
- if (do_free)
- free_colour_buffer();
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prototypes.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prototypes.h
deleted file mode 100644
index e3db4f5e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/prototypes.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * prototypes.h - prototypes header file
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#ifndef HAVE_STDLIB_H
-char *malloc _((size_t));
-char *realloc _((void *, size_t));
-char *calloc _((size_t, size_t));
-#endif
-
-#if !(defined(USES_TERMCAP_H) || defined(USES_TERM_H))
-/*
- * These prototypes are only used where we don't have the
- * headers. In some cases they need tweaking.
- * TBD: we'd much prefer to get hold of the header where
- * these are defined.
- */
-#ifdef _AIX
-#define TC_CONST const
-#else
-#define TC_CONST
-#endif
-extern int tgetent _((char *bp, TC_CONST char *name));
-extern int tgetnum _((char *id));
-extern int tgetflag _((char *id));
-extern char *tgetstr _((char *id, char **area));
-extern int tputs _((TC_CONST char *cp, int affcnt, int (*outc) (int)));
-#undef TC_CONST
-#endif
-
-/*
- * Some systems that do have termcap headers nonetheless don't
- * declare tgoto, so we detect if that is missing separately.
- */
-#ifdef TGOTO_PROTO_MISSING
-char *tgoto(const char *cap, int col, int row);
-#endif
-
-/* MISSING PROTOTYPES FOR VARIOUS OPERATING SYSTEMS */
-
-#if defined(__hpux) && defined(_HPUX_SOURCE) && !defined(_XPG4_EXTENDED)
-# define SELECT_ARG_2_T int *
-#else
-# define SELECT_ARG_2_T fd_set *
-#endif
-
-#ifdef __osf__
-char *mktemp _((char *));
-#endif
-
-#if defined(__osf__) && defined(__alpha) && defined(__GNUC__)
-/* Digital cc does not need these prototypes, gcc does need them */
-# ifndef HAVE_IOCTL_PROTO
-int ioctl _((int d, unsigned long request, void *argp));
-# endif
-# ifndef HAVE_MKNOD_PROTO
-int mknod _((const char *pathname, int mode, dev_t device));
-# endif
-int nice _((int increment));
-int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout));
-#endif
-
-#if defined(DGUX) && defined(__STDC__)
-/* Just plain missing. */
-extern int getrlimit _((int resource, struct rlimit *rlp));
-extern int setrlimit _((int resource, const struct rlimit *rlp));
-extern int getrusage _((int who, struct rusage *rusage));
-extern int gettimeofday _((struct timeval *tv, struct timezone *tz));
-extern int wait3 _((union wait *wait_status, int options, struct rusage *rusage));
-extern int getdomainname _((char *name, int maxlength));
-extern int select _((int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout));
-#endif /* DGUX and __STDC__ */
-
-#ifdef __NeXT__
-extern pid_t getppid(void);
-#endif
-
-#if defined(__sun__) && !defined(__SVR4) /* SunOS */
-extern char *strerror _((int errnum));
-#endif
-
-/**************************************************/
-/*** prototypes for functions built in compat.c ***/
-#ifndef HAVE_STRSTR
-extern char *strstr _((const char *s, const char *t));
-#endif
-
-#ifndef HAVE_GETHOSTNAME
-extern int gethostname _((char *name, size_t namelen));
-#endif
-
-#ifndef HAVE_GETTIMEOFDAY
-extern int gettimeofday _((struct timeval *tv, struct timezone *tz));
-#endif
-
-#ifndef HAVE_DIFFTIME
-extern double difftime _((time_t t2, time_t t1));
-#endif
-
-#ifndef HAVE_STRERROR
-extern char *strerror _((int errnum));
-#endif
-
-/*** end of prototypes for functions in compat.c ***/
-/***************************************************/
-
-#ifndef HAVE_MEMMOVE
-extern void bcopy _((const void *, void *, size_t));
-#endif
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.c
deleted file mode 100644
index 20c6fdf4..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.c
+++ /dev/null
@@ -1,1479 +0,0 @@
-/*
- * signals.c - 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.
- *
- */
-
-#include "zsh.mdh"
-#include "signals.pro"
-
-/* Array describing the state of each signal: an element contains *
- * 0 for the default action or some ZSIG_* flags ored together. */
-
-/**/
-mod_export int sigtrapped[VSIGCOUNT];
-
-/*
- * Trap programme lists for each signal.
- *
- * If (sigtrapped[sig] & ZSIG_FUNC) is set, this isn't used.
- * The corresponding shell function is used instead.
- *
- * Otherwise, if sigtrapped[sig] is not zero, this is NULL when a signal
- * is to be ignored, and if not NULL contains the programme list to be
- * eval'd.
- */
-
-/**/
-mod_export Eprog siglists[VSIGCOUNT];
-
-/* Total count of trapped signals */
-
-/**/
-mod_export int nsigtrapped;
-
-/* Running an exit trap? */
-
-/**/
-int in_exit_trap;
-
-/*
- * Flag that exit trap has been set in POSIX mode.
- * The setter's expectation is therefore that it is run
- * on programme exit, not function exit.
- */
-
-/**/
-static int exit_trap_posix;
-
-/* Variables used by signal queueing */
-
-/**/
-mod_export int queueing_enabled, queue_front, queue_rear;
-/**/
-mod_export int signal_queue[MAX_QUEUE_SIZE];
-/**/
-mod_export sigset_t signal_mask_queue[MAX_QUEUE_SIZE];
-#ifdef DEBUG
-/**/
-mod_export int queue_in;
-#endif
-
-/* Variables used by trap queueing */
-
-/**/
-mod_export int trap_queueing_enabled, trap_queue_front, trap_queue_rear;
-/**/
-mod_export int trap_queue[MAX_QUEUE_SIZE];
-
-/* This is only used on machines that don't understand signal sets. *
- * On SYSV machines this will represent the signals that are blocked *
- * (held) using sighold. On machines which can't block signals at *
- * all, we will simulate this by ignoring them and remembering them *
- * in this variable. */
-#if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS)
-static sigset_t blocked_set;
-#endif
-
-#ifdef POSIX_SIGNALS
-# define signal_jmp_buf sigjmp_buf
-# define signal_setjmp(b) sigsetjmp((b),1)
-# define signal_longjmp(b,n) siglongjmp((b),(n))
-#else
-# define signal_jmp_buf jmp_buf
-# define signal_setjmp(b) setjmp(b)
-# define signal_longjmp(b,n) longjmp((b),(n))
-#endif
-
-#ifdef NO_SIGNAL_BLOCKING
-# define signal_process(sig) signal_ignore(sig)
-# define signal_reset(sig) install_handler(sig)
-#else
-# define signal_process(sig) ;
-# define signal_reset(sig) ;
-#endif
-
-/* Install signal handler for given signal. *
- * If possible, we want to make sure that interrupted *
- * system calls are not restarted. */
-
-/**/
-mod_export void
-install_handler(int sig)
-{
-#ifdef POSIX_SIGNALS
- struct sigaction act;
-
- act.sa_handler = (SIGNAL_HANDTYPE) zhandler;
- sigemptyset(&act.sa_mask); /* only block sig while in handler */
- act.sa_flags = 0;
-# ifdef SA_INTERRUPT /* SunOS 4.x */
- if (interact)
- act.sa_flags |= SA_INTERRUPT; /* make sure system calls are not restarted */
-# endif
- sigaction(sig, &act, (struct sigaction *)NULL);
-#else
-# ifdef BSD_SIGNALS
- struct sigvec vec;
-
- vec.sv_handler = (SIGNAL_HANDTYPE) zhandler;
- vec.sv_mask = sigmask(sig); /* mask out this signal while in handler */
-# ifdef SV_INTERRUPT
- vec.sv_flags = SV_INTERRUPT; /* make sure system calls are not restarted */
-# endif
- sigvec(sig, &vec, (struct sigvec *)NULL);
-# else
-# ifdef SYSV_SIGNALS
- /* we want sigset rather than signal because it will *
- * block sig while in handler. signal usually doesn't */
- sigset(sig, zhandler);
-# else /* NO_SIGNAL_BLOCKING (bummer) */
- signal(sig, zhandler);
-
-# endif /* SYSV_SIGNALS */
-# endif /* BSD_SIGNALS */
-#endif /* POSIX_SIGNALS */
-}
-
-/* enable ^C interrupts */
-
-/**/
-mod_export void
-intr(void)
-{
- if (interact)
- install_handler(SIGINT);
-}
-
-/* disable ^C interrupts */
-
-#if 0 /**/
-void
-nointr(void)
-{
- if (interact)
- signal_ignore(SIGINT);
-}
-#endif
-
-/* temporarily block ^C interrupts */
-
-/**/
-mod_export void
-holdintr(void)
-{
- if (interact)
- signal_block(signal_mask(SIGINT));
-}
-
-/* release ^C interrupts */
-
-/**/
-mod_export void
-noholdintr(void)
-{
- if (interact)
- signal_unblock(signal_mask(SIGINT));
-}
-
-/* create a signal mask containing *
- * only the given signal */
-
-/**/
-mod_export sigset_t
-signal_mask(int sig)
-{
- sigset_t set;
-
- sigemptyset(&set);
- if (sig)
- sigaddset(&set, sig);
- return set;
-}
-
-/* Block the signals in the given signal *
- * set. Return the old signal set. */
-
-/**/
-#ifndef BSD_SIGNALS
-
-/**/
-mod_export sigset_t
-signal_block(sigset_t set)
-{
- sigset_t oset;
-
-#ifdef POSIX_SIGNALS
- sigprocmask(SIG_BLOCK, &set, &oset);
-
-#else
-# ifdef SYSV_SIGNALS
- int i;
-
- oset = blocked_set;
- for (i = 1; i <= NSIG; ++i) {
- if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
- sigaddset(&blocked_set, i);
- sighold(i);
- }
- }
-# else /* NO_SIGNAL_BLOCKING */
-/* We will just ignore signals if the system doesn't have *
- * the ability to block them. */
- int i;
-
- oset = blocked_set;
- for (i = 1; i <= NSIG; ++i) {
- if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
- sigaddset(&blocked_set, i);
- signal_ignore(i);
- }
- }
-# endif /* SYSV_SIGNALS */
-#endif /* POSIX_SIGNALS */
-
- return oset;
-}
-
-/**/
-#endif /* BSD_SIGNALS */
-
-/* Unblock the signals in the given signal *
- * set. Return the old signal set. */
-
-/**/
-mod_export sigset_t
-signal_unblock(sigset_t set)
-{
- sigset_t oset;
-
-#ifdef POSIX_SIGNALS
- sigprocmask(SIG_UNBLOCK, &set, &oset);
-#else
-# ifdef BSD_SIGNALS
- sigfillset(&oset);
- oset = sigsetmask(oset);
- sigsetmask(oset & ~set);
-# else
-# ifdef SYSV_SIGNALS
- int i;
-
- oset = blocked_set;
- for (i = 1; i <= NSIG; ++i) {
- if (sigismember(&set, i) && sigismember(&blocked_set, i)) {
- sigdelset(&blocked_set, i);
- sigrelse(i);
- }
- }
-# else /* NO_SIGNAL_BLOCKING */
-/* On systems that can't block signals, we are just ignoring them. So *
- * to unblock signals, we just reenable the signal handler for them. */
- int i;
-
- oset = blocked_set;
- for (i = 1; i <= NSIG; ++i) {
- if (sigismember(&set, i) && sigismember(&blocked_set, i)) {
- sigdelset(&blocked_set, i);
- install_handler(i);
- }
- }
-# endif /* SYSV_SIGNALS */
-# endif /* BSD_SIGNALS */
-#endif /* POSIX_SIGNALS */
-
- return oset;
-}
-
-/* set the process signal mask to *
- * be the given signal mask */
-
-/**/
-mod_export sigset_t
-signal_setmask(sigset_t set)
-{
- sigset_t oset;
-
-#ifdef POSIX_SIGNALS
- sigprocmask(SIG_SETMASK, &set, &oset);
-#else
-# ifdef BSD_SIGNALS
- oset = sigsetmask(set);
-# else
-# ifdef SYSV_SIGNALS
- int i;
-
- oset = blocked_set;
- for (i = 1; i <= NSIG; ++i) {
- if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
- sigaddset(&blocked_set, i);
- sighold(i);
- } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) {
- sigdelset(&blocked_set, i);
- sigrelse(i);
- }
- }
-# else /* NO_SIGNAL_BLOCKING */
- int i;
-
- oset = blocked_set;
- for (i = 1; i < NSIG; ++i) {
- if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
- sigaddset(&blocked_set, i);
- signal_ignore(i);
- } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) {
- sigdelset(&blocked_set, i);
- install_handler(i);
- }
- }
-# endif /* SYSV_SIGNALS */
-# endif /* BSD_SIGNALS */
-#endif /* POSIX_SIGNALS */
-
- return oset;
-}
-
-#if defined(NO_SIGNAL_BLOCKING)
-static int suspend_longjmp = 0;
-static signal_jmp_buf suspend_jmp_buf;
-#endif
-
-/**/
-int
-signal_suspend(UNUSED(int sig), int wait_cmd)
-{
- int ret;
-
-#if defined(POSIX_SIGNALS) || defined(BSD_SIGNALS)
- sigset_t set;
-# if defined(POSIX_SIGNALS) && defined(BROKEN_POSIX_SIGSUSPEND)
- sigset_t oset;
-# endif
-
- sigemptyset(&set);
-
- /* SIGINT from the terminal driver needs to interrupt "wait"
- * and to cause traps to fire, but otherwise should not be
- * handled by the shell until after any foreground job has
- * a chance to decide whether to exit on that signal.
- */
- if (!(wait_cmd || isset(TRAPSASYNC) ||
- (sigtrapped[SIGINT] & ~ZSIG_IGNORED)))
- sigaddset(&set, SIGINT);
-#endif /* POSIX_SIGNALS || BSD_SIGNALS */
-
-#ifdef POSIX_SIGNALS
-# ifdef BROKEN_POSIX_SIGSUSPEND
- sigprocmask(SIG_SETMASK, &set, &oset);
- ret = pause();
- sigprocmask(SIG_SETMASK, &oset, NULL);
-# else /* not BROKEN_POSIX_SIGSUSPEND */
- ret = sigsuspend(&set);
-# endif /* BROKEN_POSIX_SIGSUSPEND */
-#else /* not POSIX_SIGNALS */
-# ifdef BSD_SIGNALS
- ret = sigpause(set);
-# else
-# ifdef SYSV_SIGNALS
- ret = sigpause(sig);
-
-# else /* NO_SIGNAL_BLOCKING */
- /* need to use signal_longjmp to make this race-free *
- * between the child_unblock() and pause() */
- if (signal_setjmp(suspend_jmp_buf) == 0) {
- suspend_longjmp = 1; /* we want to signal_longjmp after catching signal */
- child_unblock(); /* do we need to do wait_cmd stuff as well? */
- ret = pause();
- }
- suspend_longjmp = 0; /* turn off using signal_longjmp since we are past *
- * the pause() function. */
-# endif /* SYSV_SIGNALS */
-# endif /* BSD_SIGNALS */
-#endif /* POSIX_SIGNALS */
-
- return ret;
-}
-
-/* last signal we handled: race prone, or what? */
-/**/
-int last_signal;
-
-/*
- * Wait for any processes that have changed state.
- *
- * The main use for this is in the SIGCHLD handler. However,
- * we also use it to pick up status changes of jobs when
- * updating jobs.
- */
-/**/
-void
-wait_for_processes(void)
-{
- /* keep WAITING until no more child processes to reap */
- for (;;) {
- /* save the errno, since WAIT may change it */
- int old_errno = errno;
- int status;
- Job jn;
- Process pn;
- pid_t pid;
- pid_t *procsubpid = &cmdoutpid;
- int *procsubval = &cmdoutval;
- int cont = 0;
- struct execstack *es = exstack;
-
- /*
- * Reap the child process.
- * If we want usage information, we need to use wait3.
- */
-#if defined(HAVE_WAIT3) || defined(HAVE_WAITPID)
-# ifdef WCONTINUED
-# define WAITFLAGS (WNOHANG|WUNTRACED|WCONTINUED)
-# else
-# define WAITFLAGS (WNOHANG|WUNTRACED)
-# endif
-#endif
-#ifdef HAVE_WAIT3
-# ifdef HAVE_GETRUSAGE
- struct rusage ru;
-
- pid = wait3((void *)&status, WAITFLAGS, &ru);
-# else
- pid = wait3((void *)&status, WAITFLAGS, NULL);
-# endif
-#else
-# ifdef HAVE_WAITPID
- pid = waitpid(-1, &status, WAITFLAGS);
-# else
- pid = wait(&status);
-# endif
-#endif
-
- if (!pid) /* no more children to reap */
- break;
-
- /* check if child returned was from process substitution */
- for (;;) {
- if (pid == *procsubpid) {
- *procsubpid = 0;
- if (WIFSIGNALED(status))
- *procsubval = (0200 | WTERMSIG(status));
- else
- *procsubval = WEXITSTATUS(status);
- use_cmdoutval = 1;
- get_usage();
- cont = 1;
- break;
- }
- if (!es)
- break;
- procsubpid = &es->cmdoutpid;
- procsubval = &es->cmdoutval;
- es = es->next;
- }
- if (cont)
- continue;
-
- /* check for WAIT error */
- if (pid == -1) {
- if (errno != ECHILD)
- zerr("wait failed: %e", errno);
- /* WAIT changed errno, so restore the original */
- errno = old_errno;
- break;
- }
-
- /* This is necessary to be sure queueing_enabled > 0 when
- * we enter printjob() from update_job(), so that we don't
- * decrement to zero in should_report_time() and improperly
- * run other handlers in the middle of processing this one */
- queue_signals();
-
- /*
- * Find the process and job containing this pid and
- * update it.
- */
- if (findproc(pid, &jn, &pn, 0)) {
- if (((jn->stat & STAT_BUILTIN) ||
- (list_pipe &&
- (thisjob == -1 ||
- (jobtab[thisjob].stat & STAT_BUILTIN)))) &&
- WIFSTOPPED(status) && WSTOPSIG(status) == SIGTSTP) {
- killjb(jn, SIGCONT);
- zwarn("job can't be suspended");
- } else {
-#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
- struct timezone dummy_tz;
- gettimeofday(&pn->endtime, &dummy_tz);
-#ifdef WIFCONTINUED
- if (WIFCONTINUED(status))
- pn->status = SP_RUNNING;
- else
-#endif
- pn->status = status;
- pn->ti = ru;
-#else
- update_process(pn, status);
-#endif
- if (WIFEXITED(status) &&
- pn->pid == jn->gleader &&
- killpg(pn->pid, 0) == -1) {
- jn->gleader = 0;
- if (!(jn->stat & STAT_NOSTTY)) {
- /*
- * This PID was in control of the terminal;
- * reclaim terminal now it has exited.
- * It's still possible some future forked
- * process of this job will become group
- * leader, however.
- */
- attachtty(mypgrp);
- }
- }
- }
- update_job(jn);
- } else if (findproc(pid, &jn, &pn, 1)) {
- pn->status = status;
- update_job(jn);
- } else {
- /* If not found, update the shell record of time spent by
- * children in sub processes anyway: otherwise, this
- * will get added on to the next found process that
- * terminates.
- */
- get_usage();
- }
- /*
- * Accumulate a list of older jobs. We only do this for
- * background jobs, which is something in the job table
- * that's not marked as in the current shell or as shell builtin
- * and is not equal to the current foreground job.
- */
- if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) &&
- jn - jobtab != thisjob) {
- int val = (WIFSIGNALED(status) ?
- 0200 | WTERMSIG(status) :
- (WIFSTOPPED(status) ?
- 0200 | WEXITSTATUS(status) :
- WEXITSTATUS(status)));
- addbgstatus(pid, val);
- }
-
- unqueue_signals();
- }
-}
-
-/* the signal handler */
-
-/**/
-mod_export void
-zhandler(int sig)
-{
- sigset_t newmask, oldmask;
-
-#if defined(NO_SIGNAL_BLOCKING)
- int do_jump;
- signal_jmp_buf jump_to;
-#endif
-
- last_signal = sig;
- signal_process(sig);
-
- sigfillset(&newmask);
- /* Block all signals temporarily */
- oldmask = signal_block(newmask);
-
-#if defined(NO_SIGNAL_BLOCKING)
- /* do we need to longjmp to signal_suspend */
- do_jump = suspend_longjmp;
- /* In case a SIGCHLD somehow arrives */
- suspend_longjmp = 0;
-
- /* Traps can cause nested signal_suspend() */
- if (sig == SIGCHLD) {
- if (do_jump) {
- /* Copy suspend_jmp_buf */
- jump_to = suspend_jmp_buf;
- }
- }
-#endif
-
- /* Are we queueing signals now? */
- if (queueing_enabled) {
- int temp_rear = ++queue_rear % MAX_QUEUE_SIZE;
-
- DPUTS(temp_rear == queue_front, "BUG: signal queue full");
- /* Make sure it's not full (extremely unlikely) */
- if (temp_rear != queue_front) {
- /* ok, not full, so add to queue */
- queue_rear = temp_rear;
- /* save signal caught */
- signal_queue[queue_rear] = sig;
- /* save current signal mask */
- signal_mask_queue[queue_rear] = oldmask;
- }
- signal_reset(sig);
- return;
- }
-
- /* Reset signal mask, signal traps ok now */
- signal_setmask(oldmask);
-
- switch (sig) {
- case SIGCHLD:
- wait_for_processes();
- break;
-
- case SIGPIPE:
- if (!handletrap(SIGPIPE)) {
- if (!interact)
- _exit(SIGPIPE);
- else if (!isatty(SHTTY)) {
- stopmsg = 1;
- zexit(SIGPIPE, 1);
- }
- }
- break;
-
- case SIGHUP:
- if (!handletrap(SIGHUP)) {
- stopmsg = 1;
- zexit(SIGHUP, 1);
- }
- break;
-
- case SIGINT:
- if (!handletrap(SIGINT)) {
- if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
- isset(INTERACTIVE) && (noerrexit & NOERREXIT_SIGNAL))
- zexit(SIGINT, 1);
- if (list_pipe || chline || simple_pline) {
- breaks = loops;
- errflag |= ERRFLAG_INT;
- inerrflush();
- check_cursh_sig(SIGINT);
- }
- lastval = 128 + SIGINT;
- }
- break;
-
-#ifdef SIGWINCH
- case SIGWINCH:
- adjustwinsize(1); /* check window size and adjust */
- (void) handletrap(SIGWINCH);
- break;
-#endif
-
- case SIGALRM:
- if (!handletrap(SIGALRM)) {
- int idle = ttyidlegetfn(NULL);
- int tmout = getiparam("TMOUT");
- if (idle >= 0 && idle < tmout)
- alarm(tmout - idle);
- else {
- /*
- * We want to exit now.
- * Cancel all errors, including a user interrupt
- * which is now redundant.
- */
- errflag = noerrs = 0;
- zwarn("timeout");
- stopmsg = 1;
- zexit(SIGALRM, 1);
- }
- }
- break;
-
- default:
- (void) handletrap(sig);
- break;
- } /* end of switch(sig) */
-
- signal_reset(sig);
-
-/* This is used to make signal_suspend() race-free */
-#if defined(NO_SIGNAL_BLOCKING)
- if (do_jump)
- signal_longjmp(jump_to, 1);
-#endif
-
-} /* handler */
-
-
-/* SIGHUP any jobs left running */
-
-/**/
-void
-killrunjobs(int from_signal)
-{
- int i, killed = 0;
-
- if (unset(HUP))
- return;
- for (i = 1; i <= maxjob; i++)
- if ((from_signal || i != thisjob) && (jobtab[i].stat & STAT_LOCKED) &&
- !(jobtab[i].stat & STAT_NOPRINT) &&
- !(jobtab[i].stat & STAT_STOPPED)) {
- if (jobtab[i].gleader != getpid() &&
- killpg(jobtab[i].gleader, SIGHUP) != -1)
- killed++;
- }
- if (killed)
- zwarn("warning: %d jobs SIGHUPed", killed);
-}
-
-
-/* send a signal to a job (simply involves kill if monitoring is on) */
-
-/**/
-int
-killjb(Job jn, int sig)
-{
- Process pn;
- int err = 0;
-
- if (jobbing) {
- if (jn->stat & STAT_SUPERJOB) {
- if (sig == SIGCONT) {
- for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
- if (killpg(pn->pid, sig) == -1)
- if (kill(pn->pid, sig) == -1 && errno != ESRCH)
- err = -1;
-
- /*
- * Note this does not kill the last process,
- * which is assumed to be the one controlling the
- * subjob, i.e. the forked zsh that was originally
- * list_pipe_pid...
- */
- for (pn = jn->procs; pn->next; pn = pn->next)
- if (kill(pn->pid, sig) == -1 && errno != ESRCH)
- err = -1;
-
- /*
- * ...we only continue that once the external processes
- * currently associated with the subjob are finished.
- */
- if (!jobtab[jn->other].procs && pn)
- if (kill(pn->pid, sig) == -1 && errno != ESRCH)
- err = -1;
-
- return err;
- }
- if (killpg(jobtab[jn->other].gleader, sig) == -1 && errno != ESRCH)
- err = -1;
-
- if (killpg(jn->gleader, sig) == -1 && errno != ESRCH)
- err = -1;
-
- return err;
- }
- else
- return killpg(jn->gleader, sig);
- }
- for (pn = jn->procs; pn; pn = pn->next) {
- /*
- * Do not kill this job's process if it's already dead as its
- * pid could have been reused by the system.
- * As the PID doesn't exist don't return an error.
- */
- if (pn->status == SP_RUNNING || WIFSTOPPED(pn->status)) {
- /*
- * kill -0 on a job is pointless. We still call kill() for each process
- * in case the user cares about it but we ignore its outcome.
- */
- if ((err = kill(pn->pid, sig)) == -1 && errno != ESRCH && sig != 0)
- return -1;
- }
- }
- return err;
-}
-
-/*
- * List for saving traps. We don't usually have that many traps
- * at once, so just use a linked list.
- */
-struct savetrap {
- int sig, flags, local, posix;
- void *list;
-};
-
-static LinkList savetraps;
-static int dontsavetrap;
-
-/*
- * Save the current trap by copying it. This does nothing to
- * the existing value of sigtrapped or siglists.
- */
-
-static void
-dosavetrap(int sig, int level)
-{
- struct savetrap *st;
- st = (struct savetrap *)zalloc(sizeof(*st));
- st->sig = sig;
- st->local = level;
- st->posix = (sig == SIGEXIT) ? exit_trap_posix : 0;
- if ((st->flags = sigtrapped[sig]) & ZSIG_FUNC) {
- /*
- * Get the old function: this assumes we haven't added
- * the new one yet.
- */
- Shfunc shf, newshf = NULL;
- if ((shf = (Shfunc)gettrapnode(sig, 1))) {
- /* Copy the node for saving */
- newshf = (Shfunc) zshcalloc(sizeof(*newshf));
- newshf->node.nam = ztrdup(shf->node.nam);
- newshf->node.flags = shf->node.flags;
- newshf->funcdef = dupeprog(shf->funcdef, 0);
- if (shf->node.flags & PM_LOADDIR) {
- dircache_set(&newshf->filename, shf->filename);
- } else {
- newshf->filename = ztrdup(shf->filename);
- }
- if (shf->sticky) {
- newshf->sticky = sticky_emulation_dup(shf->sticky, 0);
- } else
- newshf->sticky = 0;
- if (shf->node.flags & PM_UNDEFINED)
- newshf->funcdef->shf = newshf;
- }
-#ifdef DEBUG
- else dputs("BUG: no function present with function trap flag set.");
-#endif
- DPUTS(siglists[sig], "BUG: function signal has eval list, too.");
- st->list = newshf;
- } else if (sigtrapped[sig]) {
- st->list = siglists[sig] ? dupeprog(siglists[sig], 0) : NULL;
- } else {
- DPUTS(siglists[sig], "BUG: siglists not null for untrapped signal");
- st->list = NULL;
- }
- if (!savetraps)
- savetraps = znewlinklist();
- /*
- * Put this at the front of the list
- */
- zinsertlinknode(savetraps, (LinkNode)savetraps, st);
-}
-
-
-/*
- * Set a trap: note this does not handle manipulation of
- * the function table for TRAPNAL functions.
- *
- * sig is the signal number.
- *
- * l is the list to be eval'd for a trap defined with the "trap"
- * builtin and should be NULL for a function trap.
- *
- * flags includes any additional flags to be or'd into sigtrapped[sig],
- * in particular ZSIG_FUNC; the basic flags will be assigned within
- * settrap.
- */
-
-/**/
-mod_export int
-settrap(int sig, Eprog l, int flags)
-{
- if (sig == -1)
- return 1;
- if (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN)) {
- zerr("can't trap SIG%s in interactive shells", sigs[sig]);
- return 1;
- }
-
- /*
- * Call unsettrap() unconditionally, to make sure trap is saved
- * if necessary.
- */
- queue_signals();
- unsettrap(sig);
-
- DPUTS((flags & ZSIG_FUNC) && l,
- "BUG: trap function has passed eval list, too");
- siglists[sig] = l;
- if (!(flags & ZSIG_FUNC) && empty_eprog(l)) {
- sigtrapped[sig] = ZSIG_IGNORED;
- if (sig && sig <= SIGCOUNT &&
-#ifdef SIGWINCH
- sig != SIGWINCH &&
-#endif
- sig != SIGCHLD)
- signal_ignore(sig);
- } else {
- nsigtrapped++;
- sigtrapped[sig] = ZSIG_TRAPPED;
- if (sig && sig <= SIGCOUNT &&
-#ifdef SIGWINCH
- sig != SIGWINCH &&
-#endif
- sig != SIGCHLD)
- install_handler(sig);
- }
- sigtrapped[sig] |= flags;
- /*
- * Note that introducing the locallevel does not affect whether
- * sigtrapped[sig] is zero or not, i.e. a test without a mask
- * works just the same.
- */
- if (sig == SIGEXIT) {
- /* Make POSIX behaviour of EXIT trap sticky */
- exit_trap_posix = isset(POSIXTRAPS);
- /* POSIX exit traps are not local. */
- if (!exit_trap_posix)
- sigtrapped[sig] |= (locallevel << ZSIG_SHIFT);
- }
- else
- sigtrapped[sig] |= (locallevel << ZSIG_SHIFT);
- unqueue_signals();
- return 0;
-}
-
-/**/
-void
-unsettrap(int sig)
-{
- HashNode hn;
-
- queue_signals();
- hn = removetrap(sig);
- if (hn)
- shfunctab->freenode(hn);
- unqueue_signals();
-}
-
-/**/
-HashNode
-removetrap(int sig)
-{
- int trapped;
-
- if (sig == -1 ||
- (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN)))
- return NULL;
-
- queue_signals();
- trapped = sigtrapped[sig];
- /*
- * Note that we save the trap here even if there isn't an existing
- * one, to aid in removing this one. However, if there's
- * already one at the current locallevel we just overwrite it.
- *
- * Note we save EXIT traps based on the *current* setting of
- * POSIXTRAPS --- so if there is POSIX EXIT trap set but
- * we are in native mode it can be saved, replaced by a function
- * trap, and then restored.
- */
- if (!dontsavetrap &&
- (sig == SIGEXIT ? !isset(POSIXTRAPS) : isset(LOCALTRAPS)) &&
- locallevel &&
- (!trapped || locallevel > (sigtrapped[sig] >> ZSIG_SHIFT)))
- dosavetrap(sig, locallevel);
-
- if (!trapped) {
- unqueue_signals();
- return NULL;
- }
- if (sigtrapped[sig] & ZSIG_TRAPPED)
- nsigtrapped--;
- sigtrapped[sig] = 0;
- if (sig == SIGINT && interact) {
- /* PWS 1995/05/16: added test for interactive, also noholdintr() *
- * as subshells ignoring SIGINT have it blocked from delivery */
- intr();
- noholdintr();
- } else if (sig == SIGHUP)
- install_handler(sig);
- else if (sig == SIGPIPE && interact && !forklevel)
- install_handler(sig);
- else if (sig && sig <= SIGCOUNT &&
-#ifdef SIGWINCH
- sig != SIGWINCH &&
-#endif
- sig != SIGCHLD)
- signal_default(sig);
- if (sig == SIGEXIT)
- exit_trap_posix = 0;
-
- /*
- * At this point we free the appropriate structs. If we don't
- * want that to happen then either the function should already have been
- * removed from shfunctab, or the entry in siglists should have been set
- * to NULL. This is no longer necessary for saving traps as that
- * copies the structures, so here we are remove the originals.
- * That causes a little inefficiency, but a good deal more reliability.
- */
- if (trapped & ZSIG_FUNC) {
- HashNode node = gettrapnode(sig, 1);
-
- /*
- * As in dosavetrap(), don't call removeshfuncnode() because
- * that calls back into unsettrap();
- */
- if (node)
- removehashnode(shfunctab, node->nam);
- unqueue_signals();
-
- return node;
- } else if (siglists[sig]) {
- freeeprog(siglists[sig]);
- siglists[sig] = NULL;
- }
- unqueue_signals();
-
- return NULL;
-}
-
-/**/
-void
-starttrapscope(void)
-{
- /* No special SIGEXIT behaviour inside another trap. */
- if (intrap)
- return;
-
- /*
- * SIGEXIT needs to be restored at the current locallevel,
- * so give it the next higher one. dosavetrap() is called
- * automatically where necessary.
- */
- if (sigtrapped[SIGEXIT] && !exit_trap_posix) {
- locallevel++;
- unsettrap(SIGEXIT);
- locallevel--;
- }
-}
-
-/*
- * Reset traps after the end of a function: must be called after
- * endparamscope() so that the locallevel has been decremented.
- */
-
-/**/
-void
-endtrapscope(void)
-{
- LinkNode ln;
- struct savetrap *st;
- int exittr = 0;
- void *exitfn = NULL;
-
- /*
- * Remember the exit trap, but don't run it until
- * after all the other traps have been put back.
- * Don't do this inside another trap.
- */
- if (!intrap &&
- !exit_trap_posix && (exittr = sigtrapped[SIGEXIT])) {
- if (exittr & ZSIG_FUNC) {
- exitfn = removehashnode(shfunctab, "TRAPEXIT");
- } else {
- exitfn = siglists[SIGEXIT];
- siglists[SIGEXIT] = NULL;
- }
- if (sigtrapped[SIGEXIT] & ZSIG_TRAPPED)
- nsigtrapped--;
- sigtrapped[SIGEXIT] = 0;
- }
-
- if (savetraps) {
- while ((ln = firstnode(savetraps)) &&
- (st = (struct savetrap *) ln->dat) &&
- st->local > locallevel) {
- int sig = st->sig;
-
- remnode(savetraps, ln);
-
- if (st->flags && (st->list != NULL)) {
- /* prevent settrap from saving this */
- dontsavetrap++;
- if (st->flags & ZSIG_FUNC)
- settrap(sig, NULL, ZSIG_FUNC);
- else
- settrap(sig, (Eprog) st->list, 0);
- if (sig == SIGEXIT)
- exit_trap_posix = st->posix;
- dontsavetrap--;
- /*
- * counting of nsigtrapped should presumably be handled
- * in settrap...
- */
- DPUTS((sigtrapped[sig] ^ st->flags) & ZSIG_TRAPPED,
- "BUG: settrap didn't restore correct ZSIG_TRAPPED");
- if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC)
- shfunctab->addnode(shfunctab, ((Shfunc)st->list)->node.nam,
- (Shfunc) st->list);
- } else if (sigtrapped[sig]) {
- /*
- * Don't restore the old state if someone has set a
- * POSIX-style exit trap --- allow this to propagate.
- */
- if (sig != SIGEXIT || !exit_trap_posix)
- unsettrap(sig);
- }
-
- zfree(st, sizeof(*st));
- }
- }
-
- if (exittr) {
- /*
- * We already made sure this wasn't set as a POSIX exit trap.
- * We respect the user's intention when the trap in question
- * was set.
- */
- dotrapargs(SIGEXIT, &exittr, exitfn);
- if (exittr & ZSIG_FUNC)
- shfunctab->freenode((HashNode)exitfn);
- else
- freeeprog(exitfn);
- }
- DPUTS(!locallevel && savetraps && firstnode(savetraps),
- "BUG: still saved traps outside all function scope");
-}
-
-
-/*
- * Decide whether a trap needs handling.
- * If so, see if the trap should be run now or queued.
- * Return 1 if the trap has been or will be handled.
- * This only needs to be called in place of dotrap() in the
- * signal handler, since it's only while waiting for children
- * to exit that we queue traps.
- */
-/**/
-static int
-handletrap(int sig)
-{
- if (!sigtrapped[sig])
- return 0;
-
- if (trap_queueing_enabled)
- {
- /* Code borrowed from signal queueing */
- int temp_rear = ++trap_queue_rear % MAX_QUEUE_SIZE;
-
- DPUTS(temp_rear == trap_queue_front, "BUG: trap queue full");
- /* If queue is not full... */
- if (temp_rear != trap_queue_front) {
- trap_queue_rear = temp_rear;
- trap_queue[trap_queue_rear] = sig;
- }
- return 1;
- }
-
- dotrap(sig);
-
- if (sig == SIGALRM)
- {
- int tmout;
- /*
- * Reset the alarm.
- * It seems slightly more natural to do this when the
- * trap is run, rather than when it's queued, since
- * the user doesn't see the latter.
- */
- if ((tmout = getiparam("TMOUT")))
- alarm(tmout);
- }
-
- return 1;
-}
-
-
-/*
- * Queue traps if they shouldn't be run asynchronously, i.e.
- * we're not in the wait builtin and TRAPSASYNC isn't set, when
- * waiting for children to exit.
- *
- * Note that unlike signal queuing this should only be called
- * in single matching pairs and can't be nested. It is
- * only needed when waiting for a job or process to finish.
- *
- * There is presumably a race setting this up: we shouldn't be running
- * traps between forking a foreground process and this point, either.
- */
-/**/
-void
-queue_traps(int wait_cmd)
-{
- if (!isset(TRAPSASYNC) && !wait_cmd) {
- /*
- * Traps need to be handled synchronously, so
- * enable queueing.
- */
- trap_queueing_enabled = 1;
- }
-}
-
-
-/*
- * Disable trap queuing and run the traps.
- */
-/**/
-void
-unqueue_traps(void)
-{
- trap_queueing_enabled = 0;
- while (trap_queue_front != trap_queue_rear) {
- trap_queue_front = (trap_queue_front + 1) % MAX_QUEUE_SIZE;
- (void) handletrap(trap_queue[trap_queue_front]);
- }
-}
-
-
-/* Execute a trap function for a given signal, possibly
- * with non-standard sigtrapped & siglists values
- */
-
-/* Are we already executing a trap? */
-/**/
-int intrap;
-
-/* Is the current trap a function? */
-
-/**/
-int trapisfunc;
-
-/*
- * If the current trap is not a function, at what function depth
- * did the trap get called?
- */
-/**/
-int traplocallevel;
-
-/*
- * sig is the signal number.
- * *sigtr is the value to be taken as the field in sigtrapped (since
- * that may have changed by this point if we are exiting).
- * sigfn is an Eprog with a non-function eval list, or a Shfunc
- * with a function trap. It may be NULL with an ignored signal.
- */
-
-/**/
-static void
-dotrapargs(int sig, int *sigtr, void *sigfn)
-{
- LinkList args;
- char *name, num[4];
- int obreaks = breaks;
- int oretflag = retflag;
- int olastval = lastval;
- int isfunc;
- int traperr, new_trap_state, new_trap_return;
-
- /* if signal is being ignored or the trap function *
- * is NULL, then return *
- * *
- * Also return if errflag is set. In fact, the code in the *
- * function will test for this, but this way we keep status flags *
- * intact without working too hard. Special cases (e.g. calling *
- * a trap for SIGINT after the error flag was set) are handled *
- * by the calling code. (PWS 1995/06/08). *
- * *
- * This test is now replicated in dotrap(). */
- if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
- return;
-
- /*
- * Never execute special (synchronous) traps inside other traps.
- * This can cause unexpected code execution when more than one
- * of these is set.
- *
- * The down side is that it's harder to debug traps. I don't think
- * that's a big issue.
- */
- if (intrap) {
- switch (sig) {
- case SIGEXIT:
- case SIGDEBUG:
- case SIGZERR:
- return;
- }
- }
-
- queue_signals(); /* Any time we manage memory or global state */
-
- intrap++;
- *sigtr |= ZSIG_IGNORED;
-
- zcontext_save();
- /* execsave will save the old trap_return and trap_state */
- execsave();
- breaks = retflag = 0;
- traplocallevel = locallevel;
- runhookdef(BEFORETRAPHOOK, NULL);
- if (*sigtr & ZSIG_FUNC) {
- int osc = sfcontext, old_incompfunc = incompfunc;
- HashNode hn = gettrapnode(sig, 0);
-
- args = znewlinklist();
- /*
- * In case of multiple names, try to get
- * a hint of the name in use from the function table.
- * In special cases, e.g. EXIT traps, the function
- * has already been removed. Then it's OK to
- * use the standard name.
- */
- if (hn) {
- name = ztrdup(hn->nam);
- } else {
- name = (char *) zalloc(5 + strlen(sigs[sig]));
- sprintf(name, "TRAP%s", sigs[sig]);
- }
- zaddlinknode(args, name);
- sprintf(num, "%d", sig);
- zaddlinknode(args, num);
-
- trap_return = -1; /* incremented by doshfunc */
- trap_state = TRAP_STATE_PRIMED;
- trapisfunc = isfunc = 1;
-
- sfcontext = SFC_SIGNAL;
- incompfunc = 0;
- doshfunc((Shfunc)sigfn, args, 1); /* manages signal queueing */
- sfcontext = osc;
- incompfunc= old_incompfunc;
- freelinklist(args, (FreeFunc) NULL);
- zsfree(name);
- } else {
- trap_return = -2; /* not incremented, used at current level */
- trap_state = TRAP_STATE_PRIMED;
- trapisfunc = isfunc = 0;
-
- execode((Eprog)sigfn, 1, 0, "trap"); /* manages signal queueing */
- }
- runhookdef(AFTERTRAPHOOK, NULL);
-
- traperr = errflag;
-
- /* Grab values before they are restored */
- new_trap_state = trap_state;
- new_trap_return = trap_return;
-
- execrestore();
- zcontext_restore();
-
- if (new_trap_state == TRAP_STATE_FORCE_RETURN &&
- /* zero return from function isn't special */
- !(isfunc && new_trap_return == 0)) {
- if (isfunc) {
- breaks = loops;
- /*
- * For SIGINT we behave the same as the default behaviour
- * i.e. we set the error bit indicating an interrupt.
- * We do this with SIGQUIT, too, even though we don't
- * handle SIGQUIT by default. That's to try to make
- * it behave a bit more like its normal behaviour when
- * the trap handler has told us that's what it wants.
- */
- if (sig == SIGINT || sig == SIGQUIT)
- errflag |= ERRFLAG_INT;
- else
- errflag |= ERRFLAG_ERROR;
- }
- lastval = new_trap_return;
- /* return triggered */
- retflag = 1;
- } else {
- if (traperr && !EMULATION(EMULATE_SH))
- lastval = 1;
- else {
- /*
- * With no explicit forced return, we keep the
- * lastval from before the trap ran.
- */
- lastval = olastval;
- }
- if (try_tryflag) {
- if (traperr)
- errflag |= ERRFLAG_ERROR;
- else
- errflag &= ~ERRFLAG_ERROR;
- }
- breaks += obreaks;
- /* return not triggered: restore old flag */
- retflag = oretflag;
- if (breaks > loops)
- breaks = loops;
- }
-
- /*
- * If zle was running while the trap was executed, see if we
- * need to restore the display.
- */
- if (zleactive && resetneeded)
- zleentry(ZLE_CMD_REFRESH);
-
- if (*sigtr != ZSIG_IGNORED)
- *sigtr &= ~ZSIG_IGNORED;
- intrap--;
-
- unqueue_signals();
-}
-
-/* Standard call to execute a trap for a given signal. */
-
-/**/
-void
-dotrap(int sig)
-{
- void *funcprog;
- int q = queue_signal_level();
-
- if (sigtrapped[sig] & ZSIG_FUNC) {
- HashNode hn = gettrapnode(sig, 0);
- if (hn)
- funcprog = hn;
- else {
-#ifdef DEBUG
- dputs("BUG: running function trap which has escaped.");
-#endif
- funcprog = NULL;
- }
- } else
- funcprog = siglists[sig];
-
- /*
- * Copied from dotrapargs().
- * (In fact, the gain from duplicating this appears to be virtually
- * zero. Not sure why it's here.)
- */
- if ((sigtrapped[sig] & ZSIG_IGNORED) || !funcprog || errflag)
- return;
-
- dont_queue_signals();
-
- if (sig == SIGEXIT)
- ++in_exit_trap;
-
- dotrapargs(sig, sigtrapped+sig, funcprog);
-
- if (sig == SIGEXIT)
- --in_exit_trap;
-
- restore_queue_signals(q);
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.h
deleted file mode 100644
index 41ac88cc..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signals.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * signals.h - header file for signals handling code
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#define SIGNAL_HANDTYPE void (*)_((int))
-
-#ifndef HAVE_KILLPG
-# define killpg(pgrp,sig) kill(-(pgrp),sig)
-#endif
-
-#define SIGZERR (SIGCOUNT+1)
-#define SIGDEBUG (SIGCOUNT+2)
-#define VSIGCOUNT (SIGCOUNT+3)
-#define SIGEXIT 0
-
-#ifdef SV_BSDSIG
-# define SV_INTERRUPT SV_BSDSIG
-#endif
-
-/* If not a POSIX machine, then we create our *
- * own POSIX style signal sets functions. */
-#ifndef POSIX_SIGNALS
-# define sigemptyset(s) (*(s) = 0)
-# if NSIG == 32
-# define sigfillset(s) (*(s) = ~(sigset_t)0, 0)
-# else
-# define sigfillset(s) (*(s) = (1 << NSIG) - 1, 0)
-# endif
-# define sigaddset(s,n) (*(s) |= (1 << ((n) - 1)), 0)
-# define sigdelset(s,n) (*(s) &= ~(1 << ((n) - 1)), 0)
-# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0)
-#endif /* ifndef POSIX_SIGNALS */
-
-#define child_block() signal_block(sigchld_mask)
-#define child_unblock() signal_unblock(sigchld_mask)
-
-#ifdef SIGWINCH
-# define winch_block() signal_block(signal_mask(SIGWINCH))
-# define winch_unblock() signal_unblock(signal_mask(SIGWINCH))
-#else
-# define winch_block() 0
-# define winch_unblock() 0
-#endif
-
-/* ignore a signal */
-#define signal_ignore(S) signal(S, SIG_IGN)
-
-/* return a signal to it default action */
-#define signal_default(S) signal(S, SIG_DFL)
-
-/* Use a circular queue to save signals caught during *
- * critical sections of code. You call queue_signals to *
- * start queueing, and unqueue_signals to process the *
- * queue and stop queueing. Since the kernel doesn't *
- * queue signals, it is probably overkill for zsh to do *
- * this, but it shouldn't hurt anything to do it anyway. */
-
-#define MAX_QUEUE_SIZE 128
-
-#define run_queued_signals() do { \
- while (queue_front != queue_rear) { /* while signals in queue */ \
- sigset_t oset; \
- queue_front = (queue_front + 1) % MAX_QUEUE_SIZE; \
- oset = signal_setmask(signal_mask_queue[queue_front]); \
- zhandler(signal_queue[queue_front]); /* handle queued signal */ \
- signal_setmask(oset); \
- } \
-} while (0)
-
-#ifdef DEBUG
-
-#define queue_signals() (queue_in++, queueing_enabled++)
-
-#define unqueue_signals() do { \
- DPUTS(!queueing_enabled, "BUG: unqueue_signals called but not queueing"); \
- --queue_in; \
- if (!--queueing_enabled) run_queued_signals(); \
-} while (0)
-
-#define dont_queue_signals() do { \
- queue_in = queueing_enabled; \
- queueing_enabled = 0; \
- run_queued_signals(); \
-} while (0)
-
-#define restore_queue_signals(q) do { \
- DPUTS2(queueing_enabled && queue_in != q, \
- "BUG: q = %d != queue_in = %d", q, queue_in); \
- queue_in = (queueing_enabled = (q)); \
-} while (0)
-
-#else /* !DEBUG */
-
-#define queue_signals() (queueing_enabled++)
-
-#define unqueue_signals() do { \
- if (!--queueing_enabled) run_queued_signals(); \
-} while (0)
-
-#define dont_queue_signals() do { \
- queueing_enabled = 0; \
- run_queued_signals(); \
-} while (0)
-
-#define restore_queue_signals(q) (queueing_enabled = (q))
-
-#endif /* DEBUG */
-
-#define queue_signal_level() queueing_enabled
-
-#ifdef BSD_SIGNALS
-#define signal_block(S) sigblock(S)
-#else
-extern sigset_t signal_block _((sigset_t));
-#endif /* BSD_SIGNALS */
-
-extern sigset_t signal_unblock _((sigset_t));
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames1.awk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames1.awk
deleted file mode 100644
index 27d21ac7..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames1.awk
+++ /dev/null
@@ -1,19 +0,0 @@
-# This is an awk script which finds out what the possibilities for
-# the signal names are, and dumps them out so that cpp can turn them
-# into numbers. Since we don't need to decide here what the
-# real signals are, we can afford to be generous about definitions,
-# in case the definitions are in terms of other definitions.
-# However, we need to avoid definitions with parentheses, which will
-# mess up the syntax.
-BEGIN { printf "#include \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)
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames2.awk b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames2.awk
deleted file mode 100644
index 4d15681d..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/signames2.awk
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# {g,n}awk script to generate signames.c
-# This version relies on the previous output of the preprocessor
-# on sigtmp.c, sigtmp.out, which is in turn generated by signames1.awk.
-#
-# NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
-# Without 0 + hacks some nawks compare numbers as strings
-#
-/^[\t ]*XXNAMES XXSIG[A-Z][A-Z0-9]*[\t ][\t ]*[1-9][0-9]*/ {
- sigindex = index($0, "SIG")
- sigtail = substr($0, sigindex, 80)
- split(sigtail, tmp)
- signam = substr(tmp[1], 4, 20)
- signum = tmp[2]
- if (signam == "CHLD" && sig[signum] == "CLD") sig[signum] = ""
- if (signam == "POLL" && sig[signum] == "IO") sig[signum] = ""
- if (sig[signum] == "") {
- sig[signum] = signam
- if (0 + max < 0 + signum && signum < 60)
- max = signum
- if (signam == "ABRT") { msg[signum] = "abort" }
- if (signam == "ALRM") { msg[signum] = "alarm" }
- if (signam == "BUS") { msg[signum] = "bus error" }
- if (signam == "CHLD") { msg[signum] = "death of child" }
- if (signam == "CLD") { msg[signum] = "death of child" }
- if (signam == "CONT") { msg[signum] = "continued" }
- if (signam == "EMT") { msg[signum] = "EMT instruction" }
- if (signam == "FPE") { msg[signum] = "floating point exception" }
- if (signam == "HUP") { msg[signum] = "hangup" }
- if (signam == "ILL") { msg[signum] = "illegal hardware instruction" }
- if (signam == "INFO") { msg[signum] = "status request from keyboard" }
- if (signam == "INT") { msg[signum] = "interrupt" }
- if (signam == "IO") { msg[signum] = "i/o ready" }
- if (signam == "IOT") { msg[signum] = "IOT instruction" }
- if (signam == "KILL") { msg[signum] = "killed" }
- if (signam == "LOST") { msg[signum] = "resource lost" }
- if (signam == "PIPE") { msg[signum] = "broken pipe" }
- if (signam == "POLL") { msg[signum] = "pollable event occurred" }
- if (signam == "PROF") { msg[signum] = "profile signal" }
- if (signam == "PWR") { msg[signum] = "power fail" }
- if (signam == "QUIT") { msg[signum] = "quit" }
- if (signam == "SEGV") { msg[signum] = "segmentation fault" }
- if (signam == "SYS") { msg[signum] = "invalid system call" }
- if (signam == "TERM") { msg[signum] = "terminated" }
- if (signam == "TRAP") { msg[signum] = "trace trap" }
- if (signam == "URG") { msg[signum] = "urgent condition" }
- if (signam == "USR1") { msg[signum] = "user-defined signal 1" }
- if (signam == "USR2") { msg[signum] = "user-defined signal 2" }
- if (signam == "VTALRM") { msg[signum] = "virtual time alarm" }
- if (signam == "WINCH") { msg[signum] = "window size changed" }
- if (signam == "XCPU") { msg[signum] = "cpu limit exceeded" }
- if (signam == "XFSZ") { msg[signum] = "file size limit exceeded" }
- }
-}
-
-END {
- ps = "%s"
- ifdstr = sprintf("# ifdef USE_SUSPENDED\n\t%csuspended%s%c,\n%s else\n\t%cstopped%s%c,\n# endif\n", 34, ps, 34, "#", 34, ps, 34)
-
- printf "/** signames.c **/\n"
- printf "/** architecture-customized signames.c for zsh **/\n"
- printf "\n"
- printf "#define SIGCOUNT\t%d\n", max
- printf "\n"
- printf "#include %czsh.mdh%c\n", 34, 34
- printf "\n"
- printf "/**/\n"
- printf "#define sigmsg(sig) ((sig) <= SIGCOUNT ? sig_msg[sig]"
- printf " : %c%s%c)", 34, "unknown signal", 34
- printf "\n"
- printf "/**/\n"
- printf "mod_export char *sig_msg[SIGCOUNT+2] = {\n"
- printf "\t%c%s%c,\n", 34, "done", 34
-
- for (i = 1; i <= 0 + max; i++)
- if (msg[i] == "") {
- if (sig[i] == "")
- printf("\t%c%c,\n", 34, 34)
- else if (sig[i] == "STOP")
- printf ifdstr, " (signal)", " (signal)"
- else if (sig[i] == "TSTP")
- printf ifdstr, "", ""
- else if (sig[i] == "TTIN")
- printf ifdstr, " (tty input)", " (tty input)"
- else if (sig[i] == "TTOU")
- printf ifdstr, " (tty output)", " (tty output)"
- else
- printf("\t%cSIG%s%c,\n", 34, sig[i], 34)
- } else
- printf("\t%c%s%c,\n", 34, msg[i], 34)
- print "\tNULL"
- print "};"
- print ""
- print "/**/"
- printf "char *sigs[SIGCOUNT+4] = {\n"
- printf("\t%cEXIT%c,\n", 34, 34)
- for (i = 1; i <= 0 + max; i++)
- if (sig[i] == "")
- printf("\t%c%d%c,\n", 34, i, 34)
- else
- printf("\t%c%s%c,\n", 34, sig[i], 34)
- printf("\t%cZERR%c,\n", 34, 34)
- printf("\t%cDEBUG%c,\n", 34, 34)
- print "\tNULL"
- print "};"
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/string.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/string.c
deleted file mode 100644
index 9e14ef94..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/string.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * string.c - string manipulation
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 2000 Peter Stephenson
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Peter Stephenson or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Peter Stephenson and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Peter Stephenson and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Peter Stephenson and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- */
-
-#include "zsh.mdh"
-
-/**/
-mod_export char *
-dupstring(const char *s)
-{
- char *t;
-
- if (!s)
- return NULL;
- t = (char *) zhalloc(strlen((char *)s) + 1);
- strcpy(t, s);
- return t;
-}
-
-/* Duplicate string on heap when length is known */
-
-/**/
-mod_export char *
-dupstring_wlen(const char *s, unsigned len)
-{
- char *t;
-
- if (!s)
- return NULL;
- t = (char *) zhalloc(len + 1);
- memcpy(t, s, len);
- t[len] = '\0';
- return t;
-}
-
-/* Duplicate string on heap, returning length of string */
-
-/**/
-mod_export char *
-dupstring_glen(const char *s, unsigned *len_ret)
-{
- char *t;
-
- if (!s)
- return NULL;
- t = (char *) zhalloc((*len_ret = strlen((char *)s)) + 1);
- strcpy(t, s);
- return t;
-}
-
-/**/
-mod_export char *
-ztrdup(const char *s)
-{
- char *t;
-
- if (!s)
- return NULL;
- t = (char *)zalloc(strlen((char *)s) + 1);
- strcpy(t, s);
- return t;
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/**/
-mod_export wchar_t *
-wcs_ztrdup(const wchar_t *s)
-{
- wchar_t *t;
-
- if (!s)
- return NULL;
- t = (wchar_t *)zalloc(sizeof(wchar_t) * (wcslen((wchar_t *)s) + 1));
- wcscpy(t, s);
- return t;
-}
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-
-/* concatenate s1, s2, and s3 in dynamically allocated buffer */
-
-/**/
-mod_export char *
-tricat(char const *s1, char const *s2, char const *s3)
-{
- /* This version always uses permanently-allocated space. */
- char *ptr;
- size_t l1 = strlen(s1);
- size_t l2 = strlen(s2);
-
- ptr = (char *)zalloc(l1 + l2 + strlen(s3) + 1);
- strcpy(ptr, s1);
- strcpy(ptr + l1, s2);
- strcpy(ptr + l1 + l2, s3);
- return ptr;
-}
-
-/**/
-mod_export char *
-zhtricat(char const *s1, char const *s2, char const *s3)
-{
- char *ptr;
- size_t l1 = strlen(s1);
- size_t l2 = strlen(s2);
-
- ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
- strcpy(ptr, s1);
- strcpy(ptr + l1, s2);
- strcpy(ptr + l1 + l2, s3);
- return ptr;
-}
-
-/* concatenate s1 and s2 in dynamically allocated buffer */
-
-/**/
-mod_export char *
-dyncat(const char *s1, const char *s2)
-{
- /* This version always uses space from the current heap. */
- char *ptr;
- size_t l1 = strlen(s1);
-
- ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
- strcpy(ptr, s1);
- strcpy(ptr + l1, s2);
- return ptr;
-}
-
-/**/
-mod_export char *
-bicat(const char *s1, const char *s2)
-{
- /* This version always uses permanently-allocated space. */
- char *ptr;
- size_t l1 = strlen(s1);
-
- ptr = (char *)zalloc(l1 + strlen(s2) + 1);
- strcpy(ptr, s1);
- strcpy(ptr + l1, s2);
- return ptr;
-}
-
-/* like dupstring(), but with a specified length */
-
-/**/
-mod_export char *
-dupstrpfx(const char *s, int len)
-{
- char *r = zhalloc(len + 1);
-
- memcpy(r, s, len);
- r[len] = '\0';
- return r;
-}
-
-/**/
-mod_export char *
-ztrduppfx(const char *s, int len)
-{
- /* This version always uses permanently-allocated space. */
- char *r = zalloc(len + 1);
-
- memcpy(r, s, len);
- r[len] = '\0';
- return r;
-}
-
-/* Append a string to an allocated string, reallocating to make room. */
-
-/**/
-mod_export char *
-appstr(char *base, char const *append)
-{
- return strcat(realloc(base, strlen(base) + strlen(append) + 1), append);
-}
-
-/* Return a pointer to the last character of a string,
- unless the string is empty. */
-
-/**/
-mod_export char *
-strend(char *str)
-{
- if (*str == '\0')
- return str;
- return str + strlen (str) - 1;
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/utils.c b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/utils.c
deleted file mode 100644
index 075d2724..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/utils.c
+++ /dev/null
@@ -1,7520 +0,0 @@
-/*
- * utils.c - miscellaneous utilities
- *
- * 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 "utils.pro"
-
-/* name of script being sourced */
-
-/**/
-mod_export char *scriptname; /* is sometimes a function name */
-
-/* filename of script or other file containing code source e.g. autoload */
-
-/**/
-mod_export char *scriptfilename;
-
-/* != 0 if we are in a new style completion function */
-
-/**/
-mod_export int incompfunc;
-
-#ifdef MULTIBYTE_SUPPORT
-struct widechar_array {
- wchar_t *chars;
- size_t len;
-};
-typedef struct widechar_array *Widechar_array;
-
-/*
- * The wordchars variable turned into a wide character array.
- * This is much more convenient for testing.
- */
-static struct widechar_array wordchars_wide;
-
-/*
- * The same for the separators (IFS) array.
- */
-static struct widechar_array ifs_wide;
-
-/* Function to set one of the above from the multibyte array */
-
-static void
-set_widearray(char *mb_array, Widechar_array wca)
-{
- if (wca->chars) {
- free(wca->chars);
- wca->chars = NULL;
- }
- wca->len = 0;
-
- if (!isset(MULTIBYTE))
- return;
-
- if (mb_array) {
- VARARR(wchar_t, tmpwcs, strlen(mb_array));
- wchar_t *wcptr = tmpwcs;
- wint_t wci;
-
- mb_charinit();
- while (*mb_array) {
- int mblen;
-
- if (STOUC(*mb_array) <= 0x7f) {
- mb_array++;
- *wcptr++ = (wchar_t)*mb_array;
- continue;
- }
-
- mblen = mb_metacharlenconv(mb_array, &wci);
-
- if (!mblen)
- break;
- /* No good unless all characters are convertible */
- if (wci == WEOF)
- return;
- *wcptr++ = (wchar_t)wci;
-#ifdef DEBUG
- /*
- * This generates a warning from the compiler (and is
- * indeed useless) if chars are unsigned. It's
- * extreme paranoia anyway.
- */
- if (wcptr[-1] < 0)
- fprintf(stderr, "BUG: Bad cast to wchar_t\n");
-#endif
- mb_array += mblen;
- }
-
- wca->len = wcptr - tmpwcs;
- wca->chars = (wchar_t *)zalloc(wca->len * sizeof(wchar_t));
- wmemcpy(wca->chars, tmpwcs, wca->len);
- }
-}
-#endif
-
-
-/* Print an error
-
- The following functions use the following printf-like format codes
- (implemented by zerrmsg()):
-
- Code Argument types Prints
- %s const char * C string (null terminated)
- %l const char *, int C string of given length (null not required)
- %L long decimal value
- %d int decimal value
- %% (none) literal '%'
- %c int character at that codepoint
- %e int strerror() message (argument is typically 'errno')
- */
-
-static void
-zwarning(const char *cmd, const char *fmt, va_list ap)
-{
- if (isatty(2))
- zleentry(ZLE_CMD_TRASH);
-
- char *prefix = scriptname ? scriptname : (argzero ? argzero : "");
-
- if (cmd) {
- if (unset(SHINSTDIN) || locallevel) {
- nicezputs(prefix, stderr);
- fputc((unsigned char)':', stderr);
- }
- nicezputs(cmd, stderr);
- fputc((unsigned char)':', stderr);
- } else {
- /*
- * scriptname is set when sourcing scripts, so that we get the
- * correct name instead of the generic name of whatever
- * program/script is running. It's also set in shell functions,
- * so test locallevel, too.
- */
- nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" : prefix, stderr);
- fputc((unsigned char)':', stderr);
- }
-
- zerrmsg(stderr, fmt, ap);
-}
-
-
-/**/
-mod_export void
-zerr(VA_ALIST1(const char *fmt))
-VA_DCL
-{
- va_list ap;
- VA_DEF_ARG(const char *fmt);
-
- if (errflag || noerrs) {
- if (noerrs < 2)
- errflag |= ERRFLAG_ERROR;
- return;
- }
- errflag |= ERRFLAG_ERROR;
-
- VA_START(ap, fmt);
- VA_GET_ARG(ap, fmt, const char *);
- zwarning(NULL, fmt, ap);
- va_end(ap);
-}
-
-/**/
-mod_export void
-zerrnam(VA_ALIST2(const char *cmd, const char *fmt))
-VA_DCL
-{
- va_list ap;
- VA_DEF_ARG(const char *cmd);
- VA_DEF_ARG(const char *fmt);
-
- if (errflag || noerrs)
- return;
- errflag |= ERRFLAG_ERROR;
-
- VA_START(ap, fmt);
- VA_GET_ARG(ap, cmd, const char *);
- VA_GET_ARG(ap, fmt, const char *);
- zwarning(cmd, fmt, ap);
- va_end(ap);
-}
-
-/**/
-mod_export void
-zwarn(VA_ALIST1(const char *fmt))
-VA_DCL
-{
- va_list ap;
- VA_DEF_ARG(const char *fmt);
-
- if (errflag || noerrs)
- return;
-
- VA_START(ap, fmt);
- VA_GET_ARG(ap, fmt, const char *);
- zwarning(NULL, fmt, ap);
- va_end(ap);
-}
-
-/**/
-mod_export void
-zwarnnam(VA_ALIST2(const char *cmd, const char *fmt))
-VA_DCL
-{
- va_list ap;
- VA_DEF_ARG(const char *cmd);
- VA_DEF_ARG(const char *fmt);
-
- if (errflag || noerrs)
- return;
-
- VA_START(ap, fmt);
- VA_GET_ARG(ap, cmd, const char *);
- VA_GET_ARG(ap, fmt, const char *);
- zwarning(cmd, fmt, ap);
- va_end(ap);
-}
-
-
-#ifdef DEBUG
-
-/**/
-mod_export void
-dputs(VA_ALIST1(const char *message))
-VA_DCL
-{
- char *filename;
- FILE *file;
- va_list ap;
- VA_DEF_ARG(const char *message);
-
- VA_START(ap, message);
- VA_GET_ARG(ap, message, const char *);
- if ((filename = getsparam_u("ZSH_DEBUG_LOG")) != NULL &&
- (file = fopen(filename, "a")) != NULL) {
- zerrmsg(file, message, ap);
- fclose(file);
- } else
- zerrmsg(stderr, message, ap);
- va_end(ap);
-}
-
-#endif /* DEBUG */
-
-#ifdef __CYGWIN__
-/*
- * This works around an occasional problem with dllwrap on Cygwin, seen
- * on at least two installations. It fails to find the last symbol
- * exported in alphabetical order (in our case zwarnnam). Until this is
- * properly categorised and fixed we add a dummy symbol at the end.
- */
-mod_export void
-zz_plural_z_alpha(void)
-{
-}
-#endif
-
-/**/
-void
-zerrmsg(FILE *file, const char *fmt, va_list ap)
-{
- const char *str;
- int num;
-#ifdef DEBUG
- long lnum;
-#endif
-#ifdef HAVE_STRERROR_R
-#define ERRBUFSIZE (80)
- int olderrno;
- char errbuf[ERRBUFSIZE];
-#endif
- char *errmsg;
-
- if ((unset(SHINSTDIN) || locallevel) && lineno) {
-#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
- fprintf(file, "%lld: ", lineno);
-#else
- fprintf(file, "%ld: ", (long)lineno);
-#endif
- } else
- fputc((unsigned char)' ', file);
-
- while (*fmt)
- if (*fmt == '%') {
- fmt++;
- switch (*fmt++) {
- case 's':
- str = va_arg(ap, const char *);
- nicezputs(str, file);
- break;
- case 'l': {
- char *s;
- str = va_arg(ap, const char *);
- num = va_arg(ap, int);
- num = metalen(str, num);
- s = zhalloc(num + 1);
- memcpy(s, str, num);
- s[num] = '\0';
- nicezputs(s, file);
- break;
- }
-#ifdef DEBUG
- case 'L':
- lnum = va_arg(ap, long);
- fprintf(file, "%ld", lnum);
- break;
-#endif
- case 'd':
- num = va_arg(ap, int);
- fprintf(file, "%d", num);
- break;
- case '%':
- putc('%', file);
- break;
- case 'c':
- num = va_arg(ap, int);
-#ifdef MULTIBYTE_SUPPORT
- mb_charinit();
- zputs(wcs_nicechar(num, NULL, NULL), file);
-#else
- zputs(nicechar(num), file);
-#endif
- break;
- case 'e':
- /* print the corresponding message for this errno */
- num = va_arg(ap, int);
- if (num == EINTR) {
- fputs("interrupt\n", file);
- errflag |= ERRFLAG_ERROR;
- return;
- }
- errmsg = strerror(num);
- /* If the message is not about I/O problems, it looks better *
- * if we uncapitalize the first letter of the message */
- if (num == EIO)
- fputs(errmsg, file);
- else {
- fputc(tulower(errmsg[0]), file);
- fputs(errmsg + 1, file);
- }
- break;
- /* When adding format codes, update the comment above zwarning(). */
- }
- } else {
- putc(*fmt == Meta ? *++fmt ^ 32 : *fmt, file);
- fmt++;
- }
- putc('\n', file);
- fflush(file);
-}
-
-/*
- * Wrapper for setupterm() and del_curterm().
- * These are called from terminfo.c and termcap.c.
- */
-static int term_count; /* reference count of cur_term */
-
-/**/
-mod_export void
-zsetupterm(void)
-{
-#ifdef HAVE_SETUPTERM
- int errret;
-
- DPUTS(term_count < 0 || (term_count > 0 && !cur_term),
- "inconsistent term_count and/or cur_term");
- /*
- * Just because we can't set up the terminal doesn't
- * mean the modules hasn't booted---TERM may change,
- * and it should be handled dynamically---so ignore errors here.
- */
- if (term_count++ == 0)
- (void)setupterm((char *)0, 1, &errret);
-#endif
-}
-
-/**/
-mod_export void
-zdeleteterm(void)
-{
-#ifdef HAVE_SETUPTERM
- DPUTS(term_count < 1 || !cur_term,
- "inconsistent term_count and/or cur_term");
- if (--term_count == 0)
- del_curterm(cur_term);
-#endif
-}
-
-/* Output a single character, for the termcap routines. *
- * This is used instead of putchar since it can be a macro. */
-
-/**/
-mod_export int
-putraw(int c)
-{
- putc(c, stdout);
- return 0;
-}
-
-/* Output a single character, for the termcap routines. */
-
-/**/
-mod_export int
-putshout(int c)
-{
- putc(c, shout);
- return 0;
-}
-
-#ifdef MULTIBYTE_SUPPORT
-/*
- * Turn a character into a visible representation thereof. The visible
- * string is put together in a static buffer, and this function returns
- * a pointer to it. Printable characters stand for themselves, DEL is
- * represented as "^?", newline and tab are represented as "\n" and
- * "\t", and normal control characters are represented in "^C" form.
- * Characters with bit 7 set, if unprintable, are represented as "\M-"
- * followed by the visible representation of the character with bit 7
- * stripped off. Tokens are interpreted, rather than being treated as
- * literal characters.
- *
- * Note that the returned string is metafied, so that it must be
- * treated like any other zsh internal string (and not, for example,
- * output directly).
- *
- * This function is used even if MULTIBYTE_SUPPORT is defined: we
- * use it as a fallback in case we couldn't identify a wide character
- * in a multibyte string.
- */
-
-/**/
-mod_export char *
-nicechar_sel(int c, int quotable)
-{
- static char buf[10];
- char *s = buf;
- c &= 0xff;
- if (ZISPRINT(c))
- goto done;
- if (c & 0x80) {
- if (isset(PRINTEIGHTBIT))
- goto done;
- *s++ = '\\';
- *s++ = 'M';
- *s++ = '-';
- c &= 0x7f;
- if(ZISPRINT(c))
- goto done;
- }
- if (c == 0x7f) {
- if (quotable) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- } else
- *s++ = '^';
- c = '?';
- } else if (c == '\n') {
- *s++ = '\\';
- c = 'n';
- } else if (c == '\t') {
- *s++ = '\\';
- c = 't';
- } else if (c < 0x20) {
- if (quotable) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- } else
- *s++ = '^';
- c += 0x40;
- }
- done:
- /*
- * The resulting string is still metafied, so check if
- * we are returning a character in the range that needs metafication.
- * This can't happen if the character is printed "nicely", so
- * this results in a maximum of two bytes total (plus the null).
- */
- if (imeta(c)) {
- *s++ = Meta;
- *s++ = c ^ 32;
- } else
- *s++ = c;
- *s = 0;
- return buf;
-}
-
-/**/
-mod_export char *
-nicechar(int c)
-{
- return nicechar_sel(c, 0);
-}
-
-#else /* MULTIBYTE_SUPPORT */
-
-/**/
-mod_export char *
-nicechar(int c)
-{
- static char buf[10];
- char *s = buf;
- c &= 0xff;
- if (ZISPRINT(c))
- goto done;
- if (c & 0x80) {
- if (isset(PRINTEIGHTBIT))
- goto done;
- *s++ = '\\';
- *s++ = 'M';
- *s++ = '-';
- c &= 0x7f;
- if(ZISPRINT(c))
- goto done;
- }
- if (c == 0x7f) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- c = '?';
- } else if (c == '\n') {
- *s++ = '\\';
- c = 'n';
- } else if (c == '\t') {
- *s++ = '\\';
- c = 't';
- } else if (c < 0x20) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- c += 0x40;
- }
- done:
- /*
- * The resulting string is still metafied, so check if
- * we are returning a character in the range that needs metafication.
- * This can't happen if the character is printed "nicely", so
- * this results in a maximum of two bytes total (plus the null).
- */
- if (imeta(c)) {
- *s++ = Meta;
- *s++ = c ^ 32;
- } else
- *s++ = c;
- *s = 0;
- return buf;
-}
-
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Return 1 if nicechar() would reformat this character.
- */
-
-/**/
-mod_export int
-is_nicechar(int c)
-{
- c &= 0xff;
- if (ZISPRINT(c))
- return 0;
- if (c & 0x80)
- return !isset(PRINTEIGHTBIT);
- return (c == 0x7f || c == '\n' || c == '\t' || c < 0x20);
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-static mbstate_t mb_shiftstate;
-
-/*
- * Initialise multibyte state: called before a sequence of
- * wcs_nicechar(), mb_metacharlenconv(), or
- * mb_charlenconv().
- */
-
-/**/
-mod_export void
-mb_charinit(void)
-{
- memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-}
-
-/*
- * The number of bytes we need to allocate for a "nice" representation
- * of a multibyte character.
- *
- * We double MB_CUR_MAX to take account of the fact that
- * we may need to metafy. In fact the representation probably
- * doesn't allow every character to be in the meta range, but
- * we don't need to be too pedantic.
- *
- * The 12 is for the output of a UCS-4 code; we don't actually
- * need this at the same time as MB_CUR_MAX, but again it's
- * not worth calculating more exactly.
- */
-#define NICECHAR_MAX (12 + 2*MB_CUR_MAX)
-/*
- * Input a wide character. Output a printable representation,
- * which is a metafied multibyte string. With widthp return
- * the printing width.
- *
- * swide, if non-NULL, is used to help the completion code, which needs
- * to know the printing width of the each part of the representation.
- * *swide is set to the part of the returned string where the wide
- * character starts. Any string up to that point is ASCII characters,
- * so the width of it is (*swide - ). Anything left is
- * a single wide character corresponding to the remaining width.
- * Either the initial ASCII part or the wide character part may be empty
- * (but not both). (Note the complication that the wide character
- * part may contain metafied characters.)
- *
- * The caller needs to call mb_charinit() before the first call, to
- * set up the multibyte shift state for a range of characters.
- */
-
-/**/
-mod_export char *
-wcs_nicechar_sel(wchar_t c, size_t *widthp, char **swidep, int quotable)
-{
- static char *buf;
- static int bufalloc = 0, newalloc;
- char *s, *mbptr;
- int ret = 0;
- VARARR(char, mbstr, MB_CUR_MAX);
-
- /*
- * We want buf to persist beyond the return. MB_CUR_MAX and hence
- * NICECHAR_MAX may not be constant, so we have to allocate this at
- * run time. (We could probably get away with just allocating a
- * large buffer, in practice.) For efficiency, only reallocate if
- * we really need to, since this function will be called frequently.
- */
- newalloc = NICECHAR_MAX;
- if (bufalloc != newalloc)
- {
- bufalloc = newalloc;
- buf = (char *)zrealloc(buf, bufalloc);
- }
-
- s = buf;
- if (!WC_ISPRINT(c) && (c < 0x80 || !isset(PRINTEIGHTBIT))) {
- if (c == 0x7f) {
- if (quotable) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- } else
- *s++ = '^';
- c = '?';
- } else if (c == L'\n') {
- *s++ = '\\';
- c = 'n';
- } else if (c == L'\t') {
- *s++ = '\\';
- c = 't';
- } else if (c < 0x20) {
- if (quotable) {
- *s++ = '\\';
- *s++ = 'C';
- *s++ = '-';
- } else
- *s++ = '^';
- c += 0x40;
- } else if (c >= 0x80) {
- ret = -1;
- }
- }
-
- if (ret != -1)
- ret = wcrtomb(mbstr, c, &mb_shiftstate);
-
- if (ret == -1) {
- memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
- /*
- * Can't or don't want to convert character: use UCS-2 or
- * UCS-4 code in print escape format.
- *
- * This comparison fails and generates a compiler warning
- * if wchar_t is 16 bits, but the code is still correct.
- */
- if (c >= 0x10000) {
- sprintf(buf, "\\U%.8x", (unsigned int)c);
- if (widthp)
- *widthp = 10;
- } else if (c >= 0x100) {
- sprintf(buf, "\\u%.4x", (unsigned int)c);
- if (widthp)
- *widthp = 6;
- } else {
- strcpy(buf, nicechar((int)c));
- /*
- * There may be metafied characters from nicechar(),
- * so compute width and end position independently.
- */
- if (widthp)
- *widthp = ztrlen(buf);
- if (swidep)
- *swidep = buf + strlen(buf);
- return buf;
- }
- if (swidep)
- *swidep = widthp ? buf + *widthp : buf;
- return buf;
- }
-
- if (widthp) {
- int wcw = WCWIDTH(c);
- *widthp = (s - buf);
- if (wcw >= 0)
- *widthp += wcw;
- else
- (*widthp)++;
- }
- if (swidep)
- *swidep = s;
- for (mbptr = mbstr; ret; s++, mbptr++, ret--) {
- DPUTS(s >= buf + NICECHAR_MAX,
- "BUG: buffer too small in wcs_nicechar");
- if (imeta(*mbptr)) {
- *s++ = Meta;
- DPUTS(s >= buf + NICECHAR_MAX,
- "BUG: buffer too small for metafied char in wcs_nicechar");
- *s = *mbptr ^ 32;
- } else {
- *s = *mbptr;
- }
- }
- *s = 0;
- return buf;
-}
-
-/**/
-mod_export char *
-wcs_nicechar(wchar_t c, size_t *widthp, char **swidep)
-{
- return wcs_nicechar_sel(c, widthp, swidep, 0);
-}
-
-/*
- * Return 1 if wcs_nicechar() would reformat this character for display.
- */
-
-/**/
-mod_export int is_wcs_nicechar(wchar_t c)
-{
- if (!WC_ISPRINT(c) && (c < 0x80 || !isset(PRINTEIGHTBIT))) {
- if (c == 0x7f || c == L'\n' || c == L'\t' || c < 0x20)
- return 1;
- if (c >= 0x80) {
- return (c >= 0x100);
- }
- }
- return 0;
-}
-
-/**/
-mod_export int
-zwcwidth(wint_t wc)
-{
- int wcw;
- /* assume a single-byte character if not valid */
- if (wc == WEOF || unset(MULTIBYTE))
- return 1;
- wcw = WCWIDTH(wc);
- /* if not printable, assume width 1 */
- if (wcw < 0)
- return 1;
- return wcw;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Search the path for prog and return the file name.
- * The returned value is unmetafied and in the unmeta storage
- * area (N.B. should be duplicated if not used immediately and not
- * equal to *namep).
- *
- * If namep is not NULL, *namep is set to the metafied programme
- * name, which is in heap storage.
- */
-/**/
-char *
-pathprog(char *prog, char **namep)
-{
- char **pp, ppmaxlen = 0, *buf, *funmeta;
- struct stat st;
-
- for (pp = path; *pp; pp++)
- {
- int len = strlen(*pp);
- if (len > ppmaxlen)
- ppmaxlen = len;
- }
- buf = zhalloc(ppmaxlen + strlen(prog) + 2);
- for (pp = path; *pp; pp++) {
- sprintf(buf, "%s/%s", *pp, prog);
- funmeta = unmeta(buf);
- if (access(funmeta, F_OK) == 0 &&
- stat(funmeta, &st) >= 0 &&
- !S_ISDIR(st.st_mode)) {
- if (namep)
- *namep = buf;
- return funmeta;
- }
- }
-
- return NULL;
-}
-
-/* get a symlink-free pathname for s relative to PWD */
-
-/**/
-char *
-findpwd(char *s)
-{
- char *t;
-
- if (*s == '/')
- return xsymlink(s, 0);
- s = tricat((pwd[1]) ? pwd : "", "/", s);
- t = xsymlink(s, 0);
- zsfree(s);
- return t;
-}
-
-/* Check whether a string contains the *
- * name of the present directory. */
-
-/**/
-int
-ispwd(char *s)
-{
- struct stat sbuf, tbuf;
-
- /* POSIX: environment PWD must be absolute */
- if (*s != '/')
- return 0;
-
- if (stat((s = unmeta(s)), &sbuf) == 0 && stat(".", &tbuf) == 0)
- if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino) {
- /* POSIX: No element of $PWD may be "." or ".." */
- while (*s) {
- if (s[0] == '.' &&
- (!s[1] || s[1] == '/' ||
- (s[1] == '.' && (!s[2] || s[2] == '/'))))
- break;
- while (*s++ != '/' && *s)
- continue;
- }
- return !*s;
- }
- return 0;
-}
-
-static char xbuf[PATH_MAX*2+1];
-
-/**/
-static char **
-slashsplit(char *s)
-{
- char *t, **r, **q;
- int t0;
-
- if (!*s)
- return (char **) zshcalloc(sizeof(char *));
-
- for (t = s, t0 = 0; *t; t++)
- if (*t == '/')
- t0++;
- q = r = (char **) zalloc(sizeof(char *) * (t0 + 2));
-
- while ((t = strchr(s, '/'))) {
- *q++ = ztrduppfx(s, t - s);
- while (*t == '/')
- t++;
- if (!*t) {
- *q = NULL;
- return r;
- }
- s = t;
- }
- *q++ = ztrdup(s);
- *q = NULL;
- return r;
-}
-
-/* expands symlinks and .. or . expressions */
-
-/**/
-static int
-xsymlinks(char *s, int full)
-{
- char **pp, **opp;
- char xbuf2[PATH_MAX*3+1], xbuf3[PATH_MAX*2+1];
- int t0, ret = 0;
- zulong xbuflen = strlen(xbuf), pplen;
-
- opp = pp = slashsplit(s);
- for (; xbuflen < sizeof(xbuf) && *pp && ret >= 0; pp++) {
- if (!strcmp(*pp, "."))
- continue;
- if (!strcmp(*pp, "..")) {
- char *p;
-
- if (!strcmp(xbuf, "/"))
- continue;
- if (!*xbuf)
- continue;
- p = xbuf + xbuflen;
- while (*--p != '/')
- xbuflen--;
- *p = '\0';
- /* The \0 isn't included in the length */
- xbuflen--;
- continue;
- }
- /* Includes null byte. */
- pplen = strlen(*pp) + 1;
- if (xbuflen + pplen + 1 > sizeof(xbuf2)) {
- *xbuf = 0;
- ret = -1;
- break;
- }
- memcpy(xbuf2, xbuf, xbuflen);
- xbuf2[xbuflen] = '/';
- memcpy(xbuf2 + xbuflen + 1, *pp, pplen);
- t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX);
- if (t0 == -1) {
- if ((xbuflen += pplen) < sizeof(xbuf)) {
- strcat(xbuf, "/");
- strcat(xbuf, *pp);
- } else {
- *xbuf = 0;
- ret = -1;
- break;
- }
- } else {
- ret = 1;
- metafy(xbuf3, t0, META_NOALLOC);
- if (!full) {
- /*
- * If only one expansion requested, ensure the
- * full path is in xbuf.
- */
- zulong len = xbuflen;
- if (*xbuf3 == '/')
- strcpy(xbuf, xbuf3);
- else if ((len += strlen(xbuf3) + 1) < sizeof(xbuf)) {
- strcpy(xbuf + xbuflen, "/");
- strcpy(xbuf + xbuflen + 1, xbuf3);
- } else {
- *xbuf = 0;
- ret = -1;
- break;
- }
-
- while (*++pp) {
- zulong newlen = len + strlen(*pp) + 1;
- if (newlen < sizeof(xbuf)) {
- strcpy(xbuf + len, "/");
- strcpy(xbuf + len + 1, *pp);
- len = newlen;
- } else {
- *xbuf = 01;
- ret = -1;
- break;
- }
- }
- /*
- * No need to update xbuflen, we're finished
- * the expansion (for now).
- */
- break;
- }
- if (*xbuf3 == '/') {
- strcpy(xbuf, "");
- if (xsymlinks(xbuf3 + 1, 1) < 0)
- ret = -1;
- else
- xbuflen = strlen(xbuf);
- } else
- if (xsymlinks(xbuf3, 1) < 0)
- ret = -1;
- else
- xbuflen = strlen(xbuf);
- }
- }
- freearray(opp);
- return ret;
-}
-
-/*
- * expand symlinks in s, and remove other weird things:
- * note that this always expands symlinks.
- *
- * 'heap' indicates whether to malloc() or allocate on the heap.
- */
-
-/**/
-char *
-xsymlink(char *s, int heap)
-{
- if (*s != '/')
- return NULL;
- *xbuf = '\0';
- if (xsymlinks(s + 1, 1) < 0)
- zwarn("path expansion failed, using root directory");
- if (!*xbuf)
- return heap ? dupstring("/") : ztrdup("/");
- return heap ? dupstring(xbuf) : ztrdup(xbuf);
-}
-
-/**/
-void
-print_if_link(char *s, int all)
-{
- if (*s == '/') {
- *xbuf = '\0';
- if (all) {
- char *start = s + 1;
- char xbuflink[PATH_MAX+1];
- for (;;) {
- if (xsymlinks(start, 0) > 0) {
- printf(" -> ");
- zputs(*xbuf ? xbuf : "/", stdout);
- if (!*xbuf)
- break;
- strcpy(xbuflink, xbuf);
- start = xbuflink + 1;
- *xbuf = '\0';
- } else {
- break;
- }
- }
- } else {
- if (xsymlinks(s + 1, 1) > 0)
- printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
- }
- }
-}
-
-/* print a directory */
-
-/**/
-void
-fprintdir(char *s, FILE *f)
-{
- Nameddir d = finddir(s);
-
- if (!d)
- fputs(unmeta(s), f);
- else {
- putc('~', f);
- fputs(unmeta(d->node.nam), f);
- fputs(unmeta(s + strlen(d->dir)), f);
- }
-}
-
-/*
- * Substitute a directory using a name.
- * If there is none, return the original argument.
- *
- * At this level all strings involved are metafied.
- */
-
-/**/
-char *
-substnamedir(char *s)
-{
- Nameddir d = finddir(s);
-
- if (!d)
- return quotestring(s, QT_BACKSLASH);
- return zhtricat("~", d->node.nam, quotestring(s + strlen(d->dir),
- QT_BACKSLASH));
-}
-
-
-/* Returns the current username. It caches the username *
- * and uid to try to avoid requerying the password files *
- * or NIS/NIS+ database. */
-
-/**/
-uid_t cached_uid;
-/**/
-char *cached_username;
-
-/**/
-char *
-get_username(void)
-{
-#ifdef HAVE_GETPWUID
- struct passwd *pswd;
- uid_t current_uid;
-
- current_uid = getuid();
- if (current_uid != cached_uid) {
- cached_uid = current_uid;
- zsfree(cached_username);
- if ((pswd = getpwuid(current_uid)))
- cached_username = ztrdup(pswd->pw_name);
- else
- cached_username = ztrdup("");
- }
-#else /* !HAVE_GETPWUID */
- cached_uid = getuid();
-#endif /* !HAVE_GETPWUID */
- return cached_username;
-}
-
-/* static variables needed by finddir(). */
-
-static char *finddir_full;
-static Nameddir finddir_last;
-static int finddir_best;
-
-/* ScanFunc used by finddir(). */
-
-/**/
-static void
-finddir_scan(HashNode hn, UNUSED(int flags))
-{
- Nameddir nd = (Nameddir) hn;
-
- if(nd->diff > finddir_best && !dircmp(nd->dir, finddir_full)
- && !(nd->node.flags & ND_NOABBREV)) {
- finddir_last=nd;
- finddir_best=nd->diff;
- }
-}
-
-/*
- * See if a path has a named directory as its prefix.
- * If passed a NULL argument, it will invalidate any
- * cached information.
- *
- * s here is metafied.
- */
-
-/**/
-Nameddir
-finddir(char *s)
-{
- static struct nameddir homenode = { {NULL, "", 0}, NULL, 0 };
- static int ffsz;
- char **ares;
- int len;
-
- /* Invalidate directory cache if argument is NULL. This is called *
- * whenever a node is added to or removed from the hash table, and *
- * whenever the value of $HOME changes. (On startup, too.) */
- if (!s) {
- homenode.dir = home ? home : "";
- homenode.diff = home ? strlen(home) : 0;
- if(homenode.diff==1)
- homenode.diff = 0;
- if(!finddir_full)
- finddir_full = zalloc(ffsz = PATH_MAX+1);
- finddir_full[0] = 0;
- return finddir_last = NULL;
- }
-
-#if 0
- /*
- * It's not safe to use the cache while we have function
- * transformations, and it's not clear it's worth the
- * complexity of guessing here whether subst_string_by_hook
- * is going to turn up the goods.
- */
- if (!strcmp(s, finddir_full) && *finddir_full)
- return finddir_last;
-#endif
-
- if ((int)strlen(s) >= ffsz) {
- free(finddir_full);
- finddir_full = zalloc(ffsz = strlen(s) * 2);
- }
- strcpy(finddir_full, s);
- finddir_best=0;
- finddir_last=NULL;
- finddir_scan(&homenode.node, 0);
- scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0);
-
- ares = subst_string_by_hook("zsh_directory_name", "d", finddir_full);
- if (ares && arrlen_ge(ares, 2) &&
- (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
- /* better duplicate this string since it's come from REPLY */
- finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir));
- finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]");
- finddir_last->dir = dupstrpfx(finddir_full, len);
- finddir_last->diff = len - strlen(finddir_last->node.nam);
- finddir_best = len;
- }
-
- return finddir_last;
-}
-
-/* add a named directory */
-
-/**/
-mod_export void
-adduserdir(char *s, char *t, int flags, int always)
-{
- Nameddir nd;
- char *eptr;
-
- /* We don't maintain a hash table in non-interactive shells. */
- if (!interact)
- return;
-
- /* The ND_USERNAME flag means that this possible hash table *
- * entry is derived from a passwd entry. Such entries are *
- * subordinate to explicitly generated entries. */
- if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
- return;
-
- /* Normal parameter assignments generate calls to this function, *
- * with always==0. Unless the AUTO_NAME_DIRS option is set, we *
- * don't let such assignments actually create directory names. *
- * Instead, a reference to the parameter as a directory name can *
- * cause the actual creation of the hash table entry. */
- if (!always && unset(AUTONAMEDIRS) &&
- !nameddirtab->getnode2(nameddirtab, s))
- return;
-
- if (!t || *t != '/' || strlen(t) >= PATH_MAX) {
- /* We can't use this value as a directory, so simply remove *
- * the corresponding entry in the hash table, if any. */
- HashNode hn = nameddirtab->removenode(nameddirtab, s);
-
- if(hn)
- nameddirtab->freenode(hn);
- return;
- }
-
- /* add the name */
- nd = (Nameddir) zshcalloc(sizeof *nd);
- nd->node.flags = flags;
- eptr = t + strlen(t);
- while (eptr > t && eptr[-1] == '/')
- eptr--;
- if (eptr == t) {
- /*
- * Don't abbreviate multiple slashes at the start of a
- * named directory, since these are sometimes used for
- * special purposes.
- */
- nd->dir = metafy(t, -1, META_DUP);
- } else
- nd->dir = metafy(t, eptr - t, META_DUP);
- /* The variables PWD and OLDPWD are not to be displayed as ~PWD etc. */
- if (!strcmp(s, "PWD") || !strcmp(s, "OLDPWD"))
- nd->node.flags |= ND_NOABBREV;
- nameddirtab->addnode(nameddirtab, metafy(s, -1, META_DUP), nd);
-}
-
-/* Get a named directory: this function can cause a directory name *
- * to be added to the hash table, if it isn't there already. */
-
-/**/
-char *
-getnameddir(char *name)
-{
- Param pm;
- char *str;
- Nameddir nd;
-
- /* Check if it is already in the named directory table */
- if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)))
- return dupstring(nd->dir);
-
- /* Check if there is a scalar parameter with this name whose value *
- * begins with a `/'. If there is, add it to the hash table and *
- * return the new value. */
- if ((pm = (Param) paramtab->getnode(paramtab, name)) &&
- (PM_TYPE(pm->node.flags) == PM_SCALAR) &&
- (str = getsparam(name)) && *str == '/') {
- pm->node.flags |= PM_NAMEDDIR;
- adduserdir(name, str, 0, 1);
- return str;
- }
-
-#ifdef HAVE_GETPWNAM
- {
- /* Retrieve an entry from the password table/database for this user. */
- struct passwd *pw;
- if ((pw = getpwnam(name))) {
- char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir, 0)
- : ztrdup(pw->pw_dir);
- if (dir) {
- adduserdir(name, dir, ND_USERNAME, 1);
- str = dupstring(dir);
- zsfree(dir);
- return str;
- } else
- return dupstring(pw->pw_dir);
- }
- }
-#endif /* HAVE_GETPWNAM */
-
- /* There are no more possible sources of directory names, so give up. */
- return NULL;
-}
-
-/*
- * Compare directories. Both are metafied.
- */
-
-/**/
-static int
-dircmp(char *s, char *t)
-{
- if (s) {
- for (; *s == *t; s++, t++)
- if (!*s)
- return 0;
- if (!*s && *t == '/')
- return 0;
- }
- return 1;
-}
-
-/*
- * Extra functions to call before displaying the prompt.
- * The data is a Prepromptfn.
- */
-
-static LinkList prepromptfns;
-
-/* Add a function to the list of pre-prompt functions. */
-
-/**/
-mod_export void
-addprepromptfn(voidvoidfnptr_t func)
-{
- Prepromptfn ppdat = (Prepromptfn)zalloc(sizeof(struct prepromptfn));
- ppdat->func = func;
- if (!prepromptfns)
- prepromptfns = znewlinklist();
- zaddlinknode(prepromptfns, ppdat);
-}
-
-/* Remove a function from the list of pre-prompt functions. */
-
-/**/
-mod_export void
-delprepromptfn(voidvoidfnptr_t func)
-{
- LinkNode ln;
-
- for (ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
- Prepromptfn ppdat = (Prepromptfn)getdata(ln);
- if (ppdat->func == func) {
- (void)remnode(prepromptfns, ln);
- zfree(ppdat, sizeof(struct prepromptfn));
- return;
- }
- }
-#ifdef DEBUG
- dputs("BUG: failed to delete node from prepromptfns");
-#endif
-}
-
-/*
- * Functions to call at a particular time even if not at
- * the prompt. This is handled by zle. The data is a
- * Timedfn. The functions must be in time order, but this
- * is enforced by addtimedfn().
- *
- * Note on debugging: the code in sched.c currently assumes it's
- * the only user of timedfns for the purposes of checking whether
- * there's a function on the list. If this becomes no longer the case,
- * the DPUTS() tests in sched.c need rewriting.
- */
-
-/**/
-mod_export LinkList timedfns;
-
-/* Add a function to the list of timed functions. */
-
-/**/
-mod_export void
-addtimedfn(voidvoidfnptr_t func, time_t when)
-{
- Timedfn tfdat = (Timedfn)zalloc(sizeof(struct timedfn));
- tfdat->func = func;
- tfdat->when = when;
-
- if (!timedfns) {
- timedfns = znewlinklist();
- zaddlinknode(timedfns, tfdat);
- } else {
- LinkNode ln = firstnode(timedfns);
-
- /*
- * Insert the new element in the linked list. We do
- * rather too much work here since the standard
- * functions insert after a given node, whereas we
- * want to insert the new data before the first element
- * with a greater time.
- *
- * In practice, the only use of timed functions is
- * sched, which only adds the one function; so this
- * whole branch isn't used beyond the following block.
- */
- if (!ln) {
- zaddlinknode(timedfns, tfdat);
- return;
- }
- for (;;) {
- Timedfn tfdat2;
- LinkNode next = nextnode(ln);
- if (!next) {
- zaddlinknode(timedfns, tfdat);
- return;
- }
- tfdat2 = (Timedfn)getdata(next);
- if (when < tfdat2->when) {
- zinsertlinknode(timedfns, ln, tfdat);
- return;
- }
- ln = next;
- }
- }
-}
-
-/*
- * Delete a function from the list of timed functions.
- * Note that if the function apperas multiple times only
- * the first occurrence will be removed.
- *
- * Note also that when zle calls the function it does *not*
- * automatically delete the entry from the list. That must
- * be done by the function called. This is recommended as otherwise
- * the function will keep being called immediately. (It just so
- * happens this "feature" fits in well with the only current use
- * of timed functions.)
- */
-
-/**/
-mod_export void
-deltimedfn(voidvoidfnptr_t func)
-{
- LinkNode ln;
-
- for (ln = firstnode(timedfns); ln; ln = nextnode(ln)) {
- Timedfn ppdat = (Timedfn)getdata(ln);
- if (ppdat->func == func) {
- (void)remnode(timedfns, ln);
- zfree(ppdat, sizeof(struct timedfn));
- return;
- }
- }
-#ifdef DEBUG
- dputs("BUG: failed to delete node from timedfns");
-#endif
-}
-
-/* the last time we checked mail */
-
-/**/
-time_t lastmailcheck;
-
-/* the last time we checked the people in the WATCH variable */
-
-/**/
-time_t lastwatch;
-
-/*
- * Call a function given by "name" with optional arguments
- * "lnklist". If these are present the first argument is the function name.
- *
- * If "arrayp" is not zero, we also look through
- * the array "name"_functions and execute functions found there.
- *
- * If "retval" is not NULL, the return value of the first hook function to
- * return non-zero is stored in *"retval". The return value is not otherwise
- * available as the calling context is restored.
- *
- * Returns 0 if at least one function was called (regardless of that function's
- * exit status), and 1 otherwise.
- */
-
-/**/
-mod_export int
-callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval)
-{
- Shfunc shfunc;
- /*
- * Save stopmsg, since user doesn't get a chance to respond
- * to a list of jobs generated in a hook.
- */
- int osc = sfcontext, osm = stopmsg, stat = 1, ret = 0;
- int old_incompfunc = incompfunc;
-
- sfcontext = SFC_HOOK;
- incompfunc = 0;
-
- if ((shfunc = getshfunc(name))) {
- ret = doshfunc(shfunc, lnklst, 1);
- stat = 0;
- }
-
- if (arrayp) {
- char **arrptr;
- int namlen = strlen(name);
- VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN);
- memcpy(arrnam, name, namlen);
- memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN);
-
- if ((arrptr = getaparam(arrnam))) {
- arrptr = arrdup(arrptr);
- for (; *arrptr; arrptr++) {
- if ((shfunc = getshfunc(*arrptr))) {
- int newret = doshfunc(shfunc, lnklst, 1);
- if (!ret)
- ret = newret;
- stat = 0;
- }
- }
- }
- }
-
- sfcontext = osc;
- stopmsg = osm;
- incompfunc = old_incompfunc;
-
- if (retval)
- *retval = ret;
- return stat;
-}
-
-/* do pre-prompt stuff */
-
-/**/
-void
-preprompt(void)
-{
- static time_t lastperiodic;
- time_t currentmailcheck;
- LinkNode ln;
- zlong period = getiparam("PERIOD");
- zlong mailcheck = getiparam("MAILCHECK");
-
- /*
- * Handle any pending window size changes before we compute prompts,
- * then block them again to avoid interrupts during prompt display.
- */
- winch_unblock();
- winch_block();
-
- if (isset(PROMPTSP) && isset(PROMPTCR) && !use_exit_printed && shout) {
- /* The PROMPT_SP heuristic will move the prompt down to a new line
- * if there was any dangling output on the line (assuming the terminal
- * has automatic margins, but we try even if hasam isn't set).
- * Unfortunately it interacts badly with ZLE displaying message
- * when ^D has been pressed. So just disable PROMPT_SP logic in
- * this case */
- char *eolmark = getsparam("PROMPT_EOL_MARK");
- char *str;
- int percents = opts[PROMPTPERCENT], w = 0;
- if (!eolmark)
- eolmark = "%B%S%#%s%b";
- opts[PROMPTPERCENT] = 1;
- str = promptexpand(eolmark, 1, NULL, NULL, NULL);
- countprompt(str, &w, 0, -1);
- opts[PROMPTPERCENT] = percents;
- zputs(str, shout);
- fprintf(shout, "%*s\r%*s\r", (int)zterm_columns - w - !hasxn,
- "", w, "");
- fflush(shout);
- free(str);
- }
-
- /* If NOTIFY is not set, then check for completed *
- * jobs before we print the prompt. */
- if (unset(NOTIFY))
- scanjobs();
- if (errflag)
- return;
-
- /* If a shell function named "precmd" exists, *
- * then execute it. */
- callhookfunc("precmd", NULL, 1, NULL);
- if (errflag)
- return;
-
- /* If 1) the parameter PERIOD exists, 2) a hook function for *
- * "periodic" exists, 3) it's been greater than PERIOD since we *
- * executed any such hook, then execute it now. */
- if (period && ((zlong)time(NULL) > (zlong)lastperiodic + period) &&
- !callhookfunc("periodic", NULL, 1, NULL))
- lastperiodic = time(NULL);
- if (errflag)
- return;
-
- /* If WATCH is set, then check for the *
- * specified login/logout events. */
- if (watch) {
- if ((int) difftime(time(NULL), lastwatch) > getiparam("LOGCHECK")) {
- dowatch();
- lastwatch = time(NULL);
- }
- }
- if (errflag)
- return;
-
- /* Check mail */
- currentmailcheck = time(NULL);
- if (mailcheck &&
- (zlong) difftime(currentmailcheck, lastmailcheck) > mailcheck) {
- char *mailfile;
-
- if (mailpath && *mailpath && **mailpath)
- checkmailpath(mailpath);
- else {
- queue_signals();
- if ((mailfile = getsparam("MAIL")) && *mailfile) {
- char *x[2];
-
- x[0] = mailfile;
- x[1] = NULL;
- checkmailpath(x);
- }
- unqueue_signals();
- }
- lastmailcheck = currentmailcheck;
- }
-
- if (prepromptfns) {
- for(ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
- Prepromptfn ppnode = (Prepromptfn)getdata(ln);
- ppnode->func();
- }
- }
-}
-
-/**/
-static void
-checkmailpath(char **s)
-{
- struct stat st;
- char *v, *u, c;
-
- while (*s) {
- for (v = *s; *v && *v != '?'; v++);
- c = *v;
- *v = '\0';
- if (c != '?')
- u = NULL;
- else
- u = v + 1;
- if (**s == 0) {
- *v = c;
- zerr("empty MAILPATH component: %s", *s);
- } else if (mailstat(unmeta(*s), &st) == -1) {
- if (errno != ENOENT)
- zerr("%e: %s", errno, *s);
- } else if (S_ISDIR(st.st_mode)) {
- LinkList l;
- DIR *lock = opendir(unmeta(*s));
- char buf[PATH_MAX * 2 + 1], **arr, **ap;
- int buflen, ct = 1;
-
- if (lock) {
- char *fn;
-
- pushheap();
- l = newlinklist();
- while ((fn = zreaddir(lock, 1)) && !errflag) {
- if (u)
- buflen = snprintf(buf, sizeof(buf), "%s/%s?%s", *s, fn, u);
- else
- buflen = snprintf(buf, sizeof(buf), "%s/%s", *s, fn);
- if (buflen < 0 || buflen >= (int)sizeof(buf))
- continue;
- addlinknode(l, dupstring(buf));
- ct++;
- }
- closedir(lock);
- ap = arr = (char **) zhalloc(ct * sizeof(char *));
-
- while ((*ap++ = (char *)ugetnode(l)));
- checkmailpath(arr);
- popheap();
- }
- } else if (shout) {
- if (st.st_size && st.st_atime <= st.st_mtime &&
- st.st_mtime >= lastmailcheck) {
- if (!u) {
- fprintf(shout, "You have new mail.\n");
- fflush(shout);
- } else {
- char *usav;
- int uusav = underscoreused;
-
- usav = zalloc(underscoreused);
-
- if (usav)
- memcpy(usav, zunderscore, underscoreused);
-
- setunderscore(*s);
-
- u = dupstring(u);
- if (!parsestr(&u)) {
- singsub(&u);
- zputs(u, shout);
- fputc('\n', shout);
- fflush(shout);
- }
- if (usav) {
- setunderscore(usav);
- zfree(usav, uusav);
- }
- }
- }
- if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
- st.st_atime > lastmailcheck && st.st_size) {
- fprintf(shout, "The mail in %s has been read.\n", unmeta(*s));
- fflush(shout);
- }
- }
- *v = c;
- s++;
- }
-}
-
-/* This prints the XTRACE prompt. */
-
-/**/
-FILE *xtrerr = 0;
-
-/**/
-void
-printprompt4(void)
-{
- if (!xtrerr)
- xtrerr = stderr;
- if (prompt4) {
- int l, t = opts[XTRACE];
- char *s = dupstring(prompt4);
-
- opts[XTRACE] = 0;
- unmetafy(s, &l);
- s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC),
- 0, NULL, NULL, NULL), &l);
- opts[XTRACE] = t;
-
- fprintf(xtrerr, "%s", s);
- free(s);
- }
-}
-
-/**/
-mod_export void
-freestr(void *a)
-{
- zsfree(a);
-}
-
-/**/
-mod_export void
-gettyinfo(struct ttyinfo *ti)
-{
- if (SHTTY != -1) {
-#ifdef HAVE_TERMIOS_H
-# ifdef HAVE_TCGETATTR
- if (tcgetattr(SHTTY, &ti->tio) == -1)
-# else
- if (ioctl(SHTTY, TCGETS, &ti->tio) == -1)
-# endif
- zerr("bad tcgets: %e", errno);
-#else
-# ifdef HAVE_TERMIO_H
- ioctl(SHTTY, TCGETA, &ti->tio);
-# else
- ioctl(SHTTY, TIOCGETP, &ti->sgttyb);
- ioctl(SHTTY, TIOCLGET, &ti->lmodes);
- ioctl(SHTTY, TIOCGETC, &ti->tchars);
- ioctl(SHTTY, TIOCGLTC, &ti->ltchars);
-# endif
-#endif
- }
-}
-
-/**/
-mod_export void
-settyinfo(struct ttyinfo *ti)
-{
- if (SHTTY != -1) {
-#ifdef HAVE_TERMIOS_H
-# ifdef HAVE_TCGETATTR
-# ifndef TCSADRAIN
-# define TCSADRAIN 1 /* XXX Princeton's include files are screwed up */
-# endif
- while (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1 && errno == EINTR)
- ;
-# else
- while (ioctl(SHTTY, TCSETS, &ti->tio) == -1 && errno == EINTR)
- ;
-# endif
- /* zerr("settyinfo: %e",errno);*/
-#else
-# ifdef HAVE_TERMIO_H
- ioctl(SHTTY, TCSETA, &ti->tio);
-# else
- ioctl(SHTTY, TIOCSETN, &ti->sgttyb);
- ioctl(SHTTY, TIOCLSET, &ti->lmodes);
- ioctl(SHTTY, TIOCSETC, &ti->tchars);
- ioctl(SHTTY, TIOCSLTC, &ti->ltchars);
-# endif
-#endif
- }
-}
-
-/* the default tty state */
-
-/**/
-mod_export struct ttyinfo shttyinfo;
-
-/* != 0 if we need to call resetvideo() */
-
-/**/
-mod_export int resetneeded;
-
-#ifdef TIOCGWINSZ
-/* window size changed */
-
-/**/
-mod_export int winchanged;
-#endif
-
-static int
-adjustlines(int signalled)
-{
- int oldlines = zterm_lines;
-
-#ifdef TIOCGWINSZ
- if (signalled || zterm_lines <= 0)
- zterm_lines = shttyinfo.winsize.ws_row;
- else
- shttyinfo.winsize.ws_row = zterm_lines;
-#endif /* TIOCGWINSZ */
- if (zterm_lines <= 0) {
- DPUTS(signalled && zterm_lines < 0,
- "BUG: Impossible TIOCGWINSZ rows");
- zterm_lines = tclines > 0 ? tclines : 24;
- }
-
- if (zterm_lines > 2)
- termflags &= ~TERM_SHORT;
- else
- termflags |= TERM_SHORT;
-
- return (zterm_lines != oldlines);
-}
-
-static int
-adjustcolumns(int signalled)
-{
- int oldcolumns = zterm_columns;
-
-#ifdef TIOCGWINSZ
- if (signalled || zterm_columns <= 0)
- zterm_columns = shttyinfo.winsize.ws_col;
- else
- shttyinfo.winsize.ws_col = zterm_columns;
-#endif /* TIOCGWINSZ */
- if (zterm_columns <= 0) {
- DPUTS(signalled && zterm_columns < 0,
- "BUG: Impossible TIOCGWINSZ cols");
- zterm_columns = tccolumns > 0 ? tccolumns : 80;
- }
-
- if (zterm_columns > 2)
- termflags &= ~TERM_NARROW;
- else
- termflags |= TERM_NARROW;
-
- return (zterm_columns != oldcolumns);
-}
-
-/* check the size of the window and adjust if necessary. *
- * The value of from: *
- * 0: called from update_job or setupvals *
- * 1: called from the SIGWINCH handler *
- * 2: called from the LINES parameter callback *
- * 3: called from the COLUMNS parameter callback */
-
-/**/
-void
-adjustwinsize(int from)
-{
- static int getwinsz = 1;
-#ifdef TIOCGWINSZ
- int ttyrows = shttyinfo.winsize.ws_row;
- int ttycols = shttyinfo.winsize.ws_col;
-#endif
- int resetzle = 0;
-
- if (getwinsz || from == 1) {
-#ifdef TIOCGWINSZ
- if (SHTTY == -1)
- return;
- if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) {
- resetzle = (ttyrows != shttyinfo.winsize.ws_row ||
- ttycols != shttyinfo.winsize.ws_col);
- if (from == 0 && resetzle && ttyrows && ttycols)
- from = 1; /* Signal missed while a job owned the tty? */
- ttyrows = shttyinfo.winsize.ws_row;
- ttycols = shttyinfo.winsize.ws_col;
- } else {
- /* Set to value from environment on failure */
- shttyinfo.winsize.ws_row = zterm_lines;
- shttyinfo.winsize.ws_col = zterm_columns;
- resetzle = (from == 1);
- }
-#else
- resetzle = from == 1;
-#endif /* TIOCGWINSZ */
- } /* else
- return; */
-
- switch (from) {
- case 0:
- case 1:
- getwinsz = 0;
- /* Calling setiparam() here calls this function recursively, but *
- * because we've already called adjustlines() and adjustcolumns() *
- * here, recursive calls are no-ops unless a signal intervenes. *
- * The commented "else return;" above might be a safe shortcut, *
- * but I'm concerned about what happens on race conditions; e.g., *
- * suppose the user resizes his xterm during `eval $(resize)'? */
- if (adjustlines(from) && zgetenv("LINES"))
- setiparam("LINES", zterm_lines);
- if (adjustcolumns(from) && zgetenv("COLUMNS"))
- setiparam("COLUMNS", zterm_columns);
- getwinsz = 1;
- break;
- case 2:
- resetzle = adjustlines(0);
- break;
- case 3:
- resetzle = adjustcolumns(0);
- break;
- }
-
-#ifdef TIOCGWINSZ
- if (interact && from >= 2 &&
- (shttyinfo.winsize.ws_row != ttyrows ||
- shttyinfo.winsize.ws_col != ttycols)) {
- /* shttyinfo.winsize is already set up correctly */
- /* ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize); */
- }
-#endif /* TIOCGWINSZ */
-
- if (zleactive && resetzle) {
-#ifdef TIOCGWINSZ
- winchanged =
-#endif /* TIOCGWINSZ */
- resetneeded = 1;
- zleentry(ZLE_CMD_RESET_PROMPT);
- zleentry(ZLE_CMD_REFRESH);
- }
-}
-
-/*
- * Ensure the fdtable is large enough for fd, and that the
- * maximum fd is set appropriately.
- */
-static void
-check_fd_table(int fd)
-{
- if (fd <= max_zsh_fd)
- return;
-
- if (fd >= fdtable_size) {
- int old_size = fdtable_size;
- while (fd >= fdtable_size)
- fdtable = zrealloc(fdtable,
- (fdtable_size *= 2)*sizeof(*fdtable));
- memset(fdtable + old_size, 0,
- (fdtable_size - old_size) * sizeof(*fdtable));
- }
- max_zsh_fd = fd;
-}
-
-/* Move a fd to a place >= 10 and mark the new fd in fdtable. If the fd *
- * is already >= 10, it is not moved. If it is invalid, -1 is returned. */
-
-/**/
-mod_export int
-movefd(int fd)
-{
- if(fd != -1 && fd < 10) {
-#ifdef F_DUPFD
- int fe = fcntl(fd, F_DUPFD, 10);
-#else
- int fe = movefd(dup(fd));
-#endif
- /*
- * To close or not to close if fe is -1?
- * If it is -1, we haven't moved the fd, so if we close
- * it we lose it; but we're probably not going to be able
- * to use it in situ anyway. So probably better to avoid a leak.
- */
- zclose(fd);
- fd = fe;
- }
- if(fd != -1) {
- check_fd_table(fd);
- fdtable[fd] = FDT_INTERNAL;
- }
- return fd;
-}
-
-/*
- * Move fd x to y. If x == -1, fd y is closed.
- * Returns y for success, -1 for failure.
- */
-
-/**/
-mod_export int
-redup(int x, int y)
-{
- int ret = y;
-
- if(x < 0)
- zclose(y);
- else if (x != y) {
- if (dup2(x, y) == -1) {
- ret = -1;
- } else {
- check_fd_table(y);
- fdtable[y] = fdtable[x];
- if (fdtable[y] == FDT_FLOCK || fdtable[y] == FDT_FLOCK_EXEC)
- fdtable[y] = FDT_INTERNAL;
- }
- /*
- * Closing any fd to the locked file releases the lock.
- * This isn't expected to happen, it's here for completeness.
- */
- if (fdtable[x] == FDT_FLOCK)
- fdtable_flocks--;
- zclose(x);
- }
-
- return ret;
-}
-
-/*
- * Add an fd opened ithin a module.
- *
- * fdt is the type of the fd; see the FDT_ definitions in zsh.h.
- * The most likely falures are:
- *
- * FDT_EXTERNAL: the fd can be used within the shell for normal I/O but
- * it will not be closed automatically or by normal shell syntax.
- *
- * FDT_MODULE: as FDT_EXTERNAL, but it can only be closed by the module
- * (which should included zclose() as part of the sequence), not by
- * the standard shell syntax for closing file descriptors.
- *
- * FDT_INTERNAL: fd is treated like others created by the shell for
- * internal use; it can be closed and will be closed by the shell if it
- * exec's or performs an exec with a fork optimised out.
- *
- * Safe if fd is -1 to indicate failure.
- */
-/**/
-mod_export void
-addmodulefd(int fd, int fdt)
-{
- if (fd >= 0) {
- check_fd_table(fd);
- fdtable[fd] = fdt;
- }
-}
-
-/**/
-
-/*
- * Indicate that an fd has a file lock; if cloexec is 1 it will be closed
- * on exec.
- * The fd should already be known to fdtable (e.g. by movefd).
- * Note the fdtable code doesn't care what sort of lock
- * is used; this simply prevents the main shell exiting prematurely
- * when it holds a lock.
- */
-
-/**/
-mod_export void
-addlockfd(int fd, int cloexec)
-{
- if (cloexec) {
- if (fdtable[fd] != FDT_FLOCK)
- fdtable_flocks++;
- fdtable[fd] = FDT_FLOCK;
- } else {
- fdtable[fd] = FDT_FLOCK_EXEC;
- }
-}
-
-/* Close the given fd, and clear it from fdtable. */
-
-/**/
-mod_export int
-zclose(int fd)
-{
- if (fd >= 0) {
- /*
- * Careful: we allow closing of arbitrary fd's, beyond
- * max_zsh_fd. In that case we don't try anything clever.
- */
- if (fd <= max_zsh_fd) {
- if (fdtable[fd] == FDT_FLOCK)
- fdtable_flocks--;
- fdtable[fd] = FDT_UNUSED;
- while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED)
- max_zsh_fd--;
- if (fd == coprocin)
- coprocin = -1;
- if (fd == coprocout)
- coprocout = -1;
- }
- return close(fd);
- }
- return -1;
-}
-
-/*
- * Close an fd returning 0 if used for locking; return -1 if it isn't.
- */
-
-/**/
-mod_export int
-zcloselockfd(int fd)
-{
- if (fd > max_zsh_fd)
- return -1;
- if (fdtable[fd] != FDT_FLOCK && fdtable[fd] != FDT_FLOCK_EXEC)
- return -1;
- zclose(fd);
- return 0;
-}
-
-#ifdef HAVE__MKTEMP
-extern char *_mktemp(char *);
-#endif
-
-/* Get a unique filename for use as a temporary file. If "prefix" is
- * NULL, the name is relative to $TMPPREFIX; If it is non-NULL, the
- * unique suffix includes a prefixed '.' for improved readability. If
- * "use_heap" is true, we allocate the returned name on the heap.
- * The string passed as "prefix" is expected to be metafied. */
-
-/**/
-mod_export char *
-gettempname(const char *prefix, int use_heap)
-{
- char *ret, *suffix = prefix ? ".XXXXXX" : "XXXXXX";
-
- queue_signals();
- if (!prefix && !(prefix = getsparam("TMPPREFIX")))
- prefix = DEFAULT_TMPPREFIX;
- if (use_heap)
- ret = dyncat(unmeta(prefix), suffix);
- else
- ret = bicat(unmeta(prefix), suffix);
-
-#ifdef HAVE__MKTEMP
- /* Zsh uses mktemp() safely, so silence the warnings */
- ret = (char *) _mktemp(ret);
-#else
- ret = (char *) mktemp(ret);
-#endif
- unqueue_signals();
-
- return ret;
-}
-
-/* The gettempfile() "prefix" is expected to be metafied, see hist.c
- * and gettempname(). */
-
-/**/
-mod_export int
-gettempfile(const char *prefix, int use_heap, char **tempname)
-{
- char *fn;
- int fd;
- mode_t old_umask;
-#if HAVE_MKSTEMP
- char *suffix = prefix ? ".XXXXXX" : "XXXXXX";
-
- queue_signals();
- old_umask = umask(0177);
- if (!prefix && !(prefix = getsparam("TMPPREFIX")))
- prefix = DEFAULT_TMPPREFIX;
- if (use_heap)
- fn = dyncat(unmeta(prefix), suffix);
- else
- fn = bicat(unmeta(prefix), suffix);
-
- fd = mkstemp(fn);
- if (fd < 0) {
- if (!use_heap)
- free(fn);
- fn = NULL;
- }
-#else
- int failures = 0;
-
- queue_signals();
- old_umask = umask(0177);
- do {
- if (!(fn = gettempname(prefix, use_heap))) {
- fd = -1;
- break;
- }
- if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
- break;
- if (!use_heap)
- free(fn);
- fn = NULL;
- } while (errno == EEXIST && ++failures < 16);
-#endif
- *tempname = fn;
-
- umask(old_umask);
- unqueue_signals();
- return fd;
-}
-
-/* Check if a string contains a token */
-
-/**/
-mod_export int
-has_token(const char *s)
-{
- while(*s)
- if(itok(*s++))
- return 1;
- return 0;
-}
-
-/* Delete a character in a string */
-
-/**/
-mod_export void
-chuck(char *str)
-{
- while ((str[0] = str[1]))
- str++;
-}
-
-/**/
-mod_export int
-tulower(int c)
-{
- c &= 0xff;
- return (isupper(c) ? tolower(c) : c);
-}
-
-/**/
-mod_export int
-tuupper(int c)
-{
- c &= 0xff;
- return (islower(c) ? toupper(c) : c);
-}
-
-/* copy len chars from t into s, and null terminate */
-
-/**/
-void
-ztrncpy(char *s, char *t, int len)
-{
- while (len--)
- *s++ = *t++;
- *s = '\0';
-}
-
-/* copy t into *s and update s */
-
-/**/
-mod_export void
-strucpy(char **s, char *t)
-{
- char *u = *s;
-
- while ((*u++ = *t++));
- *s = u - 1;
-}
-
-/**/
-mod_export void
-struncpy(char **s, char *t, int n)
-{
- char *u = *s;
-
- while (n-- && (*u = *t++))
- u++;
- *s = u;
- if (n > 0) /* just one null-byte will do, unlike strncpy(3) */
- *u = '\0';
-}
-
-/* Return the number of elements in an array of pointers. *
- * It doesn't count the NULL pointer at the end. */
-
-/**/
-mod_export int
-arrlen(char **s)
-{
- int count;
-
- for (count = 0; *s; s++, count++);
- return count;
-}
-
-/* Return TRUE iff arrlen(s) >= lower_bound, but more efficiently. */
-
-/**/
-mod_export char
-arrlen_ge(char **s, unsigned lower_bound)
-{
- while (lower_bound--)
- if (!*s++)
- return 0 /* FALSE */;
-
- return 1 /* TRUE */;
-}
-
-/* Return TRUE iff arrlen(s) > lower_bound, but more efficiently. */
-
-/**/
-mod_export char
-arrlen_gt(char **s, unsigned lower_bound)
-{
- return arrlen_ge(s, 1+lower_bound);
-}
-
-/* Return TRUE iff arrlen(s) <= upper_bound, but more efficiently. */
-
-/**/
-mod_export char
-arrlen_le(char **s, unsigned upper_bound)
-{
- return arrlen_lt(s, 1+upper_bound);
-}
-
-/* Return TRUE iff arrlen(s) < upper_bound, but more efficiently. */
-
-/**/
-mod_export char
-arrlen_lt(char **s, unsigned upper_bound)
-{
- return !arrlen_ge(s, upper_bound);
-}
-
-/* Skip over a balanced pair of parenthesis. */
-
-/**/
-mod_export int
-skipparens(char inpar, char outpar, char **s)
-{
- int level;
-
- if (**s != inpar)
- return -1;
-
- for (level = 1; *++*s && level;)
- if (**s == inpar)
- ++level;
- else if (**s == outpar)
- --level;
-
- return level;
-}
-
-/**/
-mod_export zlong
-zstrtol(const char *s, char **t, int base)
-{
- return zstrtol_underscore(s, t, base, 0);
-}
-
-/* Convert string to zlong (see zsh.h). This function (without the z) *
- * is contained in the ANSI standard C library, but a lot of them seem *
- * to be broken. */
-
-/**/
-mod_export zlong
-zstrtol_underscore(const char *s, char **t, int base, int underscore)
-{
- const char *inp, *trunc = NULL;
- zulong calc = 0, newcalc = 0;
- int neg;
-
- while (inblank(*s))
- s++;
-
- if ((neg = IS_DASH(*s)))
- s++;
- else if (*s == '+')
- s++;
-
- if (!base) {
- if (*s != '0')
- base = 10;
- else if (*++s == 'x' || *s == 'X')
- base = 16, s++;
- else if (*s == 'b' || *s == 'B')
- base = 2, s++;
- else
- base = 8;
- }
- inp = s;
- if (base < 2 || base > 36) {
- zerr("invalid base (must be 2 to 36 inclusive): %d", base);
- return (zlong)0;
- } else if (base <= 10) {
- for (; (*s >= '0' && *s < ('0' + base)) ||
- (underscore && *s == '_'); s++) {
- if (trunc || *s == '_')
- continue;
- newcalc = calc * base + *s - '0';
- if (newcalc < calc)
- {
- trunc = s;
- continue;
- }
- calc = newcalc;
- }
- } else {
- for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
- || (*s >= 'A' && *s < ('A' + base - 10))
- || (underscore && *s == '_'); s++) {
- if (trunc || *s == '_')
- continue;
- newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
- if (newcalc < calc)
- {
- trunc = s;
- continue;
- }
- calc = newcalc;
- }
- }
-
- /*
- * Special case: check for a number that was just too long for
- * signed notation.
- * Extra special case: the lowest negative number would trigger
- * the first test, but is actually representable correctly.
- * This is a 1 in the top bit, all others zero, so test for
- * that explicitly.
- */
- if (!trunc && (zlong)calc < 0 &&
- (!neg || calc & ~((zulong)1 << (8*sizeof(zulong)-1))))
- {
- trunc = s - 1;
- calc /= base;
- }
-
- if (trunc)
- zwarn("number truncated after %d digits: %s", (int)(trunc - inp), inp);
-
- if (t)
- *t = (char *)s;
- return neg ? -(zlong)calc : (zlong)calc;
-}
-
-/*
- * If s represents a complete unsigned integer (and nothing else)
- * return 1 and set retval to the value. Otherwise return 0.
- *
- * Underscores are always allowed.
- *
- * Sensitive to OCTAL_ZEROES.
- */
-
-/**/
-mod_export int
-zstrtoul_underscore(const char *s, zulong *retval)
-{
- zulong calc = 0, newcalc = 0, base;
-
- if (*s == '+')
- s++;
-
- if (*s != '0')
- base = 10;
- else if (*++s == 'x' || *s == 'X')
- base = 16, s++;
- else if (*s == 'b' || *s == 'B')
- base = 2, s++;
- else
- base = isset(OCTALZEROES) ? 8 : 10;
- if (base <= 10) {
- for (; (*s >= '0' && *s < ('0' + base)) ||
- *s == '_'; s++) {
- if (*s == '_')
- continue;
- newcalc = calc * base + *s - '0';
- if (newcalc < calc)
- {
- return 0;
- }
- calc = newcalc;
- }
- } else {
- for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
- || (*s >= 'A' && *s < ('A' + base - 10))
- || *s == '_'; s++) {
- if (*s == '_')
- continue;
- newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
- if (newcalc < calc)
- {
- return 0;
- }
- calc = newcalc;
- }
- }
-
- if (*s)
- return 0;
- *retval = calc;
- return 1;
-}
-
-/**/
-mod_export int
-setblock_fd(int turnonblocking, int fd, long *modep)
-{
-#ifdef O_NDELAY
-# ifdef O_NONBLOCK
-# define NONBLOCK (O_NDELAY|O_NONBLOCK)
-# else /* !O_NONBLOCK */
-# define NONBLOCK O_NDELAY
-# endif /* !O_NONBLOCK */
-#else /* !O_NDELAY */
-# ifdef O_NONBLOCK
-# define NONBLOCK O_NONBLOCK
-# else /* !O_NONBLOCK */
-# define NONBLOCK 0
-# endif /* !O_NONBLOCK */
-#endif /* !O_NDELAY */
-
-#if NONBLOCK
- struct stat st;
-
- if (!fstat(fd, &st) && !S_ISREG(st.st_mode)) {
- *modep = fcntl(fd, F_GETFL, 0);
- if (*modep != -1) {
- if (!turnonblocking) {
- /* We want to know if blocking was off */
- if ((*modep & NONBLOCK) ||
- !fcntl(fd, F_SETFL, *modep | NONBLOCK))
- return 1;
- } else if ((*modep & NONBLOCK) &&
- !fcntl(fd, F_SETFL, *modep & ~NONBLOCK)) {
- /* Here we want to know if the state changed */
- return 1;
- }
- }
- } else
-#endif /* NONBLOCK */
- *modep = -1;
- return 0;
-
-#undef NONBLOCK
-}
-
-/**/
-int
-setblock_stdin(void)
-{
- long mode;
- return setblock_fd(1, 0, &mode);
-}
-
-/*
- * Check for pending input on fd. If polltty is set, we may need to
- * use termio to look for input. As a final resort, go to non-blocking
- * input and try to read a character, which in this case will be
- * returned in *readchar.
- *
- * Note that apart from setting (and restoring) non-blocking input,
- * this function does not change the input mode. The calling function
- * should have set cbreak mode if necessary.
- *
- * fd may be -1 to sleep until the timeout in microseconds. This is a
- * fallback for old systems that don't have nanosleep(). Some very old
- * systems might not have select: get with it, daddy-o.
- */
-
-/**/
-mod_export int
-read_poll(int fd, int *readchar, int polltty, zlong microseconds)
-{
- int ret = -1;
- long mode = -1;
- char c;
-#ifdef HAVE_SELECT
- fd_set foofd;
- struct timeval expire_tv;
-#else
-#ifdef FIONREAD
- int val;
-#endif
-#endif
-#ifdef HAS_TIO
- struct ttyinfo ti;
-#endif
-
- if (fd < 0 || (polltty && !isatty(fd)))
- polltty = 0; /* no tty to poll */
-
-#if defined(HAS_TIO) && !defined(__CYGWIN__)
- /*
- * Under Solaris, at least, reading from the terminal in non-canonical
- * mode requires that we use the VMIN mechanism to poll. Any attempt
- * to check any other way, or to set the terminal to non-blocking mode
- * and poll that way, fails; it will just for canonical mode input.
- * We should probably use this mechanism if the user has set non-canonical
- * mode, in which case testing here for isatty() and ~ICANON would be
- * better than testing whether bin_read() set it, but for now we've got
- * enough problems.
- *
- * Under Cygwin, you won't be surprised to here, this mechanism,
- * although present, doesn't work, and we *have* to use ordinary
- * non-blocking reads to find out if there is a character present
- * in non-canonical mode.
- *
- * I am assuming Solaris is nearer the UNIX norm. This is not necessarily
- * as plausible as it sounds, but it seems the right way to guess.
- * pws 2000/06/26
- */
- if (polltty && fd >= 0) {
- gettyinfo(&ti);
- if ((polltty = ti.tio.c_cc[VMIN])) {
- ti.tio.c_cc[VMIN] = 0;
- /* termios timeout is 10ths of a second */
- ti.tio.c_cc[VTIME] = (int) (microseconds / (zlong)100000);
- settyinfo(&ti);
- }
- }
-#else
- polltty = 0;
-#endif
-#ifdef HAVE_SELECT
- expire_tv.tv_sec = (int) (microseconds / (zlong)1000000);
- expire_tv.tv_usec = microseconds % (zlong)1000000;
- FD_ZERO(&foofd);
- if (fd > -1) {
- FD_SET(fd, &foofd);
- ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
- } else
- ret = select(0, NULL, NULL, NULL, &expire_tv);
-#else
- if (fd < 0) {
- /* OK, can't do that. Just quietly sleep for a second. */
- sleep(1);
- return 1;
- }
-#ifdef FIONREAD
- if (ioctl(fd, FIONREAD, (char *) &val) == 0)
- ret = (val > 0);
-#endif
-#endif
-
- if (fd >= 0 && ret < 0 && !errflag) {
- /*
- * Final attempt: set non-blocking read and try to read a character.
- * Praise Bill, this works under Cygwin (nothing else seems to).
- */
- if ((polltty || setblock_fd(0, fd, &mode)) && read(fd, &c, 1) > 0) {
- *readchar = c;
- ret = 1;
- }
- if (mode != -1)
- fcntl(fd, F_SETFL, mode);
- }
-#ifdef HAS_TIO
- if (polltty) {
- ti.tio.c_cc[VMIN] = 1;
- ti.tio.c_cc[VTIME] = 0;
- settyinfo(&ti);
- }
-#endif
- return (ret > 0);
-}
-
-/*
- * Sleep for the given number of microseconds --- must be within
- * range of a long at the moment, but this is only used for
- * limited internal purposes.
- */
-
-/**/
-int
-zsleep(long us)
-{
-#ifdef HAVE_NANOSLEEP
- struct timespec sleeptime;
-
- sleeptime.tv_sec = (time_t)us / (time_t)1000000;
- sleeptime.tv_nsec = (us % 1000000L) * 1000L;
- for (;;) {
- struct timespec rem;
- int ret = nanosleep(&sleeptime, &rem);
-
- if (ret == 0)
- return 1;
- else if (errno != EINTR)
- return 0;
- sleeptime = rem;
- }
-#else
- int dummy;
- return read_poll(-1, &dummy, 0, us);
-#endif
-}
-
-/**
- * Sleep for time (fairly) randomly up to max_us microseconds.
- * Don't let the wallclock time extend beyond end_time.
- * Return 1 if that seemed to work, else 0.
- *
- * For best results max_us should be a multiple of 2**16 or large
- * enough that it doesn't matter.
- */
-
-/**/
-int
-zsleep_random(long max_us, time_t end_time)
-{
- long r;
- time_t now = time(NULL);
-
- /*
- * Randomish backoff. Doesn't need to be fundamentally
- * unpredictable, just probably unlike the value another
- * exiting shell is using. On some systems the bottom 16
- * bits aren't that random but the use here doesn't
- * really care.
- */
- r = (long)(rand() & 0xFFFF);
- /*
- * Turn this into a fraction of sleep_us. Again, this
- * doesn't need to be particularly accurate and the base time
- * is sufficient that we can do the division first and not
- * worry about the range.
- */
- r = (max_us >> 16) * r;
- /*
- * Don't sleep beyond timeout.
- * Not that important as timeout is ridiculously long, but
- * if there's an interface, interface to it...
- */
- while (r && now + (time_t)(r / 1000000) > end_time)
- r >>= 1;
- if (r) /* pedantry */
- return zsleep(r);
- return 0;
-}
-
-/**/
-int
-checkrmall(char *s)
-{
- DIR *rmd;
- int count = 0;
- if (!shout)
- return 1;
- if (*s != '/') {
- if (pwd[1])
- s = zhtricat(pwd, "/", s);
- else
- s = dyncat("/", s);
- }
- const int max_count = 100;
- if ((rmd = opendir(unmeta(s)))) {
- int ignoredots = !isset(GLOBDOTS);
- char *fname;
-
- while ((fname = zreaddir(rmd, 1))) {
- if (ignoredots && *fname == '.')
- continue;
- count++;
- if (count > max_count)
- break;
- }
- closedir(rmd);
- }
- if (count > max_count)
- fprintf(shout, "zsh: sure you want to delete more than %d files in ",
- max_count);
- else if (count == 1)
- fprintf(shout, "zsh: sure you want to delete the only file in ");
- else if (count > 0)
- fprintf(shout, "zsh: sure you want to delete all %d files in ",
- count);
- else {
- /* We don't know how many files the glob will expand to; see 41707. */
- fprintf(shout, "zsh: sure you want to delete all the files in ");
- }
- nicezputs(s, shout);
- if(isset(RMSTARWAIT)) {
- fputs("? (waiting ten seconds)", shout);
- fflush(shout);
- zbeep();
- sleep(10);
- fputc('\n', shout);
- }
- if (errflag)
- return 0;
- fputs(" [yn]? ", shout);
- fflush(shout);
- zbeep();
- return (getquery("ny", 1) == 'y');
-}
-
-/**/
-mod_export ssize_t
-read_loop(int fd, char *buf, size_t len)
-{
- ssize_t got = len;
-
- while (1) {
- ssize_t ret = read(fd, buf, len);
- if (ret == len)
- break;
- if (ret <= 0) {
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- if (fd != SHTTY)
- zwarn("read failed: %e", errno);
- }
- return ret;
- }
- buf += ret;
- len -= ret;
- }
-
- return got;
-}
-
-/**/
-mod_export ssize_t
-write_loop(int fd, const char *buf, size_t len)
-{
- ssize_t wrote = len;
-
- while (1) {
- ssize_t ret = write(fd, buf, len);
- if (ret == len)
- break;
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- if (fd != SHTTY)
- zwarn("write failed: %e", errno);
- return -1;
- }
- buf += ret;
- len -= ret;
- }
-
- return wrote;
-}
-
-static int
-read1char(int echo)
-{
- char c;
- int q = queue_signal_level();
-
- dont_queue_signals();
- while (read(SHTTY, &c, 1) != 1) {
- if (errno != EINTR || errflag || retflag || breaks || contflag) {
- restore_queue_signals(q);
- return -1;
- }
- }
- restore_queue_signals(q);
- if (echo)
- write_loop(SHTTY, &c, 1);
- return STOUC(c);
-}
-
-/**/
-mod_export int
-noquery(int purge)
-{
- int val = 0;
-
-#ifdef FIONREAD
- char c;
-
- ioctl(SHTTY, FIONREAD, (char *)&val);
- if (purge) {
- for (; val; val--) {
- if (read(SHTTY, &c, 1) != 1) {
- /* Do nothing... */
- }
- }
- }
-#endif
-
- return val;
-}
-
-/**/
-int
-getquery(char *valid_chars, int purge)
-{
- int c, d, nl = 0;
- int isem = !strcmp(term, "emacs");
- struct ttyinfo ti;
-
- attachtty(mypgrp);
-
- gettyinfo(&ti);
-#ifdef HAS_TIO
- ti.tio.c_lflag &= ~ECHO;
- if (!isem) {
- ti.tio.c_lflag &= ~ICANON;
- ti.tio.c_cc[VMIN] = 1;
- ti.tio.c_cc[VTIME] = 0;
- }
-#else
- ti.sgttyb.sg_flags &= ~ECHO;
- if (!isem)
- ti.sgttyb.sg_flags |= CBREAK;
-#endif
- settyinfo(&ti);
-
- if (noquery(purge)) {
- if (!isem)
- settyinfo(&shttyinfo);
- write_loop(SHTTY, "n\n", 2);
- return 'n';
- }
-
- while ((c = read1char(0)) >= 0) {
- if (c == 'Y')
- c = 'y';
- else if (c == 'N')
- c = 'n';
- if (!valid_chars)
- break;
- if (c == '\n') {
- c = *valid_chars;
- nl = 1;
- break;
- }
- if (strchr(valid_chars, c)) {
- nl = 1;
- break;
- }
- zbeep();
- }
- if (c >= 0) {
- char buf = (char)c;
- write_loop(SHTTY, &buf, 1);
- }
- if (nl)
- write_loop(SHTTY, "\n", 1);
-
- if (isem) {
- if (c != '\n')
- while ((d = read1char(1)) >= 0 && d != '\n');
- } else {
- if (c != '\n' && !valid_chars) {
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE) && c >= 0) {
- /*
- * No waiting for a valid character, and no draining;
- * we should ensure we haven't stopped in the middle
- * of a multibyte character.
- */
- mbstate_t mbs;
- char cc = (char)c;
- memset(&mbs, 0, sizeof(mbs));
- for (;;) {
- size_t ret = mbrlen(&cc, 1, &mbs);
-
- if (ret != MB_INCOMPLETE)
- break;
- c = read1char(1);
- if (c < 0)
- break;
- cc = (char)c;
- }
- }
-#endif
- write_loop(SHTTY, "\n", 1);
- }
- }
- settyinfo(&shttyinfo);
- return c;
-}
-
-static int d;
-static char *guess, *best;
-static Patprog spckpat, spnamepat;
-
-/**/
-static void
-spscan(HashNode hn, UNUSED(int scanflags))
-{
- int nd;
-
- if (spckpat && pattry(spckpat, hn->nam))
- return;
-
- nd = spdist(hn->nam, guess, (int) strlen(guess) / 4 + 1);
- if (nd <= d) {
- best = hn->nam;
- d = nd;
- }
-}
-
-/* spellcheck a word */
-/* fix s ; if hist is nonzero, fix the history list too */
-
-/**/
-mod_export void
-spckword(char **s, int hist, int cmd, int ask)
-{
- char *t, *correct_ignore;
- char ic = '\0';
- int preflen = 0;
- int autocd = cmd && isset(AUTOCD) && strcmp(*s, ".") && strcmp(*s, "..");
-
- if ((histdone & HISTFLAG_NOEXEC) || **s == '-' || **s == '%')
- return;
- if (!strcmp(*s, "in"))
- return;
- if (!(*s)[0] || !(*s)[1])
- return;
- if (cmd) {
- if (shfunctab->getnode(shfunctab, *s) ||
- builtintab->getnode(builtintab, *s) ||
- cmdnamtab->getnode(cmdnamtab, *s) ||
- aliastab->getnode(aliastab, *s) ||
- reswdtab->getnode(reswdtab, *s))
- return;
- else if (isset(HASHLISTALL)) {
- cmdnamtab->filltable(cmdnamtab);
- if (cmdnamtab->getnode(cmdnamtab, *s))
- return;
- }
- }
- t = *s;
- if (*t == Tilde || *t == Equals || *t == String)
- t++;
- for (; *t; t++)
- if (itok(*t))
- return;
- best = NULL;
- for (t = *s; *t; t++)
- if (*t == '/')
- break;
- if (**s == Tilde && !*t)
- return;
-
- if ((correct_ignore = getsparam("CORRECT_IGNORE")) != NULL) {
- tokenize(correct_ignore = dupstring(correct_ignore));
- remnulargs(correct_ignore);
- spckpat = patcompile(correct_ignore, 0, NULL);
- } else
- spckpat = NULL;
-
- if ((correct_ignore = getsparam("CORRECT_IGNORE_FILE")) != NULL) {
- tokenize(correct_ignore = dupstring(correct_ignore));
- remnulargs(correct_ignore);
- spnamepat = patcompile(correct_ignore, 0, NULL);
- } else
- spnamepat = NULL;
-
- if (**s == String && !*t) {
- guess = *s + 1;
- if (itype_end(guess, IIDENT, 1) == guess)
- return;
- ic = String;
- d = 100;
- scanhashtable(paramtab, 1, 0, 0, spscan, 0);
- } else if (**s == Equals) {
- if (*t)
- return;
- if (hashcmd(guess = *s + 1, pathchecked))
- return;
- d = 100;
- ic = Equals;
- scanhashtable(aliastab, 1, 0, 0, spscan, 0);
- scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
- } else {
- guess = *s;
- if (*guess == Tilde || *guess == String) {
- int ne;
- ic = *guess;
- if (!*++t)
- return;
- guess = dupstring(guess);
- ne = noerrs;
- noerrs = 2;
- singsub(&guess);
- noerrs = ne;
- if (!guess)
- return;
- preflen = strlen(guess) - strlen(t);
- }
- if (access(unmeta(guess), F_OK) == 0)
- return;
- best = spname(guess);
- if (!*t && cmd) {
- if (hashcmd(guess, pathchecked))
- return;
- d = 100;
- scanhashtable(reswdtab, 1, 0, 0, spscan, 0);
- scanhashtable(aliastab, 1, 0, 0, spscan, 0);
- scanhashtable(shfunctab, 1, 0, 0, spscan, 0);
- scanhashtable(builtintab, 1, 0, 0, spscan, 0);
- scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
- if (autocd) {
- char **pp;
- for (pp = cdpath; *pp; pp++) {
- char bestcd[PATH_MAX + 1];
- int thisdist;
- /* Less than d here, instead of less than or equal *
- * as used in spscan(), so that an autocd is chosen *
- * only when it is better than anything so far, and *
- * so we prefer directories earlier in the cdpath. */
- if ((thisdist = mindist(*pp, *s, bestcd, 1)) < d) {
- best = dupstring(bestcd);
- d = thisdist;
- }
- }
- }
- }
- }
- if (errflag)
- return;
- if (best && (int)strlen(best) > 1 && strcmp(best, guess)) {
- int x;
- if (ic) {
- char *u;
- if (preflen) {
- /* do not correct the result of an expansion */
- if (strncmp(guess, best, preflen))
- return;
- /* replace the temporarily expanded prefix with the original */
- u = (char *) zhalloc(t - *s + strlen(best + preflen) + 1);
- strncpy(u, *s, t - *s);
- strcpy(u + (t - *s), best + preflen);
- } else {
- u = (char *) zhalloc(strlen(best) + 2);
- *u = '\0';
- strcpy(u + 1, best);
- }
- best = u;
- guess = *s;
- *guess = *best = ztokens[ic - Pound];
- }
- if (ask) {
- if (noquery(0)) {
- x = 'n';
- } else if (shout) {
- char *pptbuf;
- pptbuf = promptexpand(sprompt, 0, best, guess, NULL);
- zputs(pptbuf, shout);
- free(pptbuf);
- fflush(shout);
- zbeep();
- x = getquery("nyae", 0);
- if (cmd && x == 'n')
- pathchecked = path;
- } else
- x = 'n';
- } else
- x = 'y';
- if (x == 'y') {
- *s = dupstring(best);
- if (hist)
- hwrep(best);
- } else if (x == 'a') {
- histdone |= HISTFLAG_NOEXEC;
- } else if (x == 'e') {
- histdone |= HISTFLAG_NOEXEC | HISTFLAG_RECALL;
- }
- if (ic)
- **s = ic;
- }
-}
-
-/*
- * Helper for ztrftime. Called with a pointer to the length left
- * in the buffer, and a new string length to decrement from that.
- * Returns 0 if the new length fits, 1 otherwise. We assume a terminating
- * NUL and return 1 if that doesn't fit.
- */
-
-static int
-ztrftimebuf(int *bufsizeptr, int decr)
-{
- if (*bufsizeptr <= decr)
- return 1;
- *bufsizeptr -= decr;
- return 0;
-}
-
-/*
- * Like the system function, this returns the number of characters
- * copied, not including the terminating NUL. This may be zero
- * if the string didn't fit.
- *
- * As an extension, try to detect an error in strftime --- typically
- * not enough memory --- and return -1. Not guaranteed to be portable,
- * since the strftime() interface doesn't make any guarantees about
- * the state of the buffer if it returns zero.
- *
- * fmt is metafied, but we need to unmetafy it on the fly to
- * pass into strftime / combine with the output from strftime.
- * The return value in buf is not metafied.
- */
-
-/**/
-mod_export int
-ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long nsec)
-{
- int hr12;
-#ifdef HAVE_STRFTIME
- int decr;
- char *fmtstart;
-#else
- static char *astr[] =
- {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- static char *estr[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec"};
-#endif
- char *origbuf = buf;
-
-
- while (*fmt) {
- if (*fmt == Meta) {
- int chr = fmt[1] ^ 32;
- if (ztrftimebuf(&bufsize, 1))
- return -1;
- *buf++ = chr;
- fmt += 2;
- } else if (*fmt == '%') {
- int strip;
- int digs = 3;
-
-#ifdef HAVE_STRFTIME
- fmtstart =
-#endif
- fmt++;
-
- if (*fmt == '-') {
- strip = 1;
- fmt++;
- } else
- strip = 0;
- if (idigit(*fmt)) {
- /* Digit --- only useful with . */
- char *dstart = fmt;
- char *dend = fmt+1;
- while (idigit(*dend))
- dend++;
- if (*dend == '.') {
- fmt = dend;
- digs = atoi(dstart);
- }
- }
- /*
- * Assume this format will take up at least two
- * characters. Not always true, but if that matters
- * we are so close to the edge it's not a big deal.
- * Fix up some longer cases specially when we get to them.
- */
- if (ztrftimebuf(&bufsize, 2))
- return -1;
-#ifdef HAVE_STRFTIME
- /* Our internal handling doesn't handle padding and other gnu extensions,
- * so here we detect them and pass over to strftime(). We don't want
- * to do this unconditionally though, as we have some extensions that
- * strftime() doesn't have (%., %f, %L and %K) */
-morefmt:
- if (!((fmt - fmtstart == 1) || (fmt - fmtstart == 2 && strip) || *fmt == '.')) {
- while (*fmt && strchr("OE^#_-0123456789", *fmt))
- fmt++;
- if (*fmt) {
- fmt++;
- goto strftimehandling;
- }
- }
-#endif
- switch (*fmt++) {
- case '.':
- if (ztrftimebuf(&bufsize, digs))
- return -1;
- if (digs > 9)
- digs = 9;
- if (digs < 9) {
- int trunc;
- for (trunc = 8 - digs; trunc; trunc--)
- nsec /= 10;
- nsec = (nsec + 8) / 10;
- }
- sprintf(buf, "%0*ld", digs, nsec);
- buf += digs;
- break;
- case '\0':
- /* Guard against premature end of string */
- *buf++ = '%';
- fmt--;
- break;
- case 'f':
- strip = 1;
- /* FALLTHROUGH */
- case 'e':
- if (tm->tm_mday > 9)
- *buf++ = '0' + tm->tm_mday / 10;
- else if (!strip)
- *buf++ = ' ';
- *buf++ = '0' + tm->tm_mday % 10;
- break;
- case 'K':
- strip = 1;
- /* FALLTHROUGH */
- case 'H':
- case 'k':
- if (tm->tm_hour > 9)
- *buf++ = '0' + tm->tm_hour / 10;
- else if (!strip) {
- if (fmt[-1] == 'H')
- *buf++ = '0';
- else
- *buf++ = ' ';
- }
- *buf++ = '0' + tm->tm_hour % 10;
- break;
- case 'L':
- strip = 1;
- /* FALLTHROUGH */
- case 'l':
- hr12 = tm->tm_hour % 12;
- if (hr12 == 0)
- hr12 = 12;
- if (hr12 > 9)
- *buf++ = '1';
- else if (!strip)
- *buf++ = ' ';
-
- *buf++ = '0' + (hr12 % 10);
- break;
- case 'd':
- if (tm->tm_mday > 9 || !strip)
- *buf++ = '0' + tm->tm_mday / 10;
- *buf++ = '0' + tm->tm_mday % 10;
- break;
- case 'm':
- if (tm->tm_mon > 8 || !strip)
- *buf++ = '0' + (tm->tm_mon + 1) / 10;
- *buf++ = '0' + (tm->tm_mon + 1) % 10;
- break;
- case 'M':
- if (tm->tm_min > 9 || !strip)
- *buf++ = '0' + tm->tm_min / 10;
- *buf++ = '0' + tm->tm_min % 10;
- break;
- case 'N':
- if (ztrftimebuf(&bufsize, 9))
- return -1;
- sprintf(buf, "%09ld", nsec);
- buf += 9;
- break;
- case 'S':
- if (tm->tm_sec > 9 || !strip)
- *buf++ = '0' + tm->tm_sec / 10;
- *buf++ = '0' + tm->tm_sec % 10;
- break;
- case 'y':
- if (tm->tm_year > 9 || !strip)
- *buf++ = '0' + (tm->tm_year / 10) % 10;
- *buf++ = '0' + tm->tm_year % 10;
- break;
-#ifndef HAVE_STRFTIME
- case 'Y':
- {
- int year, digits, testyear;
- year = tm->tm_year + 1900;
- digits = 1;
- testyear = year;
- while (testyear > 9) {
- digits++;
- testyear /= 10;
- }
- if (ztrftimebuf(&bufsize, digits))
- return -1;
- sprintf(buf, "%d", year);
- buf += digits;
- break;
- }
- case 'a':
- if (ztrftimebuf(&bufsize, strlen(astr[tm->tm_wday]) - 2))
- return -1;
- strucpy(&buf, astr[tm->tm_wday]);
- break;
- case 'b':
- if (ztrftimebuf(&bufsize, strlen(estr[tm->tm_mon]) - 2))
- return -1;
- strucpy(&buf, estr[tm->tm_mon]);
- break;
- case 'p':
- *buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
- *buf++ = 'm';
- break;
- default:
- *buf++ = '%';
- if (fmt[-1] != '%')
- *buf++ = fmt[-1];
-#else
- case 'E':
- case 'O':
- case '^':
- case '#':
- case '_':
- case '-':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- goto morefmt;
-strftimehandling:
- default:
- /*
- * Remember we've already allowed for two characters
- * in the accounting in bufsize (but nowhere else).
- */
- {
- char origchar = fmt[-1];
- int size = fmt - fmtstart;
- char *tmp, *last;
- tmp = zhalloc(size + 1);
- strncpy(tmp, fmtstart, size);
- last = fmt-1;
- if (*last == Meta) {
- /*
- * This is for consistency in counting:
- * a metafiable character isn't actually
- * a valid strftime descriptor.
- *
- * Previous characters were explicitly checked,
- * so can't be metafied.
- */
- *last = *++fmt ^ 32;
- }
- tmp[size] = '\0';
- *buf = '\1';
- if (!strftime(buf, bufsize + 2, tmp, tm))
- {
- /*
- * Some locales don't have strings for
- * AM/PM, so empty output is valid.
- */
- if (*buf || (origchar != 'p' && origchar != 'P')) {
- if (*buf) {
- buf[0] = '\0';
- return -1;
- }
- return 0;
- }
- }
- decr = strlen(buf);
- buf += decr;
- bufsize -= decr - 2;
- }
-#endif
- break;
- }
- } else {
- if (ztrftimebuf(&bufsize, 1))
- return -1;
- *buf++ = *fmt++;
- }
- }
- *buf = '\0';
- return buf - origbuf;
-}
-
-/**/
-mod_export char *
-zjoin(char **arr, int delim, int heap)
-{
- int len = 0;
- char **s, *ret, *ptr;
-
- for (s = arr; *s; s++)
- len += strlen(*s) + 1 + (imeta(delim) ? 1 : 0);
- if (!len)
- return heap? "" : ztrdup("");
- ptr = ret = (char *) (heap ? zhalloc(len) : zalloc(len));
- for (s = arr; *s; s++) {
- strucpy(&ptr, *s);
- if (imeta(delim)) {
- *ptr++ = Meta;
- *ptr++ = delim ^ 32;
- }
- else
- *ptr++ = delim;
- }
- ptr[-1 - (imeta(delim) ? 1 : 0)] = '\0';
- return ret;
-}
-
-/* Split a string containing a colon separated list *
- * of items into an array of strings. */
-
-/**/
-mod_export char **
-colonsplit(char *s, int uniq)
-{
- int ct;
- char *t, **ret, **ptr, **p;
-
- for (t = s, ct = 0; *t; t++) /* count number of colons */
- if (*t == ':')
- ct++;
- ptr = ret = (char **) zalloc(sizeof(char *) * (ct + 2));
-
- t = s;
- do {
- s = t;
- /* move t to point at next colon */
- for (; *t && *t != ':'; t++);
- if (uniq)
- for (p = ret; p < ptr; p++)
- if ((int)strlen(*p) == t - s && ! strncmp(*p, s, t - s))
- goto cont;
- *ptr = (char *) zalloc((t - s) + 1);
- ztrncpy(*ptr++, s, t - s);
- cont: ;
- }
- while (*t++);
- *ptr = NULL;
- return ret;
-}
-
-/**/
-static int
-skipwsep(char **s)
-{
- char *t = *s;
- int i = 0;
-
- /*
- * Don't need to handle mutlibyte characters, they can't
- * be IWSEP. Do need to check for metafication.
- */
- while (*t && iwsep(*t == Meta ? t[1] ^ 32 : *t)) {
- if (*t == Meta)
- t++;
- t++;
- i++;
- }
- *s = t;
- return i;
-}
-
-/*
- * haven't worked out what allownull does; it's passed down from
- * sepsplit but all the cases it's used are either 0 or 1 without
- * a comment. it seems to be something to do with the `nulstring'
- * which i think is some kind of a metafication thing, so probably
- * allownull's value is associated with whether we are using
- * metafied strings.
- * see findsep() below for handling of `quote' argument
- */
-
-/**/
-mod_export char **
-spacesplit(char *s, int allownull, int heap, int quote)
-{
- char *t, **ret, **ptr;
- int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
- char *(*dup)(const char *) = (heap ? dupstring : ztrdup);
-
- /* ### TODO: s/calloc/alloc/ */
- ptr = ret = (char **) (heap ? hcalloc(l) : zshcalloc(l));
-
- if (quote) {
- /*
- * we will be stripping quoted separators by hacking string,
- * so make sure it's hackable.
- */
- s = dupstring(s);
- }
-
- t = s;
- skipwsep(&s);
- MB_METACHARINIT();
- if (*s && itype_end(s, ISEP, 1) != s)
- *ptr++ = dup(allownull ? "" : nulstring);
- else if (!allownull && t != s)
- *ptr++ = dup("");
- while (*s) {
- char *iend = itype_end(s, ISEP, 1);
- if (iend != s) {
- s = iend;
- skipwsep(&s);
- }
- else if (quote && *s == '\\') {
- s++;
- skipwsep(&s);
- }
- t = s;
- (void)findsep(&s, NULL, quote);
- if (s > t || allownull) {
- *ptr = (char *) (heap ? zhalloc((s - t) + 1) :
- zalloc((s - t) + 1));
- ztrncpy(*ptr++, t, s - t);
- } else
- *ptr++ = dup(nulstring);
- t = s;
- skipwsep(&s);
- }
- if (!allownull && t != s)
- *ptr++ = dup("");
- *ptr = NULL;
- return ret;
-}
-
-/*
- * Find a separator. Return 0 if already at separator, 1 if separator
- * found later, else -1. (Historical note: used to return length into
- * string but this is all that is necessary and is less ambiguous with
- * multibyte characters around.)
- *
- * *s is the string we are looking along, which will be updated
- * to the point we have got to.
- *
- * sep is a possibly multicharacter separator to look for. If NULL,
- * use normal separator characters. If *sep is NULL, split on individual
- * characters.
- *
- * quote is a flag that '\' should not be treated as a separator.
- * in this case we need to be able to strip the backslash directly
- * in the string, so the calling function must have sent us something
- * modifiable. currently this only works for sep == NULL. also in
- * in this case only, we need to turn \\ into \.
- */
-
-/**/
-static int
-findsep(char **s, char *sep, int quote)
-{
- /*
- */
- int i, ilen;
- char *t, *tt;
- convchar_t c;
-
- MB_METACHARINIT();
- if (!sep) {
- for (t = *s; *t; t += ilen) {
- if (quote && *t == '\\') {
- if (t[1] == '\\') {
- chuck(t);
- ilen = 1;
- continue;
- } else {
- ilen = MB_METACHARLENCONV(t+1, &c);
- if (WC_ZISTYPE(c, ISEP)) {
- chuck(t);
- /* then advance over new character, length ilen */
- } else {
- /* treat *t (backslash) as normal byte */
- if (isep(*t))
- break;
- ilen = 1;
- }
- }
- } else {
- ilen = MB_METACHARLENCONV(t, &c);
- if (WC_ZISTYPE(c, ISEP))
- break;
- }
- }
- i = (t > *s);
- *s = t;
- return i;
- }
- if (!sep[0]) {
- /*
- * NULL separator just means advance past first character,
- * if any.
- */
- if (**s) {
- *s += MB_METACHARLEN(*s);
- return 1;
- }
- return -1;
- }
- for (i = 0; **s; i++) {
- /*
- * The following works for multibyte characters by virtue of
- * the fact that sep may be a string (and we don't care how
- * it divides up, we need to match all of it).
- */
- for (t = sep, tt = *s; *t && *tt && *t == *tt; t++, tt++);
- if (!*t)
- return (i > 0);
- *s += MB_METACHARLEN(*s);
- }
- return -1;
-}
-
-/**/
-char *
-findword(char **s, char *sep)
-{
- char *r, *t;
- int sl;
-
- if (!**s)
- return NULL;
-
- if (sep) {
- sl = strlen(sep);
- r = *s;
- while (! findsep(s, sep, 0)) {
- r = *s += sl;
- }
- return r;
- }
- MB_METACHARINIT();
- for (t = *s; *t; t += sl) {
- convchar_t c;
- sl = MB_METACHARLENCONV(t, &c);
- if (!WC_ZISTYPE(c, ISEP))
- break;
- }
- *s = t;
- (void)findsep(s, sep, 0);
- return t;
-}
-
-/**/
-int
-wordcount(char *s, char *sep, int mul)
-{
- int r, sl, c;
-
- if (sep) {
- r = 1;
- sl = strlen(sep);
- for (; (c = findsep(&s, sep, 0)) >= 0; s += sl)
- if ((c || mul) && (sl || *(s + sl)))
- r++;
- } else {
- char *t = s;
-
- r = 0;
- if (mul <= 0)
- skipwsep(&s);
- if ((*s && itype_end(s, ISEP, 1) != s) ||
- (mul < 0 && t != s))
- r++;
- for (; *s; r++) {
- char *ie = itype_end(s, ISEP, 1);
- if (ie != s) {
- s = ie;
- if (mul <= 0)
- skipwsep(&s);
- }
- (void)findsep(&s, NULL, 0);
- t = s;
- if (mul <= 0)
- skipwsep(&s);
- }
- if (mul < 0 && t != s)
- r++;
- }
- return r;
-}
-
-/**/
-mod_export char *
-sepjoin(char **s, char *sep, int heap)
-{
- char *r, *p, **t;
- int l, sl;
- char sepbuf[2];
-
- if (!*s)
- return heap ? "" : ztrdup("");
- if (!sep) {
- /* optimise common case that ifs[0] is space */
- if (ifs && *ifs != ' ') {
- MB_METACHARINIT();
- sep = dupstrpfx(ifs, MB_METACHARLEN(ifs));
- } else {
- p = sep = sepbuf;
- *p++ = ' ';
- *p = '\0';
- }
- }
- sl = strlen(sep);
- for (t = s, l = 1 - sl; *t; l += strlen(*t) + sl, t++);
- r = p = (char *) (heap ? zhalloc(l) : zalloc(l));
- t = s;
- while (*t) {
- strucpy(&p, *t);
- if (*++t)
- strucpy(&p, sep);
- }
- *p = '\0';
- return r;
-}
-
-/**/
-char **
-sepsplit(char *s, char *sep, int allownull, int heap)
-{
- int n, sl;
- char *t, *tt, **r, **p;
-
- /* Null string? Treat as empty string. */
- if (s[0] == Nularg && !s[1])
- s++;
-
- if (!sep)
- return spacesplit(s, allownull, heap, 0);
-
- sl = strlen(sep);
- n = wordcount(s, sep, 1);
- r = p = (char **) (heap ? zhalloc((n + 1) * sizeof(char *)) :
- zalloc((n + 1) * sizeof(char *)));
-
- for (t = s; n--;) {
- tt = t;
- (void)findsep(&t, sep, 0);
- *p = (char *) (heap ? zhalloc(t - tt + 1) :
- zalloc(t - tt + 1));
- strncpy(*p, tt, t - tt);
- (*p)[t - tt] = '\0';
- p++;
- t += sl;
- }
- *p = NULL;
-
- return r;
-}
-
-/* Get the definition of a shell function */
-
-/**/
-mod_export Shfunc
-getshfunc(char *nam)
-{
- return (Shfunc) shfunctab->getnode(shfunctab, nam);
-}
-
-/*
- * Call the function func to substitute string orig by setting
- * the parameter reply.
- * Return the array from reply, or NULL if the function returned
- * non-zero status.
- * The returned value comes directly from the parameter and
- * so should be used before there is any chance of that
- * being changed or unset.
- * If arg1 is not NULL, it is used as an initial argument to
- * the function, with the original string as the second argument.
- */
-
-/**/
-char **
-subst_string_by_func(Shfunc func, char *arg1, char *orig)
-{
- int osc = sfcontext, osm = stopmsg, old_incompfunc = incompfunc;
- LinkList l = newlinklist();
- char **ret;
-
- addlinknode(l, func->node.nam);
- if (arg1)
- addlinknode(l, arg1);
- addlinknode(l, orig);
- sfcontext = SFC_SUBST;
- incompfunc = 0;
-
- if (doshfunc(func, l, 1))
- ret = NULL;
- else
- ret = getaparam("reply");
-
- sfcontext = osc;
- stopmsg = osm;
- incompfunc = old_incompfunc;
- return ret;
-}
-
-/**
- * Front end to subst_string_by_func to use hook-like logic.
- * name can refer to a function, and name + "_hook" can refer
- * to an array containing a list of functions. The functions
- * are tried in order until one returns success.
- */
-/**/
-char **
-subst_string_by_hook(char *name, char *arg1, char *orig)
-{
- Shfunc func;
- char **ret = NULL;
-
- if ((func = getshfunc(name))) {
- ret = subst_string_by_func(func, arg1, orig);
- }
-
- if (!ret) {
- char **arrptr;
- int namlen = strlen(name);
- VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN);
- memcpy(arrnam, name, namlen);
- memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN);
-
- if ((arrptr = getaparam(arrnam))) {
- /* Guard against internal modification of the array */
- arrptr = arrdup(arrptr);
- for (; *arrptr; arrptr++) {
- if ((func = getshfunc(*arrptr))) {
- ret = subst_string_by_func(func, arg1, orig);
- if (ret)
- break;
- }
- }
- }
- }
-
- return ret;
-}
-
-/**/
-mod_export char **
-mkarray(char *s)
-{
- char **t = (char **) zalloc((s) ? (2 * sizeof s) : (sizeof s));
-
- if ((*t = s))
- t[1] = NULL;
- return t;
-}
-
-/**/
-mod_export char **
-hmkarray(char *s)
-{
- char **t = (char **) zhalloc((s) ? (2 * sizeof s) : (sizeof s));
-
- if ((*t = s))
- t[1] = NULL;
- return t;
-}
-
-/**/
-mod_export void
-zbeep(void)
-{
- char *vb;
- queue_signals();
- if ((vb = getsparam_u("ZBEEP"))) {
- int len;
- vb = getkeystring(vb, &len, GETKEYS_BINDKEY, NULL);
- write_loop(SHTTY, vb, len);
- } else if (isset(BEEP))
- write_loop(SHTTY, "\07", 1);
- unqueue_signals();
-}
-
-/**/
-mod_export void
-freearray(char **s)
-{
- char **t = s;
-
- DPUTS(!s, "freearray() with zero argument");
-
- while (*s)
- zsfree(*s++);
- free(t);
-}
-
-/**/
-int
-equalsplit(char *s, char **t)
-{
- for (; *s && *s != '='; s++);
- if (*s == '=') {
- *s++ = '\0';
- *t = s;
- return 1;
- }
- return 0;
-}
-
-
-/* the ztypes table */
-
-/**/
-mod_export short int typtab[256];
-static int typtab_flags = 0;
-
-/* initialize the ztypes table */
-
-/**/
-void
-inittyptab(void)
-{
- int t0;
- char *s;
-
- if (!(typtab_flags & ZTF_INIT)) {
- typtab_flags = ZTF_INIT;
- if (interact && isset(SHINSTDIN))
- typtab_flags |= ZTF_INTERACT;
- }
-
- queue_signals();
-
- memset(typtab, 0, sizeof(typtab));
- for (t0 = 0; t0 != 32; t0++)
- typtab[t0] = typtab[t0 + 128] = ICNTRL;
- typtab[127] = ICNTRL;
- for (t0 = '0'; t0 <= '9'; t0++)
- typtab[t0] = IDIGIT | IALNUM | IWORD | IIDENT | IUSER;
- for (t0 = 'a'; t0 <= 'z'; t0++)
- typtab[t0] = typtab[t0 - 'a' + 'A'] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
-#ifndef MULTIBYTE_SUPPORT
- /*
- * This really doesn't seem to me the right thing to do when
- * we have multibyte character support... it was a hack to assume
- * eight bit characters `worked' for some values of work before
- * we could test for them properly. I'm not 100% convinced
- * having IIDENT here is a good idea at all, but this code
- * should disappear into history...
- */
- for (t0 = 0240; t0 != 0400; t0++)
- typtab[t0] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
-#endif
- /* typtab['.'] |= IIDENT; */ /* Allow '.' in variable names - broken */
- typtab['_'] = IIDENT | IUSER;
- typtab['-'] = typtab['.'] = typtab[STOUC(Dash)] = IUSER;
- typtab[' '] |= IBLANK | INBLANK;
- typtab['\t'] |= IBLANK | INBLANK;
- typtab['\n'] |= INBLANK;
- typtab['\0'] |= IMETA;
- typtab[STOUC(Meta) ] |= IMETA;
- typtab[STOUC(Marker)] |= IMETA;
- for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(LAST_NORMAL_TOK); t0++)
- typtab[t0] |= ITOK | IMETA;
- for (t0 = (int)STOUC(Snull); t0 <= (int)STOUC(Nularg); t0++)
- typtab[t0] |= ITOK | IMETA | INULL;
- for (s = ifs ? ifs : EMULATION(EMULATE_KSH|EMULATE_SH) ?
- DEFAULT_IFS_SH : DEFAULT_IFS; *s; s++) {
- int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
-#ifdef MULTIBYTE_SUPPORT
- if (!isascii(c)) {
- /* see comment for wordchars below */
- continue;
- }
-#endif
- if (inblank(c)) {
- if (s[1] == c)
- s++;
- else
- typtab[c] |= IWSEP;
- }
- typtab[c] |= ISEP;
- }
- for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++) {
- int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
-#ifdef MULTIBYTE_SUPPORT
- if (!isascii(c)) {
- /*
- * If we have support for multibyte characters, we don't
- * handle non-ASCII characters here; instead, we turn
- * wordchars into a wide character array.
- * (We may actually have a single-byte 8-bit character set,
- * but it works the same way.)
- */
- continue;
- }
-#endif
- typtab[c] |= IWORD;
- }
-#ifdef MULTIBYTE_SUPPORT
- set_widearray(wordchars, &wordchars_wide);
- set_widearray(ifs ? ifs : EMULATION(EMULATE_KSH|EMULATE_SH) ?
- DEFAULT_IFS_SH : DEFAULT_IFS, &ifs_wide);
-#endif
- for (s = SPECCHARS; *s; s++)
- typtab[STOUC(*s)] |= ISPECIAL;
- if (typtab_flags & ZTF_SP_COMMA)
- typtab[STOUC(',')] |= ISPECIAL;
- if (isset(BANGHIST) && bangchar && (typtab_flags & ZTF_INTERACT)) {
- typtab_flags |= ZTF_BANGCHAR;
- typtab[bangchar] |= ISPECIAL;
- } else
- typtab_flags &= ~ZTF_BANGCHAR;
- for (s = PATCHARS; *s; s++)
- typtab[STOUC(*s)] |= IPATTERN;
-
- unqueue_signals();
-}
-
-/**/
-mod_export void
-makecommaspecial(int yesno)
-{
- if (yesno != 0) {
- typtab_flags |= ZTF_SP_COMMA;
- typtab[STOUC(',')] |= ISPECIAL;
- } else {
- typtab_flags &= ~ZTF_SP_COMMA;
- typtab[STOUC(',')] &= ~ISPECIAL;
- }
-}
-
-/**/
-mod_export void
-makebangspecial(int yesno)
-{
- /* Name and call signature for congruence with makecommaspecial(),
- * but in this case when yesno is nonzero we defer to the state
- * saved by inittyptab().
- */
- if (yesno == 0) {
- typtab[bangchar] &= ~ISPECIAL;
- } else if (typtab_flags & ZTF_BANGCHAR) {
- typtab[bangchar] |= ISPECIAL;
- }
-}
-
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/* A wide-character version of the iblank() macro. */
-/**/
-mod_export int
-wcsiblank(wint_t wc)
-{
- if (iswspace(wc) && wc != L'\n')
- return 1;
- return 0;
-}
-
-/*
- * zistype macro extended to support wide characters.
- * Works for IIDENT, IWORD, IALNUM, ISEP.
- * We don't need this for IWSEP because that only applies to
- * a fixed set of ASCII characters.
- * Note here that use of multibyte mode is not tested:
- * that's because for ZLE this is unconditional,
- * not dependent on the option. The caller must decide.
- */
-
-/**/
-mod_export int
-wcsitype(wchar_t c, int itype)
-{
- int len;
- mbstate_t mbs;
- VARARR(char, outstr, MB_CUR_MAX);
-
- if (!isset(MULTIBYTE))
- return zistype(c, itype);
-
- /*
- * Strategy: the shell requires that the multibyte representation
- * be an extension of ASCII. So see if converting the character
- * produces an ASCII character. If it does, use zistype on that.
- * If it doesn't, use iswalnum on the original character.
- * If that fails, resort to the appropriate wide character array.
- */
- memset(&mbs, 0, sizeof(mbs));
- len = wcrtomb(outstr, c, &mbs);
-
- if (len == 0) {
- /* NULL is special */
- return zistype(0, itype);
- } else if (len == 1 && isascii(outstr[0])) {
- return zistype(outstr[0], itype);
- } else {
- switch (itype) {
- case IIDENT:
- if (!isset(POSIXIDENTIFIERS))
- return 0;
- return iswalnum(c);
-
- case IWORD:
- if (iswalnum(c))
- return 1;
- /*
- * If we are handling combining characters, any punctuation
- * characters with zero width needs to be considered part of
- * a word. If we are not handling combining characters then
- * logically they are still part of the word, even if they
- * don't get displayed properly, so always do this.
- */
- if (IS_COMBINING(c))
- return 1;
- return !!wmemchr(wordchars_wide.chars, c, wordchars_wide.len);
-
- case ISEP:
- return !!wmemchr(ifs_wide.chars, c, ifs_wide.len);
-
- default:
- return iswalnum(c);
- }
- }
-}
-
-/**/
-#endif
-
-
-/*
- * Find the end of a set of characters in the set specified by itype;
- * one of IALNUM, IIDENT, IWORD or IUSER. For non-ASCII characters, we assume
- * alphanumerics are part of the set, with the exception that
- * identifiers are not treated that way if POSIXIDENTIFIERS is set.
- *
- * See notes above for identifiers.
- * Returns the same pointer as passed if not on an identifier character.
- * If "once" is set, just test the first character, i.e. (outptr !=
- * inptr) tests whether the first character is valid in an identifier.
- *
- * Currently this is only called with itype IIDENT, IUSER or ISEP.
- */
-
-/**/
-mod_export char *
-itype_end(const char *ptr, int itype, int once)
-{
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE) &&
- (itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
- mb_charinit();
- while (*ptr) {
- int len;
- if (itok(*ptr)) {
- /* Not untokenised yet --- can happen in raw command line */
- len = 1;
- if (!zistype(*ptr,itype))
- break;
- } else {
- wint_t wc;
- len = mb_metacharlenconv(ptr, &wc);
-
- if (!len)
- break;
-
- if (wc == WEOF) {
- /* invalid, treat as single character */
- int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
- /* in this case non-ASCII characters can't match */
- if (chr > 127 || !zistype(chr,itype))
- break;
- } else if (len == 1 && isascii(*ptr)) {
- /* ASCII: can't be metafied, use standard test */
- if (!zistype(*ptr,itype))
- break;
- } else {
- /*
- * Valid non-ASCII character.
- */
- switch (itype) {
- case IWORD:
- if (!iswalnum(wc) &&
- !wmemchr(wordchars_wide.chars, wc,
- wordchars_wide.len))
- return (char *)ptr;
- break;
-
- case ISEP:
- if (!wmemchr(ifs_wide.chars, wc, ifs_wide.len))
- return (char *)ptr;
- break;
-
- default:
- if (!iswalnum(wc))
- return (char *)ptr;
- }
- }
- }
- ptr += len;
-
- if (once)
- break;
- }
- } else
-#endif
- for (;;) {
- int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
- if (!zistype(chr,itype))
- break;
- ptr += (*ptr == Meta) ? 2 : 1;
-
- if (once)
- break;
- }
-
- /*
- * Nasty. The first argument is const char * because we
- * don't modify it here. However, we really want to pass
- * back the same type as was passed down, to allow idioms like
- * p = itype_end(p, IIDENT, 0);
- * So returning a const char * isn't really the right thing to do.
- * Without having two different functions the following seems
- * to be the best we can do.
- */
- return (char *)ptr;
-}
-
-/**/
-mod_export char **
-arrdup(char **s)
-{
- char **x, **y;
-
- y = x = (char **) zhalloc(sizeof(char *) * (arrlen(s) + 1));
-
- while ((*x++ = dupstring(*s++)));
-
- return y;
-}
-
-/* Duplicate at most max elements of the array s with heap memory */
-
-/**/
-mod_export char **
-arrdup_max(char **s, unsigned max)
-{
- char **x, **y, **send;
- int len = 0;
-
- if (max)
- len = arrlen(s);
-
- /* Limit has sense only if not equal to len */
- if (max > len)
- max = len;
-
- y = x = (char **) zhalloc(sizeof(char *) * (max + 1));
-
- send = s + max;
- while (s < send)
- *x++ = dupstring(*s++);
- *x = NULL;
-
- return y;
-}
-
-/**/
-mod_export char **
-zarrdup(char **s)
-{
- char **x, **y;
-
- y = x = (char **) zalloc(sizeof(char *) * (arrlen(s) + 1));
-
- while ((*x++ = ztrdup(*s++)));
-
- return y;
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/**/
-mod_export wchar_t **
-wcs_zarrdup(wchar_t **s)
-{
- wchar_t **x, **y;
-
- y = x = (wchar_t **) zalloc(sizeof(wchar_t *) * (arrlen((char **)s) + 1));
-
- while ((*x++ = wcs_ztrdup(*s++)));
-
- return y;
-}
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/**/
-static char *
-spname(char *oldname)
-{
- char *p, spnameguess[PATH_MAX + 1], spnamebest[PATH_MAX + 1];
- static char newname[PATH_MAX + 1];
- char *new = newname, *old = oldname;
- int bestdist = 0, thisdist, thresh, maxthresh = 0;
-
- /* This loop corrects each directory component of the path, stopping *
- * when any correction distance would exceed the distance threshold. *
- * NULL is returned only if the first component cannot be corrected; *
- * otherwise a copy of oldname with a corrected prefix is returned. *
- * Rationale for this, if there ever was any, has been forgotten. */
- for (;;) {
- while (*old == '/') {
- if (new >= newname + sizeof(newname) - 1)
- return NULL;
- *new++ = *old++;
- }
- *new = '\0';
- if (*old == '\0')
- return newname;
- p = spnameguess;
- for (; *old != '/' && *old != '\0'; old++)
- if (p < spnameguess + PATH_MAX)
- *p++ = *old;
- *p = '\0';
- /* Every component is allowed a single distance 2 correction or two *
- * distance 1 corrections. Longer ones get additional corrections. */
- thresh = (int)(p - spnameguess) / 4 + 1;
- if (thresh < 3)
- thresh = 3;
- else if (thresh > 100)
- thresh = 100;
- thisdist = mindist(newname, spnameguess, spnamebest, *old == '/');
- if (thisdist >= thresh) {
- /* The next test is always true, except for the first path *
- * component. We could initialize bestdist to some large *
- * constant instead, and then compare to that constant here, *
- * because an invariant is that we've never exceeded the *
- * threshold for any component so far; but I think that looks *
- * odd to the human reader, and we may make use of the total *
- * distance for all corrections at some point in the future. */
- if (bestdist < maxthresh) {
- struncpy(&new, spnameguess, sizeof(newname) - (new - newname));
- struncpy(&new, old, sizeof(newname) - (new - newname));
- return (new >= newname + sizeof(newname) -1) ? NULL : newname;
- } else
- return NULL;
- } else {
- maxthresh = bestdist + thresh;
- bestdist += thisdist;
- }
- for (p = spnamebest; (*new = *p++);) {
- if (new >= newname + sizeof(newname) - 1)
- return NULL;
- new++;
- }
- }
-}
-
-/**/
-static int
-mindist(char *dir, char *mindistguess, char *mindistbest, int wantdir)
-{
- int mindistd, nd;
- DIR *dd;
- char *fn;
- char *buf;
- struct stat st;
- size_t dirlen;
-
- if (dir[0] == '\0')
- dir = ".";
- mindistd = 100;
-
- if (!(buf = zalloc((dirlen = strlen(dir)) + strlen(mindistguess) + 2)))
- return 0;
- sprintf(buf, "%s/%s", dir, mindistguess);
-
- if (stat(unmeta(buf), &st) == 0 && (!wantdir || S_ISDIR(st.st_mode))) {
- strcpy(mindistbest, mindistguess);
- free(buf);
- return 0;
- }
-
- if ((dd = opendir(unmeta(dir)))) {
- while ((fn = zreaddir(dd, 0))) {
- if (spnamepat && pattry(spnamepat, fn))
- continue;
- nd = spdist(fn, mindistguess,
- (int)strlen(mindistguess) / 4 + 1);
- if (nd <= mindistd) {
- if (wantdir) {
- if (!(buf = zrealloc(buf, dirlen + strlen(fn) + 2)))
- continue;
- sprintf(buf, "%s/%s", dir, fn);
- if (stat(unmeta(buf), &st) != 0 || !S_ISDIR(st.st_mode))
- continue;
- }
- strcpy(mindistbest, fn);
- mindistd = nd;
- if (mindistd == 0)
- break;
- }
- }
- closedir(dd);
- }
- free(buf);
- return mindistd;
-}
-
-/**/
-static int
-spdist(char *s, char *t, int thresh)
-{
- /* TODO: Correction for non-ASCII and multibyte-input keyboards. */
- char *p, *q;
- const char qwertykeymap[] =
- "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t1234567890-=\t\
-\tqwertyuiop[]\t\
-\tasdfghjkl;'\n\t\
-\tzxcvbnm,./\t\t\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t!@#$%^&*()_+\t\
-\tQWERTYUIOP{}\t\
-\tASDFGHJKL:\"\n\t\
-\tZXCVBNM<>?\n\n\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
- const char dvorakkeymap[] =
- "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t1234567890[]\t\
-\t',.pyfgcrl/=\t\
-\taoeuidhtns-\n\t\
-\t;qjkxbmwvz\t\t\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t!@#$%^&*(){}\t\
-\t\"<>PYFGCRL?+\t\
-\tAOEUIDHTNS_\n\t\
-\t:QJKXBMWVZ\n\n\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
- const char *keymap;
- if ( isset( DVORAK ) )
- keymap = dvorakkeymap;
- else
- keymap = qwertykeymap;
-
- if (!strcmp(s, t))
- return 0;
- /* any number of upper/lower mistakes allowed (dist = 1) */
- for (p = s, q = t; *p && tulower(*p) == tulower(*q); p++, q++);
- if (!*p && !*q)
- return 1;
- if (!thresh)
- return 200;
- for (p = s, q = t; *p && *q; p++, q++)
- if (*p == *q)
- continue; /* don't consider "aa" transposed, ash */
- else if (p[1] == q[0] && q[1] == p[0]) /* transpositions */
- return spdist(p + 2, q + 2, thresh - 1) + 1;
- else if (p[1] == q[0]) /* missing letter */
- return spdist(p + 1, q + 0, thresh - 1) + 2;
- else if (p[0] == q[1]) /* missing letter */
- return spdist(p + 0, q + 1, thresh - 1) + 2;
- else if (*p != *q)
- break;
- if ((!*p && strlen(q) == 1) || (!*q && strlen(p) == 1))
- return 2;
- for (p = s, q = t; *p && *q; p++, q++)
- if (p[0] != q[0] && p[1] == q[1]) {
- int t0;
- char *z;
-
- /* mistyped letter */
-
- if (!(z = strchr(keymap, p[0])) || *z == '\n' || *z == '\t')
- return spdist(p + 1, q + 1, thresh - 1) + 1;
- t0 = z - keymap;
- if (*q == keymap[t0 - 15] || *q == keymap[t0 - 14] ||
- *q == keymap[t0 - 13] ||
- *q == keymap[t0 - 1] || *q == keymap[t0 + 1] ||
- *q == keymap[t0 + 13] || *q == keymap[t0 + 14] ||
- *q == keymap[t0 + 15])
- return spdist(p + 1, q + 1, thresh - 1) + 2;
- return 200;
- } else if (*p != *q)
- break;
- return 200;
-}
-
-/* set cbreak mode, or the equivalent */
-
-/**/
-void
-setcbreak(void)
-{
- struct ttyinfo ti;
-
- ti = shttyinfo;
-#ifdef HAS_TIO
- ti.tio.c_lflag &= ~ICANON;
- ti.tio.c_cc[VMIN] = 1;
- ti.tio.c_cc[VTIME] = 0;
-#else
- ti.sgttyb.sg_flags |= CBREAK;
-#endif
- settyinfo(&ti);
-}
-
-/* give the tty to some process */
-
-/**/
-mod_export void
-attachtty(pid_t pgrp)
-{
- static int ep = 0;
-
- if (jobbing && interact) {
-#ifdef HAVE_TCSETPGRP
- if (SHTTY != -1 && tcsetpgrp(SHTTY, pgrp) == -1 && !ep)
-#else
-# if ardent
- if (SHTTY != -1 && setpgrp() == -1 && !ep)
-# else
- int arg = pgrp;
-
- if (SHTTY != -1 && ioctl(SHTTY, TIOCSPGRP, &arg) == -1 && !ep)
-# endif
-#endif
- {
- if (pgrp != mypgrp && kill(-pgrp, 0) == -1)
- attachtty(mypgrp);
- else {
- if (errno != ENOTTY)
- {
- zwarn("can't set tty pgrp: %e", errno);
- fflush(stderr);
- }
- opts[MONITOR] = 0;
- ep = 1;
- }
- }
- }
-}
-
-/* get the process group associated with the tty */
-
-/**/
-pid_t
-gettygrp(void)
-{
- pid_t arg;
-
- if (SHTTY == -1)
- return -1;
-
-#ifdef HAVE_TCSETPGRP
- arg = tcgetpgrp(SHTTY);
-#else
- ioctl(SHTTY, TIOCGPGRP, &arg);
-#endif
-
- return arg;
-}
-
-
-/* Escape tokens and null characters. Buf is the string which should be *
- * escaped. len is the length of the string. If len is -1, buf should be *
- * null terminated. If len is non-negative and the third parameter is not *
- * META_DUP, buf should point to an at least len+1 long memory area. The *
- * return value points to the quoted string. If the given string does not *
- * contain any special character which should be quoted and the third *
- * parameter is not META_(HEAP|)DUP, buf is returned unchanged (a *
- * terminating null character is appended to buf if necessary). Otherwise *
- * the third `heap' argument determines the method used to allocate space *
- * for the result. It can have the following values: *
- * META_REALLOC: use zrealloc on buf *
- * META_HREALLOC: use hrealloc on buf *
- * META_USEHEAP: get memory from the heap. This leaves buf unchanged. *
- * META_NOALLOC: buf points to a memory area which is long enough to hold *
- * the quoted form, just quote it and return buf. *
- * META_STATIC: store the quoted string in a static area. The original *
- * string should be at most PATH_MAX long. *
- * META_ALLOC: allocate memory for the new string with zalloc(). *
- * META_DUP: leave buf unchanged and allocate space for the return *
- * value even if buf does not contains special characters *
- * META_HEAPDUP: same as META_DUP, but uses the heap */
-
-/**/
-mod_export char *
-metafy(char *buf, int len, int heap)
-{
- int meta = 0;
- char *t, *p, *e;
- static char mbuf[PATH_MAX*2+1];
-
- if (len == -1) {
- for (e = buf, len = 0; *e; len++)
- if (imeta(*e++))
- meta++;
- } else
- for (e = buf; e < buf + len;)
- if (imeta(*e++))
- meta++;
-
- if (meta || heap == META_DUP || heap == META_HEAPDUP) {
- switch (heap) {
- case META_REALLOC:
- buf = zrealloc(buf, len + meta + 1);
- break;
- case META_HREALLOC:
- buf = hrealloc(buf, len, len + meta + 1);
- break;
- case META_ALLOC:
- case META_DUP:
- buf = memcpy(zalloc(len + meta + 1), buf, len);
- break;
- case META_USEHEAP:
- case META_HEAPDUP:
- buf = memcpy(zhalloc(len + meta + 1), buf, len);
- break;
- case META_STATIC:
-#ifdef DEBUG
- if (len > PATH_MAX) {
- fprintf(stderr, "BUG: len = %d > PATH_MAX in metafy\n", len);
- fflush(stderr);
- }
-#endif
- buf = memcpy(mbuf, buf, len);
- break;
-#ifdef DEBUG
- case META_NOALLOC:
- break;
- default:
- fprintf(stderr, "BUG: metafy called with invalid heap value\n");
- fflush(stderr);
- break;
-#endif
- }
- p = buf + len;
- e = t = buf + len + meta;
- while (meta) {
- if (imeta(*--t = *--p)) {
- *t-- ^= 32;
- *t = Meta;
- meta--;
- }
- }
- }
- *e = '\0';
- return buf;
-}
-
-
-/*
- * Duplicate a string, metafying it as we go.
- *
- * Typically, this is used only for strings imported from outside
- * zsh, as strings internally are either already metafied or passed
- * around with an associated length.
- */
-/**/
-mod_export char *
-ztrdup_metafy(const char *s)
-{
- /* To mimic ztrdup() behaviour */
- if (!s)
- return NULL;
- /*
- * metafy() does lots of different things, so the pointer
- * isn't const. Using it with META_DUP should be safe.
- */
- return metafy((char *)s, -1, META_DUP);
-}
-
-
-/*
- * Take a null-terminated, metafied string in s into a literal
- * representation by converting in place. The length is in *len
- * len is non-NULL; if len is NULL, you don't know the length of
- * the final string, but if it's to be supplied to some system
- * routine that always uses NULL termination, such as a filename
- * interpreter, that doesn't matter. Note the NULL termination
- * is always copied for purposes of that kind.
- */
-
-/**/
-mod_export char *
-unmetafy(char *s, int *len)
-{
- char *p, *t;
-
- for (p = s; *p && *p != Meta; p++);
- for (t = p; (*t = *p++);)
- if (*t++ == Meta && *p)
- t[-1] = *p++ ^ 32;
- if (len)
- *len = t - s;
- return s;
-}
-
-/* Return the character length of a metafied substring, given the *
- * unmetafied substring length. */
-
-/**/
-mod_export int
-metalen(const char *s, int len)
-{
- int mlen = len;
-
- while (len--) {
- if (*s++ == Meta) {
- mlen++;
- s++;
- }
- }
- return mlen;
-}
-
-/*
- * This function converts a zsh internal string to a form which can be
- * passed to a system call as a filename. The result is stored in a
- * single static area, sized to fit. If there is no Meta character
- * the original string is returned.
- */
-
-/**/
-mod_export char *
-unmeta(const char *file_name)
-{
- static char *fn;
- static int sz;
- char *p;
- const char *t;
- int newsz, meta;
-
- if (!file_name)
- return NULL;
-
- meta = 0;
- for (t = file_name; *t; t++) {
- if (*t == Meta)
- meta = 1;
- }
- if (!meta) {
- /*
- * don't need allocation... free if it's long, see below
- */
- if (sz > 4 * PATH_MAX) {
- zfree(fn, sz);
- fn = NULL;
- sz = 0;
- }
- return (char *) file_name;
- }
-
- newsz = (t - file_name) + 1;
- /*
- * Optimisation: don't resize if we don't have to.
- * We need a new allocation if
- * - nothing was allocated before
- * - the new string is larger than the old one
- * - the old string was larger than an arbitrary limit but the
- * new string isn't so that we free up significant space by resizing.
- */
- if (!fn || newsz > sz || (sz > 4 * PATH_MAX && newsz <= 4 * PATH_MAX))
- {
- if (fn)
- zfree(fn, sz);
- sz = newsz;
- fn = (char *)zalloc(sz);
- if (!fn) {
- sz = 0;
- /*
- * will quite likely crash in the caller anyway...
- */
- return NULL;
- }
- }
-
- for (t = file_name, p = fn; *t; p++)
- if ((*p = *t++) == Meta && *t)
- *p = *t++ ^ 32;
- *p = '\0';
- return fn;
-}
-
-/*
- * Unmetafy just one character and store the number of bytes it occupied.
- */
-/**/
-mod_export convchar_t
-unmeta_one(const char *in, int *sz)
-{
- convchar_t wc;
- int newsz;
-#ifdef MULTIBYTE_SUPPORT
- mbstate_t wstate;
-#endif
-
- if (!sz)
- sz = &newsz;
- *sz = 0;
-
- if (!in || !*in)
- return 0;
-
-#ifdef MULTIBYTE_SUPPORT
- memset(&wstate, 0, sizeof(wstate));
- *sz = mb_metacharlenconv_r(in, &wc, &wstate);
-#else
- if (in[0] == Meta) {
- *sz = 2;
- wc = STOUC(in[1] ^ 32);
- } else {
- *sz = 1;
- wc = STOUC(in[0]);
- }
-#endif
- return wc;
-}
-
-/*
- * Unmetafy and compare two strings, comparing unsigned character values.
- * "a\0" sorts after "a".
- *
- * Currently this is only used in hash table sorting, where the
- * keys are names of hash nodes and where we don't use strcoll();
- * it's not clear if that's right but it does guarantee the ordering
- * of shell structures on output.
- *
- * As we don't use strcoll(), it seems overkill to convert multibyte
- * characters to wide characters for comparison every time. In the case
- * of UTF-8, Unicode ordering is preserved when sorted raw, and for
- * other character sets we rely on an extension of ASCII so the result,
- * while it may not be correct, is at least rational.
- */
-
-/**/
-int
-ztrcmp(char const *s1, char const *s2)
-{
- int c1, c2;
-
- while(*s1 && *s1 == *s2) {
- s1++;
- s2++;
- }
-
- if(!(c1 = *s1))
- c1 = -1;
- else if(c1 == STOUC(Meta))
- c1 = *++s1 ^ 32;
- if(!(c2 = *s2))
- c2 = -1;
- else if(c2 == STOUC(Meta))
- c2 = *++s2 ^ 32;
-
- if(c1 == c2)
- return 0;
- else if(c1 < c2)
- return -1;
- else
- return 1;
-}
-
-/* Return the unmetafied length of a metafied string. */
-
-/**/
-mod_export int
-ztrlen(char const *s)
-{
- int l;
-
- for (l = 0; *s; l++) {
- if (*s++ == Meta) {
-#ifdef DEBUG
- if (! *s) {
- fprintf(stderr, "BUG: unexpected end of string in ztrlen()\n");
- break;
- } else
-#endif
- s++;
- }
- }
- return l;
-}
-
-#ifndef MULTIBYTE_SUPPORT
-/*
- * ztrlen() but with explicit end point for non-null-terminated
- * segments. eptr may not be NULL.
- */
-
-/**/
-mod_export int
-ztrlenend(char const *s, char const *eptr)
-{
- int l;
-
- for (l = 0; s < eptr; l++) {
- if (*s++ == Meta) {
-#ifdef DEBUG
- if (! *s) {
- fprintf(stderr,
- "BUG: unexpected end of string in ztrlenend()\n");
- break;
- } else
-#endif
- s++;
- }
- }
- return l;
-}
-
-#endif /* MULTIBYTE_SUPPORT */
-
-/* Subtract two pointers in a metafied string. */
-
-/**/
-mod_export int
-ztrsub(char const *t, char const *s)
-{
- int l = t - s;
-
- while (s != t) {
- if (*s++ == Meta) {
-#ifdef DEBUG
- if (! *s || s == t)
- fprintf(stderr, "BUG: substring ends in the middle of a metachar in ztrsub()\n");
- else
-#endif
- s++;
- l--;
- }
- }
- return l;
-}
-
-/*
- * Wrapper for readdir().
- *
- * If ignoredots is true, skip the "." and ".." entries.
- *
- * When __APPLE__ is defined, recode dirent names from UTF-8-MAC to UTF-8.
- *
- * Return the dirent's name, metafied.
- */
-
-/**/
-mod_export char *
-zreaddir(DIR *dir, int ignoredots)
-{
- struct dirent *de;
-#if defined(HAVE_ICONV) && defined(__APPLE__)
- static iconv_t conv_ds = (iconv_t)0;
- static char *conv_name = 0;
- char *conv_name_ptr, *orig_name_ptr;
- size_t conv_name_len, orig_name_len;
-#endif
-
- do {
- de = readdir(dir);
- if(!de)
- return NULL;
- } while(ignoredots && de->d_name[0] == '.' &&
- (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])));
-
-#if defined(HAVE_ICONV) && defined(__APPLE__)
- if (!conv_ds)
- conv_ds = iconv_open("UTF-8", "UTF-8-MAC");
- if (conv_ds != (iconv_t)(-1)) {
- /* Force initial state in case re-using conv_ds */
- (void) iconv(conv_ds, 0, &orig_name_len, 0, &conv_name_len);
-
- orig_name_ptr = de->d_name;
- orig_name_len = strlen(de->d_name);
- conv_name = zrealloc(conv_name, orig_name_len+1);
- conv_name_ptr = conv_name;
- conv_name_len = orig_name_len;
- if (iconv(conv_ds,
- &orig_name_ptr, &orig_name_len,
- &conv_name_ptr, &conv_name_len) != (size_t)(-1) &&
- orig_name_len == 0) {
- /* Completely converted, metafy and return */
- *conv_name_ptr = '\0';
- return metafy(conv_name, -1, META_STATIC);
- }
- /* Error, or conversion incomplete, keep the original name */
- }
-#endif
-
- return metafy(de->d_name, -1, META_STATIC);
-}
-
-/* Unmetafy and output a string. Tokens are skipped. */
-
-/**/
-mod_export int
-zputs(char const *s, FILE *stream)
-{
- int c;
-
- while (*s) {
- if (*s == Meta)
- c = *++s ^ 32;
- else if(itok(*s)) {
- s++;
- continue;
- } else
- c = *s;
- s++;
- if (fputc(c, stream) < 0)
- return EOF;
- }
- return 0;
-}
-
-#ifndef MULTIBYTE_SUPPORT
-/* Create a visibly-represented duplicate of a string. */
-
-/**/
-mod_export char *
-nicedup(char const *s, int heap)
-{
- int c, len = strlen(s) * 5 + 1;
- VARARR(char, buf, len);
- char *p = buf, *n;
-
- while ((c = *s++)) {
- if (itok(c)) {
- if (c <= Comma)
- c = ztokens[c - Pound];
- else
- continue;
- }
- if (c == Meta)
- c = *s++ ^ 32;
- /* The result here is metafied */
- n = nicechar(c);
- while(*n)
- *p++ = *n++;
- }
- *p = '\0';
- return heap ? dupstring(buf) : ztrdup(buf);
-}
-#endif
-
-/**/
-mod_export char *
-nicedupstring(char const *s)
-{
- return nicedup(s, 1);
-}
-
-
-#ifndef MULTIBYTE_SUPPORT
-/* Unmetafy and output a string, displaying special characters readably. */
-
-/**/
-mod_export int
-nicezputs(char const *s, FILE *stream)
-{
- int c;
-
- while ((c = *s++)) {
- if (itok(c)) {
- if (c <= Comma)
- c = ztokens[c - Pound];
- else
- continue;
- }
- if (c == Meta)
- c = *s++ ^ 32;
- if(zputs(nicechar(c), stream) < 0)
- return EOF;
- }
- return 0;
-}
-
-
-/* Return the length of the visible representation of a metafied string. */
-
-/**/
-mod_export size_t
-niceztrlen(char const *s)
-{
- size_t l = 0;
- int c;
-
- while ((c = *s++)) {
- if (itok(c)) {
- if (c <= Comma)
- c = ztokens[c - Pound];
- else
- continue;
- }
- if (c == Meta)
- c = *s++ ^ 32;
- l += strlen(nicechar(c));
- }
- return l;
-}
-#endif
-
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/*
- * Version of both nicezputs() and niceztrlen() for use with multibyte
- * characters. Input is a metafied string; output is the screen width of
- * the string.
- *
- * If the FILE * is not NULL, output to that, too.
- *
- * If outstrp is not NULL, set *outstrp to a zalloc'd version of
- * the output (still metafied).
- *
- * If flags contains NICEFLAG_HEAP, use the heap for *outstrp, else
- * zalloc.
- * If flags contsins NICEFLAG_QUOTE, the output is going to be within
- * $'...', so quote "'" and "\" with a backslash.
- */
-
-/**/
-mod_export size_t
-mb_niceformat(const char *s, FILE *stream, char **outstrp, int flags)
-{
- size_t l = 0, newl;
- int umlen, outalloc, outleft, eol = 0;
- wchar_t c;
- char *ums, *ptr, *fmt, *outstr, *outptr;
- mbstate_t mbs;
-
- if (outstrp) {
- outleft = outalloc = 5 * strlen(s);
- outptr = outstr = zalloc(outalloc);
- } else {
- outleft = outalloc = 0;
- outptr = outstr = NULL;
- }
-
- ums = ztrdup(s);
- /*
- * is this necessary at this point? niceztrlen does this
- * but it's used in lots of places. however, one day this may
- * be, too.
- */
- untokenize(ums);
- ptr = unmetafy(ums, ¨en);
-
- memset(&mbs, 0, sizeof mbs);
- while (umlen > 0) {
- size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs);
-
- switch (cnt) {
- case MB_INCOMPLETE:
- eol = 1;
- /* FALL THROUGH */
- case MB_INVALID:
- /* The byte didn't convert, so output it as a \M-... sequence. */
- fmt = nicechar_sel(*ptr, flags & NICEFLAG_QUOTE);
- newl = strlen(fmt);
- cnt = 1;
- /* Get mbs out of its undefined state. */
- memset(&mbs, 0, sizeof mbs);
- break;
- case 0:
- /* Careful: converting '\0' returns 0, but a '\0' is a
- * real character for us, so we should consume 1 byte. */
- cnt = 1;
- /* FALL THROUGH */
- default:
- if (c == L'\'' && (flags & NICEFLAG_QUOTE)) {
- fmt = "\\'";
- newl = 2;
- }
- else if (c == L'\\' && (flags & NICEFLAG_QUOTE)) {
- fmt = "\\\\";
- newl = 2;
- }
- else
- fmt = wcs_nicechar_sel(c, &newl, NULL, flags & NICEFLAG_QUOTE);
- break;
- }
-
- umlen -= cnt;
- ptr += cnt;
- l += newl;
-
- if (stream)
- zputs(fmt, stream);
- if (outstr) {
- /* Append to output string */
- int outlen = strlen(fmt);
- if (outlen >= outleft) {
- /* Reallocate to twice the length */
- int outoffset = outptr - outstr;
-
- outleft += outalloc;
- outalloc *= 2;
- outstr = zrealloc(outstr, outalloc);
- outptr = outstr + outoffset;
- }
- memcpy(outptr, fmt, outlen);
- /* Update start position */
- outptr += outlen;
- /* Update available bytes */
- outleft -= outlen;
- }
- }
-
- free(ums);
- if (outstrp) {
- *outptr = '\0';
- /* Use more efficient storage for returned string */
- if (flags & NICEFLAG_NODUP)
- *outstrp = outstr;
- else {
- *outstrp = (flags & NICEFLAG_HEAP) ? dupstring(outstr) :
- ztrdup(outstr);
- free(outstr);
- }
- }
-
- return l;
-}
-
-/*
- * Return 1 if mb_niceformat() would reformat this string, else 0.
- */
-
-/**/
-mod_export int
-is_mb_niceformat(const char *s)
-{
- int umlen, eol = 0, ret = 0;
- wchar_t c;
- char *ums, *ptr;
- mbstate_t mbs;
-
- ums = ztrdup(s);
- untokenize(ums);
- ptr = unmetafy(ums, ¨en);
-
- memset(&mbs, 0, sizeof mbs);
- while (umlen > 0) {
- size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs);
-
- switch (cnt) {
- case MB_INCOMPLETE:
- eol = 1;
- /* FALL THROUGH */
- case MB_INVALID:
- /* The byte didn't convert, so output it as a \M-... sequence. */
- if (is_nicechar(*ptr)) {
- ret = 1;
- break;
- }
- cnt = 1;
- /* Get mbs out of its undefined state. */
- memset(&mbs, 0, sizeof mbs);
- break;
- case 0:
- /* Careful: converting '\0' returns 0, but a '\0' is a
- * real character for us, so we should consume 1 byte. */
- cnt = 1;
- /* FALL THROUGH */
- default:
- if (is_wcs_nicechar(c))
- ret = 1;
- break;
- }
-
- if (ret)
- break;
-
- umlen -= cnt;
- ptr += cnt;
- }
-
- free(ums);
-
- return ret;
-}
-
-/* ztrdup multibyte string with nice formatting */
-
-/**/
-mod_export char *
-nicedup(const char *s, int heap)
-{
- char *retstr;
-
- (void)mb_niceformat(s, NULL, &retstr, heap ? NICEFLAG_HEAP : 0);
-
- return retstr;
-}
-
-
-/*
- * The guts of mb_metacharlenconv(). This version assumes we are
- * processing a true multibyte character string without tokens, and
- * takes the shift state as an argument.
- */
-
-/**/
-mod_export int
-mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
-{
- size_t ret = MB_INVALID;
- char inchar;
- const char *ptr;
- wchar_t wc;
-
- if (STOUC(*s) <= 0x7f) {
- if (wcp)
- *wcp = (wint_t)*s;
- return 1;
- }
-
- for (ptr = s; *ptr; ) {
- if (*ptr == Meta) {
- inchar = *++ptr ^ 32;
- DPUTS(!*ptr,
- "BUG: unexpected end of string in mb_metacharlen()\n");
- } else if (imeta(*ptr)) {
- /*
- * As this is metafied input, this is a token --- this
- * can't be a part of the string. It might be
- * something on the end of an unbracketed parameter
- * reference, for example.
- */
- break;
- } else
- inchar = *ptr;
- ptr++;
- ret = mbrtowc(&wc, &inchar, 1, mbsp);
-
- if (ret == MB_INVALID)
- break;
- if (ret == MB_INCOMPLETE)
- continue;
- if (wcp)
- *wcp = wc;
- return ptr - s;
- }
-
- if (wcp)
- *wcp = WEOF;
- /* No valid multibyte sequence */
- memset(mbsp, 0, sizeof(*mbsp));
- if (ptr > s) {
- return 1 + (*s == Meta); /* Treat as single byte character */
- } else
- return 0; /* Probably shouldn't happen */
-}
-
-/*
- * Length of metafied string s which contains the next multibyte
- * character; single (possibly metafied) character if string is not null
- * but character is not valid (e.g. possibly incomplete at end of string).
- * Returned value is guaranteed not to reach beyond the end of the
- * string (assuming correct metafication).
- *
- * If wcp is not NULL, the converted wide character is stored there.
- * If no conversion could be done WEOF is used.
- */
-
-/**/
-mod_export int
-mb_metacharlenconv(const char *s, wint_t *wcp)
-{
- if (!isset(MULTIBYTE) || STOUC(*s) <= 0x7f) {
- /* treat as single byte, possibly metafied */
- if (wcp)
- *wcp = (wint_t)(*s == Meta ? s[1] ^ 32 : *s);
- return 1 + (*s == Meta);
- }
- /*
- * We have to handle tokens here, since we may be looking
- * through a tokenized input. Obviously this isn't
- * a valid multibyte character, so just return WEOF
- * and let the caller handle it as a single character.
- *
- * TODO: I've a sneaking suspicion we could do more here
- * to prevent the caller always needing to handle invalid
- * characters specially, but sometimes it may need to know.
- */
- if (itok(*s)) {
- if (wcp)
- *wcp = WEOF;
- return 1;
- }
-
- return mb_metacharlenconv_r(s, wcp, &mb_shiftstate);
-}
-
-/*
- * Total number of multibyte characters in metafied string s.
- * Same answer as iterating mb_metacharlen() and counting calls
- * until end of string.
- *
- * If width is 1, return total character width rather than number.
- * If width is greater than 1, return 1 if character has non-zero width,
- * else 0.
- *
- * Ends if either *ptr is '\0', the normal case (eptr may be NULL for
- * this), or ptr is eptr (i.e. *eptr is where the null would be if null
- * terminated) for strings not delimited by nulls --- note these are
- * still metafied.
- */
-
-/**/
-mod_export int
-mb_metastrlenend(char *ptr, int width, char *eptr)
-{
- char inchar, *laststart;
- size_t ret;
- wchar_t wc;
- int num, num_in_char, complete;
-
- if (!isset(MULTIBYTE) || MB_CUR_MAX == 1)
- return eptr ? (int)(eptr - ptr) : ztrlen(ptr);
-
- laststart = ptr;
- ret = MB_INVALID;
- num = num_in_char = 0;
- complete = 1;
-
- memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
- while (*ptr && !(eptr && ptr >= eptr)) {
- if (*ptr == Meta)
- inchar = *++ptr ^ 32;
- else
- inchar = *ptr;
- ptr++;
-
- if (complete && STOUC(inchar) <= STOUC(0x7f)) {
- /*
- * We rely on 7-bit US-ASCII as a subset, so skip
- * multibyte handling if we have such a character.
- */
- num++;
- laststart = ptr;
- num_in_char = 0;
- continue;
- }
-
- ret = mbrtowc(&wc, &inchar, 1, &mb_shiftstate);
-
- if (ret == MB_INCOMPLETE) {
- /*
- * "num_in_char" is only used for incomplete characters.
- * The assumption is that we will output all trailing octets
- * that form part of an incomplete character as a single
- * character (of single width) if we don't get a complete
- * character. This is purely pragmatic --- I'm not aware
- * of a standard way of dealing with incomplete characters.
- *
- * If we do get a complete character, num_in_char
- * becomes irrelevant and is set to zero
- *
- * This is in contrast to "num" which counts the characters
- * or widths in complete characters. The two are summed,
- * so we don't count characters twice.
- */
- num_in_char++;
- complete = 0;
- } else {
- if (ret == MB_INVALID) {
- /* Reset, treat as single character */
- memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
- ptr = laststart + (*laststart == Meta) + 1;
- num++;
- } else if (width) {
- /*
- * Returns -1 if not a printable character. We
- * turn this into 0.
- */
- int wcw = WCWIDTH(wc);
- if (wcw > 0) {
- if (width == 1)
- num += wcw;
- else
- num++;
- }
- } else
- num++;
- laststart = ptr;
- num_in_char = 0;
- complete = 1;
- }
- }
-
- /* If incomplete, treat remainder as trailing single character */
- return num + (num_in_char ? 1 : 0);
-}
-
-/*
- * The equivalent of mb_metacharlenconv_r() for
- * strings that aren't metafied and hence have
- * explicit lengths.
- */
-
-/**/
-mod_export int
-mb_charlenconv_r(const char *s, int slen, wint_t *wcp, mbstate_t *mbsp)
-{
- size_t ret = MB_INVALID;
- char inchar;
- const char *ptr;
- wchar_t wc;
-
- if (slen && STOUC(*s) <= 0x7f) {
- if (wcp)
- *wcp = (wint_t)*s;
- return 1;
- }
-
- for (ptr = s; slen; ) {
- inchar = *ptr;
- ptr++;
- slen--;
- ret = mbrtowc(&wc, &inchar, 1, mbsp);
-
- if (ret == MB_INVALID)
- break;
- if (ret == MB_INCOMPLETE)
- continue;
- if (wcp)
- *wcp = wc;
- return ptr - s;
- }
-
- if (wcp)
- *wcp = WEOF;
- /* No valid multibyte sequence */
- memset(mbsp, 0, sizeof(*mbsp));
- if (ptr > s) {
- return 1; /* Treat as single byte character */
- } else
- return 0; /* Probably shouldn't happen */
-}
-
-/*
- * The equivalent of mb_metacharlenconv() for
- * strings that aren't metafied and hence have
- * explicit lengths;
- */
-
-/**/
-mod_export int
-mb_charlenconv(const char *s, int slen, wint_t *wcp)
-{
- if (!isset(MULTIBYTE) || STOUC(*s) <= 0x7f) {
- if (wcp)
- *wcp = (wint_t)*s;
- return 1;
- }
-
- return mb_charlenconv_r(s, slen, wcp, &mb_shiftstate);
-}
-
-/**/
-#else
-
-/* Simple replacement for mb_metacharlenconv */
-
-/**/
-mod_export int
-metacharlenconv(const char *x, int *c)
-{
- /*
- * Here we don't use STOUC() on the chars since they
- * may be compared against other chars and this will fail
- * if chars are signed and the high bit is set.
- */
- if (*x == Meta) {
- if (c)
- *c = x[1] ^ 32;
- return 2;
- }
- if (c)
- *c = (char)*x;
- return 1;
-}
-
-/* Simple replacement for mb_charlenconv */
-
-/**/
-mod_export int
-charlenconv(const char *x, int len, int *c)
-{
- if (!len) {
- if (c)
- *c = '\0';
- return 0;
- }
-
- if (c)
- *c = (char)*x;
- return 1;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/*
- * Expand tabs to given width, with given starting position on line.
- * len is length of unmetafied string in bytes.
- * Output to fout.
- * Return the end position on the line, i.e. if this is 0 modulo width
- * the next character is aligned with a tab stop.
- *
- * If all is set, all tabs are expanded, else only leading tabs.
- */
-
-/**/
-mod_export int
-zexpandtabs(const char *s, int len, int width, int startpos, FILE *fout,
- int all)
-{
- int at_start = 1;
-
-#ifdef MULTIBYTE_SUPPORT
- mbstate_t mbs;
- size_t ret;
- wchar_t wc;
-
- memset(&mbs, 0, sizeof(mbs));
-#endif
-
- while (len) {
- if (*s == '\t') {
- if (all || at_start) {
- s++;
- len--;
- if (width <= 0 || !(startpos % width)) {
- /* always output at least one space */
- fputc(' ', fout);
- startpos++;
- }
- if (width <= 0)
- continue; /* paranoia */
- while (startpos % width) {
- fputc(' ', fout);
- startpos++;
- }
- } else {
- /*
- * Leave tab alone.
- * Guess width to apply... we might get this wrong.
- * This is only needed if there's a following string
- * that needs tabs expanding, which is unusual.
- */
- startpos += width - startpos % width;
- s++;
- len--;
- fputc('\t', fout);
- }
- continue;
- } else if (*s == '\n' || *s == '\r') {
- fputc(*s, fout);
- s++;
- len--;
- startpos = 0;
- at_start = 1;
- continue;
- }
-
- at_start = 0;
-#ifdef MULTIBYTE_SUPPORT
- if (isset(MULTIBYTE)) {
- const char *sstart = s;
- ret = mbrtowc(&wc, s, len, &mbs);
- if (ret == MB_INVALID) {
- /* Assume single character per character */
- memset(&mbs, 0, sizeof(mbs));
- s++;
- len--;
- } else if (ret == MB_INCOMPLETE) {
- /* incomplete at end --- assume likewise, best we've got */
- s++;
- len--;
- } else {
- s += ret;
- len -= (int)ret;
- }
- if (ret == MB_INVALID || ret == MB_INCOMPLETE) {
- startpos++;
- } else {
- int wcw = WCWIDTH(wc);
- if (wcw > 0) /* paranoia */
- startpos += wcw;
- }
- fwrite(sstart, s - sstart, 1, fout);
-
- continue;
- }
-#endif /* MULTIBYTE_SUPPORT */
- fputc(*s, fout);
- s++;
- len--;
- startpos++;
- }
-
- return startpos;
-}
-
-/* check for special characters in the string */
-
-/**/
-mod_export int
-hasspecial(char const *s)
-{
- for (; *s; s++) {
- if (ispecial(*s == Meta ? *++s ^ 32 : *s))
- return 1;
- }
- return 0;
-}
-
-
-static char *
-addunprintable(char *v, const char *u, const char *uend)
-{
- for (; u < uend; u++) {
- /*
- * Just do this byte by byte; there's no great
- * advantage in being clever with multibyte
- * characters if we don't think they're printable.
- */
- int c;
- if (*u == Meta)
- c = STOUC(*++u ^ 32);
- else
- c = STOUC(*u);
- switch (c) {
- case '\0':
- *v++ = '\\';
- *v++ = '0';
- if ('0' <= u[1] && u[1] <= '7') {
- *v++ = '0';
- *v++ = '0';
- }
- break;
-
- case '\007': *v++ = '\\'; *v++ = 'a'; break;
- case '\b': *v++ = '\\'; *v++ = 'b'; break;
- case '\f': *v++ = '\\'; *v++ = 'f'; break;
- case '\n': *v++ = '\\'; *v++ = 'n'; break;
- case '\r': *v++ = '\\'; *v++ = 'r'; break;
- case '\t': *v++ = '\\'; *v++ = 't'; break;
- case '\v': *v++ = '\\'; *v++ = 'v'; break;
-
- default:
- *v++ = '\\';
- *v++ = '0' + ((c >> 6) & 7);
- *v++ = '0' + ((c >> 3) & 7);
- *v++ = '0' + (c & 7);
- break;
- }
- }
-
- return v;
-}
-
-/*
- * Quote the string s and return the result as a string from the heap.
- *
- * The last argument is a QT_ value defined in zsh.h other than QT_NONE.
- *
- * Most quote styles other than backslash assume the quotes are to
- * be added outside quotestring(). QT_SINGLE_OPTIONAL is different:
- * the single quotes are only added where necessary, so the
- * whole expression is handled here.
- *
- * The string may be metafied and contain tokens.
- */
-
-/**/
-mod_export char *
-quotestring(const char *s, int instring)
-{
- const char *u;
- char *v;
- int alloclen;
- char *buf;
- int shownull = 0;
- /*
- * quotesub is used with QT_SINGLE_OPTIONAL.
- * quotesub = 0: mechanism not active
- * quotesub = 1: mechanism pending, no "'" yet;
- * needs adding at quotestart.
- * quotesub = 2: mechanism active, added opening "'"; need
- * closing "'".
- */
- int quotesub = 0, slen;
- char *quotestart;
- convchar_t cc;
- const char *uend;
-
- slen = strlen(s);
- switch (instring)
- {
- case QT_BACKSLASH_SHOWNULL:
- shownull = 1;
- instring = QT_BACKSLASH;
- /*FALLTHROUGH*/
- case QT_BACKSLASH:
- /*
- * With QT_BACKSLASH we may need to use $'\300' stuff.
- * Keep memory usage within limits by allocating temporary
- * storage and using heap for correct size at end.
- */
- alloclen = slen * 7 + 1;
- break;
-
- case QT_BACKSLASH_PATTERN:
- alloclen = slen * 2 + 1;
- break;
-
- case QT_SINGLE_OPTIONAL:
- /*
- * Here, we may need to add single quotes.
- * Always show empty strings.
- */
- alloclen = slen * 4 + 3;
- quotesub = shownull = 1;
- break;
-
- default:
- alloclen = slen * 4 + 1;
- break;
- }
- if (!*s && shownull)
- alloclen += 2; /* for '' */
-
- quotestart = v = buf = zshcalloc(alloclen);
-
- DPUTS(instring < QT_BACKSLASH || instring == QT_BACKTICK ||
- instring > QT_BACKSLASH_PATTERN,
- "BUG: bad quote type in quotestring");
- u = s;
- if (instring == QT_DOLLARS) {
- /*
- * The only way to get Nularg here is when
- * it is placeholding for the empty string?
- */
- if (inull(*u))
- u++;
- /*
- * As we test for printability here we need to be able
- * to look for multibyte characters.
- */
- MB_METACHARINIT();
- while (*u) {
- uend = u + MB_METACHARLENCONV(u, &cc);
-
- if (
-#ifdef MULTIBYTE_SUPPORT
- cc != WEOF &&
-#endif
- WC_ISPRINT(cc)) {
- switch (cc) {
- case ZWC('\\'):
- case ZWC('\''):
- *v++ = '\\';
- break;
-
- default:
- if (isset(BANGHIST) && cc == (wchar_t)bangchar)
- *v++ = '\\';
- break;
- }
- while (u < uend)
- *v++ = *u++;
- } else {
- /* Not printable */
- v = addunprintable(v, u, uend);
- u = uend;
- }
- }
- } else if (instring == QT_BACKSLASH_PATTERN) {
- while (*u) {
- if (ipattern(*u))
- *v++ = '\\';
- *v++ = *u++;
- }
- } else {
- if (shownull) {
- /* We can't show an empty string with just backslash quoting. */
- if (!*u) {
- *v++ = '\'';
- *v++ = '\'';
- }
- }
- /*
- * Here there are syntactic special characters, so
- * we start by going through bytewise.
- */
- while (*u) {
- int dobackslash = 0;
- if (*u == Tick || *u == Qtick) {
- char c = *u++;
-
- *v++ = c;
- while (*u && *u != c)
- *v++ = *u++;
- *v++ = c;
- if (*u)
- u++;
- continue;
- } else if ((*u == Qstring || *u == '$') && u[1] == '\'' &&
- instring == QT_DOUBLE) {
- /*
- * We don't need to quote $'...' inside a double-quoted
- * string. This is largely cosmetic; it looks neater
- * if we don't but it doesn't do any harm since the
- * \ is stripped.
- */
- *v++ = *u++;
- } else if ((*u == String || *u == Qstring) &&
- (u[1] == Inpar || u[1] == Inbrack || u[1] == Inbrace)) {
- char c = (u[1] == Inpar ? Outpar : (u[1] == Inbrace ?
- Outbrace : Outbrack));
- char beg = *u;
- int level = 0;
-
- *v++ = *u++;
- *v++ = *u++;
- while (*u && (*u != c || level)) {
- if (*u == beg)
- level++;
- else if (*u == c)
- level--;
- *v++ = *u++;
- }
- if (*u)
- *v++ = *u++;
- continue;
- }
- else if (ispecial(*u) &&
- ((*u != '=' && *u != '~') ||
- u == s ||
- (isset(MAGICEQUALSUBST) &&
- (u[-1] == '=' || u[-1] == ':')) ||
- (*u == '~' && isset(EXTENDEDGLOB))) &&
- (instring == QT_BACKSLASH ||
- instring == QT_SINGLE_OPTIONAL ||
- (isset(BANGHIST) && *u == (char)bangchar &&
- instring != QT_SINGLE) ||
- (instring == QT_DOUBLE &&
- (*u == '$' || *u == '`' || *u == '\"' || *u == '\\')) ||
- (instring == QT_SINGLE && *u == '\''))) {
- if (instring == QT_SINGLE_OPTIONAL) {
- if (quotesub == 1) {
- /*
- * We haven't yet had to quote at the start.
- */
- if (*u == '\'') {
- /*
- * We don't need to.
- */
- *v++ = '\\';
- } else {
- /*
- * It's now time to add quotes.
- */
- if (v > quotestart)
- {
- char *addq;
-
- for (addq = v; addq > quotestart; addq--)
- *addq = addq[-1];
- }
- *quotestart = '\'';
- v++;
- quotesub = 2;
- }
- *v++ = *u++;
- /*
- * Next place to start quotes is here.
- */
- quotestart = v;
- } else if (*u == '\'') {
- if (unset(RCQUOTES)) {
- *v++ = '\'';
- *v++ = '\\';
- *v++ = '\'';
- /* Don't restart quotes unless we need them */
- quotesub = 1;
- quotestart = v;
- } else {
- /* simplest just to use '' always */
- *v++ = '\'';
- *v++ = '\'';
- }
- /* dealt with */
- u++;
- } else {
- /* else already quoting, just add */
- *v++ = *u++;
- }
- continue;
- } else if (*u == '\n' ||
- (instring == QT_SINGLE && *u == '\'')) {
- if (*u == '\n') {
- *v++ = '$';
- *v++ = '\'';
- *v++ = '\\';
- *v++ = 'n';
- *v++ = '\'';
- } else if (unset(RCQUOTES)) {
- *v++ = '\'';
- if (*u == '\'')
- *v++ = '\\';
- *v++ = *u;
- *v++ = '\'';
- } else
- *v++ = '\'', *v++ = '\'';
- u++;
- continue;
- } else {
- /*
- * We'll need a backslash, but don't add it
- * yet since if the character isn't printable
- * we'll have to upgrade it to $'...'.
- */
- dobackslash = 1;
- }
- }
-
- if (itok(*u) || instring != QT_BACKSLASH) {
- /* Needs to be passed straight through. */
- if (dobackslash)
- *v++ = '\\';
- if (*u == Inparmath) {
- /*
- * Already syntactically quoted: don't
- * add more.
- */
- int inmath = 1;
- *v++ = *u++;
- for (;;) {
- char uc = *u;
- *v++ = *u++;
- if (uc == '\0')
- break;
- else if (uc == Outparmath && !--inmath)
- break;
- else if (uc == Inparmath)
- ++inmath;
- }
- } else
- *v++ = *u++;
- continue;
- }
-
- /*
- * Now check if the output is unprintable in the
- * current character set.
- */
- uend = u + MB_METACHARLENCONV(u, &cc);
- if (
-#ifdef MULTIBYTE_SUPPORT
- cc != WEOF &&
-#endif
- WC_ISPRINT(cc)) {
- if (dobackslash)
- *v++ = '\\';
- while (u < uend) {
- if (*u == Meta)
- *v++ = *u++;
- *v++ = *u++;
- }
- } else {
- /* Not printable */
- *v++ = '$';
- *v++ = '\'';
- v = addunprintable(v, u, uend);
- *v++ = '\'';
- u = uend;
- }
- }
- }
- if (quotesub == 2)
- *v++ = '\'';
- *v = '\0';
-
- v = dupstring(buf);
- zfree(buf, alloclen);
- return v;
-}
-
-/*
- * Unmetafy and output a string, quoted if it contains special
- * characters.
- *
- * If stream is NULL, return the same output with any allocation on the
- * heap.
- */
-
-/**/
-mod_export char *
-quotedzputs(char const *s, FILE *stream)
-{
- int inquote = 0, c;
- char *outstr, *ptr;
-
- /* check for empty string */
- if(!*s) {
- if (!stream)
- return dupstring("''");
- fputs("''", stream);
- return NULL;
- }
-
-#ifdef MULTIBYTE_SUPPORT
- if (is_mb_niceformat(s)) {
- if (stream) {
- fputs("$'", stream);
- mb_niceformat(s, stream, NULL, NICEFLAG_QUOTE);
- fputc('\'', stream);
- return NULL;
- } else {
- char *substr;
- mb_niceformat(s, NULL, &substr, NICEFLAG_QUOTE|NICEFLAG_NODUP);
- outstr = (char *)zhalloc(4 + strlen(substr));
- sprintf(outstr, "$'%s'", substr);
- free(substr);
- return outstr;
- }
- }
-#endif /* MULTIBYTE_SUPPORT */
-
- if (!hasspecial(s)) {
- if (stream) {
- zputs(s, stream);
- return NULL;
- } else {
- return dupstring(s);
- }
- }
-
- if (!stream) {
- const char *cptr;
- int l = strlen(s) + 2;
- for (cptr = s; *cptr; cptr++) {
- if (*cptr == Meta)
- cptr++;
- else if (*cptr == '\'')
- l += isset(RCQUOTES) ? 1 : 3;
- }
- ptr = outstr = zhalloc(l + 1);
- } else {
- ptr = outstr = NULL;
- }
- if (isset(RCQUOTES)) {
- /* use rc-style quotes-within-quotes for the whole string */
- if (stream) {
- if (fputc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- while(*s) {
- if (*s == Dash)
- c = '-';
- else if (*s == Meta)
- c = *++s ^ 32;
- else
- c = *s;
- s++;
- if (c == '\'') {
- if (stream) {
- if (fputc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- } else if (c == '\n' && isset(CSHJUNKIEQUOTES)) {
- if (stream) {
- if (fputc('\\', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\\';
- }
- if (stream) {
- if (fputc(c, stream) < 0)
- return NULL;
- } else {
- if (imeta(c)) {
- *ptr++ = Meta;
- *ptr++ = c ^ 32;
- } else
- *ptr++ = c;
- }
- }
- if (stream) {
- if (fputc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- } else {
- /* use Bourne-style quoting, avoiding empty quoted strings */
- while (*s) {
- if (*s == Dash)
- c = '-';
- else if (*s == Meta)
- c = *++s ^ 32;
- else
- c = *s;
- s++;
- if (c == '\'') {
- if (inquote) {
- if (stream) {
- if (putc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- inquote=0;
- }
- if (stream) {
- if (fputs("\\'", stream) < 0)
- return NULL;
- } else {
- *ptr++ = '\\';
- *ptr++ = '\'';
- }
- } else {
- if (!inquote) {
- if (stream) {
- if (fputc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- inquote=1;
- }
- if (c == '\n' && isset(CSHJUNKIEQUOTES)) {
- if (stream) {
- if (fputc('\\', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\\';
- }
- if (stream) {
- if (fputc(c, stream) < 0)
- return NULL;
- } else {
- if (imeta(c)) {
- *ptr++ = Meta;
- *ptr++ = c ^ 32;
- } else
- *ptr++ = c;
- }
- }
- }
- if (inquote) {
- if (stream) {
- if (fputc('\'', stream) < 0)
- return NULL;
- } else
- *ptr++ = '\'';
- }
- }
- if (!stream)
- *ptr++ = '\0';
-
- return outstr;
-}
-
-/* Double-quote a metafied string. */
-
-/**/
-mod_export char *
-dquotedztrdup(char const *s)
-{
- int len = strlen(s) * 4 + 2;
- char *buf = zalloc(len);
- char *p = buf, *ret;
-
- if(isset(CSHJUNKIEQUOTES)) {
- int inquote = 0;
-
- while(*s) {
- int c = *s++;
-
- if (c == Meta)
- c = *s++ ^ 32;
- switch(c) {
- case '"':
- case '$':
- case '`':
- if(inquote) {
- *p++ = '"';
- inquote = 0;
- }
- *p++ = '\\';
- *p++ = c;
- break;
- default:
- if(!inquote) {
- *p++ = '"';
- inquote = 1;
- }
- if(c == '\n')
- *p++ = '\\';
- *p++ = c;
- break;
- }
- }
- if (inquote)
- *p++ = '"';
- } else {
- int pending = 0;
-
- *p++ = '"';
- while(*s) {
- int c = *s++;
-
- if (c == Meta)
- c = *s++ ^ 32;
- switch(c) {
- case '\\':
- if(pending)
- *p++ = '\\';
- *p++ = '\\';
- pending = 1;
- break;
- case '"':
- case '$':
- case '`':
- if(pending)
- *p++ = '\\';
- *p++ = '\\';
- /* FALL THROUGH */
- default:
- *p++ = c;
- pending = 0;
- break;
- }
- }
- if(pending)
- *p++ = '\\';
- *p++ = '"';
- }
- ret = metafy(buf, p - buf, META_DUP);
- zfree(buf, len);
- return ret;
-}
-
-/* Unmetafy and output a string, double quoting it in its entirety. */
-
-#if 0 /**/
-int
-dquotedzputs(char const *s, FILE *stream)
-{
- char *d = dquotedztrdup(s);
- int ret = zputs(d, stream);
-
- zsfree(d);
- return ret;
-}
-#endif
-
-# if defined(HAVE_NL_LANGINFO) && defined(CODESET) && !defined(__STDC_ISO_10646__)
-/* Convert a character from UCS4 encoding to UTF-8 */
-
-static size_t
-ucs4toutf8(char *dest, unsigned int wval)
-{
- size_t len;
-
- if (wval < 0x80)
- len = 1;
- else if (wval < 0x800)
- len = 2;
- else if (wval < 0x10000)
- len = 3;
- else if (wval < 0x200000)
- len = 4;
- else if (wval < 0x4000000)
- len = 5;
- else
- len = 6;
-
- switch (len) { /* falls through except to the last case */
- case 6: dest[5] = (wval & 0x3f) | 0x80; wval >>= 6;
- case 5: dest[4] = (wval & 0x3f) | 0x80; wval >>= 6;
- case 4: dest[3] = (wval & 0x3f) | 0x80; wval >>= 6;
- case 3: dest[2] = (wval & 0x3f) | 0x80; wval >>= 6;
- case 2: dest[1] = (wval & 0x3f) | 0x80; wval >>= 6;
- *dest = wval | ((0xfc << (6 - len)) & 0xfc);
- break;
- case 1: *dest = wval;
- }
-
- return len;
-}
-#endif
-
-
-/*
- * The following only occurs once or twice in the code, but in different
- * places depending how character set conversion is implemented.
- */
-#define CHARSET_FAILED() \
- if (how & GETKEY_DOLLAR_QUOTE) { \
- while ((*tdest++ = *++s)) { \
- if (how & GETKEY_UPDATE_OFFSET) { \
- if (s - sstart > *misc) \
- (*misc)++; \
- } \
- if (*s == Snull) { \
- *len = (s - sstart) + 1; \
- *tdest = '\0'; \
- return buf; \
- } \
- } \
- *len = tdest - buf; \
- return buf; \
- } \
- *t = '\0'; \
- *len = t - buf; \
- return buf
-
-/*
- * Decode a key string, turning it into the literal characters.
- * The value returned is a newly allocated string from the heap.
- *
- * The length is returned in *len. This is usually the length of
- * the final unmetafied string. The exception is the case of
- * a complete GETKEY_DOLLAR_QUOTE conversion where *len is the
- * length of the input string which has been used (up to and including
- * the terminating single quote); as the final string is metafied and
- * NULL-terminated its length is not required. If both GETKEY_DOLLAR_QUOTE
- * and GETKEY_UPDATE_OFFSET are present in "how", the string is not
- * expected to be terminated (this is used in completion to parse
- * a partial $'...'-quoted string) and the length passed back is
- * that of the converted string. Note in both cases that this is a length
- * in bytes (i.e. the same as given by a raw pointer difference), not
- * characters, which may occupy multiple bytes.
- *
- * how is a set of bits from the GETKEY_ values defined in zsh.h;
- * not all combinations of bits are useful. Callers will typically
- * use one of the GETKEYS_ values which define sets of bits.
- * Note, for example that:
- * - GETKEY_SINGLE_CHAR must not be combined with GETKEY_DOLLAR_QUOTE.
- * - GETKEY_UPDATE_OFFSET is only allowed if GETKEY_DOLLAR_QUOTE is
- * also present.
- *
- * *misc is used for various purposes:
- * - If GETKEY_BACKSLASH_MINUS is set, it indicates the presence
- * of \- in the input.
- * - If GETKEY_BACKSLASH_C is set, it indicates the presence
- * of \c in the input.
- * - If GETKEY_UPDATE_OFFSET is set, it is set on input to some
- * mystical completion offset and is updated to a new offset based
- * on the converted characters. All Hail the Completion System
- * [makes the mystic completion system runic sign in the air].
- *
- * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is
- * in use.
- */
-
-/**/
-mod_export char *
-getkeystring(char *s, int *len, int how, int *misc)
-{
- char *buf, tmp[1];
- char *t, *tdest = NULL, *u = NULL, *sstart = s, *tbuf = NULL;
- char svchar = '\0';
- int meta = 0, control = 0, ignoring = 0;
- int i;
-#if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
- wint_t wval;
- int count;
-#else
- unsigned int wval;
-# if defined(HAVE_NL_LANGINFO) && defined(CODESET)
-# if defined(HAVE_ICONV)
- iconv_t cd;
- char inbuf[4];
- size_t inbytes, outbytes;
-# endif
- size_t count;
-# endif
-#endif
-
- DPUTS((how & GETKEY_UPDATE_OFFSET) &&
- (how & ~(GETKEYS_DOLLARS_QUOTE|GETKEY_UPDATE_OFFSET)),
- "BUG: offset updating in getkeystring only supported with $'.");
- DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR)) ==
- (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR),
- "BUG: incompatible options in getkeystring");
-
- if (how & GETKEY_SINGLE_CHAR)
- t = buf = tmp;
- else {
- /* Length including terminating NULL */
- int maxlen = 1;
- /*
- * We're not necessarily guaranteed the output string will
- * be no longer than the input with \u and \U when output
- * characters need to be metafied. As this is the only
- * case where the string can get longer (?I think),
- * include it in the allocation length here but don't
- * bother taking account of other factors.
- */
- for (t = s; *t; t++) {
- if (*t == '\\') {
- if (!t[1]) {
- maxlen++;
- break;
- }
- if (t[1] == 'u' || t[1] == 'U')
- maxlen += MB_CUR_MAX * 2;
- else
- maxlen += 2;
- /* skip the backslash and the following character */
- t++;
- } else
- maxlen++;
- }
- if (how & GETKEY_DOLLAR_QUOTE) {
- /*
- * We're going to unmetafy into a new string, but
- * to get a proper metafied input we're going to metafy
- * into an intermediate buffer. This is necessary if we have
- * \u and \U's with multiple metafied bytes. We can't
- * simply remetafy the entire string because there may
- * be tokens (indeed, we know there are lexical nulls floating
- * around), so we have to be aware character by character
- * what we are converting.
- *
- * In this case, buf is the final buffer (as usual),
- * but t points into a temporary buffer that just has
- * to be long enough to hold the result of one escape
- * code transformation. We count this is a full multibyte
- * character (MB_CUR_MAX) with every character metafied
- * (*2) plus a little bit of fuzz (for e.g. the odd backslash).
- */
- buf = tdest = zhalloc(maxlen);
- t = tbuf = zhalloc(MB_CUR_MAX * 3 + 1);
- } else {
- t = buf = zhalloc(maxlen);
- }
- }
- for (; *s; s++) {
- if (*s == '\\' && s[1]) {
- int miscadded;
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
- (*misc)--;
- miscadded = 1;
- } else
- miscadded = 0;
- switch (*++s) {
- case 'a':
-#ifdef __STDC__
- *t++ = '\a';
-#else
- *t++ = '\07';
-#endif
- break;
- case 'n':
- *t++ = '\n';
- break;
- case 'b':
- *t++ = '\b';
- break;
- case 't':
- *t++ = '\t';
- break;
- case 'v':
- *t++ = '\v';
- break;
- case 'f':
- *t++ = '\f';
- break;
- case 'r':
- *t++ = '\r';
- break;
- case 'E':
- if (!(how & GETKEY_EMACS)) {
- *t++ = '\\', s--;
- if (miscadded)
- (*misc)++;
- continue;
- }
- /* FALL THROUGH */
- case 'e':
- *t++ = '\033';
- break;
- case 'M':
- /* HERE: GETKEY_UPDATE_OFFSET */
- if (how & GETKEY_EMACS) {
- if (s[1] == '-')
- s++;
- meta = 1 + control; /* preserve the order of ^ and meta */
- } else {
- if (miscadded)
- (*misc)++;
- *t++ = '\\', s--;
- }
- continue;
- case 'C':
- /* HERE: GETKEY_UPDATE_OFFSET */
- if (how & GETKEY_EMACS) {
- if (s[1] == '-')
- s++;
- control = 1;
- } else {
- if (miscadded)
- (*misc)++;
- *t++ = '\\', s--;
- }
- continue;
- case Meta:
- if (miscadded)
- (*misc)++;
- *t++ = '\\', s--;
- break;
- case '-':
- if (how & GETKEY_BACKSLASH_MINUS) {
- *misc = 1;
- break;
- }
- goto def;
- case 'c':
- if (how & GETKEY_BACKSLASH_C) {
- *misc = 1;
- *t = '\0';
- *len = t - buf;
- return buf;
- }
- goto def;
- case 'U':
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
- (*misc) -= 4;
- /* FALLTHROUGH */
- case 'u':
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
- (*misc) -= 6; /* HERE don't really believe this */
- /*
- * We've now adjusted the offset for all the input
- * characters, so we need to add for each
- * byte of output below.
- */
- }
- wval = 0;
- for (i=(*s == 'u' ? 4 : 8); i>0; i--) {
- if (*++s && idigit(*s))
- wval = wval * 16 + (*s - '0');
- else if (*s && ((*s >= 'a' && *s <= 'f') ||
- (*s >= 'A' && *s <= 'F')))
- wval = wval * 16 + (*s & 0x1f) + 9;
- else {
- s--;
- break;
- }
- }
- if (how & GETKEY_SINGLE_CHAR) {
- *misc = wval;
- return s+1;
- }
-#if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
- count = wctomb(t, (wchar_t)wval);
- if (count == -1) {
- zerr("character not in range");
- CHARSET_FAILED();
- }
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
- (*misc) += count;
- t += count;
-# else
-# if defined(HAVE_NL_LANGINFO) && defined(CODESET)
- if (!strcmp(nl_langinfo(CODESET), "UTF-8")) {
- count = ucs4toutf8(t, wval);
- t += count;
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
- (*misc) += count;
- } else {
-# ifdef HAVE_ICONV
- ICONV_CONST char *inptr = inbuf;
- const char *codesetstr = nl_langinfo(CODESET);
- inbytes = 4;
- outbytes = 6;
- /* store value in big endian form */
- for (i=3;i>=0;i--) {
- inbuf[i] = wval & 0xff;
- wval >>= 8;
- }
-
- /*
- * If the code set isn't handled, we'd better
- * assume it's US-ASCII rather than just failing
- * hopelessly. Solaris has a weird habit of
- * returning 646. This is handled by the
- * native iconv(), but not by GNU iconv; what's
- * more, some versions of the native iconv don't
- * handle standard names like ASCII.
- *
- * This should only be a problem if there's a
- * mismatch between the NLS and the iconv in use,
- * which probably only means if libiconv is in use.
- * We checked at configure time if our libraries
- * pulled in _libiconv_version, which should be
- * a good test.
- *
- * It shouldn't ever be NULL, but while we're
- * being paranoid...
- */
-#ifdef ICONV_FROM_LIBICONV
- if (!codesetstr || !*codesetstr)
- codesetstr = "US-ASCII";
-#endif
- cd = iconv_open(codesetstr, "UCS-4BE");
-#ifdef ICONV_FROM_LIBICONV
- if (cd == (iconv_t)-1 && !strcmp(codesetstr, "646")) {
- codesetstr = "US-ASCII";
- cd = iconv_open(codesetstr, "UCS-4BE");
- }
-#endif
- if (cd == (iconv_t)-1) {
- zerr("cannot do charset conversion (iconv failed)");
- CHARSET_FAILED();
- }
- count = iconv(cd, &inptr, &inbytes, &t, &outbytes);
- iconv_close(cd);
- if (count == (size_t)-1) {
- zerr("character not in range");
- CHARSET_FAILED();
- }
- if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
- (*misc) += count;
-# else
- zerr("cannot do charset conversion (iconv not available)");
- CHARSET_FAILED();
-# endif
- }
-# else
- zerr("cannot do charset conversion (NLS not supported)");
- CHARSET_FAILED();
-# endif
-# endif
- if (how & GETKEY_DOLLAR_QUOTE) {
- char *t2;
- for (t2 = tbuf; t2 < t; t2++) {
- if (imeta(*t2)) {
- *tdest++ = Meta;
- *tdest++ = *t2 ^ 32;
- } else
- *tdest++ = *t2;
- }
- /* reset temporary buffer after handling */
- t = tbuf;
- }
- continue;
- case '\'':
- case '\\':
- if (how & GETKEY_DOLLAR_QUOTE) {
- /*
- * Usually \' and \\ will have the initial
- * \ turned into a Bnull, however that's not
- * necessarily the case when called from
- * completion.
- */
- *t++ = *s;
- break;
- }
- /* FALLTHROUGH */
- default:
- def:
- /* HERE: GETKEY_UPDATE_OFFSET? */
- if ((idigit(*s) && *s < '8') || *s == 'x') {
- if (!(how & GETKEY_OCTAL_ESC)) {
- if (*s == '0')
- s++;
- else if (*s != 'x') {
- *t++ = '\\', s--;
- continue;
- }
- }
- if (s[1] && s[2] && s[3]) {
- svchar = s[3];
- s[3] = '\0';
- u = s;
- }
- *t++ = zstrtol(s + (*s == 'x'), &s,
- (*s == 'x') ? 16 : 8);
- if ((how & GETKEY_PRINTF_PERCENT) && t[-1] == '%')
- *t++ = '%';
- if (svchar) {
- u[3] = svchar;
- svchar = '\0';
- }
- s--;
- } else {
- if (!(how & GETKEY_EMACS) && *s != '\\') {
- if (miscadded)
- (*misc)++;
- *t++ = '\\';
- }
- *t++ = *s;
- }
- break;
- }
- } else if ((how & GETKEY_DOLLAR_QUOTE) && *s == Snull) {
- /* return length to following character */
- *len = (s - sstart) + 1;
- *tdest = '\0';
- return buf;
- } else if (*s == '^' && !control && (how & GETKEY_CTRL) && s[1]) {
- control = 1;
- continue;
-#ifdef MULTIBYTE_SUPPORT
- } else if ((how & GETKEY_SINGLE_CHAR) &&
- isset(MULTIBYTE) && STOUC(*s) > 127) {
- wint_t wc;
- int len;
- len = mb_metacharlenconv(s, &wc);
- if (wc != WEOF) {
- *misc = (int)wc;
- return s + len;
- }
-#endif
-
- } else if (*s == Meta)
- *t++ = *++s ^ 32;
- else {
- if (itok(*s)) {
- /*
- * We need to be quite careful here. We haven't
- * necessarily got an input stream with all tokens
- * removed, so the majority of tokens need passing
- * through untouched and without Meta handling.
- * However, me may need to handle tokenized
- * backslashes.
- */
- if (meta || control) {
- /*
- * Presumably we should be using meta or control
- * on the character representing the token.
- *
- * Special case: $'\M-\\' where the token is a Bnull.
- * This time we dump the Bnull since we're
- * replacing the whole thing. The lexer
- * doesn't know about the meta or control modifiers.
- */
- if ((how & GETKEY_DOLLAR_QUOTE) && *s == Bnull)
- *t++ = *++s;
- else
- *t++ = ztokens[*s - Pound];
- } else if (how & GETKEY_DOLLAR_QUOTE) {
- /*
- * We don't want to metafy this, it's a real
- * token.
- */
- *tdest++ = *s;
- if (*s == Bnull) {
- /*
- * Bnull is a backslash which quotes a couple
- * of special characters that always appear
- * literally next. See strquote handling
- * in gettokstr() in lex.c. We need
- * to retain the Bnull (as above) so that quote
- * handling in completion can tell where the
- * backslash was.
- */
- *tdest++ = *++s;
- }
- /* reset temporary buffer, now handled */
- t = tbuf;
- continue;
- } else
- *t++ = *s;
- } else
- *t++ = *s;
- }
- if (meta == 2) {
- t[-1] |= 0x80;
- meta = 0;
- }
- if (control) {
- if (t[-1] == '?')
- t[-1] = 0x7f;
- else
- t[-1] &= 0x9f;
- control = 0;
- }
- if (meta) {
- t[-1] |= 0x80;
- meta = 0;
- }
- if (how & GETKEY_DOLLAR_QUOTE) {
- char *t2;
- for (t2 = tbuf; t2 < t; t2++) {
- /*
- * In POSIX mode, an embedded NULL is discarded and
- * terminates processing. It just does, that's why.
- */
- if (isset(POSIXSTRINGS)) {
- if (*t2 == '\0')
- ignoring = 1;
- if (ignoring)
- break;
- }
- if (imeta(*t2)) {
- *tdest++ = Meta;
- *tdest++ = *t2 ^ 32;
- } else {
- *tdest++ = *t2;
- }
- }
- /*
- * Reset use of temporary buffer.
- */
- t = tbuf;
- }
- if ((how & GETKEY_SINGLE_CHAR) && t != tmp) {
- *misc = STOUC(tmp[0]);
- return s + 1;
- }
- }
- /*
- * When called from completion, where we use GETKEY_UPDATE_OFFSET to
- * update the index into the metafied editor line, we don't necessarily
- * have the end of a $'...' quotation, else we should do.
- */
- DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET)) ==
- GETKEY_DOLLAR_QUOTE, "BUG: unterminated $' substitution");
- *t = '\0';
- if (how & GETKEY_DOLLAR_QUOTE)
- *tdest = '\0';
- if (how & GETKEY_SINGLE_CHAR)
- *misc = 0;
- else
- *len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf;
- return buf;
-}
-
-/* Return non-zero if s is a prefix of t. */
-
-/**/
-mod_export int
-strpfx(const char *s, const char *t)
-{
- while (*s && *s == *t)
- s++, t++;
- return !*s;
-}
-
-/* Return non-zero if s is a suffix of t. */
-
-/**/
-mod_export int
-strsfx(char *s, char *t)
-{
- int ls = strlen(s), lt = strlen(t);
-
- if (ls <= lt)
- return !strcmp(t + lt - ls, s);
- return 0;
-}
-
-/**/
-static int
-upchdir(int n)
-{
- char buf[PATH_MAX+1];
- char *s;
- int err = -1;
-
- while (n > 0) {
- for (s = buf; s < buf + PATH_MAX - 4 && n--; )
- *s++ = '.', *s++ = '.', *s++ = '/';
- s[-1] = '\0';
- if (chdir(buf))
- return err;
- err = -2;
- }
- return 0;
-}
-
-/*
- * Initialize a "struct dirsav".
- * The structure will be set to the directory we want to save
- * the first time we change to a different directory.
- */
-
-/**/
-mod_export void
-init_dirsav(Dirsav d)
-{
- d->ino = d->dev = 0;
- d->dirname = NULL;
- d->dirfd = d->level = -1;
-}
-
-/*
- * Change directory, without following symlinks. Returns 0 on success, -1
- * on failure. Sets errno to ENOTDIR if any symlinks are encountered. If
- * fchdir() fails, or the current directory is unreadable, we might end up
- * in an unwanted directory in case of failure.
- *
- * path is an unmetafied but null-terminated string, as needed by system
- * calls.
- */
-
-/**/
-mod_export int
-lchdir(char const *path, struct dirsav *d, int hard)
-{
- char const *pptr;
- int level;
- struct stat st1;
- struct dirsav ds;
-#ifdef HAVE_LSTAT
- char buf[PATH_MAX + 1], *ptr;
- int err;
- struct stat st2;
-#endif
-#ifdef HAVE_FCHDIR
- int close_dir = 0;
-#endif
-
- if (!d) {
- init_dirsav(&ds);
- d = &ds;
- }
-#ifdef HAVE_LSTAT
- if ((*path == '/' || !hard) &&
- (d != &ds || hard)){
-#else
- if (*path == '/') {
-#endif
- level = -1;
-#ifndef HAVE_FCHDIR
- if (!d->dirname)
- zgetdir(d);
-#endif
- } else {
- level = 0;
- if (!d->dev && !d->ino) {
- stat(".", &st1);
- d->dev = st1.st_dev;
- d->ino = st1.st_ino;
- }
- }
-
-#ifdef HAVE_LSTAT
- if (!hard)
-#endif
- {
- if (d != &ds) {
- for (pptr = path; *pptr; level++) {
- while (*pptr && *pptr++ != '/');
- while (*pptr == '/')
- pptr++;
- }
- d->level = level;
- }
- return zchdir((char *) path);
- }
-
-#ifdef HAVE_LSTAT
-#ifdef HAVE_FCHDIR
- if (d->dirfd < 0) {
- close_dir = 1;
- if ((d->dirfd = open(".", O_RDONLY | O_NOCTTY)) < 0 &&
- zgetdir(d) && *d->dirname != '/')
- d->dirfd = open("..", O_RDONLY | O_NOCTTY);
- }
-#endif
- if (*path == '/')
- if (chdir("/") < 0)
- zwarn("failed to chdir(/): %e", errno);
- for(;;) {
- while(*path == '/')
- path++;
- if(!*path) {
- if (d == &ds)
- zsfree(ds.dirname);
- else
- d->level = level;
-#ifdef HAVE_FCHDIR
- if (d->dirfd >=0 && close_dir) {
- close(d->dirfd);
- d->dirfd = -1;
- }
-#endif
- return 0;
- }
- for(pptr = path; *++pptr && *pptr != '/'; ) ;
- if(pptr - path > PATH_MAX) {
- err = ENAMETOOLONG;
- break;
- }
- for(ptr = buf; path != pptr; )
- *ptr++ = *path++;
- *ptr = 0;
- if(lstat(buf, &st1)) {
- err = errno;
- break;
- }
- if(!S_ISDIR(st1.st_mode)) {
- err = ENOTDIR;
- break;
- }
- if(chdir(buf)) {
- err = errno;
- break;
- }
- if (level >= 0)
- level++;
- if(lstat(".", &st2)) {
- err = errno;
- break;
- }
- if(st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
- err = ENOTDIR;
- break;
- }
- }
- if (restoredir(d)) {
- int restoreerr = errno;
- int i;
- /*
- * Failed to restore the directory.
- * Just be definite, cd to root and report the result.
- */
- for (i = 0; i < 2; i++) {
- const char *cdest;
- if (i)
- cdest = "/";
- else {
- if (!home)
- continue;
- cdest = home;
- }
- zsfree(pwd);
- pwd = ztrdup(cdest);
- if (chdir(pwd) == 0)
- break;
- }
- if (i == 2)
- zerr("lost current directory, failed to cd to /: %e", errno);
- else
- zerr("lost current directory: %e: changed to `%s'", restoreerr,
- pwd);
- if (d == &ds)
- zsfree(ds.dirname);
-#ifdef HAVE_FCHDIR
- if (d->dirfd >=0 && close_dir) {
- close(d->dirfd);
- d->dirfd = -1;
- }
-#endif
- errno = err;
- return -2;
- }
- if (d == &ds)
- zsfree(ds.dirname);
-#ifdef HAVE_FCHDIR
- if (d->dirfd >=0 && close_dir) {
- close(d->dirfd);
- d->dirfd = -1;
- }
-#endif
- errno = err;
- return -1;
-#endif /* HAVE_LSTAT */
-}
-
-/**/
-mod_export int
-restoredir(struct dirsav *d)
-{
- int err = 0;
- struct stat sbuf;
-
- if (d->dirname && *d->dirname == '/')
- return chdir(d->dirname);
-#ifdef HAVE_FCHDIR
- if (d->dirfd >= 0) {
- if (!fchdir(d->dirfd)) {
- if (!d->dirname) {
- return 0;
- } else if (chdir(d->dirname)) {
- close(d->dirfd);
- d->dirfd = -1;
- err = -2;
- }
- } else {
- close(d->dirfd);
- d->dirfd = err = -1;
- }
- } else
-#endif
- if (d->level > 0)
- err = upchdir(d->level);
- else if (d->level < 0)
- err = -1;
- if (d->dev || d->ino) {
- stat(".", &sbuf);
- if (sbuf.st_ino != d->ino || sbuf.st_dev != d->dev)
- err = -2;
- }
- return err;
-}
-
-
-/* Check whether the shell is running with privileges in effect. *
- * This is the case if EITHER the euid is zero, OR (if the system *
- * supports POSIX.1e (POSIX.6) capability sets) the process' *
- * Effective or Inheritable capability sets are non-empty. */
-
-/**/
-int
-privasserted(void)
-{
- if(!geteuid())
- return 1;
-#ifdef HAVE_CAP_GET_PROC
- {
- cap_t caps = cap_get_proc();
- if(caps) {
- /* POSIX doesn't define a way to test whether a capability set *
- * is empty or not. Typical. I hope this is conforming... */
- cap_flag_value_t val;
- cap_value_t n;
- for(n = 0; !cap_get_flag(caps, n, CAP_EFFECTIVE, &val); n++)
- if(val) {
- cap_free(caps);
- return 1;
- }
- }
- cap_free(caps);
- }
-#endif /* HAVE_CAP_GET_PROC */
- return 0;
-}
-
-/**/
-mod_export int
-mode_to_octal(mode_t mode)
-{
- int m = 0;
-
- if(mode & S_ISUID)
- m |= 04000;
- if(mode & S_ISGID)
- m |= 02000;
- if(mode & S_ISVTX)
- m |= 01000;
- if(mode & S_IRUSR)
- m |= 00400;
- if(mode & S_IWUSR)
- m |= 00200;
- if(mode & S_IXUSR)
- m |= 00100;
- if(mode & S_IRGRP)
- m |= 00040;
- if(mode & S_IWGRP)
- m |= 00020;
- if(mode & S_IXGRP)
- m |= 00010;
- if(mode & S_IROTH)
- m |= 00004;
- if(mode & S_IWOTH)
- m |= 00002;
- if(mode & S_IXOTH)
- m |= 00001;
- return m;
-}
-
-#ifdef MAILDIR_SUPPORT
-/*
- * Stat a file. If it's a maildir, check all messages
- * in the maildir and present the grand total as a file.
- * The fields in the 'struct stat' are from the mail directory.
- * The following fields are emulated:
- *
- * st_nlink always 1
- * st_size total number of bytes in all files
- * st_blocks total number of messages
- * st_atime access time of newest file in maildir
- * st_mtime modify time of newest file in maildir
- * st_mode S_IFDIR changed to S_IFREG
- *
- * This is good enough for most mail-checking applications.
- */
-
-/**/
-int
-mailstat(char *path, struct stat *st)
-{
- DIR *dd;
- struct dirent *fn;
- struct stat st_ret, st_tmp;
- static struct stat st_ret_last;
- char *dir, *file = 0;
- int i;
- time_t atime = 0, mtime = 0;
- size_t plen = strlen(path), dlen;
-
- /* First see if it's a directory. */
- if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
- return i;
-
- st_ret = *st;
- st_ret.st_nlink = 1;
- st_ret.st_size = 0;
- st_ret.st_blocks = 0;
- st_ret.st_mode &= ~S_IFDIR;
- st_ret.st_mode |= S_IFREG;
-
- /* See if cur/ is present */
- dir = appstr(ztrdup(path), "/cur");
- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
- st_ret.st_atime = st_tmp.st_atime;
-
- /* See if tmp/ is present */
- dir[plen] = 0;
- dir = appstr(dir, "/tmp");
- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
- st_ret.st_mtime = st_tmp.st_mtime;
-
- /* And new/ */
- dir[plen] = 0;
- dir = appstr(dir, "/new");
- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
- st_ret.st_mtime = st_tmp.st_mtime;
-
-#if THERE_IS_EXACTLY_ONE_MAILDIR_IN_MAILPATH
- {
- static struct stat st_new_last;
- /* Optimization - if new/ didn't change, nothing else did. */
- if (st_tmp.st_dev == st_new_last.st_dev &&
- st_tmp.st_ino == st_new_last.st_ino &&
- st_tmp.st_atime == st_new_last.st_atime &&
- st_tmp.st_mtime == st_new_last.st_mtime) {
- *st = st_ret_last;
- return 0;
- }
- st_new_last = st_tmp;
- }
-#endif
-
- /* Loop over new/ and cur/ */
- for (i = 0; i < 2; i++) {
- dir[plen] = 0;
- dir = appstr(dir, i ? "/cur" : "/new");
- if ((dd = opendir(dir)) == NULL) {
- zsfree(file);
- zsfree(dir);
- return 0;
- }
- dlen = strlen(dir) + 1; /* include the "/" */
- while ((fn = readdir(dd)) != NULL) {
- if (fn->d_name[0] == '.')
- continue;
- if (file) {
- file[dlen] = 0;
- file = appstr(file, fn->d_name);
- } else {
- file = tricat(dir, "/", fn->d_name);
- }
- if (stat(file, &st_tmp) != 0)
- continue;
- st_ret.st_size += st_tmp.st_size;
- st_ret.st_blocks++;
- if (st_tmp.st_atime != st_tmp.st_mtime &&
- st_tmp.st_atime > atime)
- atime = st_tmp.st_atime;
- if (st_tmp.st_mtime > mtime)
- mtime = st_tmp.st_mtime;
- }
- closedir(dd);
- }
- zsfree(file);
- zsfree(dir);
-
- if (atime) st_ret.st_atime = atime;
- if (mtime) st_ret.st_mtime = mtime;
-
- *st = st_ret_last = st_ret;
- return 0;
-}
-#endif
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/wcwidth9.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/wcwidth9.h
deleted file mode 100644
index 448f548e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/wcwidth9.h
+++ /dev/null
@@ -1,1325 +0,0 @@
-#ifndef WCWIDTH9_H
-#define WCWIDTH9_H
-
-#include
-#include
-
-struct wcwidth9_interval {
- long first;
- long last;
-};
-
-static const struct wcwidth9_interval wcwidth9_private[] = {
- {0x00e000, 0x00f8ff},
- {0x0f0000, 0x0ffffd},
- {0x100000, 0x10fffd},
-};
-
-static const struct wcwidth9_interval wcwidth9_nonprint[] = {
- {0x0000, 0x001f},
- {0x007f, 0x009f},
- {0x00ad, 0x00ad},
- {0x070f, 0x070f},
- {0x180b, 0x180e},
- {0x200b, 0x200f},
- {0x2028, 0x2029},
- {0x202a, 0x202e},
- {0x206a, 0x206f},
- {0xd800, 0xdfff},
- {0xfeff, 0xfeff},
- {0xfff9, 0xfffb},
- {0xfffe, 0xffff},
-};
-
-static const struct wcwidth9_interval wcwidth9_combining[] = {
- {0x0300, 0x036f},
- {0x0483, 0x0489},
- {0x0591, 0x05bd},
- {0x05bf, 0x05bf},
- {0x05c1, 0x05c2},
- {0x05c4, 0x05c5},
- {0x05c7, 0x05c7},
- {0x0610, 0x061a},
- {0x064b, 0x065f},
- {0x0670, 0x0670},
- {0x06d6, 0x06dc},
- {0x06df, 0x06e4},
- {0x06e7, 0x06e8},
- {0x06ea, 0x06ed},
- {0x0711, 0x0711},
- {0x0730, 0x074a},
- {0x07a6, 0x07b0},
- {0x07eb, 0x07f3},
- {0x0816, 0x0819},
- {0x081b, 0x0823},
- {0x0825, 0x0827},
- {0x0829, 0x082d},
- {0x0859, 0x085b},
- {0x08d4, 0x08e1},
- {0x08e3, 0x0903},
- {0x093a, 0x093c},
- {0x093e, 0x094f},
- {0x0951, 0x0957},
- {0x0962, 0x0963},
- {0x0981, 0x0983},
- {0x09bc, 0x09bc},
- {0x09be, 0x09c4},
- {0x09c7, 0x09c8},
- {0x09cb, 0x09cd},
- {0x09d7, 0x09d7},
- {0x09e2, 0x09e3},
- {0x0a01, 0x0a03},
- {0x0a3c, 0x0a3c},
- {0x0a3e, 0x0a42},
- {0x0a47, 0x0a48},
- {0x0a4b, 0x0a4d},
- {0x0a51, 0x0a51},
- {0x0a70, 0x0a71},
- {0x0a75, 0x0a75},
- {0x0a81, 0x0a83},
- {0x0abc, 0x0abc},
- {0x0abe, 0x0ac5},
- {0x0ac7, 0x0ac9},
- {0x0acb, 0x0acd},
- {0x0ae2, 0x0ae3},
- {0x0b01, 0x0b03},
- {0x0b3c, 0x0b3c},
- {0x0b3e, 0x0b44},
- {0x0b47, 0x0b48},
- {0x0b4b, 0x0b4d},
- {0x0b56, 0x0b57},
- {0x0b62, 0x0b63},
- {0x0b82, 0x0b82},
- {0x0bbe, 0x0bc2},
- {0x0bc6, 0x0bc8},
- {0x0bca, 0x0bcd},
- {0x0bd7, 0x0bd7},
- {0x0c00, 0x0c03},
- {0x0c3e, 0x0c44},
- {0x0c46, 0x0c48},
- {0x0c4a, 0x0c4d},
- {0x0c55, 0x0c56},
- {0x0c62, 0x0c63},
- {0x0c81, 0x0c83},
- {0x0cbc, 0x0cbc},
- {0x0cbe, 0x0cc4},
- {0x0cc6, 0x0cc8},
- {0x0cca, 0x0ccd},
- {0x0cd5, 0x0cd6},
- {0x0ce2, 0x0ce3},
- {0x0d01, 0x0d03},
- {0x0d3e, 0x0d44},
- {0x0d46, 0x0d48},
- {0x0d4a, 0x0d4d},
- {0x0d57, 0x0d57},
- {0x0d62, 0x0d63},
- {0x0d82, 0x0d83},
- {0x0dca, 0x0dca},
- {0x0dcf, 0x0dd4},
- {0x0dd6, 0x0dd6},
- {0x0dd8, 0x0ddf},
- {0x0df2, 0x0df3},
- {0x0e31, 0x0e31},
- {0x0e34, 0x0e3a},
- {0x0e47, 0x0e4e},
- {0x0eb1, 0x0eb1},
- {0x0eb4, 0x0eb9},
- {0x0ebb, 0x0ebc},
- {0x0ec8, 0x0ecd},
- {0x0f18, 0x0f19},
- {0x0f35, 0x0f35},
- {0x0f37, 0x0f37},
- {0x0f39, 0x0f39},
- {0x0f3e, 0x0f3f},
- {0x0f71, 0x0f84},
- {0x0f86, 0x0f87},
- {0x0f8d, 0x0f97},
- {0x0f99, 0x0fbc},
- {0x0fc6, 0x0fc6},
- {0x102b, 0x103e},
- {0x1056, 0x1059},
- {0x105e, 0x1060},
- {0x1062, 0x1064},
- {0x1067, 0x106d},
- {0x1071, 0x1074},
- {0x1082, 0x108d},
- {0x108f, 0x108f},
- {0x109a, 0x109d},
- {0x135d, 0x135f},
- {0x1712, 0x1714},
- {0x1732, 0x1734},
- {0x1752, 0x1753},
- {0x1772, 0x1773},
- {0x17b4, 0x17d3},
- {0x17dd, 0x17dd},
- {0x180b, 0x180d},
- {0x1885, 0x1886},
- {0x18a9, 0x18a9},
- {0x1920, 0x192b},
- {0x1930, 0x193b},
- {0x1a17, 0x1a1b},
- {0x1a55, 0x1a5e},
- {0x1a60, 0x1a7c},
- {0x1a7f, 0x1a7f},
- {0x1ab0, 0x1abe},
- {0x1b00, 0x1b04},
- {0x1b34, 0x1b44},
- {0x1b6b, 0x1b73},
- {0x1b80, 0x1b82},
- {0x1ba1, 0x1bad},
- {0x1be6, 0x1bf3},
- {0x1c24, 0x1c37},
- {0x1cd0, 0x1cd2},
- {0x1cd4, 0x1ce8},
- {0x1ced, 0x1ced},
- {0x1cf2, 0x1cf4},
- {0x1cf8, 0x1cf9},
- {0x1dc0, 0x1df5},
- {0x1dfb, 0x1dff},
- {0x20d0, 0x20f0},
- {0x2cef, 0x2cf1},
- {0x2d7f, 0x2d7f},
- {0x2de0, 0x2dff},
- {0x302a, 0x302f},
- {0x3099, 0x309a},
- {0xa66f, 0xa672},
- {0xa674, 0xa67d},
- {0xa69e, 0xa69f},
- {0xa6f0, 0xa6f1},
- {0xa802, 0xa802},
- {0xa806, 0xa806},
- {0xa80b, 0xa80b},
- {0xa823, 0xa827},
- {0xa880, 0xa881},
- {0xa8b4, 0xa8c5},
- {0xa8e0, 0xa8f1},
- {0xa926, 0xa92d},
- {0xa947, 0xa953},
- {0xa980, 0xa983},
- {0xa9b3, 0xa9c0},
- {0xa9e5, 0xa9e5},
- {0xaa29, 0xaa36},
- {0xaa43, 0xaa43},
- {0xaa4c, 0xaa4d},
- {0xaa7b, 0xaa7d},
- {0xaab0, 0xaab0},
- {0xaab2, 0xaab4},
- {0xaab7, 0xaab8},
- {0xaabe, 0xaabf},
- {0xaac1, 0xaac1},
- {0xaaeb, 0xaaef},
- {0xaaf5, 0xaaf6},
- {0xabe3, 0xabea},
- {0xabec, 0xabed},
- {0xfb1e, 0xfb1e},
- {0xfe00, 0xfe0f},
- {0xfe20, 0xfe2f},
- {0x101fd, 0x101fd},
- {0x102e0, 0x102e0},
- {0x10376, 0x1037a},
- {0x10a01, 0x10a03},
- {0x10a05, 0x10a06},
- {0x10a0c, 0x10a0f},
- {0x10a38, 0x10a3a},
- {0x10a3f, 0x10a3f},
- {0x10ae5, 0x10ae6},
- {0x11000, 0x11002},
- {0x11038, 0x11046},
- {0x1107f, 0x11082},
- {0x110b0, 0x110ba},
- {0x11100, 0x11102},
- {0x11127, 0x11134},
- {0x11173, 0x11173},
- {0x11180, 0x11182},
- {0x111b3, 0x111c0},
- {0x111ca, 0x111cc},
- {0x1122c, 0x11237},
- {0x1123e, 0x1123e},
- {0x112df, 0x112ea},
- {0x11300, 0x11303},
- {0x1133c, 0x1133c},
- {0x1133e, 0x11344},
- {0x11347, 0x11348},
- {0x1134b, 0x1134d},
- {0x11357, 0x11357},
- {0x11362, 0x11363},
- {0x11366, 0x1136c},
- {0x11370, 0x11374},
- {0x11435, 0x11446},
- {0x114b0, 0x114c3},
- {0x115af, 0x115b5},
- {0x115b8, 0x115c0},
- {0x115dc, 0x115dd},
- {0x11630, 0x11640},
- {0x116ab, 0x116b7},
- {0x1171d, 0x1172b},
- {0x11c2f, 0x11c36},
- {0x11c38, 0x11c3f},
- {0x11c92, 0x11ca7},
- {0x11ca9, 0x11cb6},
- {0x16af0, 0x16af4},
- {0x16b30, 0x16b36},
- {0x16f51, 0x16f7e},
- {0x16f8f, 0x16f92},
- {0x1bc9d, 0x1bc9e},
- {0x1d165, 0x1d169},
- {0x1d16d, 0x1d172},
- {0x1d17b, 0x1d182},
- {0x1d185, 0x1d18b},
- {0x1d1aa, 0x1d1ad},
- {0x1d242, 0x1d244},
- {0x1da00, 0x1da36},
- {0x1da3b, 0x1da6c},
- {0x1da75, 0x1da75},
- {0x1da84, 0x1da84},
- {0x1da9b, 0x1da9f},
- {0x1daa1, 0x1daaf},
- {0x1e000, 0x1e006},
- {0x1e008, 0x1e018},
- {0x1e01b, 0x1e021},
- {0x1e023, 0x1e024},
- {0x1e026, 0x1e02a},
- {0x1e8d0, 0x1e8d6},
- {0x1e944, 0x1e94a},
- {0xe0100, 0xe01ef},
-};
-
-static const struct wcwidth9_interval wcwidth9_doublewidth[] = {
- {0x1100, 0x115f},
- {0x231a, 0x231b},
- {0x2329, 0x232a},
- {0x23e9, 0x23ec},
- {0x23f0, 0x23f0},
- {0x23f3, 0x23f3},
- {0x25fd, 0x25fe},
- {0x2614, 0x2615},
- {0x2648, 0x2653},
- {0x267f, 0x267f},
- {0x2693, 0x2693},
- {0x26a1, 0x26a1},
- {0x26aa, 0x26ab},
- {0x26bd, 0x26be},
- {0x26c4, 0x26c5},
- {0x26ce, 0x26ce},
- {0x26d4, 0x26d4},
- {0x26ea, 0x26ea},
- {0x26f2, 0x26f3},
- {0x26f5, 0x26f5},
- {0x26fa, 0x26fa},
- {0x26fd, 0x26fd},
- {0x2705, 0x2705},
- {0x270a, 0x270b},
- {0x2728, 0x2728},
- {0x274c, 0x274c},
- {0x274e, 0x274e},
- {0x2753, 0x2755},
- {0x2757, 0x2757},
- {0x2795, 0x2797},
- {0x27b0, 0x27b0},
- {0x27bf, 0x27bf},
- {0x2b1b, 0x2b1c},
- {0x2b50, 0x2b50},
- {0x2b55, 0x2b55},
- {0x2e80, 0x2e99},
- {0x2e9b, 0x2ef3},
- {0x2f00, 0x2fd5},
- {0x2ff0, 0x2ffb},
- {0x3000, 0x303e},
- {0x3041, 0x3096},
- {0x3099, 0x30ff},
- {0x3105, 0x312d},
- {0x3131, 0x318e},
- {0x3190, 0x31ba},
- {0x31c0, 0x31e3},
- {0x31f0, 0x321e},
- {0x3220, 0x3247},
- {0x3250, 0x32fe},
- {0x3300, 0x4dbf},
- {0x4e00, 0xa48c},
- {0xa490, 0xa4c6},
- {0xa960, 0xa97c},
- {0xac00, 0xd7a3},
- {0xf900, 0xfaff},
- {0xfe10, 0xfe19},
- {0xfe30, 0xfe52},
- {0xfe54, 0xfe66},
- {0xfe68, 0xfe6b},
- {0xff01, 0xff60},
- {0xffe0, 0xffe6},
- {0x16fe0, 0x16fe0},
- {0x17000, 0x187ec},
- {0x18800, 0x18af2},
- {0x1b000, 0x1b001},
- {0x1f004, 0x1f004},
- {0x1f0cf, 0x1f0cf},
- {0x1f18e, 0x1f18e},
- {0x1f191, 0x1f19a},
- {0x1f200, 0x1f202},
- {0x1f210, 0x1f23b},
- {0x1f240, 0x1f248},
- {0x1f250, 0x1f251},
- {0x1f300, 0x1f320},
- {0x1f32d, 0x1f335},
- {0x1f337, 0x1f37c},
- {0x1f37e, 0x1f393},
- {0x1f3a0, 0x1f3ca},
- {0x1f3cf, 0x1f3d3},
- {0x1f3e0, 0x1f3f0},
- {0x1f3f4, 0x1f3f4},
- {0x1f3f8, 0x1f43e},
- {0x1f440, 0x1f440},
- {0x1f442, 0x1f4fc},
- {0x1f4ff, 0x1f53d},
- {0x1f54b, 0x1f54e},
- {0x1f550, 0x1f567},
- {0x1f57a, 0x1f57a},
- {0x1f595, 0x1f596},
- {0x1f5a4, 0x1f5a4},
- {0x1f5fb, 0x1f64f},
- {0x1f680, 0x1f6c5},
- {0x1f6cc, 0x1f6cc},
- {0x1f6d0, 0x1f6d2},
- {0x1f6eb, 0x1f6ec},
- {0x1f6f4, 0x1f6f6},
- {0x1f910, 0x1f91e},
- {0x1f920, 0x1f927},
- {0x1f930, 0x1f930},
- {0x1f933, 0x1f93e},
- {0x1f940, 0x1f94b},
- {0x1f950, 0x1f95e},
- {0x1f980, 0x1f991},
- {0x1f9c0, 0x1f9c0},
- {0x20000, 0x2fffd},
- {0x30000, 0x3fffd},
-};
-
-static const struct wcwidth9_interval wcwidth9_ambiguous[] = {
- {0x00a1, 0x00a1},
- {0x00a4, 0x00a4},
- {0x00a7, 0x00a8},
- {0x00aa, 0x00aa},
- {0x00ad, 0x00ae},
- {0x00b0, 0x00b4},
- {0x00b6, 0x00ba},
- {0x00bc, 0x00bf},
- {0x00c6, 0x00c6},
- {0x00d0, 0x00d0},
- {0x00d7, 0x00d8},
- {0x00de, 0x00e1},
- {0x00e6, 0x00e6},
- {0x00e8, 0x00ea},
- {0x00ec, 0x00ed},
- {0x00f0, 0x00f0},
- {0x00f2, 0x00f3},
- {0x00f7, 0x00fa},
- {0x00fc, 0x00fc},
- {0x00fe, 0x00fe},
- {0x0101, 0x0101},
- {0x0111, 0x0111},
- {0x0113, 0x0113},
- {0x011b, 0x011b},
- {0x0126, 0x0127},
- {0x012b, 0x012b},
- {0x0131, 0x0133},
- {0x0138, 0x0138},
- {0x013f, 0x0142},
- {0x0144, 0x0144},
- {0x0148, 0x014b},
- {0x014d, 0x014d},
- {0x0152, 0x0153},
- {0x0166, 0x0167},
- {0x016b, 0x016b},
- {0x01ce, 0x01ce},
- {0x01d0, 0x01d0},
- {0x01d2, 0x01d2},
- {0x01d4, 0x01d4},
- {0x01d6, 0x01d6},
- {0x01d8, 0x01d8},
- {0x01da, 0x01da},
- {0x01dc, 0x01dc},
- {0x0251, 0x0251},
- {0x0261, 0x0261},
- {0x02c4, 0x02c4},
- {0x02c7, 0x02c7},
- {0x02c9, 0x02cb},
- {0x02cd, 0x02cd},
- {0x02d0, 0x02d0},
- {0x02d8, 0x02db},
- {0x02dd, 0x02dd},
- {0x02df, 0x02df},
- {0x0300, 0x036f},
- {0x0391, 0x03a1},
- {0x03a3, 0x03a9},
- {0x03b1, 0x03c1},
- {0x03c3, 0x03c9},
- {0x0401, 0x0401},
- {0x0410, 0x044f},
- {0x0451, 0x0451},
- {0x2010, 0x2010},
- {0x2013, 0x2016},
- {0x2018, 0x2019},
- {0x201c, 0x201d},
- {0x2020, 0x2022},
- {0x2024, 0x2027},
- {0x2030, 0x2030},
- {0x2032, 0x2033},
- {0x2035, 0x2035},
- {0x203b, 0x203b},
- {0x203e, 0x203e},
- {0x2074, 0x2074},
- {0x207f, 0x207f},
- {0x2081, 0x2084},
- {0x20ac, 0x20ac},
- {0x2103, 0x2103},
- {0x2105, 0x2105},
- {0x2109, 0x2109},
- {0x2113, 0x2113},
- {0x2116, 0x2116},
- {0x2121, 0x2122},
- {0x2126, 0x2126},
- {0x212b, 0x212b},
- {0x2153, 0x2154},
- {0x215b, 0x215e},
- {0x2160, 0x216b},
- {0x2170, 0x2179},
- {0x2189, 0x2189},
- {0x2190, 0x2199},
- {0x21b8, 0x21b9},
- {0x21d2, 0x21d2},
- {0x21d4, 0x21d4},
- {0x21e7, 0x21e7},
- {0x2200, 0x2200},
- {0x2202, 0x2203},
- {0x2207, 0x2208},
- {0x220b, 0x220b},
- {0x220f, 0x220f},
- {0x2211, 0x2211},
- {0x2215, 0x2215},
- {0x221a, 0x221a},
- {0x221d, 0x2220},
- {0x2223, 0x2223},
- {0x2225, 0x2225},
- {0x2227, 0x222c},
- {0x222e, 0x222e},
- {0x2234, 0x2237},
- {0x223c, 0x223d},
- {0x2248, 0x2248},
- {0x224c, 0x224c},
- {0x2252, 0x2252},
- {0x2260, 0x2261},
- {0x2264, 0x2267},
- {0x226a, 0x226b},
- {0x226e, 0x226f},
- {0x2282, 0x2283},
- {0x2286, 0x2287},
- {0x2295, 0x2295},
- {0x2299, 0x2299},
- {0x22a5, 0x22a5},
- {0x22bf, 0x22bf},
- {0x2312, 0x2312},
- {0x2460, 0x24e9},
- {0x24eb, 0x254b},
- {0x2550, 0x2573},
- {0x2580, 0x258f},
- {0x2592, 0x2595},
- {0x25a0, 0x25a1},
- {0x25a3, 0x25a9},
- {0x25b2, 0x25b3},
- {0x25b6, 0x25b7},
- {0x25bc, 0x25bd},
- {0x25c0, 0x25c1},
- {0x25c6, 0x25c8},
- {0x25cb, 0x25cb},
- {0x25ce, 0x25d1},
- {0x25e2, 0x25e5},
- {0x25ef, 0x25ef},
- {0x2605, 0x2606},
- {0x2609, 0x2609},
- {0x260e, 0x260f},
- {0x261c, 0x261c},
- {0x261e, 0x261e},
- {0x2640, 0x2640},
- {0x2642, 0x2642},
- {0x2660, 0x2661},
- {0x2663, 0x2665},
- {0x2667, 0x266a},
- {0x266c, 0x266d},
- {0x266f, 0x266f},
- {0x269e, 0x269f},
- {0x26bf, 0x26bf},
- {0x26c6, 0x26cd},
- {0x26cf, 0x26d3},
- {0x26d5, 0x26e1},
- {0x26e3, 0x26e3},
- {0x26e8, 0x26e9},
- {0x26eb, 0x26f1},
- {0x26f4, 0x26f4},
- {0x26f6, 0x26f9},
- {0x26fb, 0x26fc},
- {0x26fe, 0x26ff},
- {0x273d, 0x273d},
- {0x2776, 0x277f},
- {0x2b56, 0x2b59},
- {0x3248, 0x324f},
- {0xe000, 0xf8ff},
- {0xfe00, 0xfe0f},
- {0xfffd, 0xfffd},
- {0x1f100, 0x1f10a},
- {0x1f110, 0x1f12d},
- {0x1f130, 0x1f169},
- {0x1f170, 0x1f18d},
- {0x1f18f, 0x1f190},
- {0x1f19b, 0x1f1ac},
- {0xe0100, 0xe01ef},
- {0xf0000, 0xffffd},
- {0x100000, 0x10fffd},
-};
-
-static const struct wcwidth9_interval wcwidth9_emoji_width[] = {
- {0x1f1e6, 0x1f1ff},
- {0x1f321, 0x1f321},
- {0x1f324, 0x1f32c},
- {0x1f336, 0x1f336},
- {0x1f37d, 0x1f37d},
- {0x1f396, 0x1f397},
- {0x1f399, 0x1f39b},
- {0x1f39e, 0x1f39f},
- {0x1f3cb, 0x1f3ce},
- {0x1f3d4, 0x1f3df},
- {0x1f3f3, 0x1f3f5},
- {0x1f3f7, 0x1f3f7},
- {0x1f43f, 0x1f43f},
- {0x1f441, 0x1f441},
- {0x1f4fd, 0x1f4fd},
- {0x1f549, 0x1f54a},
- {0x1f56f, 0x1f570},
- {0x1f573, 0x1f579},
- {0x1f587, 0x1f587},
- {0x1f58a, 0x1f58d},
- {0x1f590, 0x1f590},
- {0x1f5a5, 0x1f5a5},
- {0x1f5a8, 0x1f5a8},
- {0x1f5b1, 0x1f5b2},
- {0x1f5bc, 0x1f5bc},
- {0x1f5c2, 0x1f5c4},
- {0x1f5d1, 0x1f5d3},
- {0x1f5dc, 0x1f5de},
- {0x1f5e1, 0x1f5e1},
- {0x1f5e3, 0x1f5e3},
- {0x1f5e8, 0x1f5e8},
- {0x1f5ef, 0x1f5ef},
- {0x1f5f3, 0x1f5f3},
- {0x1f5fa, 0x1f5fa},
- {0x1f6cb, 0x1f6cf},
- {0x1f6e0, 0x1f6e5},
- {0x1f6e9, 0x1f6e9},
- {0x1f6f0, 0x1f6f0},
- {0x1f6f3, 0x1f6f3},
-};
-
-static const struct wcwidth9_interval wcwidth9_not_assigned[] = {
- {0x0378, 0x0379},
- {0x0380, 0x0383},
- {0x038b, 0x038b},
- {0x038d, 0x038d},
- {0x03a2, 0x03a2},
- {0x0530, 0x0530},
- {0x0557, 0x0558},
- {0x0560, 0x0560},
- {0x0588, 0x0588},
- {0x058b, 0x058c},
- {0x0590, 0x0590},
- {0x05c8, 0x05cf},
- {0x05eb, 0x05ef},
- {0x05f5, 0x05ff},
- {0x061d, 0x061d},
- {0x070e, 0x070e},
- {0x074b, 0x074c},
- {0x07b2, 0x07bf},
- {0x07fb, 0x07ff},
- {0x082e, 0x082f},
- {0x083f, 0x083f},
- {0x085c, 0x085d},
- {0x085f, 0x089f},
- {0x08b5, 0x08b5},
- {0x08be, 0x08d3},
- {0x0984, 0x0984},
- {0x098d, 0x098e},
- {0x0991, 0x0992},
- {0x09a9, 0x09a9},
- {0x09b1, 0x09b1},
- {0x09b3, 0x09b5},
- {0x09ba, 0x09bb},
- {0x09c5, 0x09c6},
- {0x09c9, 0x09ca},
- {0x09cf, 0x09d6},
- {0x09d8, 0x09db},
- {0x09de, 0x09de},
- {0x09e4, 0x09e5},
- {0x09fc, 0x0a00},
- {0x0a04, 0x0a04},
- {0x0a0b, 0x0a0e},
- {0x0a11, 0x0a12},
- {0x0a29, 0x0a29},
- {0x0a31, 0x0a31},
- {0x0a34, 0x0a34},
- {0x0a37, 0x0a37},
- {0x0a3a, 0x0a3b},
- {0x0a3d, 0x0a3d},
- {0x0a43, 0x0a46},
- {0x0a49, 0x0a4a},
- {0x0a4e, 0x0a50},
- {0x0a52, 0x0a58},
- {0x0a5d, 0x0a5d},
- {0x0a5f, 0x0a65},
- {0x0a76, 0x0a80},
- {0x0a84, 0x0a84},
- {0x0a8e, 0x0a8e},
- {0x0a92, 0x0a92},
- {0x0aa9, 0x0aa9},
- {0x0ab1, 0x0ab1},
- {0x0ab4, 0x0ab4},
- {0x0aba, 0x0abb},
- {0x0ac6, 0x0ac6},
- {0x0aca, 0x0aca},
- {0x0ace, 0x0acf},
- {0x0ad1, 0x0adf},
- {0x0ae4, 0x0ae5},
- {0x0af2, 0x0af8},
- {0x0afa, 0x0b00},
- {0x0b04, 0x0b04},
- {0x0b0d, 0x0b0e},
- {0x0b11, 0x0b12},
- {0x0b29, 0x0b29},
- {0x0b31, 0x0b31},
- {0x0b34, 0x0b34},
- {0x0b3a, 0x0b3b},
- {0x0b45, 0x0b46},
- {0x0b49, 0x0b4a},
- {0x0b4e, 0x0b55},
- {0x0b58, 0x0b5b},
- {0x0b5e, 0x0b5e},
- {0x0b64, 0x0b65},
- {0x0b78, 0x0b81},
- {0x0b84, 0x0b84},
- {0x0b8b, 0x0b8d},
- {0x0b91, 0x0b91},
- {0x0b96, 0x0b98},
- {0x0b9b, 0x0b9b},
- {0x0b9d, 0x0b9d},
- {0x0ba0, 0x0ba2},
- {0x0ba5, 0x0ba7},
- {0x0bab, 0x0bad},
- {0x0bba, 0x0bbd},
- {0x0bc3, 0x0bc5},
- {0x0bc9, 0x0bc9},
- {0x0bce, 0x0bcf},
- {0x0bd1, 0x0bd6},
- {0x0bd8, 0x0be5},
- {0x0bfb, 0x0bff},
- {0x0c04, 0x0c04},
- {0x0c0d, 0x0c0d},
- {0x0c11, 0x0c11},
- {0x0c29, 0x0c29},
- {0x0c3a, 0x0c3c},
- {0x0c45, 0x0c45},
- {0x0c49, 0x0c49},
- {0x0c4e, 0x0c54},
- {0x0c57, 0x0c57},
- {0x0c5b, 0x0c5f},
- {0x0c64, 0x0c65},
- {0x0c70, 0x0c77},
- {0x0c84, 0x0c84},
- {0x0c8d, 0x0c8d},
- {0x0c91, 0x0c91},
- {0x0ca9, 0x0ca9},
- {0x0cb4, 0x0cb4},
- {0x0cba, 0x0cbb},
- {0x0cc5, 0x0cc5},
- {0x0cc9, 0x0cc9},
- {0x0cce, 0x0cd4},
- {0x0cd7, 0x0cdd},
- {0x0cdf, 0x0cdf},
- {0x0ce4, 0x0ce5},
- {0x0cf0, 0x0cf0},
- {0x0cf3, 0x0d00},
- {0x0d04, 0x0d04},
- {0x0d0d, 0x0d0d},
- {0x0d11, 0x0d11},
- {0x0d3b, 0x0d3c},
- {0x0d45, 0x0d45},
- {0x0d49, 0x0d49},
- {0x0d50, 0x0d53},
- {0x0d64, 0x0d65},
- {0x0d80, 0x0d81},
- {0x0d84, 0x0d84},
- {0x0d97, 0x0d99},
- {0x0db2, 0x0db2},
- {0x0dbc, 0x0dbc},
- {0x0dbe, 0x0dbf},
- {0x0dc7, 0x0dc9},
- {0x0dcb, 0x0dce},
- {0x0dd5, 0x0dd5},
- {0x0dd7, 0x0dd7},
- {0x0de0, 0x0de5},
- {0x0df0, 0x0df1},
- {0x0df5, 0x0e00},
- {0x0e3b, 0x0e3e},
- {0x0e5c, 0x0e80},
- {0x0e83, 0x0e83},
- {0x0e85, 0x0e86},
- {0x0e89, 0x0e89},
- {0x0e8b, 0x0e8c},
- {0x0e8e, 0x0e93},
- {0x0e98, 0x0e98},
- {0x0ea0, 0x0ea0},
- {0x0ea4, 0x0ea4},
- {0x0ea6, 0x0ea6},
- {0x0ea8, 0x0ea9},
- {0x0eac, 0x0eac},
- {0x0eba, 0x0eba},
- {0x0ebe, 0x0ebf},
- {0x0ec5, 0x0ec5},
- {0x0ec7, 0x0ec7},
- {0x0ece, 0x0ecf},
- {0x0eda, 0x0edb},
- {0x0ee0, 0x0eff},
- {0x0f48, 0x0f48},
- {0x0f6d, 0x0f70},
- {0x0f98, 0x0f98},
- {0x0fbd, 0x0fbd},
- {0x0fcd, 0x0fcd},
- {0x0fdb, 0x0fff},
- {0x10c6, 0x10c6},
- {0x10c8, 0x10cc},
- {0x10ce, 0x10cf},
- {0x1249, 0x1249},
- {0x124e, 0x124f},
- {0x1257, 0x1257},
- {0x1259, 0x1259},
- {0x125e, 0x125f},
- {0x1289, 0x1289},
- {0x128e, 0x128f},
- {0x12b1, 0x12b1},
- {0x12b6, 0x12b7},
- {0x12bf, 0x12bf},
- {0x12c1, 0x12c1},
- {0x12c6, 0x12c7},
- {0x12d7, 0x12d7},
- {0x1311, 0x1311},
- {0x1316, 0x1317},
- {0x135b, 0x135c},
- {0x137d, 0x137f},
- {0x139a, 0x139f},
- {0x13f6, 0x13f7},
- {0x13fe, 0x13ff},
- {0x169d, 0x169f},
- {0x16f9, 0x16ff},
- {0x170d, 0x170d},
- {0x1715, 0x171f},
- {0x1737, 0x173f},
- {0x1754, 0x175f},
- {0x176d, 0x176d},
- {0x1771, 0x1771},
- {0x1774, 0x177f},
- {0x17de, 0x17df},
- {0x17ea, 0x17ef},
- {0x17fa, 0x17ff},
- {0x180f, 0x180f},
- {0x181a, 0x181f},
- {0x1878, 0x187f},
- {0x18ab, 0x18af},
- {0x18f6, 0x18ff},
- {0x191f, 0x191f},
- {0x192c, 0x192f},
- {0x193c, 0x193f},
- {0x1941, 0x1943},
- {0x196e, 0x196f},
- {0x1975, 0x197f},
- {0x19ac, 0x19af},
- {0x19ca, 0x19cf},
- {0x19db, 0x19dd},
- {0x1a1c, 0x1a1d},
- {0x1a5f, 0x1a5f},
- {0x1a7d, 0x1a7e},
- {0x1a8a, 0x1a8f},
- {0x1a9a, 0x1a9f},
- {0x1aae, 0x1aaf},
- {0x1abf, 0x1aff},
- {0x1b4c, 0x1b4f},
- {0x1b7d, 0x1b7f},
- {0x1bf4, 0x1bfb},
- {0x1c38, 0x1c3a},
- {0x1c4a, 0x1c4c},
- {0x1c89, 0x1cbf},
- {0x1cc8, 0x1ccf},
- {0x1cf7, 0x1cf7},
- {0x1cfa, 0x1cff},
- {0x1df6, 0x1dfa},
- {0x1f16, 0x1f17},
- {0x1f1e, 0x1f1f},
- {0x1f46, 0x1f47},
- {0x1f4e, 0x1f4f},
- {0x1f58, 0x1f58},
- {0x1f5a, 0x1f5a},
- {0x1f5c, 0x1f5c},
- {0x1f5e, 0x1f5e},
- {0x1f7e, 0x1f7f},
- {0x1fb5, 0x1fb5},
- {0x1fc5, 0x1fc5},
- {0x1fd4, 0x1fd5},
- {0x1fdc, 0x1fdc},
- {0x1ff0, 0x1ff1},
- {0x1ff5, 0x1ff5},
- {0x1fff, 0x1fff},
- {0x2065, 0x2065},
- {0x2072, 0x2073},
- {0x208f, 0x208f},
- {0x209d, 0x209f},
- {0x20bf, 0x20cf},
- {0x20f1, 0x20ff},
- {0x218c, 0x218f},
- {0x23ff, 0x23ff},
- {0x2427, 0x243f},
- {0x244b, 0x245f},
- {0x2b74, 0x2b75},
- {0x2b96, 0x2b97},
- {0x2bba, 0x2bbc},
- {0x2bc9, 0x2bc9},
- {0x2bd2, 0x2beb},
- {0x2bf0, 0x2bff},
- {0x2c2f, 0x2c2f},
- {0x2c5f, 0x2c5f},
- {0x2cf4, 0x2cf8},
- {0x2d26, 0x2d26},
- {0x2d28, 0x2d2c},
- {0x2d2e, 0x2d2f},
- {0x2d68, 0x2d6e},
- {0x2d71, 0x2d7e},
- {0x2d97, 0x2d9f},
- {0x2da7, 0x2da7},
- {0x2daf, 0x2daf},
- {0x2db7, 0x2db7},
- {0x2dbf, 0x2dbf},
- {0x2dc7, 0x2dc7},
- {0x2dcf, 0x2dcf},
- {0x2dd7, 0x2dd7},
- {0x2ddf, 0x2ddf},
- {0x2e45, 0x2e7f},
- {0x2e9a, 0x2e9a},
- {0x2ef4, 0x2eff},
- {0x2fd6, 0x2fef},
- {0x2ffc, 0x2fff},
- {0x3040, 0x3040},
- {0x3097, 0x3098},
- {0x3100, 0x3104},
- {0x312e, 0x3130},
- {0x318f, 0x318f},
- {0x31bb, 0x31bf},
- {0x31e4, 0x31ef},
- {0x321f, 0x321f},
- {0x32ff, 0x32ff},
- {0x4db6, 0x4dbf},
- {0x9fd6, 0x9fff},
- {0xa48d, 0xa48f},
- {0xa4c7, 0xa4cf},
- {0xa62c, 0xa63f},
- {0xa6f8, 0xa6ff},
- {0xa7af, 0xa7af},
- {0xa7b8, 0xa7f6},
- {0xa82c, 0xa82f},
- {0xa83a, 0xa83f},
- {0xa878, 0xa87f},
- {0xa8c6, 0xa8cd},
- {0xa8da, 0xa8df},
- {0xa8fe, 0xa8ff},
- {0xa954, 0xa95e},
- {0xa97d, 0xa97f},
- {0xa9ce, 0xa9ce},
- {0xa9da, 0xa9dd},
- {0xa9ff, 0xa9ff},
- {0xaa37, 0xaa3f},
- {0xaa4e, 0xaa4f},
- {0xaa5a, 0xaa5b},
- {0xaac3, 0xaada},
- {0xaaf7, 0xab00},
- {0xab07, 0xab08},
- {0xab0f, 0xab10},
- {0xab17, 0xab1f},
- {0xab27, 0xab27},
- {0xab2f, 0xab2f},
- {0xab66, 0xab6f},
- {0xabee, 0xabef},
- {0xabfa, 0xabff},
- {0xd7a4, 0xd7af},
- {0xd7c7, 0xd7ca},
- {0xd7fc, 0xd7ff},
- {0xfa6e, 0xfa6f},
- {0xfada, 0xfaff},
- {0xfb07, 0xfb12},
- {0xfb18, 0xfb1c},
- {0xfb37, 0xfb37},
- {0xfb3d, 0xfb3d},
- {0xfb3f, 0xfb3f},
- {0xfb42, 0xfb42},
- {0xfb45, 0xfb45},
- {0xfbc2, 0xfbd2},
- {0xfd40, 0xfd4f},
- {0xfd90, 0xfd91},
- {0xfdc8, 0xfdef},
- {0xfdfe, 0xfdff},
- {0xfe1a, 0xfe1f},
- {0xfe53, 0xfe53},
- {0xfe67, 0xfe67},
- {0xfe6c, 0xfe6f},
- {0xfe75, 0xfe75},
- {0xfefd, 0xfefe},
- {0xff00, 0xff00},
- {0xffbf, 0xffc1},
- {0xffc8, 0xffc9},
- {0xffd0, 0xffd1},
- {0xffd8, 0xffd9},
- {0xffdd, 0xffdf},
- {0xffe7, 0xffe7},
- {0xffef, 0xfff8},
- {0xfffe, 0xffff},
- {0x1000c, 0x1000c},
- {0x10027, 0x10027},
- {0x1003b, 0x1003b},
- {0x1003e, 0x1003e},
- {0x1004e, 0x1004f},
- {0x1005e, 0x1007f},
- {0x100fb, 0x100ff},
- {0x10103, 0x10106},
- {0x10134, 0x10136},
- {0x1018f, 0x1018f},
- {0x1019c, 0x1019f},
- {0x101a1, 0x101cf},
- {0x101fe, 0x1027f},
- {0x1029d, 0x1029f},
- {0x102d1, 0x102df},
- {0x102fc, 0x102ff},
- {0x10324, 0x1032f},
- {0x1034b, 0x1034f},
- {0x1037b, 0x1037f},
- {0x1039e, 0x1039e},
- {0x103c4, 0x103c7},
- {0x103d6, 0x103ff},
- {0x1049e, 0x1049f},
- {0x104aa, 0x104af},
- {0x104d4, 0x104d7},
- {0x104fc, 0x104ff},
- {0x10528, 0x1052f},
- {0x10564, 0x1056e},
- {0x10570, 0x105ff},
- {0x10737, 0x1073f},
- {0x10756, 0x1075f},
- {0x10768, 0x107ff},
- {0x10806, 0x10807},
- {0x10809, 0x10809},
- {0x10836, 0x10836},
- {0x10839, 0x1083b},
- {0x1083d, 0x1083e},
- {0x10856, 0x10856},
- {0x1089f, 0x108a6},
- {0x108b0, 0x108df},
- {0x108f3, 0x108f3},
- {0x108f6, 0x108fa},
- {0x1091c, 0x1091e},
- {0x1093a, 0x1093e},
- {0x10940, 0x1097f},
- {0x109b8, 0x109bb},
- {0x109d0, 0x109d1},
- {0x10a04, 0x10a04},
- {0x10a07, 0x10a0b},
- {0x10a14, 0x10a14},
- {0x10a18, 0x10a18},
- {0x10a34, 0x10a37},
- {0x10a3b, 0x10a3e},
- {0x10a48, 0x10a4f},
- {0x10a59, 0x10a5f},
- {0x10aa0, 0x10abf},
- {0x10ae7, 0x10aea},
- {0x10af7, 0x10aff},
- {0x10b36, 0x10b38},
- {0x10b56, 0x10b57},
- {0x10b73, 0x10b77},
- {0x10b92, 0x10b98},
- {0x10b9d, 0x10ba8},
- {0x10bb0, 0x10bff},
- {0x10c49, 0x10c7f},
- {0x10cb3, 0x10cbf},
- {0x10cf3, 0x10cf9},
- {0x10d00, 0x10e5f},
- {0x10e7f, 0x10fff},
- {0x1104e, 0x11051},
- {0x11070, 0x1107e},
- {0x110c2, 0x110cf},
- {0x110e9, 0x110ef},
- {0x110fa, 0x110ff},
- {0x11135, 0x11135},
- {0x11144, 0x1114f},
- {0x11177, 0x1117f},
- {0x111ce, 0x111cf},
- {0x111e0, 0x111e0},
- {0x111f5, 0x111ff},
- {0x11212, 0x11212},
- {0x1123f, 0x1127f},
- {0x11287, 0x11287},
- {0x11289, 0x11289},
- {0x1128e, 0x1128e},
- {0x1129e, 0x1129e},
- {0x112aa, 0x112af},
- {0x112eb, 0x112ef},
- {0x112fa, 0x112ff},
- {0x11304, 0x11304},
- {0x1130d, 0x1130e},
- {0x11311, 0x11312},
- {0x11329, 0x11329},
- {0x11331, 0x11331},
- {0x11334, 0x11334},
- {0x1133a, 0x1133b},
- {0x11345, 0x11346},
- {0x11349, 0x1134a},
- {0x1134e, 0x1134f},
- {0x11351, 0x11356},
- {0x11358, 0x1135c},
- {0x11364, 0x11365},
- {0x1136d, 0x1136f},
- {0x11375, 0x113ff},
- {0x1145a, 0x1145a},
- {0x1145c, 0x1145c},
- {0x1145e, 0x1147f},
- {0x114c8, 0x114cf},
- {0x114da, 0x1157f},
- {0x115b6, 0x115b7},
- {0x115de, 0x115ff},
- {0x11645, 0x1164f},
- {0x1165a, 0x1165f},
- {0x1166d, 0x1167f},
- {0x116b8, 0x116bf},
- {0x116ca, 0x116ff},
- {0x1171a, 0x1171c},
- {0x1172c, 0x1172f},
- {0x11740, 0x1189f},
- {0x118f3, 0x118fe},
- {0x11900, 0x11abf},
- {0x11af9, 0x11bff},
- {0x11c09, 0x11c09},
- {0x11c37, 0x11c37},
- {0x11c46, 0x11c4f},
- {0x11c6d, 0x11c6f},
- {0x11c90, 0x11c91},
- {0x11ca8, 0x11ca8},
- {0x11cb7, 0x11fff},
- {0x1239a, 0x123ff},
- {0x1246f, 0x1246f},
- {0x12475, 0x1247f},
- {0x12544, 0x12fff},
- {0x1342f, 0x143ff},
- {0x14647, 0x167ff},
- {0x16a39, 0x16a3f},
- {0x16a5f, 0x16a5f},
- {0x16a6a, 0x16a6d},
- {0x16a70, 0x16acf},
- {0x16aee, 0x16aef},
- {0x16af6, 0x16aff},
- {0x16b46, 0x16b4f},
- {0x16b5a, 0x16b5a},
- {0x16b62, 0x16b62},
- {0x16b78, 0x16b7c},
- {0x16b90, 0x16eff},
- {0x16f45, 0x16f4f},
- {0x16f7f, 0x16f8e},
- {0x16fa0, 0x16fdf},
- {0x16fe1, 0x16fff},
- {0x187ed, 0x187ff},
- {0x18af3, 0x1afff},
- {0x1b002, 0x1bbff},
- {0x1bc6b, 0x1bc6f},
- {0x1bc7d, 0x1bc7f},
- {0x1bc89, 0x1bc8f},
- {0x1bc9a, 0x1bc9b},
- {0x1bca4, 0x1cfff},
- {0x1d0f6, 0x1d0ff},
- {0x1d127, 0x1d128},
- {0x1d1e9, 0x1d1ff},
- {0x1d246, 0x1d2ff},
- {0x1d357, 0x1d35f},
- {0x1d372, 0x1d3ff},
- {0x1d455, 0x1d455},
- {0x1d49d, 0x1d49d},
- {0x1d4a0, 0x1d4a1},
- {0x1d4a3, 0x1d4a4},
- {0x1d4a7, 0x1d4a8},
- {0x1d4ad, 0x1d4ad},
- {0x1d4ba, 0x1d4ba},
- {0x1d4bc, 0x1d4bc},
- {0x1d4c4, 0x1d4c4},
- {0x1d506, 0x1d506},
- {0x1d50b, 0x1d50c},
- {0x1d515, 0x1d515},
- {0x1d51d, 0x1d51d},
- {0x1d53a, 0x1d53a},
- {0x1d53f, 0x1d53f},
- {0x1d545, 0x1d545},
- {0x1d547, 0x1d549},
- {0x1d551, 0x1d551},
- {0x1d6a6, 0x1d6a7},
- {0x1d7cc, 0x1d7cd},
- {0x1da8c, 0x1da9a},
- {0x1daa0, 0x1daa0},
- {0x1dab0, 0x1dfff},
- {0x1e007, 0x1e007},
- {0x1e019, 0x1e01a},
- {0x1e022, 0x1e022},
- {0x1e025, 0x1e025},
- {0x1e02b, 0x1e7ff},
- {0x1e8c5, 0x1e8c6},
- {0x1e8d7, 0x1e8ff},
- {0x1e94b, 0x1e94f},
- {0x1e95a, 0x1e95d},
- {0x1e960, 0x1edff},
- {0x1ee04, 0x1ee04},
- {0x1ee20, 0x1ee20},
- {0x1ee23, 0x1ee23},
- {0x1ee25, 0x1ee26},
- {0x1ee28, 0x1ee28},
- {0x1ee33, 0x1ee33},
- {0x1ee38, 0x1ee38},
- {0x1ee3a, 0x1ee3a},
- {0x1ee3c, 0x1ee41},
- {0x1ee43, 0x1ee46},
- {0x1ee48, 0x1ee48},
- {0x1ee4a, 0x1ee4a},
- {0x1ee4c, 0x1ee4c},
- {0x1ee50, 0x1ee50},
- {0x1ee53, 0x1ee53},
- {0x1ee55, 0x1ee56},
- {0x1ee58, 0x1ee58},
- {0x1ee5a, 0x1ee5a},
- {0x1ee5c, 0x1ee5c},
- {0x1ee5e, 0x1ee5e},
- {0x1ee60, 0x1ee60},
- {0x1ee63, 0x1ee63},
- {0x1ee65, 0x1ee66},
- {0x1ee6b, 0x1ee6b},
- {0x1ee73, 0x1ee73},
- {0x1ee78, 0x1ee78},
- {0x1ee7d, 0x1ee7d},
- {0x1ee7f, 0x1ee7f},
- {0x1ee8a, 0x1ee8a},
- {0x1ee9c, 0x1eea0},
- {0x1eea4, 0x1eea4},
- {0x1eeaa, 0x1eeaa},
- {0x1eebc, 0x1eeef},
- {0x1eef2, 0x1efff},
- {0x1f02c, 0x1f02f},
- {0x1f094, 0x1f09f},
- {0x1f0af, 0x1f0b0},
- {0x1f0c0, 0x1f0c0},
- {0x1f0d0, 0x1f0d0},
- {0x1f0f6, 0x1f0ff},
- {0x1f10d, 0x1f10f},
- {0x1f12f, 0x1f12f},
- {0x1f16c, 0x1f16f},
- {0x1f1ad, 0x1f1e5},
- {0x1f203, 0x1f20f},
- {0x1f23c, 0x1f23f},
- {0x1f249, 0x1f24f},
- {0x1f252, 0x1f2ff},
- {0x1f6d3, 0x1f6df},
- {0x1f6ed, 0x1f6ef},
- {0x1f6f7, 0x1f6ff},
- {0x1f774, 0x1f77f},
- {0x1f7d5, 0x1f7ff},
- {0x1f80c, 0x1f80f},
- {0x1f848, 0x1f84f},
- {0x1f85a, 0x1f85f},
- {0x1f888, 0x1f88f},
- {0x1f8ae, 0x1f90f},
- {0x1f91f, 0x1f91f},
- {0x1f928, 0x1f92f},
- {0x1f931, 0x1f932},
- {0x1f93f, 0x1f93f},
- {0x1f94c, 0x1f94f},
- {0x1f95f, 0x1f97f},
- {0x1f992, 0x1f9bf},
- {0x1f9c1, 0x1ffff},
- {0x2a6d7, 0x2a6ff},
- {0x2b735, 0x2b73f},
- {0x2b81e, 0x2b81f},
- {0x2cea2, 0x2f7ff},
- {0x2fa1e, 0xe0000},
- {0xe0002, 0xe001f},
- {0xe0080, 0xe00ff},
- {0xe01f0, 0xeffff},
- {0xffffe, 0xfffff},
-};
-
-#define WCWIDTH9_ARRAY_SIZE(arr) ((sizeof(arr)/sizeof((arr)[0])) / ((size_t)(!(sizeof(arr) % sizeof((arr)[0])))))
-
-static inline bool wcwidth9_intable(const struct wcwidth9_interval *table, size_t n_items, int c) {
- int mid, bot, top;
-
- if (c < table[0].first) {
- return false;
- }
-
- bot = 0;
- top = (int)(n_items - 1);
- while (top >= bot) {
- mid = (bot + top) / 2;
-
- if (table[mid].last < c) {
- bot = mid + 1;
- } else if (table[mid].first > c) {
- top = mid - 1;
- } else {
- return true;
- }
- }
-
- return false;
-}
-
-static inline int wcwidth9(int c) {
- if (c == 0) {
- return 0;
- }
- if (c < 0|| c > 0x10ffff) {
- return -1;
- }
-
- if (wcwidth9_intable(wcwidth9_nonprint, WCWIDTH9_ARRAY_SIZE(wcwidth9_nonprint), c)) {
- return -1;
- }
-
- if (wcwidth9_intable(wcwidth9_combining, WCWIDTH9_ARRAY_SIZE(wcwidth9_combining), c)) {
- return 0;
- }
-
- if (wcwidth9_intable(wcwidth9_not_assigned, WCWIDTH9_ARRAY_SIZE(wcwidth9_not_assigned), c)) {
- return -1;
- }
-
- if (wcwidth9_intable(wcwidth9_private, WCWIDTH9_ARRAY_SIZE(wcwidth9_private), c)) {
- return -3;
- }
-
- if (wcwidth9_intable(wcwidth9_ambiguous, WCWIDTH9_ARRAY_SIZE(wcwidth9_ambiguous), c)) {
- return -2;
- }
-
- if (wcwidth9_intable(wcwidth9_doublewidth, WCWIDTH9_ARRAY_SIZE(wcwidth9_doublewidth), c)) {
- return 2;
- }
-
- if (wcwidth9_intable(wcwidth9_emoji_width, WCWIDTH9_ARRAY_SIZE(wcwidth9_emoji_width), c)) {
- return 2;
- }
-
- return 1;
-}
-
-#endif /* WCWIDTH9_H */
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.h
deleted file mode 100644
index 8e7f20b2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.h
+++ /dev/null
@@ -1,3305 +0,0 @@
-/*
- * zsh.h - standard 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.
- *
- */
-
-/* A few typical macros */
-#define minimum(a,b) ((a) < (b) ? (a) : (b))
-
-/*
- * Our longest integer type: will be a 64 bit either if long already is,
- * or if we found some alternative such as long long.
- */
-#ifdef ZSH_64_BIT_TYPE
-typedef ZSH_64_BIT_TYPE zlong;
-#if defined(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX)
-#define ZLONG_MAX LLONG_MAX
-#else
-#ifdef ZLONG_IS_LONG_64
-#define ZLONG_MAX LONG_MAX
-#else
-/* umm... */
-#define ZLONG_MAX ((zlong)9223372036854775807)
-#endif
-#endif
-#ifdef ZSH_64_BIT_UTYPE
-typedef ZSH_64_BIT_UTYPE zulong;
-#else
-typedef unsigned zlong zulong;
-#endif
-#else
-typedef long zlong;
-typedef unsigned long zulong;
-#define ZLONG_MAX LONG_MAX
-#endif
-
-/*
- * Work out how to define large integer constants that will fit
- * in a zlong.
- */
-#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
-/* We have some 64-bit type */
-#ifdef LONG_IS_64_BIT
-/* It's long */
-#define ZLONG_CONST(x) x ## l
-#else
-/* It's long long */
-#ifdef ZLONG_IS_LONG_LONG
-#define ZLONG_CONST(x) x ## ll
-#else
-/*
- * There's some 64-bit type, but we don't know what it is.
- * We'll just cast it and hope the compiler does the right thing.
- */
-#define ZLONG_CONST(x) ((zlong)x)
-#endif
-#endif
-#else
-/* We're stuck with long */
-#define ZLONG_CONST(x) (x ## l)
-#endif
-
-/*
- * Double float support requires 64-bit alignment, so if longs and
- * pointers are less we need to pad out.
- */
-#ifndef LONG_IS_64_BIT
-# define PAD_64_BIT 1
-#endif
-
-/* math.c */
-typedef struct {
- union {
- zlong l;
- double d;
- } u;
- int type;
-} mnumber;
-
-#define MN_INTEGER 1 /* mnumber is integer */
-#define MN_FLOAT 2 /* mnumber is floating point */
-#define MN_UNSET 4 /* mnumber not yet retrieved */
-
-typedef struct mathfunc *MathFunc;
-typedef mnumber (*NumMathFunc)(char *, int, mnumber *, int);
-typedef mnumber (*StrMathFunc)(char *, char *, int);
-
-struct mathfunc {
- MathFunc next;
- char *name;
- int flags; /* MFF_* flags defined below */
- NumMathFunc nfunc;
- StrMathFunc sfunc;
- char *module;
- int minargs;
- int maxargs;
- int funcid;
-};
-
-/* Math function takes a string argument */
-#define MFF_STR 1
-/* Math function has been loaded from library */
-#define MFF_ADDED 2
-/* Math function is implemented by a shell function */
-#define MFF_USERFUNC 4
-/* When autoloading, enable all features in module */
-#define MFF_AUTOALL 8
-
-
-#define NUMMATHFUNC(name, func, min, max, id) \
- { NULL, name, 0, func, NULL, NULL, min, max, id }
-#define STRMATHFUNC(name, func, id) \
- { NULL, name, MFF_STR, NULL, func, NULL, 0, 0, id }
-
-/* Character tokens are sometimes casted to (unsigned char)'s. *
- * Unfortunately, some compilers don't correctly cast signed to *
- * unsigned promotions; i.e. (int)(unsigned char)((char) -1) evaluates *
- * to -1, instead of 255 like it should. We circumvent the troubles *
- * of such shameful delinquency by casting to a larger unsigned type *
- * then back down to unsigned char. */
-
-#ifdef BROKEN_SIGNED_TO_UNSIGNED_CASTING
-# define STOUC(X) ((unsigned char)(unsigned short)(X))
-#else
-# define STOUC(X) ((unsigned char)(X))
-#endif
-
-/* Meta together with the character following Meta denotes the character *
- * which is the exclusive or of 32 and the character following Meta. *
- * This is used to represent characters which otherwise has special *
- * meaning for zsh. These are the characters for which the imeta() test *
- * is true: the null character, and the characters from Meta to Marker. */
-
-#define Meta ((char) 0x83)
-
-/* Note that the fourth character in DEFAULT_IFS is Meta *
- * followed by a space which denotes the null character. */
-
-#define DEFAULT_IFS " \t\n\203 "
-
-/* As specified in the standard (POSIX 2008) */
-
-#define DEFAULT_IFS_SH " \t\n"
-
-/*
- * Character tokens.
- * These should match the characters in ztokens, defined in lex.c
- */
-#define Pound ((char) 0x84)
-#define String ((char) 0x85)
-#define Hat ((char) 0x86)
-#define Star ((char) 0x87)
-#define Inpar ((char) 0x88)
-#define Inparmath ((char) 0x89)
-#define Outpar ((char) 0x8a)
-#define Outparmath ((char) 0x8b)
-#define Qstring ((char) 0x8c)
-#define Equals ((char) 0x8d)
-#define Bar ((char) 0x8e)
-#define Inbrace ((char) 0x8f)
-#define Outbrace ((char) 0x90)
-#define Inbrack ((char) 0x91)
-#define Outbrack ((char) 0x92)
-#define Tick ((char) 0x93)
-#define Inang ((char) 0x94)
-#define Outang ((char) 0x95)
-#define OutangProc ((char) 0x96)
-#define Quest ((char) 0x97)
-#define Tilde ((char) 0x98)
-#define Qtick ((char) 0x99)
-#define Comma ((char) 0x9a)
-#define Dash ((char) 0x9b) /* Only in patterns */
-#define Bang ((char) 0x9c) /* Only in patterns */
-/*
- * Marks the last of the group above.
- * Remaining tokens are even more special.
- */
-#define LAST_NORMAL_TOK Bang
-/*
- * Null arguments: placeholders for single and double quotes
- * and backslashes.
- */
-#define Snull ((char) 0x9d)
-#define Dnull ((char) 0x9e)
-#define Bnull ((char) 0x9f)
-/*
- * Backslash which will be returned to "\" instead of being stripped
- * when we turn the string into a printable format.
- */
-#define Bnullkeep ((char) 0xa0)
-/*
- * Null argument that does not correspond to any character.
- * This should be last as it does not appear in ztokens and
- * is used to initialise the IMETA type in inittyptab().
- */
-#define Nularg ((char) 0xa1)
-
-/*
- * Take care to update the use of IMETA appropriately when adding
- * tokens here.
- */
-/*
- * Marker is used in the following special circumstances:
- * - In paramsubst for rc_expand_param.
- * - In pattern character arrays as guaranteed not to mark a character in
- * a string.
- * - In assignments with the ASSPM_KEY_VALUE flag set in order to
- * mark that there is a key / value pair following. If this
- * comes from [key]=value the Marker is followed by a null;
- * if from [key]+=value the Marker is followed by a '+' then a null.
- * All the above are local uses --- any case where the Marker has
- * escaped beyond the context in question is an error.
- */
-#define Marker ((char) 0xa2)
-
-/* chars that need to be quoted if meant literally */
-
-#define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\""
-
-/* chars that need to be quoted for pattern matching */
-
-#define PATCHARS "#^*()|[]<>?~\\"
-
-/*
- * Check for a possibly tokenized dash.
- *
- * A dash only needs to be a token in a character range, [a-z], but
- * it's difficult in general to ensure that. So it's turned into
- * a token at the usual point in the lexer. However, we need
- * to check for a literal dash at many points.
- */
-#define IS_DASH(x) ((x) == '-' || (x) == Dash)
-
-/*
- * Types of quote. This is used in various places, so care needs
- * to be taken when changing them. (Oooh, don't you look surprised.)
- * - Passed to quotestring() to indicate style. This is the ultimate
- * destiny of most of the other uses of members of the enum.
- * - In paramsubst(), to count q's in parameter substitution.
- * - In the completion code, where we maintain a stack of quotation types.
- */
-enum {
- /*
- * No quote. Not a valid quote, but useful in the substitution
- * and completion code to indicate we're not doing any quoting.
- */
- QT_NONE,
- /* Backslash: \ */
- QT_BACKSLASH,
- /* Single quote: ' */
- QT_SINGLE,
- /* Double quote: " */
- QT_DOUBLE,
- /* Print-style quote: $' */
- QT_DOLLARS,
- /*
- * Backtick: `
- * Not understood by many parts of the code; here for a convenience
- * in those cases where we need to represent a complete set.
- */
- QT_BACKTICK,
- /*
- * Single quotes, but the default is not to quote unless necessary.
- * This is only useful as an argument to quotestring().
- */
- QT_SINGLE_OPTIONAL,
- /*
- * Only quote pattern characters.
- * ${(b)foo} guarantees that ${~foo} matches the string
- * contained in foo.
- */
- QT_BACKSLASH_PATTERN,
- /*
- * As QT_BACKSLASH, but a NULL string is shown as ''.
- */
- QT_BACKSLASH_SHOWNULL,
- /*
- * Quoting as produced by quotedzputs(), used for human
- * readability of parameter values.
- */
- QT_QUOTEDZPUTS
-};
-
-#define QT_IS_SINGLE(x) ((x) == QT_SINGLE || (x) == QT_SINGLE_OPTIONAL)
-
-/*
- * Lexical tokens: unlike the character tokens above, these never
- * appear in strings and don't necessarily represent a single character.
- */
-
-enum lextok {
- NULLTOK, /* 0 */
- SEPER,
- NEWLIN,
- SEMI,
- DSEMI,
- AMPER, /* 5 */
- INPAR,
- OUTPAR,
- DBAR,
- DAMPER,
- OUTANG, /* 10 */
- OUTANGBANG,
- DOUTANG,
- DOUTANGBANG,
- INANG,
- INOUTANG, /* 15 */
- DINANG,
- DINANGDASH,
- INANGAMP,
- OUTANGAMP,
- AMPOUTANG, /* 20 */
- OUTANGAMPBANG,
- DOUTANGAMP,
- DOUTANGAMPBANG,
- TRINANG,
- BAR, /* 25 */
- BARAMP,
- INOUTPAR,
- DINPAR,
- DOUTPAR,
- AMPERBANG, /* 30 */
- SEMIAMP,
- SEMIBAR,
- DOUTBRACK,
- STRING,
- ENVSTRING, /* 35 */
- ENVARRAY,
- ENDINPUT,
- LEXERR,
-
- /* Tokens for reserved words */
- BANG, /* ! */
- DINBRACK, /* [[ */ /* 40 */
- INBRACE, /* { */
- OUTBRACE, /* } */
- CASE, /* case */
- COPROC, /* coproc */
- DOLOOP, /* do */ /* 45 */
- DONE, /* done */
- ELIF, /* elif */
- ELSE, /* else */
- ZEND, /* end */
- ESAC, /* esac */ /* 50 */
- FI, /* fi */
- FOR, /* for */
- FOREACH, /* foreach */
- FUNC, /* function */
- IF, /* if */ /* 55 */
- NOCORRECT, /* nocorrect */
- REPEAT, /* repeat */
- SELECT, /* select */
- THEN, /* then */
- TIME, /* time */ /* 60 */
- UNTIL, /* until */
- WHILE, /* while */
- TYPESET /* typeset or similar */
-};
-
-/* Redirection types. If you modify this, you may also have to modify *
- * redirtab in parse.c and getredirs() in text.c and the IS_* macros *
- * below. */
-
-enum {
- REDIR_WRITE, /* > */
- REDIR_WRITENOW, /* >| */
- REDIR_APP, /* >> */
- REDIR_APPNOW, /* >>| */
- REDIR_ERRWRITE, /* &>, >& */
- REDIR_ERRWRITENOW, /* >&| */
- REDIR_ERRAPP, /* >>& */
- REDIR_ERRAPPNOW, /* >>&| */
- REDIR_READWRITE, /* <> */
- REDIR_READ, /* < */
- REDIR_HEREDOC, /* << */
- REDIR_HEREDOCDASH, /* <<- */
- REDIR_HERESTR, /* <<< */
- REDIR_MERGEIN, /* <&n */
- REDIR_MERGEOUT, /* >&n */
- REDIR_CLOSE, /* >&-, <&- */
- REDIR_INPIPE, /* < <(...) */
- REDIR_OUTPIPE /* > >(...) */
-};
-#define REDIR_TYPE_MASK (0x1f)
-/* Redir using {var} syntax */
-#define REDIR_VARID_MASK (0x20)
-/* Mark here-string that came from a here-document */
-#define REDIR_FROM_HEREDOC_MASK (0x40)
-
-#define IS_WRITE_FILE(X) ((X)>=REDIR_WRITE && (X)<=REDIR_READWRITE)
-#define IS_APPEND_REDIR(X) (IS_WRITE_FILE(X) && ((X) & 2))
-#define IS_CLOBBER_REDIR(X) (IS_WRITE_FILE(X) && ((X) & 1))
-#define IS_ERROR_REDIR(X) ((X)>=REDIR_ERRWRITE && (X)<=REDIR_ERRAPPNOW)
-#define IS_READFD(X) (((X)>=REDIR_READWRITE && (X)<=REDIR_MERGEIN) || (X)==REDIR_INPIPE)
-#define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG)
-
-/*
- * Values for the fdtable array. They say under what circumstances
- * the fd will be close. The fdtable is an unsigned char, so these are
- * #define's rather than an enum.
- */
-/* Entry not used. */
-#define FDT_UNUSED 0
-/*
- * Entry used internally by the shell, should not be visible to other
- * processes.
- */
-#define FDT_INTERNAL 1
-/*
- * Entry visible to other processes, for example created using
- * the {varid}> file syntax.
- */
-#define FDT_EXTERNAL 2
-/*
- * Entry visible to other processes but controlled by a module.
- * The difference from FDT_EXTERNAL is that closing this using
- * standard fd syntax will fail as there is some tidying up that
- * needs to be done by the module's own mechanism.
- */
-#define FDT_MODULE 3
-/*
- * Entry used by output from the XTRACE option.
- */
-#define FDT_XTRACE 4
-/*
- * Entry used for file locking.
- */
-#define FDT_FLOCK 5
-/*
- * As above, but the fd is not marked for closing on exec,
- * so the shell can still exec the last process.
- */
-#define FDT_FLOCK_EXEC 6
-/*
- * Entry used by a process substition.
- * This marker is not tested internally as we associated the file
- * descriptor with a job for closing.
- *
- * This is not used unless PATH_DEV_FD is defined.
- */
-#define FDT_PROC_SUBST 7
-/*
- * Mask to get the basic FDT type.
- */
-#define FDT_TYPE_MASK 15
-
-/*
- * Bit flag that fd is saved for later restoration.
- * Currently this is only use with FDT_INTERNAL. We use this fact so as
- * not to have to mask checks against other types.
- */
-#define FDT_SAVED_MASK 16
-
-/* Flags for input stack */
-#define INP_FREE (1<<0) /* current buffer can be free'd */
-#define INP_ALIAS (1<<1) /* expanding alias or history */
-#define INP_HIST (1<<2) /* expanding history */
-#define INP_CONT (1<<3) /* continue onto previously stacked input */
-#define INP_ALCONT (1<<4) /* stack is continued from alias expn. */
-#define INP_HISTCONT (1<<5) /* stack is continued from history expn. */
-#define INP_LINENO (1<<6) /* update line number */
-#define INP_APPEND (1<<7) /* Append new lines to allow backup */
-#define INP_RAW_KEEP (1<<8) /* Input needed in raw mode even if alias */
-
-/* Flags for metafy */
-#define META_REALLOC 0
-#define META_USEHEAP 1
-#define META_STATIC 2
-#define META_DUP 3
-#define META_ALLOC 4
-#define META_NOALLOC 5
-#define META_HEAPDUP 6
-#define META_HREALLOC 7
-
-/* Context to save and restore (bit fields) */
-enum {
- /* History mechanism */
- ZCONTEXT_HIST = (1<<0),
- /* Lexical analyser */
- ZCONTEXT_LEX = (1<<1),
- /* Parser */
- ZCONTEXT_PARSE = (1<<2)
-};
-
-/**************************/
-/* Abstract types for zsh */
-/**************************/
-
-typedef struct alias *Alias;
-typedef struct asgment *Asgment;
-typedef struct builtin *Builtin;
-typedef struct cmdnam *Cmdnam;
-typedef struct complist *Complist;
-typedef struct conddef *Conddef;
-typedef struct dirsav *Dirsav;
-typedef struct emulation_options *Emulation_options;
-typedef struct execcmd_params *Execcmd_params;
-typedef struct features *Features;
-typedef struct feature_enables *Feature_enables;
-typedef struct funcstack *Funcstack;
-typedef struct funcwrap *FuncWrap;
-typedef struct hashnode *HashNode;
-typedef struct hashtable *HashTable;
-typedef struct heap *Heap;
-typedef struct heapstack *Heapstack;
-typedef struct histent *Histent;
-typedef struct hookdef *Hookdef;
-typedef struct imatchdata *Imatchdata;
-typedef struct jobfile *Jobfile;
-typedef struct job *Job;
-typedef struct linkedmod *Linkedmod;
-typedef struct linknode *LinkNode;
-typedef union linkroot *LinkList;
-typedef struct module *Module;
-typedef struct nameddir *Nameddir;
-typedef struct options *Options;
-typedef struct optname *Optname;
-typedef struct param *Param;
-typedef struct paramdef *Paramdef;
-typedef struct patstralloc *Patstralloc;
-typedef struct patprog *Patprog;
-typedef struct prepromptfn *Prepromptfn;
-typedef struct process *Process;
-typedef struct redir *Redir;
-typedef struct reswd *Reswd;
-typedef struct shfunc *Shfunc;
-typedef struct timedfn *Timedfn;
-typedef struct value *Value;
-
-/********************************/
-/* Definitions for linked lists */
-/********************************/
-
-/* linked list abstract data type */
-
-struct linknode {
- LinkNode next;
- LinkNode prev;
- void *dat;
-};
-
-struct linklist {
- LinkNode first;
- LinkNode last;
- int flags;
-};
-
-union linkroot {
- struct linklist list;
- struct linknode node;
-};
-
-/* Macros for manipulating link lists */
-
-#define firstnode(X) ((X)->list.first)
-#define lastnode(X) ((X)->list.last)
-#define peekfirst(X) (firstnode(X)->dat)
-#define peeklast(X) (lastnode(X)->dat)
-#define addlinknode(X,Y) insertlinknode(X,lastnode(X),Y)
-#define zaddlinknode(X,Y) zinsertlinknode(X,lastnode(X),Y)
-#define uaddlinknode(X,Y) uinsertlinknode(X,lastnode(X),Y)
-#define empty(X) (firstnode(X) == NULL)
-#define nonempty(X) (firstnode(X) != NULL)
-#define getaddrdata(X) (&((X)->dat))
-#define getdata(X) ((X)->dat)
-#define setdata(X,Y) ((X)->dat = (Y))
-#define nextnode(X) ((X)->next)
-#define prevnode(X) ((X)->prev)
-#define pushnode(X,Y) insertlinknode(X,&(X)->node,Y)
-#define zpushnode(X,Y) zinsertlinknode(X,&(X)->node,Y)
-#define incnode(X) (X = nextnode(X))
-#define decnode(X) (X = prevnode(X))
-#define firsthist() (hist_ring? hist_ring->down->histnum : curhist)
-#define setsizednode(X,Y,Z) (firstnode(X)[(Y)].dat = (void *) (Z))
-
-/* stack allocated linked lists */
-
-#define local_list0(N) union linkroot N
-#define init_list0(N) \
- do { \
- (N).list.first = NULL; \
- (N).list.last = &(N).node; \
- (N).list.flags = 0; \
- } while (0)
-#define local_list1(N) union linkroot N; struct linknode __n0
-#define init_list1(N,V0) \
- do { \
- (N).list.first = &__n0; \
- (N).list.last = &__n0; \
- (N).list.flags = 0; \
- __n0.next = NULL; \
- __n0.prev = &(N).node; \
- __n0.dat = (void *) (V0); \
- } while (0)
-
-/*************************************/
-/* Specific elements of linked lists */
-/*************************************/
-
-typedef void (*voidvoidfnptr_t) _((void));
-
-/*
- * Element of the prepromptfns list.
- */
-struct prepromptfn {
- voidvoidfnptr_t func;
-};
-
-
-/*
- * Element of the timedfns list.
- */
-struct timedfn {
- voidvoidfnptr_t func;
- time_t when;
-};
-
-/********************************/
-/* Definitions for syntax trees */
-/********************************/
-
-/* These are control flags that are passed *
- * down the execution pipeline. */
-#define Z_TIMED (1<<0) /* pipeline is being timed */
-#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */
-#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */
-#define Z_DISOWN (1<<3) /* run this sublist without job control (&|) */
-/* (1<<4) is used for Z_END, see the wordcode definitions */
-/* (1<<5) is used for Z_SIMPLE, see the wordcode definitions */
-
-/*
- * Condition types.
- *
- * Careful when changing these: both cond_binary_ops in text.c and
- * condstr in cond.c depend on these. (The zsh motto is "two instances
- * are better than one". Or something.)
- */
-
-#define COND_NOT 0
-#define COND_AND 1
-#define COND_OR 2
-#define COND_STREQ 3
-#define COND_STRDEQ 4
-#define COND_STRNEQ 5
-#define COND_STRLT 6
-#define COND_STRGTR 7
-#define COND_NT 8
-#define COND_OT 9
-#define COND_EF 10
-#define COND_EQ 11
-#define COND_NE 12
-#define COND_LT 13
-#define COND_GT 14
-#define COND_LE 15
-#define COND_GE 16
-#define COND_REGEX 17
-#define COND_MOD 18
-#define COND_MODI 19
-
-typedef int (*CondHandler) _((char **, int));
-
-struct conddef {
- Conddef next; /* next in list */
- char *name; /* the condition name */
- int flags; /* see CONDF_* below */
- CondHandler handler; /* handler function */
- int min; /* minimum number of strings */
- int max; /* maximum number of strings */
- int condid; /* for overloading handler functions */
- char *module; /* module to autoload */
-};
-
-/* Condition is an infix */
-#define CONDF_INFIX 1
-/* Condition has been loaded from library */
-#define CONDF_ADDED 2
-/* When autoloading, enable all features in library */
-#define CONDF_AUTOALL 4
-
-#define CONDDEF(name, flags, handler, min, max, condid) \
- { NULL, name, flags, handler, min, max, condid, NULL }
-
-/* Flags for redirections */
-
-enum {
- /* Mark a here-string that came from a here-document */
- REDIRF_FROM_HEREDOC = 1
-};
-
-/* tree element for redirection lists */
-
-struct redir {
- int type;
- int flags;
- int fd1, fd2;
- char *name;
- char *varid;
- char *here_terminator;
- char *munged_here_terminator;
-};
-
-/* The number of fds space is allocated for *
- * each time a multio must increase in size. */
-#define MULTIOUNIT 8
-
-/* A multio is a list of fds associated with a certain fd. *
- * Thus if you do "foo >bar >ble", the multio for fd 1 will have *
- * two fds, the result of open("bar",...), and the result of *
- * open("ble",....). */
-
-/* structure used for multiple i/o redirection */
-/* one for each fd open */
-
-struct multio {
- int ct; /* # of redirections on this fd */
- int rflag; /* 0 if open for reading, 1 if open for writing */
- int pipe; /* fd of pipe if ct > 1 */
- int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */
-};
-
-/* lvalue for variable assignment/expansion */
-
-struct value {
- int isarr;
- Param pm; /* parameter node */
- int flags; /* flags defined below */
- int start; /* first element of array slice, or -1 */
- int end; /* 1-rel last element of array slice, or -1 */
- char **arr; /* cache for hash turned into array */
-};
-
-enum {
- VALFLAG_INV = 0x0001, /* We are performing inverse subscripting */
- VALFLAG_EMPTY = 0x0002, /* Subscripted range is empty */
- VALFLAG_SUBST = 0x0004 /* Substitution, so apply padding, case flags */
-};
-
-#define MAX_ARRLEN 262144
-
-/********************************************/
-/* Definitions for word code */
-/********************************************/
-
-typedef unsigned int wordcode;
-typedef wordcode *Wordcode;
-
-typedef struct funcdump *FuncDump;
-typedef struct eprog *Eprog;
-
-struct funcdump {
- FuncDump next; /* next in list */
- dev_t dev; /* device */
- ino_t ino; /* indoe number */
- int fd; /* file descriptor */
- Wordcode map; /* pointer to header */
- Wordcode addr; /* mapped region */
- int len; /* length */
- int count; /* reference count */
- char *filename;
-};
-
-/*
- * A note on the use of reference counts in Eprogs.
- *
- * When an Eprog is created, nref is set to -1 if the Eprog is on the
- * heap; then no attempt is ever made to free it. (This information is
- * already present in EF_HEAP; we use the redundancy for debugging
- * checks.)
- *
- * Otherwise, nref is initialised to 1. Calling freeprog() decrements
- * nref and frees the Eprog if the count is now zero. When the Eprog
- * is in use, we call useeprog() at the start and freeprog() at the
- * end to increment and decrement the reference counts. If an attempt
- * is made to free the Eprog from within, this will then take place
- * when execution is finished, typically in the call to freeeprog()
- * in execode(). If the Eprog was on the heap, neither useeprog()
- * nor freeeprog() has any effect.
- */
-struct eprog {
- int flags; /* EF_* below */
- int len; /* total block length */
- int npats; /* Patprog cache size */
- int nref; /* number of references: delete when zero */
- Patprog *pats; /* the memory block, the patterns */
- Wordcode prog; /* memory block ctd, the code */
- char *strs; /* memory block ctd, the strings */
- Shfunc shf; /* shell function for autoload */
- FuncDump dump; /* dump file this is in */
-};
-
-#define EF_REAL 1
-#define EF_HEAP 2
-#define EF_MAP 4
-#define EF_RUN 8
-
-typedef struct estate *Estate;
-
-struct estate {
- Eprog prog; /* the eprog executed */
- Wordcode pc; /* program counter, current pos */
- char *strs; /* strings from prog */
-};
-
-typedef struct eccstr *Eccstr;
-
-struct eccstr {
- Eccstr left, right;
- char *str;
- wordcode offs, aoffs;
- int nfunc;
- int hashval;
-};
-
-#define EC_NODUP 0
-#define EC_DUP 1
-#define EC_DUPTOK 2
-
-#define WC_CODEBITS 5
-
-#define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1)))
-#define wc_data(C) ((C) >> WC_CODEBITS)
-#define wc_bdata(D) ((D) << WC_CODEBITS)
-#define wc_bld(C,D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS))
-
-#define WC_END 0
-#define WC_LIST 1
-#define WC_SUBLIST 2
-#define WC_PIPE 3
-#define WC_REDIR 4
-#define WC_ASSIGN 5
-#define WC_SIMPLE 6
-#define WC_TYPESET 7
-#define WC_SUBSH 8
-#define WC_CURSH 9
-#define WC_TIMED 10
-#define WC_FUNCDEF 11
-#define WC_FOR 12
-#define WC_SELECT 13
-#define WC_WHILE 14
-#define WC_REPEAT 15
-#define WC_CASE 16
-#define WC_IF 17
-#define WC_COND 18
-#define WC_ARITH 19
-#define WC_AUTOFN 20
-#define WC_TRY 21
-
-/* increment as necessary */
-#define WC_COUNT 22
-
-#define WCB_END() wc_bld(WC_END, 0)
-
-#define WC_LIST_TYPE(C) wc_data(C)
-#define Z_END (1<<4)
-#define Z_SIMPLE (1<<5)
-#define WC_LIST_FREE (6) /* Next bit available in integer */
-#define WC_LIST_SKIP(C) (wc_data(C) >> WC_LIST_FREE)
-#define WCB_LIST(T,O) wc_bld(WC_LIST, ((T) | ((O) << WC_LIST_FREE)))
-
-#define WC_SUBLIST_TYPE(C) (wc_data(C) & ((wordcode) 3))
-#define WC_SUBLIST_END 0
-#define WC_SUBLIST_AND 1
-#define WC_SUBLIST_OR 2
-#define WC_SUBLIST_FLAGS(C) (wc_data(C) & ((wordcode) 0x1c))
-#define WC_SUBLIST_COPROC 4
-#define WC_SUBLIST_NOT 8
-#define WC_SUBLIST_SIMPLE 16
-#define WC_SUBLIST_FREE (5) /* Next bit available in integer */
-#define WC_SUBLIST_SKIP(C) (wc_data(C) >> WC_SUBLIST_FREE)
-#define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, \
- ((T) | (F) | ((O) << WC_SUBLIST_FREE)))
-
-#define WC_PIPE_TYPE(C) (wc_data(C) & ((wordcode) 1))
-#define WC_PIPE_END 0
-#define WC_PIPE_MID 1
-#define WC_PIPE_LINENO(C) (wc_data(C) >> 1)
-#define WCB_PIPE(T,L) wc_bld(WC_PIPE, ((T) | ((L) << 1)))
-
-#define WC_REDIR_TYPE(C) ((int)(wc_data(C) & REDIR_TYPE_MASK))
-#define WC_REDIR_VARID(C) ((int)(wc_data(C) & REDIR_VARID_MASK))
-#define WC_REDIR_FROM_HEREDOC(C) ((int)(wc_data(C) & REDIR_FROM_HEREDOC_MASK))
-#define WCB_REDIR(T) wc_bld(WC_REDIR, (T))
-/* Size of redir is 4 words if REDIR_VARID_MASK is set, else 3 */
-#define WC_REDIR_WORDS(C) \
- ((WC_REDIR_VARID(C) ? 4 : 3) + \
- (WC_REDIR_FROM_HEREDOC(C) ? 2 : 0))
-
-#define WC_ASSIGN_TYPE(C) (wc_data(C) & ((wordcode) 1))
-#define WC_ASSIGN_TYPE2(C) ((wc_data(C) & ((wordcode) 2)) >> 1)
-#define WC_ASSIGN_SCALAR 0
-#define WC_ASSIGN_ARRAY 1
-#define WC_ASSIGN_NEW 0
-/*
- * In normal assignment, this indicate += to append.
- * In assignment following a typeset, where that's not allowed,
- * we overload this to indicate a variable without an
- * assignment.
- */
-#define WC_ASSIGN_INC 1
-#define WC_ASSIGN_NUM(C) (wc_data(C) >> 2)
-#define WCB_ASSIGN(T,A,N) wc_bld(WC_ASSIGN, ((T) | ((A) << 1) | ((N) << 2)))
-
-#define WC_SIMPLE_ARGC(C) wc_data(C)
-#define WCB_SIMPLE(N) wc_bld(WC_SIMPLE, (N))
-
-#define WC_TYPESET_ARGC(C) wc_data(C)
-#define WCB_TYPESET(N) wc_bld(WC_TYPESET, (N))
-
-#define WC_SUBSH_SKIP(C) wc_data(C)
-#define WCB_SUBSH(O) wc_bld(WC_SUBSH, (O))
-
-#define WC_CURSH_SKIP(C) wc_data(C)
-#define WCB_CURSH(O) wc_bld(WC_CURSH, (O))
-
-#define WC_TIMED_TYPE(C) wc_data(C)
-#define WC_TIMED_EMPTY 0
-#define WC_TIMED_PIPE 1
-#define WCB_TIMED(T) wc_bld(WC_TIMED, (T))
-
-#define WC_FUNCDEF_SKIP(C) wc_data(C)
-#define WCB_FUNCDEF(O) wc_bld(WC_FUNCDEF, (O))
-
-#define WC_FOR_TYPE(C) (wc_data(C) & 3)
-#define WC_FOR_PPARAM 0
-#define WC_FOR_LIST 1
-#define WC_FOR_COND 2
-#define WC_FOR_SKIP(C) (wc_data(C) >> 2)
-#define WCB_FOR(T,O) wc_bld(WC_FOR, ((T) | ((O) << 2)))
-
-#define WC_SELECT_TYPE(C) (wc_data(C) & 1)
-#define WC_SELECT_PPARAM 0
-#define WC_SELECT_LIST 1
-#define WC_SELECT_SKIP(C) (wc_data(C) >> 1)
-#define WCB_SELECT(T,O) wc_bld(WC_SELECT, ((T) | ((O) << 1)))
-
-#define WC_WHILE_TYPE(C) (wc_data(C) & 1)
-#define WC_WHILE_WHILE 0
-#define WC_WHILE_UNTIL 1
-#define WC_WHILE_SKIP(C) (wc_data(C) >> 1)
-#define WCB_WHILE(T,O) wc_bld(WC_WHILE, ((T) | ((O) << 1)))
-
-#define WC_REPEAT_SKIP(C) wc_data(C)
-#define WCB_REPEAT(O) wc_bld(WC_REPEAT, (O))
-
-#define WC_TRY_SKIP(C) wc_data(C)
-#define WCB_TRY(O) wc_bld(WC_TRY, (O))
-
-#define WC_CASE_TYPE(C) (wc_data(C) & 7)
-#define WC_CASE_HEAD 0
-#define WC_CASE_OR 1
-#define WC_CASE_AND 2
-#define WC_CASE_TESTAND 3
-#define WC_CASE_FREE (3) /* Next bit available in integer */
-#define WC_CASE_SKIP(C) (wc_data(C) >> WC_CASE_FREE)
-#define WCB_CASE(T,O) wc_bld(WC_CASE, ((T) | ((O) << WC_CASE_FREE)))
-
-#define WC_IF_TYPE(C) (wc_data(C) & 3)
-#define WC_IF_HEAD 0
-#define WC_IF_IF 1
-#define WC_IF_ELIF 2
-#define WC_IF_ELSE 3
-#define WC_IF_SKIP(C) (wc_data(C) >> 2)
-#define WCB_IF(T,O) wc_bld(WC_IF, ((T) | ((O) << 2)))
-
-#define WC_COND_TYPE(C) (wc_data(C) & 127)
-#define WC_COND_SKIP(C) (wc_data(C) >> 7)
-#define WCB_COND(T,O) wc_bld(WC_COND, ((T) | ((O) << 7)))
-
-#define WCB_ARITH() wc_bld(WC_ARITH, 0)
-
-#define WCB_AUTOFN() wc_bld(WC_AUTOFN, 0)
-
-/********************************************/
-/* Definitions for job table and job control */
-/********************************************/
-
-/* Entry in filelist linked list in job table */
-
-struct jobfile {
- /* Record to be deleted or closed */
- union {
- char *name; /* Name of file to delete */
- int fd; /* File descriptor to close */
- } u;
- /* Discriminant */
- int is_fd;
-};
-
-/* entry in the job table */
-
-struct job {
- pid_t gleader; /* process group leader of this job */
- pid_t other; /* subjob id (SUPERJOB)
- * or subshell pid (SUBJOB) */
- int stat; /* see STATs below */
- char *pwd; /* current working dir of shell when *
- * this job was spawned */
- struct process *procs; /* list of processes */
- struct process *auxprocs; /* auxiliary processes e.g multios */
- LinkList filelist; /* list of files to delete when done */
- /* elements are struct jobfile */
- int stty_in_env; /* if STTY=... is present */
- struct ttyinfo *ty; /* the modes specified by STTY */
-};
-
-#define STAT_CHANGED (0x0001) /* status changed and not reported */
-#define STAT_STOPPED (0x0002) /* all procs stopped or exited */
-#define STAT_TIMED (0x0004) /* job is being timed */
-#define STAT_DONE (0x0008) /* job is done */
-#define STAT_LOCKED (0x0010) /* shell is finished creating this job, */
- /* may be deleted from job table */
-#define STAT_NOPRINT (0x0020) /* job was killed internally, */
- /* we don't want to show that */
-#define STAT_INUSE (0x0040) /* this job entry is in use */
-#define STAT_SUPERJOB (0x0080) /* job has a subjob */
-#define STAT_SUBJOB (0x0100) /* job is a subjob */
-#define STAT_WASSUPER (0x0200) /* was a super-job, sub-job needs to be */
- /* deleted */
-#define STAT_CURSH (0x0400) /* last command is in current shell */
-#define STAT_NOSTTY (0x0800) /* the tty settings are not inherited */
- /* from this job when it exits. */
-#define STAT_ATTACH (0x1000) /* delay reattaching shell to tty */
-#define STAT_SUBLEADER (0x2000) /* is super-job, but leader is sub-shell */
-
-#define STAT_BUILTIN (0x4000) /* job at tail of pipeline is a builtin */
-#define STAT_SUBJOB_ORPHANED (0x8000)
- /* STAT_SUBJOB with STAT_SUPERJOB exited */
-#define STAT_DISOWN (0x10000) /* STAT_SUPERJOB with disown pending */
-
-#define SP_RUNNING -1 /* fake status for jobs currently running */
-
-struct timeinfo {
- long ut; /* user space time */
- long st; /* system space time */
-};
-
-#define JOBTEXTSIZE 80
-
-/* Size to initialise the job table to, and to increment it by when needed. */
-#define MAXJOBS_ALLOC (50)
-
-/* node in job process lists */
-
-#ifdef HAVE_GETRUSAGE
-typedef struct rusage child_times_t;
-#else
-typedef struct timeinfo child_times_t;
-#endif
-
-struct process {
- struct process *next;
- pid_t pid; /* process id */
- char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */
- int status; /* return code from waitpid/wait3() */
- child_times_t ti;
- struct timeval bgtime; /* time job was spawned */
- struct timeval endtime; /* time job exited */
-};
-
-struct execstack {
- struct execstack *next;
-
- pid_t list_pipe_pid;
- int nowait;
- int pline_level;
- int list_pipe_child;
- int list_pipe_job;
- char list_pipe_text[JOBTEXTSIZE];
- int lastval;
- int noeval;
- int badcshglob;
- pid_t cmdoutpid;
- int cmdoutval;
- int use_cmdoutval;
- pid_t procsubstpid;
- int trap_return;
- int trap_state;
- int trapisfunc;
- int traplocallevel;
- int noerrs;
- int this_noerrexit;
- char *underscore;
-};
-
-struct heredocs {
- struct heredocs *next;
- int type;
- int pc;
- char *str;
-};
-
-struct dirsav {
- int dirfd, level;
- char *dirname;
- dev_t dev;
- ino_t ino;
-};
-
-#define MAX_PIPESTATS 256
-
-/*******************************/
-/* Definitions for Hash Tables */
-/*******************************/
-
-typedef void *(*VFunc) _((void *));
-typedef void (*FreeFunc) _((void *));
-
-typedef unsigned (*HashFunc) _((const char *));
-typedef void (*TableFunc) _((HashTable));
-/*
- * Note that this is deliberately "char *", not "const char *",
- * since the AddNodeFunc is passed a pointer to a string that
- * will be stored and later freed.
- */
-typedef void (*AddNodeFunc) _((HashTable, char *, void *));
-typedef HashNode (*GetNodeFunc) _((HashTable, const char *));
-typedef HashNode (*RemoveNodeFunc) _((HashTable, const char *));
-typedef void (*FreeNodeFunc) _((HashNode));
-typedef int (*CompareFunc) _((const char *, const char *));
-
-/* type of function that is passed to *
- * scanhashtable or scanmatchtable */
-typedef void (*ScanFunc) _((HashNode, int));
-typedef void (*ScanTabFunc) _((HashTable, ScanFunc, int));
-
-typedef void (*PrintTableStats) _((HashTable));
-
-/* hash table for standard open hashing */
-
-struct hashtable {
- /* HASHTABLE DATA */
- int hsize; /* size of nodes[] (number of hash values) */
- int ct; /* number of elements */
- HashNode *nodes; /* array of size hsize */
- void *tmpdata;
-
- /* HASHTABLE METHODS */
- HashFunc hash; /* pointer to hash function for this table */
- TableFunc emptytable; /* pointer to function to empty table */
- TableFunc filltable; /* pointer to function to fill table */
- CompareFunc cmpnodes; /* pointer to function to compare two nodes */
- AddNodeFunc addnode; /* pointer to function to add new node */
- GetNodeFunc getnode; /* pointer to function to get an enabled node */
- GetNodeFunc getnode2; /* pointer to function to get node */
- /* (getnode2 will ignore DISABLED flag) */
- RemoveNodeFunc removenode; /* pointer to function to delete a node */
- ScanFunc disablenode; /* pointer to function to disable a node */
- ScanFunc enablenode; /* pointer to function to enable a node */
- FreeNodeFunc freenode; /* pointer to function to free a node */
- ScanFunc printnode; /* pointer to function to print a node */
- ScanTabFunc scantab; /* pointer to function to scan table */
-
-#ifdef HASHTABLE_INTERNAL_MEMBERS
- HASHTABLE_INTERNAL_MEMBERS /* internal use in hashtable.c */
-#endif
-};
-
-/* generic hash table node */
-
-struct hashnode {
- HashNode next; /* next in hash chain */
- char *nam; /* hash key */
- int flags; /* various flags */
-};
-
-/* The flag to disable nodes in a hash table. Currently *
- * you can disable builtins, shell functions, aliases and *
- * reserved words. */
-#define DISABLED (1<<0)
-
-/* node in shell option table */
-
-struct optname {
- struct hashnode node;
- int optno; /* option number */
-};
-
-/* node in shell reserved word hash table (reswdtab) */
-
-struct reswd {
- struct hashnode node;
- int token; /* corresponding lexer token */
-};
-
-/* node in alias hash table (aliastab) */
-
-struct alias {
- struct hashnode node;
- char *text; /* expansion of alias */
- int inuse; /* alias is being expanded */
-};
-
-/* bit 0 of flags is the DISABLED flag */
-/* is this alias global? */
-#define ALIAS_GLOBAL (1<<1)
-/* is this an alias for suffix handling? */
-#define ALIAS_SUFFIX (1<<2)
-
-/* structure for foo=bar assignments */
-
-struct asgment {
- struct linknode node;
- char *name;
- int flags;
- union {
- char *scalar;
- LinkList array;
- } value;
-};
-
-/* Flags for flags element of asgment */
-enum {
- /* Array value */
- ASG_ARRAY = 1,
- /* Key / value array pair */
- ASG_KEY_VALUE = 2
-};
-
-/*
- * Assignment is array?
- */
-#define ASG_ARRAYP(asg) ((asg)->flags & ASG_ARRAY)
-
-/*
- * Assignment has value?
- * If the assignment is an arrray, then it certainly has a value --- we
- * can only tell if there's an expicit assignment.
- */
-
-#define ASG_VALUEP(asg) (ASG_ARRAYP(asg) || \
- ((asg)->value.scalar != (char *)0))
-
-/* node in command path hash table (cmdnamtab) */
-
-struct cmdnam {
- struct hashnode node;
- union {
- char **name; /* full pathname for external commands */
- char *cmd; /* file name for hashed commands */
- }
- u;
-};
-
-/* flag for nodes explicitly added to *
- * cmdnamtab with hash builtin */
-#define HASHED (1<<1)
-
-/* node in shell function hash table (shfunctab) */
-
-struct shfunc {
- struct hashnode node;
- char *filename; /* Name of file located in.
- For not yet autoloaded file, name
- of explicit directory, if not NULL. */
- zlong lineno; /* line number in above file */
- Eprog funcdef; /* function definition */
- Eprog redir; /* redirections to apply */
- Emulation_options sticky; /* sticky emulation definitions, if any */
-};
-
-/* Shell function context types. */
-
-#define SFC_NONE 0 /* no function running */
-#define SFC_DIRECT 1 /* called directly from the user */
-#define SFC_SIGNAL 2 /* signal handler */
-#define SFC_HOOK 3 /* one of the special functions */
-#define SFC_WIDGET 4 /* user defined widget */
-#define SFC_COMPLETE 5 /* called from completion code */
-#define SFC_CWIDGET 6 /* new style completion widget */
-#define SFC_SUBST 7 /* used to perform substitution task */
-
-/* tp in funcstack */
-
-enum {
- FS_SOURCE,
- FS_FUNC,
- FS_EVAL
-};
-
-/* node in function stack */
-
-struct funcstack {
- Funcstack prev; /* previous in stack */
- char *name; /* name of function/sourced file called */
- char *filename; /* file function resides in */
- char *caller; /* name of caller */
- zlong flineno; /* line number in file */
- zlong lineno; /* line offset from beginning of function */
- int tp; /* type of entry: sourced file, func, eval */
-};
-
-/* node in list of function call wrappers */
-
-typedef int (*WrapFunc) _((Eprog, FuncWrap, char *));
-
-struct funcwrap {
- FuncWrap next;
- int flags;
- WrapFunc handler;
- Module module;
-};
-
-#define WRAPF_ADDED 1
-
-#define WRAPDEF(func) \
- { NULL, 0, func, NULL }
-
-/*
- * User-defined hook arrays
- */
-
-/* Name appended to function name to get hook array */
-#define HOOK_SUFFIX "_functions"
-/* Length of that including NUL byte */
-#define HOOK_SUFFIX_LEN 11
-
-/* node in builtin command hash table (builtintab) */
-
-/*
- * Handling of options.
- *
- * Option strings are standard in that a trailing `:' indicates
- * a mandatory argument. In addition, `::' indicates an optional
- * argument which must immediately follow the option letter if it is present.
- * `:%' indicates an optional numeric argument which may follow
- * the option letter or be in the next word; the only test is
- * that the next character is a digit, and no actual conversion is done.
- */
-
-#define MAX_OPS 128
-
-/* Macros taking struct option * and char argument */
-/* Option was set as -X */
-#define OPT_MINUS(ops,c) ((ops)->ind[c] & 1)
-/* Option was set as +X */
-#define OPT_PLUS(ops,c) ((ops)->ind[c] & 2)
-/*
- * Option was set any old how, maybe including an argument
- * (cheap test when we don't care). Some bits of code
- * expect this to be 1 or 0.
- */
-#define OPT_ISSET(ops,c) ((ops)->ind[c] != 0)
-/* Option has an argument */
-#define OPT_HASARG(ops,c) ((ops)->ind[c] > 3)
-/* The argument for the option; not safe if it doesn't have one */
-#define OPT_ARG(ops,c) ((ops)->args[((ops)->ind[c] >> 2) - 1])
-/* Ditto, but safely returns NULL if there is no argument. */
-#define OPT_ARG_SAFE(ops,c) (OPT_HASARG(ops,c) ? OPT_ARG(ops,c) : NULL)
-
-struct options {
- unsigned char ind[MAX_OPS];
- char **args;
- int argscount, argsalloc;
-};
-
-/* Flags to parseargs() */
-
-enum {
- PARSEARGS_TOPLEVEL = 0x1, /* Call to initialise shell */
- PARSEARGS_LOGIN = 0x2 /* Shell is login shell */
-};
-
-
-/*
- * Handler arguments are: builtin name, null-terminated argument
- * list excluding command name, option structure, the funcid element from the
- * builtin structure.
- */
-
-typedef int (*HandlerFunc) _((char *, char **, Options, int));
-typedef int (*HandlerFuncAssign) _((char *, char **, LinkList, Options, int));
-#define NULLBINCMD ((HandlerFunc) 0)
-
-struct builtin {
- struct hashnode node;
- HandlerFunc handlerfunc; /* pointer to function that executes this builtin */
- int minargs; /* minimum number of arguments */
- int maxargs; /* maximum number of arguments, or -1 for no limit */
- int funcid; /* xbins (see above) for overloaded handlerfuncs */
- char *optstr; /* string of legal options */
- char *defopts; /* options set by default for overloaded handlerfuncs */
-};
-
-#define BUILTIN(name, flags, handler, min, max, funcid, optstr, defopts) \
- { { NULL, name, flags }, handler, min, max, funcid, optstr, defopts }
-#define BIN_PREFIX(name, flags) \
- BUILTIN(name, flags | BINF_PREFIX, NULLBINCMD, 0, 0, 0, NULL, NULL)
-
-/* builtin flags */
-/* DISABLE IS DEFINED AS (1<<0) */
-#define BINF_PLUSOPTS (1<<1) /* +xyz legal */
-#define BINF_PRINTOPTS (1<<2)
-#define BINF_ADDED (1<<3) /* is in the builtins hash table */
-#define BINF_MAGICEQUALS (1<<4) /* needs automatic MAGIC_EQUAL_SUBST substitution */
-#define BINF_PREFIX (1<<5)
-#define BINF_DASH (1<<6)
-#define BINF_BUILTIN (1<<7)
-#define BINF_COMMAND (1<<8)
-#define BINF_EXEC (1<<9)
-#define BINF_NOGLOB (1<<10)
-#define BINF_PSPECIAL (1<<11)
-/* Builtin option handling */
-#define BINF_SKIPINVALID (1<<12) /* Treat invalid option as argument */
-#define BINF_KEEPNUM (1<<13) /* `[-+]NUM' can be an option */
-#define BINF_SKIPDASH (1<<14) /* Treat `-' as argument (maybe `+') */
-#define BINF_DASHDASHVALID (1<<15) /* Handle `--' even if SKIPINVALD */
-#define BINF_CLEARENV (1<<16) /* new process started with cleared env */
-#define BINF_AUTOALL (1<<17) /* autoload all features at once */
- /*
- * Handles options itself. This is only useful if the option string for a
- * builtin with an empty option string. It is used to indicate that "--"
- * does not terminate options.
- */
-#define BINF_HANDLES_OPTS (1<<18)
-/*
- * Handles the assignement interface. The argv list actually contains
- * two nested litsts, the first of normal arguments, and the second of
- * assignment structures.
- */
-#define BINF_ASSIGN (1<<19)
-
-/**
- * Parameters passed to execcmd().
- * These are not opaque --- they are also used by the pipeline manager.
- */
-struct execcmd_params {
- LinkList args; /* All command prefixes, arguments & options */
- LinkList redir; /* Redirections */
- Wordcode beg; /* The code at the start of the command */
- Wordcode varspc; /* The code for assignment parsed as such */
- Wordcode assignspc; /* The code for assignment parsed as typeset */
- int type; /* The WC_* type of the command */
- int postassigns; /* The number of assignspc assiguments */
- int htok; /* tokens in parameter list */
-};
-
-struct module {
- struct hashnode node;
- union {
- void *handle;
- Linkedmod linked;
- char *alias;
- } u;
- LinkList autoloads;
- LinkList deps;
- int wrapper;
-};
-
-/* We are in the process of loading the module */
-#define MOD_BUSY (1<<0)
-/*
- * We are in the process of unloading the module.
- * Note this is not needed to indicate a module is actually
- * unloaded: for that, the handle (or linked pointer) is set to NULL.
- */
-#define MOD_UNLOAD (1<<1)
-/* We are in the process of setting up the module */
-#define MOD_SETUP (1<<2)
-/* Module is statically linked into the main binary */
-#define MOD_LINKED (1<<3)
-/* Module setup has been carried out (and module has not been finished) */
-#define MOD_INIT_S (1<<4)
-/* Module boot has been carried out (and module has not been finished) */
-#define MOD_INIT_B (1<<5)
-/* Module record is an alias */
-#define MOD_ALIAS (1<<6)
-
-typedef int (*Module_generic_func) _((void));
-typedef int (*Module_void_func) _((Module));
-typedef int (*Module_features_func) _((Module, char ***));
-typedef int (*Module_enables_func) _((Module, int **));
-
-struct linkedmod {
- char *name;
- Module_void_func setup;
- Module_features_func features;
- Module_enables_func enables;
- Module_void_func boot;
- Module_void_func cleanup;
- Module_void_func finish;
-};
-
-/*
- * Structure combining all the concrete features available in
- * a module and with space for information about abstract features.
- */
-struct features {
- /* List of builtins provided by the module and the size thereof */
- Builtin bn_list;
- int bn_size;
- /* List of conditions provided by the module and the size thereof */
- Conddef cd_list;
- int cd_size;
- /* List of math functions provided by the module and the size thereof */
- MathFunc mf_list;
- int mf_size;
- /* List of parameters provided by the module and the size thereof */
- Paramdef pd_list;
- int pd_size;
- /* Number of abstract features */
- int n_abstract;
-};
-
-/*
- * Structure describing enables for one feature.
- */
-struct feature_enables {
- /* String feature to enable (N.B. no leading +/- allowed) */
- char *str;
- /* Optional compiled pattern for str sans +/-, NULL for string match */
- Patprog pat;
-};
-
-/* C-function hooks */
-
-typedef int (*Hookfn) _((Hookdef, void *));
-
-struct hookdef {
- Hookdef next;
- char *name;
- Hookfn def;
- int flags;
- LinkList funcs;
-};
-
-#define HOOKF_ALL 1
-
-#define HOOKDEF(name, func, flags) { NULL, name, (Hookfn) func, flags, NULL }
-
-/*
- * Types used in pattern matching. Most of these longs could probably
- * happily be ints.
- */
-
-struct patprog {
- long startoff; /* length before start of programme */
- long size; /* total size from start of struct */
- long mustoff; /* offset to string that must be present */
- long patmlen; /* length of pure string or longest match */
- int globflags; /* globbing flags to set at start */
- int globend; /* globbing flags set after finish */
- int flags; /* PAT_* flags */
- int patnpar; /* number of active parentheses */
- char patstartch;
-};
-
-struct patstralloc {
- int unmetalen; /* Unmetafied length of trial string */
- int unmetalenp; /* Unmetafied length of path prefix.
- If 0, no path prefix. */
- char *alloced; /* Allocated string, may be NULL */
- char *progstrunmeta; /* Unmetafied pure string in pattern, cached */
- int progstrunmetalen; /* Length of the foregoing */
-};
-
-/* Flags used in pattern matchers (Patprog) and passed down to patcompile */
-
-#define PAT_HEAPDUP 0x0000 /* Dummy flag for default behavior */
-#define PAT_FILE 0x0001 /* Pattern is a file name */
-#define PAT_FILET 0x0002 /* Pattern is top level file, affects ~ */
-#define PAT_ANY 0x0004 /* Match anything (cheap "*") */
-#define PAT_NOANCH 0x0008 /* Not anchored at end */
-#define PAT_NOGLD 0x0010 /* Don't glob dots */
-#define PAT_PURES 0x0020 /* Pattern is a pure string: set internally */
-#define PAT_STATIC 0x0040 /* Don't copy pattern to heap as per default */
-#define PAT_SCAN 0x0080 /* Scanning, so don't try must-match test */
-#define PAT_ZDUP 0x0100 /* Copy pattern in real memory */
-#define PAT_NOTSTART 0x0200 /* Start of string is not real start */
-#define PAT_NOTEND 0x0400 /* End of string is not real end */
-#define PAT_HAS_EXCLUDP 0x0800 /* (internal): top-level path1~path2. */
-#define PAT_LCMATCHUC 0x1000 /* equivalent to setting (#l) */
-
-/**
- * Indexes into the array of active pattern characters.
- * This must match the array zpc_chars in pattern.c.
- */
-enum zpc_chars {
- /*
- * These characters both terminate a pattern segment and
- * a pure string segment.
- */
- ZPC_SLASH, /* / active as file separator */
- ZPC_NULL, /* \0 as string terminator */
- ZPC_BAR, /* | for "or" */
- ZPC_OUTPAR, /* ) for grouping */
- ZPC_TILDE, /* ~ for exclusion (extended glob) */
- ZPC_SEG_COUNT, /* No. of the above characters */
- /*
- * These characters terminate a pure string segment.
- */
- ZPC_INPAR = ZPC_SEG_COUNT, /* ( for grouping */
- ZPC_QUEST, /* ? as wildcard */
- ZPC_STAR, /* * as wildcard */
- ZPC_INBRACK, /* [ for character class */
- ZPC_INANG, /* < for numeric glob */
- ZPC_HAT, /* ^ for exclusion (extended glob) */
- ZPC_HASH, /* # for repetition (extended glob) */
- ZPC_BNULLKEEP, /* Special backslashed null not removed */
- /*
- * These characters are only valid before a parenthesis
- */
- ZPC_NO_KSH_GLOB,
- ZPC_KSH_QUEST = ZPC_NO_KSH_GLOB, /* ? for ?(...) in KSH_GLOB */
- ZPC_KSH_STAR, /* * for *(...) in KSH_GLOB */
- ZPC_KSH_PLUS, /* + for +(...) in KSH_GLOB */
- ZPC_KSH_BANG, /* ! for !(...) in KSH_GLOB */
- ZPC_KSH_BANG2, /* ! for !(...) in KSH_GLOB, untokenised */
- ZPC_KSH_AT, /* @ for @(...) in KSH_GLOB */
- ZPC_COUNT /* Number of special chararacters */
-};
-
-/*
- * Structure to save disables special characters for function scope.
- */
-struct zpc_disables_save {
- struct zpc_disables_save *next;
- /*
- * Bit vector of ZPC_COUNT disabled characters.
- * We'll live dangerously and assume ZPC_COUNT is no greater
- * than the number of bits in an unsigned int.
- */
- unsigned int disables;
-};
-
-typedef struct zpc_disables_save *Zpc_disables_save;
-
-/*
- * Special match types used in character classes. These
- * are represented as tokens, with Meta added. The character
- * class is represented as a metafied string, with only these
- * tokens special. Note that an active leading "!" or "^" for
- * negation is not part of the string but is flagged in the
- * surrounding context.
- *
- * These types are also used in character and equivalence classes
- * in completion matching.
- *
- * This must be kept ordered by the array colon_stuffs in pattern.c.
- */
-/* Special value for first definition */
-#define PP_FIRST 1
-/* POSIX-defined types: [:alpha:] etc. */
-#define PP_ALPHA 1
-#define PP_ALNUM 2
-#define PP_ASCII 3
-#define PP_BLANK 4
-#define PP_CNTRL 5
-#define PP_DIGIT 6
-#define PP_GRAPH 7
-#define PP_LOWER 8
-#define PP_PRINT 9
-#define PP_PUNCT 10
-#define PP_SPACE 11
-#define PP_UPPER 12
-#define PP_XDIGIT 13
-/* Zsh additions: [:IDENT:] etc. */
-#define PP_IDENT 14
-#define PP_IFS 15
-#define PP_IFSSPACE 16
-#define PP_WORD 17
-#define PP_INCOMPLETE 18
-#define PP_INVALID 19
-/* Special value for last definition */
-#define PP_LAST 19
-
-/* Unknown type. Not used in a valid token. */
-#define PP_UNKWN 20
-/* Range: token followed by the (possibly multibyte) start and end */
-#define PP_RANGE 21
-
-/*
- * Argument to get_match_ret() in glob.c
- */
-struct imatchdata {
- /* Metafied trial string */
- char *mstr;
- /* Its length */
- int mlen;
- /* Unmetafied string */
- char *ustr;
- /* Its length */
- int ulen;
- /* Flags (SUB_*) */
- int flags;
- /* Replacement string (metafied) */
- char *replstr;
- /*
- * List of bits of matches to concatenate with replacement string.
- * The data is a struct repldata. It is not used in cases like
- * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match
- * is anchored. It goes on the heap.
- */
- LinkList repllist;
-};
-
-/* Globbing flags: lower 8 bits gives approx count */
-#define GF_LCMATCHUC 0x0100
-#define GF_IGNCASE 0x0200
-#define GF_BACKREF 0x0400
-#define GF_MATCHREF 0x0800
-#define GF_MULTIBYTE 0x1000 /* Use multibyte if supported by build */
-
-enum {
- /* Valid multibyte character from charref */
- ZMB_VALID,
- /* Incomplete multibyte character from charref */
- ZMB_INCOMPLETE,
- /* Invalid multibyte character charref */
- ZMB_INVALID
-};
-
-/* Dummy Patprog pointers. Used mainly in executable code, but the
- * pattern code needs to know about it, too. */
-
-#define dummy_patprog1 ((Patprog) 1)
-#define dummy_patprog2 ((Patprog) 2)
-
-/* standard node types for get/set/unset union in parameter */
-
-/*
- * note non-standard const in pointer declaration: structures are
- * assumed to be read-only.
- */
-typedef const struct gsu_scalar *GsuScalar;
-typedef const struct gsu_integer *GsuInteger;
-typedef const struct gsu_float *GsuFloat;
-typedef const struct gsu_array *GsuArray;
-typedef const struct gsu_hash *GsuHash;
-
-struct gsu_scalar {
- char *(*getfn) _((Param));
- void (*setfn) _((Param, char *));
- void (*unsetfn) _((Param, int));
-};
-
-struct gsu_integer {
- zlong (*getfn) _((Param));
- void (*setfn) _((Param, zlong));
- void (*unsetfn) _((Param, int));
-};
-
-struct gsu_float {
- double (*getfn) _((Param));
- void (*setfn) _((Param, double));
- void (*unsetfn) _((Param, int));
-};
-
-struct gsu_array {
- char **(*getfn) _((Param));
- void (*setfn) _((Param, char **));
- void (*unsetfn) _((Param, int));
-};
-
-struct gsu_hash {
- HashTable (*getfn) _((Param));
- void (*setfn) _((Param, HashTable));
- void (*unsetfn) _((Param, int));
-};
-
-
-/* node used in parameter hash table (paramtab) */
-
-struct param {
- struct hashnode node;
-
- /* the value of this parameter */
- union {
- void *data; /* used by special parameter functions */
- char **arr; /* value if declared array (PM_ARRAY) */
- char *str; /* value if declared string (PM_SCALAR) */
- zlong val; /* value if declared integer (PM_INTEGER) */
- zlong *valptr; /* value if special pointer to integer */
- double dval; /* value if declared float
- (PM_EFLOAT|PM_FFLOAT) */
- HashTable hash; /* value if declared assoc (PM_HASHED) */
- } u;
-
- /*
- * get/set/unset methods.
- *
- * Unlike the data union, this points to a single instance
- * for every type (although there are special types, e.g.
- * tied arrays have a different gsu_scalar struct from the
- * normal one). It's really a poor man's vtable.
- */
- union {
- GsuScalar s;
- GsuInteger i;
- GsuFloat f;
- GsuArray a;
- GsuHash h;
- } gsu;
-
- int base; /* output base or floating point prec */
- int width; /* field width */
- char *env; /* location in environment, if exported */
- char *ename; /* name of corresponding environment var */
- Param old; /* old struct for use with local */
- int level; /* if (old != NULL), level of localness */
-};
-
-/* structure stored in struct param's u.data by tied arrays */
-struct tieddata {
- char ***arrptr; /* pointer to corresponding array */
- int joinchar; /* character used to join arrays */
-};
-
-/* flags for parameters */
-
-/* parameter types */
-#define PM_SCALAR 0 /* scalar */
-#define PM_ARRAY (1<<0) /* array */
-#define PM_INTEGER (1<<1) /* integer */
-#define PM_EFLOAT (1<<2) /* double with %e output */
-#define PM_FFLOAT (1<<3) /* double with %f output */
-#define PM_HASHED (1<<4) /* association */
-
-#define PM_TYPE(X) \
- (X & (PM_SCALAR|PM_INTEGER|PM_EFLOAT|PM_FFLOAT|PM_ARRAY|PM_HASHED))
-
-#define PM_LEFT (1<<5) /* left justify, remove leading blanks */
-#define PM_RIGHT_B (1<<6) /* right justify, fill with leading blanks */
-#define PM_RIGHT_Z (1<<7) /* right justify, fill with leading zeros */
-#define PM_LOWER (1<<8) /* all lower case */
-
-/* The following are the same since they *
- * both represent -u option to typeset */
-#define PM_UPPER (1<<9) /* all upper case */
-#define PM_UNDEFINED (1<<9) /* undefined (autoloaded) shell function */
-
-#define PM_READONLY (1<<10) /* readonly */
-#define PM_TAGGED (1<<11) /* tagged */
-#define PM_EXPORTED (1<<12) /* exported */
-#define PM_ABSPATH_USED (1<<12) /* (function): loaded using absolute path */
-
-/* The following are the same since they *
- * both represent -U option to typeset */
-#define PM_UNIQUE (1<<13) /* remove duplicates */
-#define PM_UNALIASED (1<<13) /* do not expand aliases when autoloading */
-
-#define PM_HIDE (1<<14) /* Special behaviour hidden by local */
-#define PM_CUR_FPATH (1<<14) /* (function): can use $fpath with filename */
-#define PM_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */
-#define PM_WARNNESTED (1<<15) /* (function): non-recursive WARNNESTEDVAR */
-#define PM_TIED (1<<16) /* array tied to colon-path or v.v. */
-#define PM_TAGGED_LOCAL (1<<16) /* (function): non-recursive PM_TAGGED */
-
-#define PM_KSHSTORED (1<<17) /* function stored in ksh form */
-#define PM_ZSHSTORED (1<<18) /* function stored in zsh form */
-
-/* Remaining flags do not correspond directly to command line arguments */
-#define PM_DONTIMPORT_SUID (1<<19) /* do not import if running setuid */
-#define PM_LOADDIR (1<<19) /* (function) filename gives load directory */
-#define PM_SINGLE (1<<20) /* special can only have a single instance */
-#define PM_ANONYMOUS (1<<20) /* (function) anonymous function */
-#define PM_LOCAL (1<<21) /* this parameter will be made local */
-#define PM_SPECIAL (1<<22) /* special builtin parameter */
-#define PM_DONTIMPORT (1<<23) /* do not import this variable */
-#define PM_RESTRICTED (1<<24) /* cannot be changed in restricted mode */
-#define PM_UNSET (1<<25) /* has null value */
-#define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */
-#define PM_AUTOLOAD (1<<27) /* autoloaded from module */
-#define PM_NORESTORE (1<<28) /* do not restore value of local special */
-#define PM_AUTOALL (1<<28) /* autoload all features in module
- * when loading: valid only if PM_AUTOLOAD
- * is also present.
- */
-#define PM_HASHELEM (1<<29) /* is a hash-element */
-#define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */
-
-/* The option string corresponds to the first of the variables above */
-#define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz"
-
-/* These typeset options take an optional numeric argument */
-#define TYPESET_OPTNUM "LRZiEF"
-
-/* Flags for extracting elements of arrays and associative arrays */
-#define SCANPM_WANTVALS (1<<0) /* Return value includes hash values */
-#define SCANPM_WANTKEYS (1<<1) /* Return value includes hash keys */
-#define SCANPM_WANTINDEX (1<<2) /* Return value includes array index */
-#define SCANPM_MATCHKEY (1<<3) /* Subscript matched against key */
-#define SCANPM_MATCHVAL (1<<4) /* Subscript matched against value */
-#define SCANPM_MATCHMANY (1<<5) /* Subscript matched repeatedly, return all */
-#define SCANPM_ASSIGNING (1<<6) /* Assigning whole array/hash */
-#define SCANPM_KEYMATCH (1<<7) /* keys of hash treated as patterns */
-#define SCANPM_DQUOTED (1<<8) /* substitution was double-quoted
- * (only used for testing early end of
- * subscript)
- */
-#define SCANPM_ARRONLY (1<<9) /* value is array but we don't
- * necessarily want to match multiple
- * elements
- */
-#define SCANPM_CHECKING (1<<10) /* Check if set, no need to create */
-/* "$foo[@]"-style substitution
- * Only sign bit is significant
- */
-#define SCANPM_ISVAR_AT ((int)(((unsigned int)-1)<<15))
-
-/*
- * Flags for doing matches inside parameter substitutions, i.e.
- * ${...#...} and friends. This could be an enum, but so
- * could a lot of other things.
- */
-
-#define SUB_END 0x0001 /* match end instead of beginning, % or %% */
-#define SUB_LONG 0x0002 /* % or # doubled, get longest match */
-#define SUB_SUBSTR 0x0004 /* match a substring */
-#define SUB_MATCH 0x0008 /* include the matched portion */
-#define SUB_REST 0x0010 /* include the unmatched portion */
-#define SUB_BIND 0x0020 /* index of beginning of string */
-#define SUB_EIND 0x0040 /* index of end of string */
-#define SUB_LEN 0x0080 /* length of match */
-#define SUB_ALL 0x0100 /* match complete string */
-#define SUB_GLOBAL 0x0200 /* global substitution ${..//all/these} */
-#define SUB_DOSUBST 0x0400 /* replacement string needs substituting */
-#define SUB_RETFAIL 0x0800 /* return status 0 if no match */
-#define SUB_START 0x1000 /* force match at start with SUB_END
- * and no SUB_SUBSTR */
-#define SUB_LIST 0x2000 /* no substitution, return list of matches */
-
-/*
- * Structure recording multiple matches inside a test string.
- * b and e are the beginning and end of the match.
- * replstr is the replacement string, if any.
- */
-struct repldata {
- int b, e; /* beginning and end of chunk to replace */
- char *replstr; /* replacement string to use */
-};
-typedef struct repldata *Repldata;
-
-/*
- * Flags to zshtokenize.
- */
-enum {
- /* Do glob substitution */
- ZSHTOK_SUBST = 0x0001,
- /* Use sh-style globbing */
- ZSHTOK_SHGLOB = 0x0002
-};
-
-/* Flags as the second argument to prefork */
-enum {
- /* argument handled like typeset foo=bar */
- PREFORK_TYPESET = 0x01,
- /* argument handled like the RHS of foo=bar */
- PREFORK_ASSIGN = 0x02,
- /* single word substitution */
- PREFORK_SINGLE = 0x04,
- /* explicitly split nested substitution */
- PREFORK_SPLIT = 0x08,
- /* SHWORDSPLIT in parameter expn */
- PREFORK_SHWORDSPLIT = 0x10,
- /* SHWORDSPLIT forced off in nested subst */
- PREFORK_NOSHWORDSPLIT = 0x20,
- /* Prefork is part of a parameter subexpression */
- PREFORK_SUBEXP = 0x40,
- /* Prefork detected an assignment list with [key]=value syntax,
- * Only used on return from prefork, not meaningful passed down.
- * Also used as flag to globlist.
- */
- PREFORK_KEY_VALUE = 0x80,
- /* No untokenise: used only as flag to globlist */
- PREFORK_NO_UNTOK = 0x100
-};
-
-/*
- * Bit flags passed back from multsub() to paramsubst().
- * Some flags go from a nested parmsubst() through the enclosing
- * stringsubst() and prefork().
- */
-enum {
- /*
- * Set if the string had whitespace at the start
- * that should cause word splitting against any preceeding string.
- */
- MULTSUB_WS_AT_START = 1,
- /*
- * Set if the string had whitespace at the end
- * that should cause word splitting against any following string.
- */
- MULTSUB_WS_AT_END = 2,
- /*
- * Set by nested paramsubst() to indicate the return
- * value is a parameter name, rather than a value.
- */
- MULTSUB_PARAM_NAME = 4
-};
-
-/*
- * Structure for adding parameters in a module.
- * The flags should declare the type; note PM_SCALAR is zero.
- *
- * Special hashes are recognized by getnfn so the PM_HASHED
- * is optional. These get slightly non-standard attention:
- * the function createspecialhash is used to create them.
- *
- * The get/set/unset attribute may be NULL; in that case the
- * parameter is assigned methods suitable for handling the
- * tie variable var, if that is not NULL, else standard methods.
- *
- * pm is set when the parameter is added to the parameter table
- * and serves as a flag that the parameter has been added.
- */
-struct paramdef {
- char *name;
- int flags;
- void *var; /* tied internal variable, if any */
- const void *gsu; /* get/set/unset structure, if special */
- GetNodeFunc getnfn; /* function to get node, if special hash */
- ScanTabFunc scantfn; /* function to scan table, if special hash */
- Param pm; /* structure inserted into param table */
-};
-
-/*
- * Shorthand for common uses of adding parameters, with no special
- * hash properties.
- */
-#define PARAMDEF(name, flags, var, gsu) \
- { name, flags, (void *) var, (void *) gsu, \
- NULL, NULL, NULL \
- }
-/*
- * Note that the following definitions are appropriate for defining
- * parameters that reference a variable (var). Hence the get/set/unset
- * methods used will assume var needs dereferencing to get the value.
- */
-#define INTPARAMDEF(name, var) \
- { name, PM_INTEGER, (void *) var, NULL, NULL, NULL, NULL }
-#define STRPARAMDEF(name, var) \
- { name, PM_SCALAR, (void *) var, NULL, NULL, NULL, NULL }
-#define ARRPARAMDEF(name, var) \
- { name, PM_ARRAY, (void *) var, NULL, NULL, NULL, NULL }
-/*
- * The following is appropriate for a module function that behaves
- * in a special fashion. Parameters used in a module that don't
- * have special behaviour shouldn't be declared in a table but
- * should just be added with the standard parameter functions.
- *
- * These parameters are not marked as removable, since they
- * shouldn't be loaded as local parameters, unlike the special
- * Zle parameters that are added and removed on each call to Zle.
- * We add the PM_REMOVABLE flag when removing the feature corresponding
- * to the parameter.
- */
-#define SPECIALPMDEF(name, flags, gsufn, getfn, scanfn) \
- { name, flags | PM_SPECIAL | PM_HIDE | PM_HIDEVAL, \
- NULL, gsufn, getfn, scanfn, NULL }
-
-/*
- * Flags for assignsparam and assignaparam.
- */
-enum {
- /* Add to rather than override value */
- ASSPM_AUGMENT = 1 << 0,
- /* Test for warning if creating global variable in function */
- ASSPM_WARN_CREATE = 1 << 1,
- /* Test for warning if using nested variable in function */
- ASSPM_WARN_NESTED = 1 << 2,
- ASSPM_WARN = (ASSPM_WARN_CREATE|ASSPM_WARN_NESTED),
- /* Import from environment, so exercise care evaluating value */
- ASSPM_ENV_IMPORT = 1 << 3,
- /* Array is key / value pairs.
- * This is normal for associative arrays but variant behaviour for
- * normal arrays.
- */
- ASSPM_KEY_VALUE = 1 << 4
-};
-
-/* node for named directory hash table (nameddirtab) */
-
-struct nameddir {
- struct hashnode node;
- char *dir; /* the directory in full */
- int diff; /* strlen(.dir) - strlen(.nam) */
-};
-
-/* flags for named directories */
-/* DISABLED is defined (1<<0) */
-#define ND_USERNAME (1<<1) /* nam is actually a username */
-#define ND_NOABBREV (1<<2) /* never print as abbrev (PWD or OLDPWD) */
-
-/* Storage for single group/name mapping */
-typedef struct {
- /* Name of group */
- char *name;
- /* Group identifier */
- gid_t gid;
-} groupmap;
-typedef groupmap *Groupmap;
-
-/* Storage for a set of group/name mappings */
-typedef struct {
- /* The set of name to gid mappings */
- Groupmap array;
- /* A count of the valid entries in groupmap. */
- int num;
-} groupset;
-typedef groupset *Groupset;
-
-/* flags for controlling printing of hash table nodes */
-#define PRINT_NAMEONLY (1<<0)
-#define PRINT_TYPE (1<<1)
-#define PRINT_LIST (1<<2)
-#define PRINT_KV_PAIR (1<<3)
-#define PRINT_INCLUDEVALUE (1<<4)
-#define PRINT_TYPESET (1<<5)
-#define PRINT_LINE (1<<6)
-
-/* flags for printing for the whence builtin */
-#define PRINT_WHENCE_CSH (1<<7)
-#define PRINT_WHENCE_VERBOSE (1<<8)
-#define PRINT_WHENCE_SIMPLE (1<<9)
-#define PRINT_WHENCE_FUNCDEF (1<<10)
-#define PRINT_WHENCE_WORD (1<<11)
-
-/* Return values from loop() */
-
-enum loop_return {
- /* Loop executed OK */
- LOOP_OK,
- /* Loop executed no code */
- LOOP_EMPTY,
- /* Loop encountered an error */
- LOOP_ERROR
-};
-
-/* Return values from source() */
-
-enum source_return {
- /* Source ran OK */
- SOURCE_OK = 0,
- /* File not found */
- SOURCE_NOT_FOUND = 1,
- /* Internal error sourcing file */
- SOURCE_ERROR = 2
-};
-
-enum noerrexit_bits {
- /* Suppress ERR_EXIT and traps: global */
- NOERREXIT_EXIT = 1,
- /* Suppress ERR_RETURN: per function call */
- NOERREXIT_RETURN = 2,
- /* NOERREXIT only needed on way down */
- NOERREXIT_UNTIL_EXEC = 4,
- /* Force exit on SIGINT */
- NOERREXIT_SIGNAL = 8
-};
-
-/***********************************/
-/* Definitions for history control */
-/***********************************/
-
-/* history entry */
-
-struct histent {
- struct hashnode node;
-
- Histent up; /* previous line (moving upward) */
- Histent down; /* next line (moving downward) */
- char *zle_text; /* the edited history line,
- * a metafied, NULL-terminated string,
- * i.e the same format as the original
- * entry
- */
- time_t stim; /* command started time (datestamp) */
- time_t ftim; /* command finished time */
- short *words; /* Position of words in history */
- /* line: as pairs of start, end */
- int nwords; /* Number of words in history line */
- zlong histnum; /* A sequential history number */
-};
-
-#define HIST_MAKEUNIQUE 0x00000001 /* Kill this new entry if not unique */
-#define HIST_OLD 0x00000002 /* Command is already written to disk*/
-#define HIST_READ 0x00000004 /* Command was read back from disk*/
-#define HIST_DUP 0x00000008 /* Command duplicates a later line */
-#define HIST_FOREIGN 0x00000010 /* Command came from another shell */
-#define HIST_TMPSTORE 0x00000020 /* Kill when user enters another cmd */
-#define HIST_NOWRITE 0x00000040 /* Keep internally but don't write */
-
-#define GETHIST_UPWARD (-1)
-#define GETHIST_DOWNWARD 1
-#define GETHIST_EXACT 0
-
-/* Parts of the code where history expansion is disabled *
- * should be within a pair of STOPHIST ... ALLOWHIST */
-
-#define STOPHIST (stophist += 4);
-#define ALLOWHIST (stophist -= 4);
-
-#define HISTFLAG_DONE 1
-#define HISTFLAG_NOEXEC 2
-#define HISTFLAG_RECALL 4
-#define HISTFLAG_SETTY 8
-
-#define HFILE_APPEND 0x0001
-#define HFILE_SKIPOLD 0x0002
-#define HFILE_SKIPDUPS 0x0004
-#define HFILE_SKIPFOREIGN 0x0008
-#define HFILE_FAST 0x0010
-#define HFILE_NO_REWRITE 0x0020
-#define HFILE_USE_OPTIONS 0x8000
-
-/*
- * Flags argument to bufferwords() used
- * also by lexflags variable.
- */
-/*
- * Kick the lexer into special string-analysis
- * mode without parsing. Any bit set in
- * the flags has this effect, but this
- * has otherwise all the default effects.
- */
-#define LEXFLAGS_ACTIVE 0x0001
-/*
- * Being used from zle. This is slightly more intrusive
- * (=> grotesquely non-modular) than use from within
- * the main shell, so it's a separate flag.
- */
-#define LEXFLAGS_ZLE 0x0002
-/*
- * Parse comments and treat each comment as a single string
- */
-#define LEXFLAGS_COMMENTS_KEEP 0x0004
-/*
- * Parse comments and strip them.
- */
-#define LEXFLAGS_COMMENTS_STRIP 0x0008
-/*
- * Either of the above
- */
-#define LEXFLAGS_COMMENTS (LEXFLAGS_COMMENTS_KEEP|LEXFLAGS_COMMENTS_STRIP)
-/*
- * Treat newlines as whitespace
- */
-#define LEXFLAGS_NEWLINE 0x0010
-
-/******************************************/
-/* Definitions for programable completion */
-/******************************************/
-
-/* Nothing special. */
-#define IN_NOTHING 0
-/* In command position. */
-#define IN_CMD 1
-/* In a mathematical environment. */
-#define IN_MATH 2
-/* In a condition. */
-#define IN_COND 3
-/* In a parameter assignment (e.g. `foo=bar'). */
-#define IN_ENV 4
-/* In a parameter name in an assignment. */
-#define IN_PAR 5
-
-
-/******************************/
-/* Definition for zsh options */
-/******************************/
-
-/* Possible values of emulation */
-
-#define EMULATE_CSH (1<<1) /* C shell */
-#define EMULATE_KSH (1<<2) /* Korn shell */
-#define EMULATE_SH (1<<3) /* Bourne shell */
-#define EMULATE_ZSH (1<<4) /* `native' mode */
-
-/* Test for a shell emulation. Use this rather than emulation directly. */
-#define EMULATION(X) (emulation & (X))
-
-/* Return only base shell emulation field. */
-#define SHELL_EMULATION() (emulation & ((1<<5)-1))
-
-/* Additional flags */
-
-#define EMULATE_FULLY (1<<5) /* "emulate -R" in effect */
-/*
- * Higher bits are used in options.c, record lowest unused bit...
- */
-#define EMULATE_UNUSED (1<<6)
-
-/* option indices */
-
-enum {
- OPT_INVALID,
- ALIASESOPT,
- ALIASFUNCDEF,
- ALLEXPORT,
- ALWAYSLASTPROMPT,
- ALWAYSTOEND,
- APPENDHISTORY,
- AUTOCD,
- AUTOCONTINUE,
- AUTOLIST,
- AUTOMENU,
- AUTONAMEDIRS,
- AUTOPARAMKEYS,
- AUTOPARAMSLASH,
- AUTOPUSHD,
- AUTOREMOVESLASH,
- AUTORESUME,
- BADPATTERN,
- BANGHIST,
- BAREGLOBQUAL,
- BASHAUTOLIST,
- BASHREMATCH,
- BEEP,
- BGNICE,
- BRACECCL,
- BSDECHO,
- CASEGLOB,
- CASEMATCH,
- CBASES,
- CDABLEVARS,
- CHASEDOTS,
- CHASELINKS,
- CHECKJOBS,
- CHECKRUNNINGJOBS,
- CLOBBER,
- APPENDCREATE,
- COMBININGCHARS,
- COMPLETEALIASES,
- COMPLETEINWORD,
- CORRECT,
- CORRECTALL,
- CONTINUEONERROR,
- CPRECEDENCES,
- CSHJUNKIEHISTORY,
- CSHJUNKIELOOPS,
- CSHJUNKIEQUOTES,
- CSHNULLCMD,
- CSHNULLGLOB,
- DEBUGBEFORECMD,
- EMACSMODE,
- EQUALS,
- ERREXIT,
- ERRRETURN,
- EXECOPT,
- EXTENDEDGLOB,
- EXTENDEDHISTORY,
- EVALLINENO,
- FLOWCONTROL,
- FORCEFLOAT,
- FUNCTIONARGZERO,
- GLOBOPT,
- GLOBALEXPORT,
- GLOBALRCS,
- GLOBASSIGN,
- GLOBCOMPLETE,
- GLOBDOTS,
- GLOBSTARSHORT,
- GLOBSUBST,
- HASHCMDS,
- HASHDIRS,
- HASHEXECUTABLESONLY,
- HASHLISTALL,
- HISTALLOWCLOBBER,
- HISTBEEP,
- HISTEXPIREDUPSFIRST,
- HISTFCNTLLOCK,
- HISTFINDNODUPS,
- HISTIGNOREALLDUPS,
- HISTIGNOREDUPS,
- HISTIGNORESPACE,
- HISTLEXWORDS,
- HISTNOFUNCTIONS,
- HISTNOSTORE,
- HISTREDUCEBLANKS,
- HISTSAVEBYCOPY,
- HISTSAVENODUPS,
- HISTSUBSTPATTERN,
- HISTVERIFY,
- HUP,
- IGNOREBRACES,
- IGNORECLOSEBRACES,
- IGNOREEOF,
- INCAPPENDHISTORY,
- INCAPPENDHISTORYTIME,
- INTERACTIVE,
- INTERACTIVECOMMENTS,
- KSHARRAYS,
- KSHAUTOLOAD,
- KSHGLOB,
- KSHOPTIONPRINT,
- KSHTYPESET,
- KSHZEROSUBSCRIPT,
- LISTAMBIGUOUS,
- LISTBEEP,
- LISTPACKED,
- LISTROWSFIRST,
- LISTTYPES,
- LOCALLOOPS,
- LOCALOPTIONS,
- LOCALPATTERNS,
- LOCALTRAPS,
- LOGINSHELL,
- LONGLISTJOBS,
- MAGICEQUALSUBST,
- MAILWARNING,
- MARKDIRS,
- MENUCOMPLETE,
- MONITOR,
- MULTIBYTE,
- MULTIFUNCDEF,
- MULTIOS,
- NOMATCH,
- NOTIFY,
- NULLGLOB,
- NUMERICGLOBSORT,
- OCTALZEROES,
- OVERSTRIKE,
- PATHDIRS,
- PATHSCRIPT,
- PIPEFAIL,
- POSIXALIASES,
- POSIXARGZERO,
- POSIXBUILTINS,
- POSIXCD,
- POSIXIDENTIFIERS,
- POSIXJOBS,
- POSIXSTRINGS,
- POSIXTRAPS,
- PRINTEIGHTBIT,
- PRINTEXITVALUE,
- PRIVILEGED,
- PROMPTBANG,
- PROMPTCR,
- PROMPTPERCENT,
- PROMPTSP,
- PROMPTSUBST,
- PUSHDIGNOREDUPS,
- PUSHDMINUS,
- PUSHDSILENT,
- PUSHDTOHOME,
- RCEXPANDPARAM,
- RCQUOTES,
- RCS,
- RECEXACT,
- REMATCHPCRE,
- RESTRICTED,
- RMSTARSILENT,
- RMSTARWAIT,
- SHAREHISTORY,
- SHFILEEXPANSION,
- SHGLOB,
- SHINSTDIN,
- SHNULLCMD,
- SHOPTIONLETTERS,
- SHORTLOOPS,
- SHWORDSPLIT,
- SINGLECOMMAND,
- SINGLELINEZLE,
- SOURCETRACE,
- SUNKEYBOARDHACK,
- TRANSIENTRPROMPT,
- TRAPSASYNC,
- TYPESETSILENT,
- UNSET,
- VERBOSE,
- VIMODE,
- WARNCREATEGLOBAL,
- WARNNESTEDVAR,
- XTRACE,
- USEZLE,
- DVORAK,
- OPT_SIZE
-};
-
-/*
- * Size required to fit an option number.
- * If OPT_SIZE goes above 256 this will need to expand.
- */
-typedef unsigned char OptIndex;
-
-#undef isset
-#define isset(X) (opts[X])
-#define unset(X) (!opts[X])
-
-#define interact (isset(INTERACTIVE))
-#define jobbing (isset(MONITOR))
-#define islogin (isset(LOGINSHELL))
-
-/*
- * Record of emulation and options that need to be set
- * for a full "emulate".
- */
-struct emulation_options {
- /* The emulation itself */
- int emulation;
- /* The number of options in on_opts. */
- int n_on_opts;
- /* The number of options in off_opts. */
- int n_off_opts;
- /*
- * Array of options to be turned on.
- * Only options specified explicitly in the emulate command
- * are recorded. Null if n_on_opts is zero.
- */
- OptIndex *on_opts;
- /* Array of options to be turned off, similar. */
- OptIndex *off_opts;
-};
-
-/***********************************************/
-/* Definitions for terminal and display control */
-/***********************************************/
-
-/* tty state structure */
-
-struct ttyinfo {
-#ifdef HAVE_TERMIOS_H
- struct termios tio;
-#else
-# ifdef HAVE_TERMIO_H
- struct termio tio;
-# else
- struct sgttyb sgttyb;
- int lmodes;
- struct tchars tchars;
- struct ltchars ltchars;
-# endif
-#endif
-#ifdef TIOCGWINSZ
- struct winsize winsize;
-#endif
-};
-
-#ifndef __INTERIX
-/* defines for whether tabs expand to spaces */
-#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
-#define SGTTYFLAG shttyinfo.tio.c_oflag
-#else /* we're using sgtty */
-#define SGTTYFLAG shttyinfo.sgttyb.sg_flags
-#endif
-# ifdef TAB3
-#define SGTABTYPE TAB3
-# else
-# ifdef OXTABS
-#define SGTABTYPE OXTABS
-# else
-# ifdef XTABS
-#define SGTABTYPE XTABS
-# endif
-# endif
-# endif
-#endif
-
-/* flags for termflags */
-
-#define TERM_BAD 0x01 /* terminal has extremely basic capabilities */
-#define TERM_UNKNOWN 0x02 /* unknown terminal type */
-#define TERM_NOUP 0x04 /* terminal has no up capability */
-#define TERM_SHORT 0x08 /* terminal is < 3 lines high */
-#define TERM_NARROW 0x10 /* terminal is < 3 columns wide */
-
-/* interesting termcap strings */
-
-#define TCCLEARSCREEN 0
-#define TCLEFT 1
-#define TCMULTLEFT 2
-#define TCRIGHT 3
-#define TCMULTRIGHT 4
-#define TCUP 5
-#define TCMULTUP 6
-#define TCDOWN 7
-#define TCMULTDOWN 8
-#define TCDEL 9
-#define TCMULTDEL 10
-#define TCINS 11
-#define TCMULTINS 12
-#define TCCLEAREOD 13
-#define TCCLEAREOL 14
-#define TCINSLINE 15
-#define TCDELLINE 16
-#define TCNEXTTAB 17
-#define TCBOLDFACEBEG 18
-#define TCSTANDOUTBEG 19
-#define TCUNDERLINEBEG 20
-#define TCALLATTRSOFF 21
-#define TCSTANDOUTEND 22
-#define TCUNDERLINEEND 23
-#define TCHORIZPOS 24
-#define TCUPCURSOR 25
-#define TCDOWNCURSOR 26
-#define TCLEFTCURSOR 27
-#define TCRIGHTCURSOR 28
-#define TCSAVECURSOR 29
-#define TCRESTRCURSOR 30
-#define TCBACKSPACE 31
-#define TCFGCOLOUR 32
-#define TCBGCOLOUR 33
-#define TC_COUNT 34
-
-#define tccan(X) (tclen[X])
-
-/*
- * Text attributes for displaying in ZLE
- */
-
-#define TXTBOLDFACE 0x0001
-#define TXTSTANDOUT 0x0002
-#define TXTUNDERLINE 0x0004
-#define TXTFGCOLOUR 0x0008
-#define TXTBGCOLOUR 0x0010
-
-#define TXT_ATTR_ON_MASK 0x001F
-
-#define txtisset(X) (txtattrmask & (X))
-#define txtset(X) (txtattrmask |= (X))
-#define txtunset(X) (txtattrmask &= ~(X))
-
-#define TXTNOBOLDFACE 0x0020
-#define TXTNOSTANDOUT 0x0040
-#define TXTNOUNDERLINE 0x0080
-#define TXTNOFGCOLOUR 0x0100
-#define TXTNOBGCOLOUR 0x0200
-
-#define TXT_ATTR_OFF_MASK 0x03E0
-/* Bits to shift off right to get on */
-#define TXT_ATTR_OFF_ON_SHIFT 5
-#define TXT_ATTR_OFF_FROM_ON(attr) \
- (((attr) & TXT_ATTR_ON_MASK) << TXT_ATTR_OFF_ON_SHIFT)
-#define TXT_ATTR_ON_FROM_OFF(attr) \
- (((attr) & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT)
-/*
- * Indicates to zle_refresh.c that the character entry is an
- * index into the list of multiword symbols.
- */
-#define TXT_MULTIWORD_MASK 0x0400
-
-/* Mask for colour to use in foreground */
-#define TXT_ATTR_FG_COL_MASK 0x000FF000
-/* Bits to shift the foreground colour */
-#define TXT_ATTR_FG_COL_SHIFT (12)
-/* Mask for colour to use in background */
-#define TXT_ATTR_BG_COL_MASK 0x0FF00000
-/* Bits to shift the background colour */
-#define TXT_ATTR_BG_COL_SHIFT (20)
-
-/* Flag to use termcap AF sequence to set colour, if available */
-#define TXT_ATTR_FG_TERMCAP 0x10000000
-/* Flag to use termcap AB sequence to set colour, if available */
-#define TXT_ATTR_BG_TERMCAP 0x20000000
-
-/* Things to turn on, including values for the colour elements */
-#define TXT_ATTR_ON_VALUES_MASK \
- (TXT_ATTR_ON_MASK|TXT_ATTR_FG_COL_MASK|TXT_ATTR_BG_COL_MASK|\
- TXT_ATTR_FG_TERMCAP|TXT_ATTR_BG_TERMCAP)
-
-/* Mask out everything to do with setting a foreground colour */
-#define TXT_ATTR_FG_ON_MASK \
- (TXTFGCOLOUR|TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_TERMCAP)
-
-/* Mask out everything to do with setting a background colour */
-#define TXT_ATTR_BG_ON_MASK \
- (TXTBGCOLOUR|TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_TERMCAP)
-
-/* Mask out everything to do with activating colours */
-#define TXT_ATTR_COLOUR_ON_MASK \
- (TXT_ATTR_FG_ON_MASK|TXT_ATTR_BG_ON_MASK)
-
-#define txtchangeisset(T,X) ((T) & (X))
-#define txtchangeget(T,A) (((T) & A ## _MASK) >> A ## _SHIFT)
-#define txtchangeset(T, X, Y) ((void)(T && (*T &= ~(Y), *T |= (X))))
-
-/*
- * For outputting sequences to change colour: specify foreground
- * or background.
- */
-#define COL_SEQ_FG (0)
-#define COL_SEQ_BG (1)
-#define COL_SEQ_COUNT (2)
-
-/*
- * Flags to testcap() and set_colour_attribute (which currently only
- * handles TSC_PROMPT).
- */
-enum {
- /* Raw output: use stdout rather than shout */
- TSC_RAW = 0x0001,
- /* Output to current prompt buffer: only used when assembling prompt */
- TSC_PROMPT = 0x0002,
- /* Mask to get the output mode */
- TSC_OUTPUT_MASK = 0x0003,
- /* Change needs reset of other attributes */
- TSC_DIRTY = 0x0004
-};
-
-/****************************************/
-/* Definitions for the %_ prompt escape */
-/****************************************/
-
-#define CMDSTACKSZ 256
-
-#define CS_FOR 0
-#define CS_WHILE 1
-#define CS_REPEAT 2
-#define CS_SELECT 3
-#define CS_UNTIL 4
-#define CS_IF 5
-#define CS_IFTHEN 6
-#define CS_ELSE 7
-#define CS_ELIF 8
-#define CS_MATH 9
-#define CS_COND 10
-#define CS_CMDOR 11
-#define CS_CMDAND 12
-#define CS_PIPE 13
-#define CS_ERRPIPE 14
-#define CS_FOREACH 15
-#define CS_CASE 16
-#define CS_FUNCDEF 17
-#define CS_SUBSH 18
-#define CS_CURSH 19
-#define CS_ARRAY 20
-#define CS_QUOTE 21
-#define CS_DQUOTE 22
-#define CS_BQUOTE 23
-#define CS_CMDSUBST 24
-#define CS_MATHSUBST 25
-#define CS_ELIFTHEN 26
-#define CS_HEREDOC 27
-#define CS_HEREDOCD 28
-#define CS_BRACE 29
-#define CS_BRACEPAR 30
-#define CS_ALWAYS 31
-
-/* Increment as necessary */
-#define CS_COUNT 32
-
-/*********************
- * Memory management *
- *********************/
-
-/*
- * A Heapid is a type for identifying, uniquely up to the point where
- * the count of new identifiers wraps. all heaps that are or
- * (importantly) have been valid. Each valid heap is given an
- * identifier, and every time we push a heap we save the old identifier
- * and give the heap a new identifier so that when the heap is popped
- * or freed we can spot anything using invalid memory from the popped
- * heap.
- *
- * We could make this unsigned long long if we wanted a big range.
- */
-typedef unsigned int Heapid;
-
-#ifdef ZSH_HEAP_DEBUG
-
-/* printf format specifier corresponding to Heapid */
-#define HEAPID_FMT "%x"
-
-/* Marker that memory is permanently allocated */
-#define HEAPID_PERMANENT (UINT_MAX)
-
-/*
- * Heap debug verbosity.
- * Bits to be 'or'ed into the variable also called heap_debug_verbosity.
- */
-enum heap_debug_verbosity {
- /* Report when we push a heap */
- HDV_PUSH = 0x01,
- /* Report when we pop a heap */
- HDV_POP = 0x02,
- /* Report when we create a new heap from which to allocate */
- HDV_CREATE = 0x04,
- /* Report every time we free a complete heap */
- HDV_FREE = 0x08,
- /* Report when we temporarily install a new set of heaps */
- HDV_NEW = 0x10,
- /* Report when we restore an old set of heaps */
- HDV_OLD = 0x20,
- /* Report when we temporarily switch heaps */
- HDV_SWITCH = 0x40,
- /*
- * Report every time we allocate memory from the heap.
- * This is very verbose, and arguably not very useful: we
- * would expect to allocate memory from a heap we create.
- * For much debugging heap_debug_verbosity = 0x7f should be sufficient.
- */
- HDV_ALLOC = 0x80
-};
-
-#define HEAP_ERROR(heap_id) \
- fprintf(stderr, "%s:%d: HEAP DEBUG: invalid heap: " HEAPID_FMT ".\n", \
- __FILE__, __LINE__, heap_id)
-#endif
-
-/* heappush saves the current heap state using this structure */
-
-struct heapstack {
- struct heapstack *next; /* next one in list for this heap */
- size_t used;
-#ifdef ZSH_HEAP_DEBUG
- Heapid heap_id;
-#endif
-};
-
-/* A zsh heap. */
-
-struct heap {
- struct heap *next; /* next one */
- size_t size; /* size of heap */
- size_t used; /* bytes used from the heap */
- struct heapstack *sp; /* used by pushheap() to save the value used */
-
-#ifdef ZSH_HEAP_DEBUG
- unsigned int heap_id;
-#endif
-
-/* Uncomment the following if the struct needs padding to 64-bit size. */
-/* Make sure sizeof(heap) is a multiple of 8
-#if defined(PAD_64_BIT) && !defined(__GNUC__)
- size_t dummy;
-#endif
-*/
-#define arena(X) ((char *) (X) + sizeof(struct heap))
-}
-#if defined(PAD_64_BIT) && defined(__GNUC__)
- __attribute__ ((aligned (8)))
-#endif
-;
-
-# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do
-# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0);
-
-# define SWITCHHEAPS(o, h) do { o = switch_heaps(h); do
-# define SWITCHBACKHEAPS(o) while (0); switch_heaps(o); } while (0);
-
-/****************/
-/* Debug macros */
-/****************/
-
-#ifdef DEBUG
-#define STRINGIFY_LITERAL(x) # x
-#define STRINGIFY(x) STRINGIFY_LITERAL(x)
-#define ERRMSG(x) (__FILE__ ":" STRINGIFY(__LINE__) ": " x)
-# define DPUTS(X,Y) if (!(X)) {;} else dputs(ERRMSG(Y))
-# define DPUTS1(X,Y,Z1) if (!(X)) {;} else dputs(ERRMSG(Y), Z1)
-# define DPUTS2(X,Y,Z1,Z2) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2)
-# define DPUTS3(X,Y,Z1,Z2,Z3) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2, Z3)
-#else
-# define DPUTS(X,Y)
-# define DPUTS1(X,Y,Z1)
-# define DPUTS2(X,Y,Z1,Z2)
-# define DPUTS3(X,Y,Z1,Z2,Z3)
-#endif
-
-/**************************/
-/* Signal handling macros */
-/**************************/
-
-/* These used in the sigtrapped[] array */
-
-#define ZSIG_TRAPPED (1<<0) /* Signal is trapped */
-#define ZSIG_IGNORED (1<<1) /* Signal is ignored */
-#define ZSIG_FUNC (1<<2) /* Trap is a function, not an eval list */
-/* Mask to get the above flags */
-#define ZSIG_MASK (ZSIG_TRAPPED|ZSIG_IGNORED|ZSIG_FUNC)
-/* No. of bits to shift local level when storing in sigtrapped */
-#define ZSIG_ALIAS (1<<3) /* Trap is stored under an alias */
-#define ZSIG_SHIFT 4
-
-/*
- * State of traps, stored in trap_state.
- */
-enum trap_state {
- /* Traps are not active; trap_return is not useful. */
- TRAP_STATE_INACTIVE,
- /*
- * Traps are set but haven't triggered; trap_return gives
- * minus function depth.
- */
- TRAP_STATE_PRIMED,
- /*
- * Trap has triggered to force a return; trap_return givens
- * return value.
- */
- TRAP_STATE_FORCE_RETURN
-};
-
-#define IN_EVAL_TRAP() \
- (intrap && !trapisfunc && traplocallevel == locallevel)
-
-/*
- * Bits in the errflag variable.
- */
-enum errflag_bits {
- /*
- * Standard internal error bit.
- */
- ERRFLAG_ERROR = 1,
- /*
- * User interrupt.
- */
- ERRFLAG_INT = 2,
- /*
- * Hard error --- return to top-level prompt in interactive
- * shell. In non-interactive shell we'll typically already
- * have exited. This is reset by "errflag = 0" in
- * loop(toplevel = 1, ...).
- */
- ERRFLAG_HARD = 4
-};
-
-/***********/
-/* Sorting */
-/***********/
-
-typedef int (*CompareFn) _((const void *, const void *));
-
-enum {
- SORTIT_ANYOLDHOW = 0, /* Defaults */
- SORTIT_IGNORING_CASE = 1,
- SORTIT_NUMERICALLY = 2,
- SORTIT_BACKWARDS = 4,
- /*
- * Ignore backslashes that quote another character---which may
- * be another backslash; the second backslash is active.
- */
- SORTIT_IGNORING_BACKSLASHES = 8,
- /*
- * Ignored by strmetasort(); used by paramsubst() to indicate
- * there is some sorting to do.
- */
- SORTIT_SOMEHOW = 16,
-};
-
-/*
- * Element of array passed to qsort().
- */
-struct sortelt {
- /* The original string. */
- char *orig;
- /* The string used for comparison. */
- const char *cmp;
- /*
- * The length of the string if passed down to the sort algorithm.
- * Used to sort the lengths together with the strings.
- */
- int origlen;
- /*
- * The length of the string, if needed, else -1.
- * The length is only needed if there are embededded nulls.
- */
- int len;
-};
-
-typedef struct sortelt *SortElt;
-
-/*********************************************************/
-/* Structures to save and restore for individual modules */
-/*********************************************************/
-
-/* History */
-struct hist_stack {
- int histactive;
- int histdone;
- int stophist;
- int hlinesz;
- zlong defev;
- char *hline;
- char *hptr;
- short *chwords;
- int chwordlen;
- int chwordpos;
- int (*hgetc) _((void));
- void (*hungetc) _((int));
- void (*hwaddc) _((int));
- void (*hwbegin) _((int));
- void (*hwabort) _((void));
- void (*hwend) _((void));
- void (*addtoline) _((int));
- unsigned char *cstack;
- int csp;
- int hist_keep_comment;
-};
-
-/*
- * State of a lexical token buffer.
- *
- * It would be neater to include the pointer to the start of the buffer,
- * however the current code structure means that the standard instance
- * of this, tokstr, is visible in lots of places, so that's not
- * convenient.
- */
-
-struct lexbufstate {
- /*
- * Next character to be added.
- * Set to NULL when the buffer is to be visible from elsewhere.
- */
- char *ptr;
- /* Allocated buffer size */
- int siz;
- /* Length in use */
- int len;
-};
-
-/* Lexical analyser */
-struct lex_stack {
- int dbparens;
- int isfirstln;
- int isfirstch;
- int lexflags;
- enum lextok tok;
- char *tokstr;
- char *zshlextext;
- struct lexbufstate lexbuf;
- int lex_add_raw;
- char *tokstr_raw;
- struct lexbufstate lexbuf_raw;
- int lexstop;
- zlong toklineno;
-};
-
-/* Parser */
-struct parse_stack {
- struct heredocs *hdocs;
-
- int incmdpos;
- int aliasspaceflag;
- int incond;
- int inredir;
- int incasepat;
- int isnewlin;
- int infor;
- int inrepeat_;
- int intypeset;
-
- int eclen, ecused, ecnpats;
- Wordcode ecbuf;
- Eccstr ecstrs;
- int ecsoffs, ecssub, ecnfunc;
-};
-
-/************************/
-/* Flags to casemodifiy */
-/************************/
-
-enum {
- CASMOD_NONE, /* dummy for tests */
- CASMOD_UPPER,
- CASMOD_LOWER,
- CASMOD_CAPS
-};
-
-/*******************************************/
-/* Flags to third argument of getkeystring */
-/*******************************************/
-
-/*
- * By default handles some subset of \-escapes. The following bits
- * turn on extra features.
- */
-enum {
- /*
- * Handle octal where the first digit is non-zero e.g. \3, \33, \333
- * Otherwise \0333 etc. is handled, i.e. one of \0123 or \123 will
- * work, but not both.
- */
- GETKEY_OCTAL_ESC = (1 << 0),
- /*
- * Handle Emacs-like key sequences \C-x etc.
- * Also treat \E like \e and use backslashes to escape the
- * next character if not special, i.e. do all the things we
- * don't do with the echo builtin.
- */
- GETKEY_EMACS = (1 << 1),
- /* Handle ^X etc. */
- GETKEY_CTRL = (1 << 2),
- /* Handle \c (uses misc arg to getkeystring()) */
- GETKEY_BACKSLASH_C = (1 << 3),
- /* Do $'...' quoting (len arg to getkeystring() not used) */
- GETKEY_DOLLAR_QUOTE = (1 << 4),
- /* Handle \- (uses misc arg to getkeystring()) */
- GETKEY_BACKSLASH_MINUS = (1 << 5),
- /* Parse only one character (len arg to getkeystring() not used) */
- GETKEY_SINGLE_CHAR = (1 << 6),
- /*
- * If beyond offset in misc arg, add 1 to it for each character removed.
- * Yes, I know that doesn't seem to make much sense.
- * It's for use in completion, comprenez?
- */
- GETKEY_UPDATE_OFFSET = (1 << 7),
- /*
- * When replacing numeric escapes for printf format strings, % -> %%
- */
- GETKEY_PRINTF_PERCENT = (1 << 8)
-};
-
-/*
- * Standard combinations used within the shell.
- * Note GETKEYS_... instead of GETKEY_...: this is important in some cases.
- */
-/* echo builtin */
-#define GETKEYS_ECHO (GETKEY_BACKSLASH_C)
-/* printf format string: \123 -> S, \0123 -> NL 3, \045 -> %% */
-#define GETKEYS_PRINTF_FMT \
- (GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C|GETKEY_PRINTF_PERCENT)
-/* printf argument: \123 -> \123, \0123 -> S */
-#define GETKEYS_PRINTF_ARG (GETKEY_BACKSLASH_C)
-/* Full print without -e */
-#define GETKEYS_PRINT (GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C|GETKEY_EMACS)
-/* bindkey */
-#define GETKEYS_BINDKEY (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL)
-/* $'...' */
-#define GETKEYS_DOLLARS_QUOTE (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_DOLLAR_QUOTE)
-/* Single character for math processing */
-#define GETKEYS_MATH \
- (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_SINGLE_CHAR)
-/* Used to process separators etc. with print-style escapes */
-#define GETKEYS_SEP (GETKEY_OCTAL_ESC|GETKEY_EMACS)
-/* Used for suffix removal */
-#define GETKEYS_SUFFIX \
- (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_BACKSLASH_MINUS)
-
-/**********************************/
-/* Flags to third argument of zle */
-/**********************************/
-
-#define ZLRF_HISTORY 0x01 /* OK to access the history list */
-#define ZLRF_NOSETTY 0x02 /* Don't set tty before return */
-#define ZLRF_IGNOREEOF 0x04 /* Ignore an EOF from the keyboard */
-
-/***************************/
-/* Context of zleread call */
-/***************************/
-
-enum {
- ZLCON_LINE_START, /* Command line at PS1 */
- ZLCON_LINE_CONT, /* Command line at PS2 */
- ZLCON_SELECT, /* Select loop */
- ZLCON_VARED /* Vared command */
-};
-
-/****************/
-/* Entry points */
-/****************/
-
-/* compctl entry point pointers */
-
-typedef int (*CompctlReadFn) _((char *, char **, Options, char *));
-
-/* ZLE entry point pointer */
-
-typedef char * (*ZleEntryPoint)(int cmd, va_list ap);
-
-/* Commands to pass to entry point */
-
-enum {
- ZLE_CMD_GET_LINE,
- ZLE_CMD_READ,
- ZLE_CMD_ADD_TO_LINE,
- ZLE_CMD_TRASH,
- ZLE_CMD_RESET_PROMPT,
- ZLE_CMD_REFRESH,
- ZLE_CMD_SET_KEYMAP,
- ZLE_CMD_GET_KEY,
- ZLE_CMD_SET_HIST_LINE
-};
-
-/***************************************/
-/* Hooks in core. */
-/***************************************/
-
-#define EXITHOOK (zshhooks + 0)
-#define BEFORETRAPHOOK (zshhooks + 1)
-#define AFTERTRAPHOOK (zshhooks + 2)
-
-#ifdef MULTIBYTE_SUPPORT
-/* Final argument to mb_niceformat() */
-enum {
- NICEFLAG_HEAP = 1, /* Heap allocation where needed */
- NICEFLAG_QUOTE = 2, /* Result will appear in $'...' */
- NICEFLAG_NODUP = 4, /* Leave allocated */
-};
-
-/* Metafied input */
-#define nicezputs(str, outs) (void)mb_niceformat((str), (outs), NULL, 0)
-#define MB_METACHARINIT() mb_charinit()
-typedef wint_t convchar_t;
-#define MB_METACHARLENCONV(str, cp) mb_metacharlenconv((str), (cp))
-#define MB_METACHARLEN(str) mb_metacharlenconv(str, NULL)
-#define MB_METASTRLEN(str) mb_metastrlenend(str, 0, NULL)
-#define MB_METASTRWIDTH(str) mb_metastrlenend(str, 1, NULL)
-#define MB_METASTRLEN2(str, widthp) mb_metastrlenend(str, widthp, NULL)
-#define MB_METASTRLEN2END(str, widthp, eptr) \
- mb_metastrlenend(str, widthp, eptr)
-
-/* Unmetafined input */
-#define MB_CHARINIT() mb_charinit()
-#define MB_CHARLENCONV(str, len, cp) mb_charlenconv((str), (len), (cp))
-#define MB_CHARLEN(str, len) mb_charlenconv((str), (len), NULL)
-
-/*
- * We replace broken implementations with one that uses Unicode
- * characters directly as wide characters. In principle this is only
- * likely to work if __STDC_ISO_10646__ is defined, since that's pretty
- * much what the definition tells us. However, we happen to know this
- * works on MacOS which doesn't define that.
- */
-#ifdef ENABLE_UNICODE9
-#define WCWIDTH(wc) u9_wcwidth(wc)
-#else
-#define WCWIDTH(wc) wcwidth(wc)
-#endif
-/*
- * Note WCWIDTH_WINT() takes wint_t, typically as a convchar_t.
- * It's written to use the wint_t from mb_metacharlenconv() without
- * further tests.
- *
- * This version has a non-multibyte definition that simply returns
- * 1. We never expose WCWIDTH() in the non-multibyte world since
- * it's just a proxy for wcwidth() itself.
- */
-#define WCWIDTH_WINT(wc) zwcwidth(wc)
-
-#define MB_INCOMPLETE ((size_t)-2)
-#define MB_INVALID ((size_t)-1)
-
-/*
- * MB_CUR_MAX is the maximum number of bytes that a single wide
- * character will convert into. We use it to keep strings
- * sufficiently long. It should always be defined, but if it isn't
- * just assume we are using Unicode which requires 6 characters.
- * (Note that it's not necessarily defined to a constant.)
- */
-#ifndef MB_CUR_MAX
-#define MB_CUR_MAX 6
-#endif
-
-/* Convert character or string to wide character or string */
-#define ZWC(c) L ## c
-#define ZWS(s) L ## s
-
-/*
- * Test for a combining character.
- *
- * wc is assumed to be a wchar_t (i.e. we don't need zwcwidth).
- *
- * Pedantic note: in Unicode, a combining character need not be
- * zero length. However, we are concerned here about display;
- * we simply need to know whether the character will be displayed
- * on top of another one. We use "combining character" in this
- * sense throughout the shell. I am not aware of a way of
- * detecting the Unicode trait in standard libraries.
- */
-#define IS_COMBINING(wc) (wc != 0 && WCWIDTH(wc) == 0)
-/*
- * Test for the base of a combining character.
- *
- * We assume a combining character can be successfully displayed with
- * any non-space printable character, which is what a graphic character
- * is, as long as it has non-zero width. We need to avoid all forms of
- * space because the shell will split words on any whitespace.
- */
-#define IS_BASECHAR(wc) (iswgraph(wc) && WCWIDTH(wc) > 0)
-
-#else /* not MULTIBYTE_SUPPORT */
-
-#define MB_METACHARINIT()
-typedef int convchar_t;
-#define MB_METACHARLENCONV(str, cp) metacharlenconv((str), (cp))
-#define MB_METACHARLEN(str) (*(str) == Meta ? 2 : 1)
-#define MB_METASTRLEN(str) ztrlen(str)
-#define MB_METASTRWIDTH(str) ztrlen(str)
-#define MB_METASTRLEN2(str, widthp) ztrlen(str)
-#define MB_METASTRLEN2END(str, widthp, eptr) ztrlenend(str, eptr)
-
-#define MB_CHARINIT()
-#define MB_CHARLENCONV(str, len, cp) charlenconv((str), (len), (cp))
-#define MB_CHARLEN(str, len) ((len) ? 1 : 0)
-
-#define WCWIDTH_WINT(c) (1)
-
-/* Leave character or string as is. */
-#define ZWC(c) c
-#define ZWS(s) s
-
-#endif /* MULTIBYTE_SUPPORT */
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.mdd b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.mdd
deleted file mode 100644
index d95f5d51..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.mdd
+++ /dev/null
@@ -1,147 +0,0 @@
-name=zsh/main
-link=static
-load=yes
-# load=static should replace use of alwayslink
-functions='Functions/Chpwd/* Functions/Exceptions/* Functions/Math/* Functions/Misc/* Functions/MIME/* Functions/Prompts/* Functions/VCS_Info/* Functions/VCS_Info/Backends/*'
-
-nozshdep=1
-alwayslink=1
-
-# autofeatures not specified because of alwayslink
-
-objects="signames.o builtin.o module.o lex.o exec.o mem.o \
-string.o parse.o hashtable.o init.o input.o loop.o utils.o params.o options.o \
-signals.o pattern.o prompt.o compat.o jobs.o glob.o"
-
-headers="../config.h zsh_system.h zsh.h sigcount.h signals.h \
-prototypes.h hashtable.h ztype.h"
-hdrdeps="zshcurses.h zshterm.h"
-
-:<<\Make
-@CONFIG_MK@
-
-# If we're using gcc as the preprocessor, get rid of the additional
-# lines generated by the preprocessor as they can confuse the script.
-# We don't need these in other cases either, but can't necessarily rely
-# on the option to remove them being the same.
-signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
- $(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
- case "`$(CPP) --version &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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.rc b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.rc
deleted file mode 100644
index 93c82ba1..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh.rc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Use this file as follows
-//
-// myapp.exe : myapp.o myapp.res
-// gcc -mwindows myapp.o myapp.res -o $@
-//
-// myapp.res : myapp.rc resource.h
-// windres $< -O coff -o $@
-IDR_MAINFRAME ICON DISCARDABLE "zsh.ico"
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh_system.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh_system.h
deleted file mode 100644
index 8289ee97..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/zsh_system.h
+++ /dev/null
@@ -1,900 +0,0 @@
-/*
- * system.h - system configuration header file
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#if 0
-/*
- * Setting _XPG_IV here is actually wrong and is not needed
- * with currently supported versions (5.43C20 and above)
- */
-#ifdef sinix
-# define _XPG_IV 1
-#endif
-#endif
-
-#if defined(__linux) || defined(__GNU__) || defined(__GLIBC__) || defined(LIBC_MUSL) || defined(__CYGWIN__)
-/*
- * Turn on numerous extensions.
- * This is in order to get the functions for manipulating /dev/ptmx.
- */
-#define _GNU_SOURCE 1
-#endif
-#ifdef LIBC_MUSL
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-/* NeXT has half-implemented POSIX support *
- * which currently fools configure */
-#ifdef __NeXT__
-# undef HAVE_TERMIOS_H
-# undef HAVE_SYS_UTSNAME_H
-#endif
-
-#ifndef ZSH_NO_XOPEN
-# ifdef ZSH_CURSES_SOURCE
-# define _XOPEN_SOURCE_EXTENDED 1
-# else
-# ifdef MULTIBYTE_SUPPORT
-/*
- * Needed for wcwidth() which is part of XSI.
- * Various other uses of the interface mean we can't get away with just
- * _XOPEN_SOURCE.
- */
-# define _XOPEN_SOURCE_EXTENDED 1
-# endif /* MULTIBYTE_SUPPORT */
-# endif /* ZSH_CURSES_SOURCE */
-#endif /* ZSH_NO_XOPEN */
-
-/*
- * Solaris by default zeroes all elements of the tm structure in
- * strptime(). Unfortunately that gives us no way of telling whether
- * the tm_isdst element has been set from the input pattern. If it
- * hasn't we want it to be -1 (undetermined) on input to mktime(). So
- * we stop strptime() zeroing the struct tm and instead set all the
- * elements ourselves.
- *
- * This is likely to be harmless everywhere else.
- */
-#define _STRPTIME_DONTZERO
-
-#ifdef PROTOTYPES
-# define _(Args) Args
-#else
-# define _(Args) ()
-#endif
-
-#ifndef HAVE_ALLOCA
-# define alloca zhalloc
-#else
-# ifdef __GNUC__
-# define alloca __builtin_alloca
-# else
-# if HAVE_ALLOCA_H
-# include
-# 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
-# endif
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include
-#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
-#endif
-
-#include
-#include
-#include
-#include
-#include
-
-#ifdef HAVE_PWD_H
-# include
-#endif
-
-#ifdef HAVE_GRP_H
-# include
-#endif
-
-#ifdef HAVE_DIRENT_H
-# include
-#else /* !HAVE_DIRENT_H */
-# ifdef HAVE_SYS_NDIR_H
-# include
-# endif
-# ifdef HAVE_SYS_DIR_H
-# include
-# endif
-# ifdef HAVE_NDIR_H
-# include
-# 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
-#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
-# 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
-# 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
-#endif
-
-#ifdef TIME_WITH_SYS_TIME
-# include
-# include
-#else
-# ifdef HAVE_SYS_TIME_H
-# include
-# else
-# include
-# 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
-#endif
-
-#ifdef HAVE_SYS_TIMES_H
-# include
-#endif
-
-#if STDC_HEADERS || HAVE_STRING_H
-# include
-/* An ANSI string.h and pre-ANSI memory.h might conflict. */
-# if !STDC_HEADERS && HAVE_MEMORY_H
-# include
-# endif /* not STDC_HEADERS and HAVE_MEMORY_H */
-#else /* not STDC_HEADERS and not HAVE_STRING_H */
-# include
-/* memory.h and strings.h conflict on some systems. */
-#endif /* not STDC_HEADERS and not HAVE_STRING_H */
-
-#ifdef HAVE_LOCALE_H
-# include
-#endif
-
-#ifdef HAVE_LIMITS_H
-# include
-#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
-#else
-# include
-#endif
-
-/* The following will only be defined if is POSIX. *
- * So we don't have to worry about union wait. But some machines *
- * (NeXT) include from other include files, so we *
- * need to undef and then redefine the wait macros if *
- * is not POSIX. */
-
-#ifdef HAVE_SYS_WAIT_H
-# include
-#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
-# endif
-#elif defined(SELECT_IN_SYS_SOCKET_H)
-# include
-#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
-#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
-# else
-# include
-# 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
-# define VDISABLEVAL -1
-# define HAS_TIO 1
-# else /* not TERMIOS and TERMIO */
-# include
-# endif /* HAVE_TERMIO_H */
-#endif /* HAVE_TERMIOS_H */
-
-#if defined(GWINSZ_IN_SYS_IOCTL) || defined(IOCTL_IN_SYS_IOCTL)
-# include
-#endif
-#ifdef WINSIZE_IN_PTEM
-# include
-# include
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include
-#endif
-
-#ifdef HAVE_SYS_UTSNAME_H
-# include
-#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
-# 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 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
-#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
-# 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
-# include
-#endif
-#ifdef HAVE_LANGINFO_H
-# include
-# ifdef HAVE_ICONV
-# include
-# 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
-# endif
-# ifdef ZSH_HAVE_CURSES_H
-# include "zshcurses.h"
-# endif
-# include "zshterm.h"
-# else
-# ifdef USES_TERMCAP_H
-# include
-# endif
-# endif
-#endif
-
-#ifdef HAVE_SRAND_DETERMINISTIC
-# define srand srand_deterministic
-#endif
-
-#ifdef ZSH_VALGRIND
-# include "valgrind/valgrind.h"
-# include "valgrind/memcheck.h"
-#endif
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/ztype.h b/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/ztype.h
deleted file mode 100644
index ae723677..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Src/ztype.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * ztype.h - character classification macros
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#define IDIGIT (1 << 0)
-#define IALNUM (1 << 1)
-#define IBLANK (1 << 2)
-#define INBLANK (1 << 3)
-#define ITOK (1 << 4)
-#define ISEP (1 << 5)
-#define IALPHA (1 << 6)
-#define IIDENT (1 << 7)
-#define IUSER (1 << 8)
-#define ICNTRL (1 << 9)
-#define IWORD (1 << 10)
-#define ISPECIAL (1 << 11)
-#define IMETA (1 << 12)
-#define IWSEP (1 << 13)
-#define INULL (1 << 14)
-#define IPATTERN (1 << 15)
-#define zistype(X,Y) (typtab[STOUC(X)] & Y)
-#define idigit(X) zistype(X,IDIGIT)
-#define ialnum(X) zistype(X,IALNUM)
-#define iblank(X) zistype(X,IBLANK) /* blank, not including \n */
-#define inblank(X) zistype(X,INBLANK) /* blank or \n */
-#define itok(X) zistype(X,ITOK)
-#define isep(X) zistype(X,ISEP)
-#define ialpha(X) zistype(X,IALPHA)
-#define iident(X) zistype(X,IIDENT)
-#define iuser(X) zistype(X,IUSER) /* username char */
-#define icntrl(X) zistype(X,ICNTRL)
-#define iword(X) zistype(X,IWORD)
-#define ispecial(X) zistype(X,ISPECIAL)
-#define imeta(X) zistype(X,IMETA)
-#define iwsep(X) zistype(X,IWSEP)
-#define inull(X) zistype(X,INULL)
-#define ipattern(X) zistype(X,IPATTERN)
-
-/*
- * Bit flags for typtab_flags --- preserved after
- * shell initialisation.
- */
-#define ZTF_INIT (0x0001) /* One-off initialisation done */
-#define ZTF_INTERACT (0x0002) /* Shell interative and reading from stdin */
-#define ZTF_SP_COMMA (0x0004) /* Treat comma as a special characters */
-#define ZTF_BANGCHAR (0x0008) /* Treat bangchar as a special character */
-
-#ifdef MULTIBYTE_SUPPORT
-#define WC_ZISTYPE(X,Y) wcsitype((X),(Y))
-# ifdef ENABLE_UNICODE9
-# define WC_ISPRINT(X) u9_iswprint(X)
-# else
-# define WC_ISPRINT(X) iswprint(X)
-# endif
-#else
-#define WC_ZISTYPE(X,Y) zistype((X),(Y))
-#define WC_ISPRINT(X) isprint(X)
-#endif
-
-#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
-#define ZISPRINT(c) isprint_ascii(c)
-#else
-#define ZISPRINT(c) isprint(c)
-#endif
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.cvsignore b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.cvsignore
deleted file mode 100644
index 855d7290..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-Makefile
-*.tmp
-*.swp
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.distfiles b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.distfiles
deleted file mode 100644
index f03668b3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/.distfiles
+++ /dev/null
@@ -1,2 +0,0 @@
-DISTFILES_SRC='
-'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A01grammar.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A01grammar.ztst
deleted file mode 100644
index e4b6870d..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A01grammar.ztst
+++ /dev/null
@@ -1,790 +0,0 @@
-#
-# This file contains tests corresponding to the `Shell Grammar' texinfo node.
-#
-
-%prep
-
- mkdir basic.tmp && cd basic.tmp
-
- touch foo bar
- echo "'" >unmatched_quote.txt
-
-%test
-#
-# Tests for `Simple Commands and Pipelines'
-#
-
- # Test skipping early to ensure we run the remainder...
- if [[ -n $ZTST_test_skip ]]; then
- ZTST_skip="Test system verification for skipping"
- else
- print "This is standard output"
- print "This is standard error" >&2
- false
- fi
-1:Test skipping if ZTST_test_skip is set
->This is standard output
-?This is standard error
-
- echo foo | cat | sed 's/foo/bar/'
-0:Basic pipeline handling
->bar
-
- false | true
-0:Exit status of pipeline with builtins (true)
-
- true | false
-1:Exit status of pipeline with builtins (false)
-
- false
- $nonexistent_variable
-0:Executing command that evaluates to empty resets status
-
- false
- sleep 1 &
- print $?
- # a tidy test is a happy test
- wait $!
-0:Starting background command resets status
->0
-
- false
- . /dev/null
-0:Sourcing empty file resets status
-
- fn() { local foo; read foo; print $foo; }
- coproc fn
- print -p coproc test output
- read -p bar
- print $bar
-0:Basic coprocess handling
->coproc test output
-
- true | false && print true || print false
-0:Basic sublist (i)
->false
-
- false | true && print true || print false
-0:Basic sublist (ii)
->true
-
- (cd /NonExistentDirectory >&/dev/null) || print false
-0:Basic subshell list with error
->false
-
- { cd /NonExistentDirectory >&/dev/null } || print false
-0:Basic current shell list with error
->false
-
-#
-# Tests for `Precommand Modifiers'
-#
- - $ZTST_testdir/../Src/zsh -fc "[[ \$0 = \"-$ZTST_testdir/../Src/zsh\" ]]"
-0:`-' precommand modifier
-
- echo f*
- noglob echo f*
-0:`noglob' precommand modifier
->foo
->f*
-
- (exec /bin/sh; echo bar)
-0:`exec' precommand modifier
-
- (exec -l $ZTST_testdir/../Src/zsh -fc 'echo $0' | sed 's%/.*/%%' )
-0:`exec' with -l option
->-zsh
-
- (exec -a /bin/SPLATTER /bin/sh -c 'echo $0')
-0:`exec' with -a option
->/bin/SPLATTER
-
- (exec -a/bin/SPLOOSH /bin/sh -c 'echo $0')
-0:`exec' with -a option, no space
->/bin/SPLOOSH
-
- (export FOO=bar; exec -c /bin/sh -c 'echo x${FOO}x')
-0:`exec' with -c option
->xx
-
- cat() { echo Function cat executed; }
- command cat && unfunction cat
-0:`command' precommand modifier
-External command cat executed
-
- 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 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
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A02alias.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A02alias.ztst
deleted file mode 100644
index e68e93e0..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A02alias.ztst
+++ /dev/null
@@ -1,139 +0,0 @@
-# To get the "command not found" message when aliasing is suppressed
-# we need, er, a command that isn't found.
-# The other aliases are only ever used as aliases.
-
-%prep
- alias ThisCommandDefinitelyDoesNotExist=echo
-
- alias -g bar=echo
-
- alias '\bar=echo'
-
-%test
- ThisCommandDefinitelyDoesNotExist ThisCommandDefinitelyDoesNotExist
-0:Basic aliasing
->ThisCommandDefinitelyDoesNotExist
-
- bar bar
-0:Global aliasing
->echo
-
- \ThisCommandDefinitelyDoesNotExist ThisCommandDefinitelyDoesNotExist
-127:Not aliasing
-?(eval):1: command not found: ThisCommandDefinitelyDoesNotExist
-
- \bar \bar
-0:Aliasing with a backslash
->bar
-
- (alias '!=echo This command has the argument'
- eval 'print Without
- ! true'
- setopt posixaliases
- eval 'print With
- ! true')
-1:POSIX_ALIASES option
->Without
->This command has the argument true
->With
-
- print -u $ZTST_fd 'This test hangs the shell when it fails...'
- alias cat='LC_ALL=C cat'
- cat <(echo foo | cat)
-0:Alias expansion works at the end of parsed strings
->foo
-
- alias -g '&&=(){ return $?; } && '
- alias not_the_print_command=print
- eval 'print This is output
- && print And so is this
- && { print And this too; false; }
- && print But not this
- && print Nor this
- true
- && not_the_print_command And aliases are expanded'
-0:We can now alias special tokens. Woo hoo.
->This is output
->And so is this
->And this too
->And aliases are expanded
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- unsetopt PROMPT_SP
- PROMPT="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
- exec 2>&1
- alias \{=echo
- { begin
- {end
- fc -l -2' 2>/dev/null
-0:Aliasing reserved tokens
->begin
->end
-*>*5*{ begin
-*>*6*{end
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- unsetopt PROMPT_SP
- PROMPT="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
- exec 2>&1
- alias -g S=\"
- echo S a string S "
- fc -l -1' 2>/dev/null
-0:Global aliasing quotes
-> a string S
-*>*5*echo S a string S "
-# "
-# Note there is a trailing space on the "> a string S " line
-
- (
- unalias -a
- alias
- )
-0:unalias -a
-
- alias -s foo=print
- type bar.foo; type -w bar.foo
- unalias -as
-0:unalias -as
->foo is a suffix alias for print
->foo: suffix alias
-
- aliases[x=y]=z
- alias -L | grep x=y
- echo $pipestatus[1]
-0:printing invalid aliases warns
->0
-?(eval):2: invalid alias 'x=y' encountered while printing aliases
-# Currently, 'alias -L' returns 0 in this case. Perhaps it should return 1.
-
- alias -s mysuff='print -r "You said it.";'
- eval 'thingummy.mysuff'
-127:No endless loop with suffix alias in command position
->You said it.
-?(eval):1: command not found: thingummy.mysuff
-
- alias +x; alias -z
-1:error message has the correct sign
-?(eval):alias:1: bad option: +x
-?(eval):alias:1: bad option: -z
-
- # Usual issue that aliases aren't expanded until we
- # trigger a new parse...
- (alias badalias=notacommand
- eval 'badalias() { print does not work; }')
-1:ALIAS_FUNC_DEF off by default.
-?(eval):1: defining function based on alias `badalias'
-?(eval):1: parse error near `()'
-
- (alias goodalias=isafunc
- setopt ALIAS_FUNC_DEF
- eval 'goodalias() { print does now work; }'
- isafunc)
-0:ALIAS_FUNC_DEF causes the icky behaviour to be avaliable
->does now work
-
- (alias thisisokthough='thisworks() { print That worked; }'
- eval thisisokthough
- thisworks)
-0:NO_ALIAS_FUNC_DEF works if the alias is a complete definition
->That worked
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A03quoting.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A03quoting.ztst
deleted file mode 100644
index da3ce359..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A03quoting.ztst
+++ /dev/null
@@ -1,80 +0,0 @@
-%test
- print 'single quotes' "double quotes" `echo backquotes`
-0:Simple use of quotes
->single quotes double quotes backquotes
-
- foo=text
- print -r '$foo\\\' "$foo\$foo\\\"\``echo bar`\`\"" `print -r $foo\\\``
-0:Quoting inside quotes
->$foo\\\ text$foo\"`bar`" text`
-
- print -r $'\'ut queant laxis\'\n"resonare fibris"'
-0:$'-style quotes
->'ut queant laxis'
->"resonare fibris"
-
- print -r $'\'a \\\' is \'a backslash\' is \'a \\\''
-0:$'-style quotes with backslashed backslashes
->'a \' is 'a backslash' is 'a \'
-
- chars=$(print -r $'BS\\MBS\M-\\')
- for (( i = 1; i <= $#chars; i++ )); do
- char=$chars[$i]
- print $(( [#16] #char ))
- done
-0:$'-style quote with metafied backslash
->16#42
->16#53
->16#5C
->16#4D
->16#42
->16#53
->16#DC
-
- print -r ''''
- setopt rcquotes
-# We need to set rcquotes here for the next example since it is
-# needed while parsing.
-0:No RC_QUOTES with single quotes
->
-
- print -r ''''
- unsetopt rcquotes
-0:Yes RC_QUOTES with single quotes
->'
-# ' Deconfuse Emacs quoting rules
-
- print '<\u0041>'
- printf '%s\n' $'<\u0042>'
- print '<\u0043>'
- printf '%s\n' $'<\u0044>'
-0:\u in both print and printf
->
->
->
->
-
- null1="$(print -r a$'b\0c'd)"
- null2="$(setopt posixstrings; print -r a$'b\0c'd)"
- for string in $null1 $null2; do
- print ":"
- for (( i = 1; i <= $#string; i++ )); do
- char=$string[$i]
- print $(( [#16] #char ))
- done
- done
-0:Embedded null characters in $'...' strings.
->:
->16#61
->16#62
->16#0
->16#63
->16#64
->:
->16#61
->16#62
->16#64
-
- () { print $# } '' "" $''
-0:$'' should not be elided, in common with other empty quotes
->3
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A04redirect.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A04redirect.ztst
deleted file mode 100644
index d7fe22fb..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A04redirect.ztst
+++ /dev/null
@@ -1,588 +0,0 @@
-# Tests corresponding to the `Redirection' texinfo node.
-
-%prep
- mkdir redir.tmp && cd redir.tmp
-
- myfd=99
- (echo >&$myfd) 2>msg
- bad_fd_msg="${$(redir && cat redir
-0:'>' and '<' redirection
->This is file redir
-
- rm -f redir
- print 'This is still file redir' <>redir >&0 && cat <>redir
-0:'<>' redirection
->This is still file redir
-
- rm -f redir
- print 'With a bar' >|redir && cat redir
-0:'>|' redirection
->With a bar
-
- rm -f redir
- print 'With a bang' >!redir && cat redir
-0:'>!' redirection
->With a bang
-
- rm -f redir
- print 'Line 1' >>redir && print 'Line 2' >>redir && cat redir
-0:'>>' redirection
->Line 1
->Line 2
-
- rm -f redir
- print 'Line a' >>|redir && print 'Line b' >>!redir
-0:'>>|' and '>>!' redirection
-
- foo=bar
- cat <<' HERE'
- $foo
- HERE
- eval "$(print 'cat < $foo
->bar
-
- cat <<-HERE
-# note tabs at the start of the following lines
- $foo$foo
- HERE
-0:Here-documents stripping tabs
->barbar
-
- cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" #
-# tabs again. sorry about the max miller.
- Here's a funny thing. Here is a funny thing.
- I went home last night. There's a funny thing.
- Man walks into a $foo. Ouch, it's an iron $foo.
- $HERE `$(THERE) `$((AND)) \EVERYWHERE
-0:Here-documents don't perform shell expansion on the initial word
->Here's a funny thing. Here is a funny thing.
->I went home last night. There's a funny thing.
->Man walks into a $foo. Ouch, it's an iron $foo.
-
- cat <<-$'\x45\x4e\x44\t\x44\x4f\x43'
-# tabs again
- This message is unfathomable.
- END DOC
-0:Here-documents do perform $'...' expansion on the initial word
->This message is unfathomable.
-
- cat <<<"This is a line with a $foo in it"
-0:'<<<' redirection
->This is a line with a bar in it
-
- cat <<<$'a\nb\nc'
-0:here-strings with $'...' quoting
->a
->b
->c
-
-# The following tests check that output of parsed here-documents works.
-# This isn't completely trivial because we convert the here-documents
-# internally to here-strings. So we check again that we can output
-# the reevaluated here-strings correctly. Hence there are three slightly
-# different stages. We don't care how the output actually looks, so
-# we don't test that.
- heretest() {
- print First line
- cat <<-HERE
- $foo$foo met celeste 'but with extra' "stuff to test quoting"
- HERE
- print Last line
- }
- heretest
- eval "$(functions heretest)"
- heretest
- eval "$(functions heretest)"
- heretest
-0:Re-evaluation of function output with here document, unquoted
->First line
->barbar met celeste 'but with extra' "stuff to test quoting"
->Last line
->First line
->barbar met celeste 'but with extra' "stuff to test quoting"
->Last line
->First line
->barbar met celeste 'but with extra' "stuff to test quoting"
->Last line
-
- heretest() {
- print First line
- cat <<' HERE'
- $foo$foo met celeste 'but with extra' "stuff to test quoting"
- HERE
- print Last line
- }
- heretest
- eval "$(functions heretest)"
- heretest
- eval "$(functions heretest)"
- heretest
-0:Re-evaluation of function output with here document, quoted
->First line
-> $foo$foo met celeste 'but with extra' "stuff to test quoting"
->Last line
->First line
-> $foo$foo met celeste 'but with extra' "stuff to test quoting"
->Last line
->First line
-> $foo$foo met celeste 'but with extra' "stuff to test quoting"
->Last line
-
- read -r line <<' HERE'
- HERE
-1:No input, not even newline, from empty here document.
-
- #
- # exec tests: perform these in subshells so if they fail the
- # shell won't exit.
- #
- (exec 3>redir && print hello >&3 && print goodbye >&3 && cat redir)
-0:'>&' redirection
->hello
->goodbye
-
- (exec 3hello
->goodbye
-
- ({exec 3<&- } 2>/dev/null
- exec 3<&-
- read foo <&-)
-1:'<&-' redirection with numeric fd (no error message on failure)
-
- (exec {varid}<&0
- exec {varid}<&-
- print About to close a second time >&2
- read {varid}<&-)
-1:'<&-' redirection with fd in variable (error message on failure)
-?About to close a second time
-*?\(eval\):*: failed to close file descriptor *
-
- print foo >&-
-0:'>&-' redirection
-
- (exec >&-
- print foo)
-0:'>&-' with attempt to use closed fd
-*?\(eval\):2: write error:*
-
- fn() { local foo; read foo; print $foo; }
- coproc fn
- print test output >&p
- read bar <&p
- print $bar
-0:'>&p' and '<&p' redirection
->test output
-
- ( print Output; print Error >& 2 ) >&errout && cat errout
-0:'>&FILE' handling
->Output
->Error
-
- rm -f errout
- ( print Output2; print Error2 >& 2 ) &>errout && cat errout
-0:'&>FILE' handling
->Output2
->Error2
-
- rm -f errout
- ( print Output3; print Error3 >& 2 ) >&|errout && cat errout
- ( print Output4; print Error4 >& 2 ) >&!errout && cat errout
- ( print Output5; print Error5 >& 2 ) &>|errout && cat errout
- ( print Output6; print Error6 >& 2 ) &>!errout &&
- ( print Output7; print Error7 >& 2 ) >>&errout &&
- ( print Output8; print Error8 >& 2 ) &>>errout &&
- ( print Output9; print Error9 >& 2 ) >>&|errout &&
- ( print Output10; print Error10 >& 2 ) &>>|errout &&
- ( print Output11; print Error11 >& 2 ) >>&!errout &&
- ( print Output12; print Error12 >& 2 ) &>>!errout && cat errout
-0:'>&|', '>&!', '&>|', '&>!' redirection
->Output3
->Error3
->Output4
->Error4
->Output5
->Error5
->Output6
->Error6
->Output7
->Error7
->Output8
->Error8
->Output9
->Error9
->Output10
->Error10
->Output11
->Error11
->Output12
->Error12
-
- rm -f errout
- ( print Output; print Error 1>&2 ) 1>errout 2>&1 && cat errout
-0:'Combining > with >& (1)'
->Output
->Error
-
- rm -f errout
- ( print Output; print Error 1>&2 ) 2>&1 1>errout && print errout: &&
- cat errout
-0:'Combining > with >& (2)'
->Error
->errout:
->Output
-
- rm -f errout
- print doo be doo be doo >foo >bar
- print "foo: $(foo: doo be doo be doo
->bar: doo be doo be doo
-
- rm -f foo bar
- print dont be dont be dont >foo | sed 's/dont/wont/g' >bar
-0:setup file+pipe multio
-
- print "foo: $(foo: dont be dont be dont
->bar: wont be wont be wont
-
- rm -f *
- touch out1 out2
- print All files >*
- print *
- print "out1: $(out1 out2
->out1: All files
->out2: All files
-
- print This is out1 >out1
- print This is out2 >out2
-0:setup multio for input
-
-# Currently, This is out1
->This is out2
-
- cat out1 | sed s/out/bout/ This is bout1
->This is bout2
-
- unset NULLCMD
- >out1
-1:null redir with NULLCMD unset
-?(eval):2: redirection with no command
-
- echo this should still work >out1
- print "$(this should still work
-
- READNULLCMD=cat
- print cat input >out1
- out1
- [[ ! -s out1 ]] || print out1 is not empty
-0:null redir with NULLCMD=:
-out1
- cat input
-
- NULLCMD=cat
- >out1
- cat out1
-0:null redir with NULLCMD=cat
-input
-
- (myfd=
- exec {myfd}>logfile
- if [[ -z $myfd ]]; then
- print "Ooops, failed to set myfd to a file descriptor." >&2
- else
- print This is my logfile. >&$myfd
- print Examining contents of logfile...
- cat logfile
- fi)
-0:Using {fdvar}> syntax to open a new file descriptor
->Examining contents of logfile...
->This is my logfile.
-
- (setopt noclobber
- exec {myfd}>logfile2
- echo $myfd
- exec {myfd}>logfile3) | read myfd
- (( ! ${pipestatus[1]} ))
-1q:NO_CLOBBER prevents overwriting parameter with allocated fd
-?(eval):4: can't clobber parameter myfd containing file descriptor $myfd
-
- (setopt noclobber
- exec {myfd}>logfile2b
- print First open >&$myfd
- rm -f logfile2b # prevent normal file no_clobberation
- myotherfd="${myfd}+0"
- exec {myotherfd}>logfile2b
- print Overwritten >&$myotherfd)
- cat logfile2b
-0:NO_CLOBBER doesn't complain about any other expression
->Overwritten
-
- (exec {myfd}>logfile4
- echo $myfd
- exec {myfd}>&-
- print This message should disappear >&$myfd) | read myfd
- (( ! ${pipestatus[1]} ))
-1q:Closing file descriptor using brace syntax
-?(eval):4: $myfd:$bad_fd_msg
-
- typeset -r myfd
- echo This should not appear {myfd}>nologfile
-1:Error opening file descriptor using readonly variable
-?(eval):2: can't allocate file descriptor to readonly parameter myfd
-
- (typeset +r myfd
- exec {myfd}>newlogfile
- typeset -r myfd
- exec {myfd}>&-)
-1:Error closing file descriptor using readonly variable
-?(eval):4: can't close file descriptor from readonly parameter myfd
-
-# This tests the here-string to filename optimisation; we can't
-# test that it's actually being optimised, but we can test that it
-# still works.
- cat =(<<<$'This string has been replaced\nby a file containing it.\n')
-0:Optimised here-string to filename
->This string has been replaced
->by a file containing it.
-
- print This f$'\x69'le contains d$'\x61'ta. >redirfile
- print redirection:
- catoutfile
- print output:
- cat outfile
- print append:
- cat>>outfileredirection:
->output:
->This file contains data.
->append:
->more output:
->This file contains data.
->This file contains data.
-
- $ZTST_testdir/../Src/zsh -fc 'exec >/nonexistent/nonexistent
- echo output'
-0:failed exec redir, no POSIX_BUILTINS
->output
-?zsh:1: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
- exec >/nonexistent/nonexistent
- echo output'
-1:failed exec redir, POSIX_BUILTINS
-?zsh:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
- set >/nonexistent/nonexistent
- echo output'
-1:failed special builtin redir, POSIX_BUILTINS
-?zsh:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
- command set >/nonexistent/nonexistent
- echo output'
-0:failed special builtin redir with command prefix, POSIX_BUILTINS
->output
-?zsh:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
- echo >/nonexistent/nonexistent
- echo output'
-0:failed unspecial builtin redir, POSIX_BUILTINS
->output
-?zsh:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
- . /nonexistent/nonexistent
- echo output'
-1:failed dot, POSIX_BUILTINS
-?zsh:.:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -c '
- . /nonexistent/nonexistent
- echo output'
-0:failed dot, NO_POSIX_BUILTINS
->output
-?zsh:.:2: no such file or directory: /nonexistent/nonexistent
-
- $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
- readonly foo
- foo=bar set output
- echo output'
-0:failed assignment on posix special, CONTINUE_ON_ERROR
->output
-?zsh: read-only variable: foo
-
- $ZTST_testdir/../Src/zsh -f <<<'
- readonly foo
- foo=bar set output
- echo output'
-1:failed assignment on posix special, NO_CONTINUE_ON_ERROR
-?zsh: read-only variable: foo
-
- $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
- readonly foo
- foo=bar echo output
- echo output'
-0:failed assignment on non-posix-special, CONTINUE_ON_ERROR
->output
-?zsh: read-only variable: foo
-
- [input1
- () {
- local var
- read var
- print I just read $var
- } output1
- print Nothing output yet
- cat output1
-0:anonymous function redirections are applied immediately
->Nothing output yet
->I just read any old rubbish
-
- redirfn() {
- local var
- read var
- print I want to tell you about $var
- print Also, this might be an error >&2
- } output2 2>&1
- print something I heard on the radio >input2
- redirfn
- print No output until after this
- cat output2
-0:redirections with normal function definition
->No output until after this
->I want to tell you about something I heard on the radio
->Also, this might be an error
-
- which redirfn
-0:text output of function with redirections
->redirfn () {
-> local var
-> read var
-> print I want to tell you about $var
-> print Also, this might be an error >&2
->} < input2 > output2 2>&1
-
- 1func 2func 3func() { print Ich heisse $0 } >output3
- for i in 1 2 3; do
- f=${i}func
- print Running $f
- $f
- cat output3
- unfunction $f
- done
-0:multiply named functions with redirection
->Running 1func
->Ich heisse 1func
->Running 2func
->Ich heisse 2func
->Running 3func
->Ich heisse 3func
-
- redirfn2() { print The latest output; } >&3
- redirfn2 3>output4
- print No output yet
- cat output4
-0:Redirections in both function definition and command line
->No output yet
->The latest output
-
-# This relies on the fact that the test harness always loads
-# the zsh/parameter module.
- print $functions[redirfn]
-0:Output from $functions[] for definition with redirection
->{
-> local var
-> read var
-> print I want to tell you about $var
-> print Also, this might be an error >&2
->} < input2 > output2 2>&1
-
- noredirfn() { print This rather boring function has no redirection.; }
- print $functions[noredirfn]
-0:Output from $functions[] for definition with no redirection
-> print This rather boring function has no redirection.
-
- (x=43
- x=$(print This should appear, really >&2; print Not used) exec >test.log
- print x=$x)
- cat test.log
-0:Assignment with exec used for redirection: no POSIX_BUILTINS
->x=43
-?This should appear, really
-
- (setopt POSIX_BUILTINS
- x=45
- x=$(print This should appear, too >&2; print And this) exec >test.log
- print x=$x)
- cat test.log
-0:Assignment with exec used for redirection: POSIX_BUILTINS
->x=And this
-?This should appear, too
-
- fn-two-heres() {
-# tabs below
- cat <<-x <<-y
- foo
- x
- bar
- y
- }
- which -x2 fn-two-heres
- fn-two-heres
- eval "$(which -x2 fn-two-heres)"
- fn-two-heres
- print $functions[fn-two-heres]
-0:Two here-documents in a line are shown correctly.
->fn-two-heres () {
-> cat <foo
->x
->bar
->y
->}
->foo
->bar
->foo
->bar
-> cat <foo
->x
->bar
->y
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A05execution.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A05execution.ztst
deleted file mode 100644
index 0804691a..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A05execution.ztst
+++ /dev/null
@@ -1,312 +0,0 @@
-%prep
-
- storepath=($path)
-
- mkdir command.tmp command.tmp/dir1 command.tmp/dir2
-
- cd command.tmp
-
- print '#!/bin/sh\necho This is top' >tstcmd
-
- print '#!/bin/sh\necho This is dir1' >dir1/tstcmd
-
- print '#!/bin/sh\necho This is dir2' >dir2/tstcmd
-
- chmod 755 tstcmd dir1/tstcmd dir2/tstcmd
-
-%test
- ./tstcmd
-0:./prog execution
->This is top
-
- path=($ZTST_testdir/command.tmp/dir1
- $ZTST_testdir/command.tmp/dir2
- .)
- tstcmd
- path=($storepath)
-0:path (1)
->This is dir1
-
- path=(. command.tmp/dir{1,2})
- tstcmd
- path=($storepath)
-0:path (2)
->This is top
-
- functst() { print $# arguments:; print -l $*; }
- functst "Eines Morgens" "als Gregor Samsa"
- functst ""
- functst "aus unrhigen Trumen erwachte"
- foo="fand er sich in seinem Bett"
- bar=
- rod="zu einem ungeheuren Ungeziefer verwandelt."
- functst $foo $bar $rod
-# set up alias for next test
- alias foo='print This is alias one'
-0:function argument passing
->2 arguments:
->Eines Morgens
->als Gregor Samsa
->1 arguments:
->
->1 arguments:
->aus unrhigen Trumen erwachte
->2 arguments:
->fand er sich in seinem Bett
->zu einem ungeheuren Ungeziefer verwandelt.
-
- alias foo='print This is alias two'
- fn() { foo; }
- fn
-0:Aliases in functions
->This is alias one
-
- foo='Global foo'
- traptst() { local foo="Local foo"; trap 'print $foo' EXIT; }
- traptst
-0:EXIT trap environment
->Global foo
-
- functst() { return 0; print Ha ha; return 1; }
- functst
-0:return (1)
-
- functst() { return 1; print Ho ho; return 0; }
- functst
-1:return (2)
-
- unfunction functst
- fpath=(.)
- print "print This is functst." >functst
- autoload functst
- functst
-0:autoloading (1)
->This is functst.
-
- unfunction functst
- print "functst() { print This, too, is functst; }; print Hello." >functst
- typeset -fu functst
- functst
- functst
-0:autoloading with initialization
->Hello.
->This, too, is functst
-
- unfunction functst
- print "print Yet another version" >functst
- functst() { autoload -X; }
- functst
-0:autoloading via -X
->Yet another version
-
- chpwd() { print Changed to $PWD; }
- cd .
- unfunction chpwd
-0q:chpwd
->Changed to $ZTST_testdir/command.tmp
-
- chpwd() { print chpwd: changed to $PWD; }
- chpwdfn1() { print chpwdfn1: changed to $PWD; }
- chpwdfn2() { print chpwdfn2: changed to $PWD; }
- chpwd_functions=(chpwdfn1 '' chpwdnonexistentfn chpwdfn2)
- cd .
- unfunction chpwd
- unset chpwd_functions
-0q:chpwd_functions
->chpwd: changed to $ZTST_testdir/command.tmp
->chpwdfn1: changed to $ZTST_testdir/command.tmp
->chpwdfn2: changed to $ZTST_testdir/command.tmp
-
-# Hard to test periodic, precmd and preexec non-interactively.
-
- fn() { TRAPEXIT() { print Exit; }; }
- fn
-0:TRAPEXIT
->Exit
-
- unsetopt DEBUG_BEFORE_CMD
- unfunction fn
- print 'TRAPDEBUG() {
- print Line $LINENO
- }
- :
- unfunction TRAPDEBUG
- ' > fn
- autoload fn
- fn
- rm fn
-0:TRAPDEBUG
->Line 1
->Line 1
-
- unsetopt DEBUG_BEFORE_CMD
- unfunction fn
- print 'trap '\''print Line $LINENO'\'' DEBUG
- :
- trap - DEBUG
- ' > fn
- autoload fn
- fn
- rm fn
-0:trap DEBUG
->Line 1
->Line 2
-
- TRAPZERR() { print Command failed; }
- true
- false
- true
- false
- unfunction TRAPZERR
-0:TRAPZERR
->Command failed
->Command failed
-
- trap 'print Command failed again.' ZERR
- true
- false
- true
- false
- trap - ZERR
-0:trap ZERR
->Command failed again.
->Command failed again.
-
- false
- sleep 1000 &
- print $?
- kill $!
-0:Status reset by starting a backgrounded command
->0
-
- { setopt MONITOR } 2>/dev/null
- [[ -o MONITOR ]] || print -u $ZTST_fd 'Unable to change MONITOR option'
- repeat 2048; do (return 2 |
- return 1 |
- while true; do
- false
- break
- done;
- print "${pipestatus[@]}")
- ZTST_hashmark
- done | sort | uniq -c | sed 's/^ *//'
-0:Check whether '$pipestatus[]' behaves.
->2048 2 1 0
-F:This test checks for a bug in '$pipestatus[]' handling. If it breaks then
-F:the bug is still there or it reappeared. See workers-29973 for details.
-
- { setopt MONITOR } 2>/dev/null
- externFunc() { awk >/dev/null 2>&1; true; }
- false | true | false | true | externFunc
- echo $pipestatus
-0:Check $pipestatus with a known difficult case
->1 0 1 0 0
-F:This similar test was triggering a reproducible failure with pipestatus.
-
- { unsetopt MONITOR } 2>/dev/null
- coproc { read -et 5 || { print -u $ZTST_fd KILLED; kill -HUP -$$ } }
- print -u $ZTST_fd 'This test takes 5 seconds to fail...'
- { printf "%d\n" {1..20000} } 2>/dev/null | ( read -e )
- hang(){ printf "%d\n" {2..20000} | cat }; hang 2>/dev/null | ( read -e )
- print -p done
- read -et 6 -p
-0:Bug regression: piping a shell construct to an external process may hang
->1
->2
->done
-F:This test checks for a file descriptor leak that could cause the left
-F:side of a pipe to block on write after the right side has exited
-
- { setopt MONITOR } 2>/dev/null
- if [[ -o MONITOR ]]
- then
- ( while :; do print "This is a line"; done ) | () : &
- sleep 1
- jobs -l
- else
- print -u $ZTST_fd "Skipping pipe leak test, requires MONITOR option"
- print "[0] 0 0"
- fi
-0:Bug regression: piping to anonymous function; piping to backround function
-*>\[<->\] <-> <->
-F:This test checks for two different bugs, a parser segfault piping to an
-F:anonymous function, and a descriptor leak when backgrounding a pipeline
-
- print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir
- autoload -Uk autoload_redir
- autoload_redir
- print No output yet
- cat autoload.log
- functions autoload_redir
-0:
->No output yet
->Autoloaded ksh style
->autoload_redir () {
-> print Autoloaded ksh style
->} > autoload.log
-
-# This tests that we record the status of processes that have already exited
-# for when we wait for them.
-#
-# Actually, we don't guarantee here that the jobs have already exited, but
-# the order of the waits means it's highly likely we do need to recall a
-# previous status, barring accidents which shouldn't happen very often. In
-# other words, we rely on the test working repeatedly rather than just
-# once. The monitor option is irrelevant to the logic, so we'll make
-# our job easier by turning it off.
- { unsetopt MONITOR } 2>/dev/null
- (exit 1) &
- one=$!
- (exit 2) &
- two=$!
- (exit 3) &
- three=$!
- wait $three
- print $?
- wait $two
- print $?
- wait $one
- print $?
-0:The status of recently exited background jobs is recorded
->3
->2
->1
-
-# Regression test for workers/34060 (patch in 34065)
- setopt ERR_EXIT NULL_GLOB
- if false; then :; else echo if:$?; fi
- if false; then :; else for x in _*_; do :; done; echo for:$?; fi
-0:False "if" condition handled correctly by "for" loops with ERR_EXIT
->if:1
->for:0
-
-# Regression test for workers/34065 (uses setopt from preceding test)
- select x; do :; done; echo $?
- select x in; do :; done; echo $?
- select x in _*_; do :; done; echo $?
- unsetopt ERR_EXIT NULL_GLOB
-0:The status of "select" is zero when the loop body does not execute
->0
->0
->0
-
-# Regression test for workers/36392
- print -u $ZTST_fd 'This test takes 3 seconds and hangs the shell when it fails...'
- callfromchld() { true && { print CHLD } }
- TRAPCHLD() { callfromchld }
- sleep 2 & sleep 3; print OK
-0:Background job exit does not affect reaping foreground job
->CHLD
->OK
-
-# Regression test for workers/39839 and workers/39844
- () { if return 11; then :; fi }; echo $?
- () { while return 13; do :; done }; echo $?
- () { until return 17; do :; done }; echo $?
- () { until false; do return 19; done }; echo $?
-0:"return" in "if" or "while" conditional
->11
->13
->17
->19
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A06assign.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A06assign.ztst
deleted file mode 100644
index bf39aee7..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A06assign.ztst
+++ /dev/null
@@ -1,631 +0,0 @@
-# Tests of parameter assignments
-
-%prep
- mkdir assign.tmp && cd assign.tmp
-
- touch tmpfile1 tmpfile2
-
-%test
-
- typeset -A assoc
- assoc=(one 1 two 2 odd)
-1:assign to association with odd no. of values
-?(eval):2: bad set of key/value pairs for associative array
-
-# tests of array element assignment
-
- array=(1 2 3 4 5)
- array[1]=42
- print $array
-0:Replacement of array element
->42 2 3 4 5
-
- array=(1 2 3 4 5)
- array[1]=(42 43)
- print $array
-0:Replacement of array element with array
->42 43 2 3 4 5
-
- array=(1 2 3 4 5)
- array[1,2]=(42 43)
- print $array
-0:Replacement of start of array
->42 43 3 4 5
-
- array=(1 2 3 4 5)
- array[1,4]=(42 43)
- print $array
-0:Replacement of start of array with shorter slice
->42 43 5
-
- array=(1 2 3 4 5)
- array[1,6]=(42 43)
- print $array
-0:Replacement of array by extending slice
->42 43
-
- array=(1 2 3 4 5)
- array[3]=(42 43)
- print $array
-0:Replacement of middle element with array
->1 2 42 43 4 5
-
- array=(1 2 3 4 5)
- array[3,4]=(42 43 44)
- print $array
-0:Replacement of slice in middle
->1 2 42 43 44 5
-
- array=(1 2 3 4 5)
- array[7,8]=(42 43)
- print $array
- # check that [6] was left empty...
- array[6]=41
- print $array
-0:Appending by replacing elements off the end
->1 2 3 4 5 42 43
->1 2 3 4 5 41 42 43
-
- array=(1 2 3 4 5)
- array[-1]=42
- print $array
-0:Replacement of last element of array, negative indices
->1 2 3 4 42
-
- array=(1 2 3 4 5)
- array[-1]=(42 43)
- print $array
-0:Replacement of last element of array with array, negative indices
->1 2 3 4 42 43
-
- array=(1 2 3 4 5)
- array[-3,-2]=(42 43 44)
- print $array
-0:Replacement of middle of array, negative indices
->1 2 42 43 44 5
-
- array=(1 2 3 4 5)
- array[-5,-1]=(42 43)
- print $array
-0:Replacement of entire array, negative indices
->42 43
-
- array=(1 2 3 4 5)
- array[-7,-1]=(42 43)
- print $array
-0:Replacement of more than entire array, negative indices
->42 43
-
- array=(1 2 3 4 5)
- array[-7]=42
- print $array
-0:Replacement of element off start of array.
->42 1 2 3 4 5
-
- array=(1 2 3 4 5)
- array[-7]=42
- array[-6]=43
- print $array
-0:Replacement off start doesn't leave gaps. Hope this is right.
->43 1 2 3 4 5
-
- array=(1 2 3 4 5)
- array[1,-1]=(42 43)
- print $array
- array[-3,3]=(1 2 3 4 5)
- print $array
-0:Replacement of entire array, mixed indices
->42 43
->1 2 3 4 5
-
- array=(1 2 3 4 5)
- array[-7,7]=(42 43)
- print $array
-0:Replacement of more than entire array, mixed indices
->42 43
-
- array=(1 2 3 4 5)
- array[3,-2]=(42 43 44)
- print $array
- array[-3,5]=(100 99)
- print $array
-0:Replacement of slice in middle, mixed indices
->1 2 42 43 44 5
->1 2 42 100 99 5
-
-# tests of var+=scalar
-
- s+=foo
- echo $s
-0:append scalar to unset scalar
->foo
-
- s=foo
- s+=bar
- echo $s
-0:append to scalar
->foobar
-
- set -- a b c
- 2+=end
- echo $2
-0:append to positional parameter
->bend
-
- a=(first second)
- a+=last
- print -l $a
-0:add scalar to array
->first
->second
->last
-
- setopt ksharrays
- a=(first second)
- a+=last
- print -l $a
- unsetopt ksharrays
-0:add scalar to array with ksharrays set
->firstlast
-
- a=(1 2)
- a[@]+=3
- print -l $a
-0:add scalar to array with alternate syntax
->1
->2
->3
-
- integer i=10
- i+=20
- (( i == 30 ))
-0:add to integer
-
- float f=3.4
- f+=2.3
- printf "%g\n" f
-0:add to float
->5.7
-
- typeset -A hash
- hash=(one 1)
- hash+=string
- [[ $hash[@] == string ]]
-0:add scalar to association
-
-# tests of var+=(array)
-
- unset a
- a+=(1 2 3)
- print -l $a
-0:add array to unset parameter
->1
->2
->3
-
- a=(a)
- a+=(b)
- print -l $a
-0:add array to existing array
->a
->b
-
- s=foo
- s+=(bar)
- print -l $s
-0:add array to scalar
->foo
->bar
-
- integer i=1
- i+=(2 3)
- print -l $i
-0:add array to integer
->1
->2
->3
-
- float f=2.5
- f+=(3.5 4.5)
- printf '%g\n' $f
-0:add array to float
->2.5
->3.5
->4.5
-
- typeset -A h
- h+=(a 1 b 2)
- print -l $h
-0:add to empty association
->1
->2
-
- typeset -A h
- h=(a 1)
- h+=(b 2 c 3)
- print -l $h
-0:add to association
->1
->2
->3
-
- typeset -A h
- h=(a 1 b 2)
- h+=()
- print -l $h
-0:add empty array to association
->1
->2
-
-# tests of var[range]+=scalar
-
- s=sting
- s[2]+=art
- echo $s
-0:insert scalar inside another
->starting
-
- s=inert
- s[-4]+=s
- echo $s
-0:insert scalar inside another with negative index
->insert
-
- s=append
- s[2,6]+=age
- echo $s
-0:append scalar to scalar using a range
->appendage
-
- s=123456789
- s[3,-5]+=X
- echo $s
-0:insert scalar inside another, specifying a slice
->12345X6789
-
- a=(a b c)
- a[2]+=oo
- echo $a
-0:append to array element
->a boo c
-
- a=(a b c d)
- a[-2]+=ool
- echo $a
-0:append to array element with negative index
->a b cool d
-
- a=(a b c d)
- a[2,-1]+=oom
- echo $a
-0:append to array element, specifying a slice
->a b c doom
-
- setopt ksharrays
- a=(a b c d)
- a[0]+=0
- echo $a
- unsetopt ksharrays
-0:append to array element with ksharrays set
->a0
-
- typeset -A h
- h=(one foo)
- h[one]+=bar
- echo $h
-0:append to association element
->foobar
-
- typeset -A h
- h[foo]+=bar
- echo ${(kv)h}
-0:append to non-existent association element
->foo bar
-
- typeset -A h
- h=(one a two b three c four d)
- h[(I)*o*]+=append
-1:attempt to append to slice of association
-?(eval):3: h: attempt to set slice of associative array
-
- integer i=123
- i[2]+=6
-1:attempt to add to indexed integer variable
-?(eval):2: attempt to add to slice of a numeric variable
-
- float f=1234.5
- f[2,4]+=3
-1:attempt to add to slice of float variable
-?(eval):2: attempt to add to slice of a numeric variable
-
- unset u
- u[3]+=third
- echo $u[1]:$u[3]
-0:append to unset variable with index
->:third
-
-# tests of var[range]+=(array)
-
- a=(1 2 3)
- a[2]+=(a b)
- echo $a
-0:insert array inside another
->1 2 a b 3
-
- a=(a b c)
- a[-1]+=(d)
- echo $a
-0:append to array using negative index
->a b c d
-
- a=(1 2 3 4)
- a[-1,-3]+=(x)
- echo $a
-0:insert array using negative range
->1 2 x 3 4
-
- s=string
- s[2]+=(a b)
-1:attempt to insert array into string
-?(eval):2: s: attempt to assign array value to non-array
-
- integer i=365
- i[2]+=(1 2)
-1:attempt to insert array into string
-?(eval):2: i: attempt to assign array value to non-array
-
- typeset -A h
- h=(a 1)
- h[a]+=(b 2)
-1:attempt to append array to hash element
-?(eval):3: h: attempt to set slice of associative array
-
- unset u
- u[-34,-2]+=(a z)
- echo $u
-0:add array to indexed unset variable
->a z
-
- repeat 10 PATH=. echo hello
-0:saving and restoring of exported special parameters
->hello
->hello
->hello
->hello
->hello
->hello
->hello
->hello
->hello
->hello
-
- repeat 10 FOO=BAR BAR=FOO echo $FOO $BAR
-0:save and restore multiple variables around builtin
->
->
->
->
->
->
->
->
->
->
-
- call() { print $HELLO; }
- export HELLO=world
- call
- HELLO=universe call
- call
- HELLO=${HELLO}liness call
- call
- unset HELLO
-0:save and restore when using original value in temporary
->world
->universe
->world
->worldliness
->world
-
- (integer i n x
- float f
- setopt globassign
- i=tmpfile1
- n=tmpf*
- x=*2
- f=2+2
- typeset -p i n x f)
-0:GLOB_ASSIGN with numeric types
->typeset -i i=0
->typeset -a n=( tmpfile1 tmpfile2 )
->typeset x=tmpfile2
->typeset -E f=4.000000000e+00
-
- setopt globassign
- foo=tmpf*
- print $foo
- unsetopt globassign
- foo=tmpf*
- print $foo
-0:GLOB_ASSIGN option
->tmpfile1 tmpfile2
->tmpf*
-
- (setopt globassign
- typeset -A foo
- touch gatest1 gatest2
- foo=(gatest*)
- print ${(t)foo}
- rm -rf gatest*)
-0:GLOB_ASSIGN doesn't monkey with type if not scalar assignment.
->association-local
-
- A=(first second)
- A="${A[*]}" /bin/sh -c 'echo $A'
- print -l "${A[@]}"
-0:command execution with assignments shadowing array parameter
->first second
->first
->second
-
- setopt ksharrays
- A=(first second)
- A="${A[*]}" /bin/sh -c 'echo $A'
- print -l "${A[@]}"
- unsetopt ksharrays
-0:command execution with assignments shadowing array parameter with ksharrays
->first second
->first
->second
-
- typeset -aU unique_array=(first second)
- unique_array[1]=second
- print $unique_array
-0:assignment to unique array
->second
-
- typeset -a array=(first)
- array[1,3]=(FIRST)
- print $array
-0:slice beyond length of array
->FIRST
-
-# tests of string assignments
-
- a="abc"
- a[1]=x
- print $a
-0:overwrite first character in string
->xbc
-
- a="abc"
- a[2]="x"
- print $a
-0:overwrite middle character in string
->axc
-
- a="abc"
- a[3]="x"
- print $a
-0:overwrite last character in string
->abx
-
- a="abc"
- a[-1]="x"
- print $a
-0:overwrite -1 character in string
->abx
-
- a="abc"
- a[-2]="x"
- print $a
-0:overwrite -2 character (middle) in string
->axc
-
- a="ab"
- a[-2]="x"
- print $a
-0:overwrite -2 character (first) in string
->xb
-
- a="abc"
- a[-3]="x"
- print $a
-0:overwrite -3 character (first) in string
->xbc
-
- a="abc"
- a[-4]="x"
- print $a
-0:overwrite -4 character (before first) in string
->xabc
-
- a="abc"
- a[-5]="x"
- print $a
-0:overwrite -5 character (before-before first) in string
->xabc
-
- a="abc"
- a[-4,0]="x"
- print $a
-0:overwrite [-4,0] characters (before first) in string
->xabc
-
- a="abc"
- a[-4,-4]="x"
- print $a
-0:overwrite [-4,-4] character (before first) in string
->xabc
-
- a="abc"
- a[-40,-30]="x"
- print $a
-0:overwrite [-40,-30] characters (far before first) in string
->xabc
-
- a="abc"
- a[-40,1]="x"
- print $a
-0:overwrite [-40,1] characters in short string
->xbc
-
- a="abc"
- a[-40,40]="x"
- print $a
-0:overwrite [-40,40] characters in short string
->x
-
- a="abc"
- a[2,40]="x"
- print $a
-0:overwrite [2,40] characters in short string
->ax
-
- a="abc"
- a[2,-1]="x"
- print $a
-0:overwrite [2,-1] characters in short string
->ax
-
- a="abc"
- a[-2,-1]="x"
- print $a
-0:overwrite [-2,-1] characters in short string
->ax
-
- a="a"
- a[-1]="xx"
- print $a
-0:overwrite [-1] character with "xx"
->xx
-
- a="a"
- a[-2]="xx"
- print $a
-0:overwrite [-2] character (before first) with "xx"
->xxa
-
- a="a"
- a[2]="xx"
- print $a
-0:overwrite [2] character (after last) with "xx"
->axx
-
- a=""
- a[1]="xx"
- print $a
-0:overwrite [1] character (string: "") with "xx"
->xx
-
- a=""
- a[-1]="xx"
- print $a
-0:overwrite [-1] character (string: "") with "xx"
->xx
-
- a=""
- a[2]="xx"
- print $a
-0:overwrite [2] character (string: "") with "xx"
->xx
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A07control.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A07control.ztst
deleted file mode 100644
index b1a24873..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/A07control.ztst
+++ /dev/null
@@ -1,165 +0,0 @@
-# Test control commands for loops and functions.
-
-%test
-
- fn3() { return $1; print Error }
- fn2() { fn3 $1 }
- fn() {
- print start $1
- fn2 $1
- return
- print Error
- }
- for val in -1 0 1 255; do
- fn $val; print $?
- done
-0:Passing of return values back through functions
->start -1
->-1
->start 0
->0
->start 1
->1
->start 255
->255
-
- $ZTST_testdir/../Src/zsh -fc 'fn() {
- continue
- }
- fn'
-1:continue outside loop
-?fn:continue:1: not in while, until, select, or repeat loop
-
- for outer in 0 1 2 3; do
- print outer $outer
- for inner in 0 1 2 3; do
- print inner $inner
- continue $(( (outer & 1) ? 2 : 1 ))
- print error
- done
- print outer end
- done
-0:continue with valid argument
->outer 0
->inner 0
->inner 1
->inner 2
->inner 3
->outer end
->outer 1
->inner 0
->outer 2
->inner 0
->inner 1
->inner 2
->inner 3
->outer end
->outer 3
->inner 0
-
- for outer in 0 1; do
- continue 0
- print -- $outer got here, status $?
- done
-1:continue error case 0
-?(eval):continue:2: argument is not positive: 0
-
- for outer in 0 1; do
- continue -1
- print -- $outer got here, status $?
- done
-1:continue error case -1
-?(eval):continue:2: argument is not positive: -1
-
- fn() {
- break
- }
- for outer in 0 1; do
- print $outer
- fn
- done
-0:break from within function (this is a feature, I disovered)
->0
-
- for outer in 0 1 2 3; do
- print outer $outer
- for inner in 0 1 2 3; do
- print inner $inner
- break $(( (outer & 1) ? 2 : 1 ))
- print error
- done
- print outer end
- done
-0:break with valid argument
->outer 0
->inner 0
->outer end
->outer 1
->inner 0
-
- for outer in 0 1; do
- break 0
- print -- $outer got here, status $?
- done
-1:break error case 0
-?(eval):break:2: argument is not positive: 0
-
- for outer in 0 1; do
- break -1
- print -- $outer got here, status $?
- done
-1:break error case -1
-?(eval):break:2: argument is not positive: -1
-
- false
- for x in; do
- print nothing executed
- done
-0:Status 0 from for with explicit empty list
-
- set --
- false
- for x; do
- print nothing executed
- done
-0:Status 0 from for with implicit empty list
-
- (exit 2)
- for x in 1 2; do
- print $?
- done
-0:Status from previous command propagated into for loop
->2
->0
-
- false
- for x in $(echo 1 2; (exit 3)); do
- print $?
- done
-0:Status from expansion propagated into for loop
->3
->0
-
- false
- for x in $(exit 4); do
- print not executed
- done
-0:Status from expansion not propagated after unexecuted for loop
-
- false
- for x in NonExistentFilePrefix*(N); do
- print not executed, either
- done
-0:Status from before for loop not propagated if empty after expansion
-
- for x in $(echo 1; false); do
- done
-0:Status reset by empty list in for loop
-
- false
- for x in $(echo 1; false); do
- echo $?
- (exit 4)
- done
-4:Last status from loop body is kept even with other funny business going on
->1
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B01cd.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B01cd.ztst
deleted file mode 100644
index 94447e71..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B01cd.ztst
+++ /dev/null
@@ -1,144 +0,0 @@
-# This file serves as a model for how to write tests, so is more heavily
-# commented than the others. All tests are run in the Test subdirectory
-# of the distribution, which must be writable. They should end with
-# the suffix `.ztst': this is not required by the test harness itself,
-# but it is needed by the Makefile to run all the tests.
-
-# Blank lines with no other special meaning (e.g. separating chunks of
-# code) and all those with a `#' in the first column are ignored.
-
-# All section names start with a % in the first column. The names
-# must be in the expected order, though not all sections are required.
-# The sections are %prep (preparatory setup: code executed should return
-# status 0, but no other tests are performed), %test (the main tests), and
-# %clean (to cleanup: the code is simply unconditionally executed).
-#
-# Literal shell code to be evaluated must be indented with any number
-# of spaces and/or tabs, to differentiate it from tags with a special
-# meaning to the test harness. Note that this is true even in sections
-# where there are no such tags. Also note that file descriptor 9
-# is reserved for input from the test script, and file descriptor 8
-# preserves the original stdout. Option settings are preserved between the
-# execution of different code chunks; initially, all standard zsh options
-# (the effect of `emulate -R zsh') are set.
-
-%prep
-# This optional section prepares the test, creating directories and files
-# and so on. Chunks of code are separated by blank lines (which is not
-# necessary before the end of the section); each chunk of code is evaluated
-# in one go and must return status 0, or the preparation is deemed to have
-# failed and the test ends with an appropriate error message. Standard
-# output from this section is redirected to /dev/null, but standard error
-# is not redirected.
-#
-# Tests should use subdirectories ending in `.tmp'. These will be
-# removed with all the contents even if the test is aborted.
- mkdir cdtst.tmp cdtst.tmp/real cdtst.tmp/sub
-
- ln -s ../real cdtst.tmp/sub/fake
-
- setopt chaselinks
- cd .
- unsetopt chaselinks
- mydir=$PWD
-
-%test
-# This is where the tests are run. It consists of blocks separated
-# by blank lines. Each block has the same format and there may be any
-# number of them. It consists of indented code, plus optional sets of lines
-# beginning '<', '>' and '?' which may appear in any order. These correspond
-# to stdin (fed to the code), stdout (compared with code output) and
-# stderr (compared with code error output) respectively. These subblocks
-# may occur in any order, but the natural one is: code, stdin, stdout,
-# stderr.
-#
-# The rules for '<', '>' and '?' lines are the same: only the first
-# character is stripped (with the excpetion for '*' noted below), with
-# subsequent whitespace being significant; lines are not subject to any
-# substitution unless the `q' flag (see below) is set.
-#
-# Each line of a '>' and '?' chunk may be preceded by a '*', so the line
-# starts '*>' or '*?'. This signifies that for any line with '*' in front
-# the actual output should be pattern matched against the corresponding
-# lines in the test output. Each line following '>' or '?' must be a
-# valid pattern, so characters special to patterns such as parentheses
-# must be quoted with a backslash. The EXTENDED_GLOB option is used for
-# all such patterns.
-#
-# Each chunk of indented code is to be evaluated in one go and is to
-# be followed by a line starting (in the first column) with
-# the expected status returned by the code when run, or - if it is
-# irrelevant. An optional set of single-letter flags follows the status
-# or -. The following are understood:
-# . d Don't diff stdout against the expected stdout.
-# D Don't diff stderr against the expected stderr.
-# q All redirection lines given in the test script (not the lines
-# actually produced by the test) are subject to ordinary quoted shell
-# expansion (i.e. not globbing).
-# This can be followed by a `:' and a message describing the
-# test, which will be printed if the test fails, along with a
-# description of the failure that occurred. The `:' and message are
-# optional, but highly recommended.
-# Hence a complete status line looks something like:
-# 0dDq:Checking whether the world will end with a bang or a whimper
-#
-# If either or both of the '>' and '?' sets of lines is absent, it is
-# assumed the corresponding output should be empty and it is an error if it
-# is not. If '<' is empty, stdin is an empty (but opened) file.
-#
-# It is also possible to add lines in the redirection section beginning
-# with `F:'. The remaining text on all such lines will be concatenated
-# (with newlines in between) and displayed in the event of an error.
-# This text is useful for explaining certain frequent errors, for example
-# ones which may arise from the environment rather than from the shell
-# itself. (The example below isn't particularly useful as errors with
-# `cd' are unusual.)
-#
-# A couple of features aren't used in this file, but are usefuil in cases
-# where features may not be available so should not be tested. They boh
-# take the form of variables. Note that to keep the test framework simple
-# there is no magic in setting the variables: the chunk of code being
-# executed needs to avoid executing any test code by appropriate structure
-# (typically "if"). In both cases, the value of the variable is output
-# as a warning that the test was skipped.
-# ZTST_unimplemented: Set this in the %prep phase if the entire test file
-# is to be skipped.
-# ZTST_skip: Set this in any test case if that single test case is to be
-# skipped. Testing resumes at the next test case in the same file.
- cd cdtst.tmp/sub/fake &&
- pwd &&
- print $PWD
-0q:Preserving symbolic links in the current directory string
->$mydir/cdtst.tmp/sub/fake
->$mydir/cdtst.tmp/sub/fake
-F:This test shouldn't really fail. The fact that it has indicates
-F:something is broken. But you already knew that.
-
- cd ../../.. &&
- pwd &&
- print $PWD
-0q:Changing directory up through symbolic links without following them
->$mydir
->$mydir
-
- setopt chaselinks
- cd cdtst.tmp/sub/fake &&
- pwd &&
- print $PWD
-0q:Resolving symbolic links with chaselinks set
->$mydir/cdtst.tmp/real
->$mydir/cdtst.tmp/real
-
- ln -s nonexistent link_to_nonexistent
- pwd1=$(pwd -P)
- cd -s link_to_nonexistent
- pwd2=$(pwd -P)
- [[ $pwd1 = $pwd2 ]] || print "Ooops, changed to directory '$pwd2'"
-0:
-?(eval):cd:3: not a directory: link_to_nonexistent
-
-%clean
-# This optional section cleans up after the test, if necessary,
-# e.g. killing processes etc. This is in addition to the removal of *.tmp
-# subdirectories. This is essentially like %prep, except that status
-# return values are ignored.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B02typeset.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B02typeset.ztst
deleted file mode 100644
index b27bb4f6..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B02typeset.ztst
+++ /dev/null
@@ -1,723 +0,0 @@
-# There are certain usages of typeset and its synonyms that it is not
-# possible to test here, because they must appear at the top level and
-# everything that follows is processed by an "eval" within a function.
-
-# Equivalences:
-# declare typeset
-# export typeset -xg
-# float typeset -E
-# functions typeset -f
-# integer typeset -i
-# local typeset +g -m approximately
-# readonly typeset -r
-
-# Tested elsewhere:
-# Equivalence of autoload and typeset -fu A05execution
-# Associative array creation & assignment D04parameter, D06subscript
-# Effects of GLOBAL_EXPORT E01options
-# Function tracing (typeset -ft) E02xtrace
-
-# Not yet tested:
-# Assorted illegal flag combinations
-
-%prep
- ## Do not remove the next line, it's used by V10private.ztst
- # test_zsh_param_private
-
- mkdir typeset.tmp && cd typeset.tmp
-
- setopt noglob
-
- scalar=scalar
- array=(a r r a y)
-
- scope00() {
- typeset scalar
- scalar=local
- typeset -a array
- array=(l o c a l)
- print $scalar $array
- }
- scope01() {
- local scalar
- scalar=local
- local -a array
- array=(l o c a l)
- print $scalar $array
- }
- scope02() {
- declare scalar
- scalar=local
- declare -a array
- array=(l o c a l)
- print $scalar $array
- }
- scope10() {
- export outer=outer
- /bin/sh -fc 'echo $outer'
- }
- scope11() {
- typeset -x outer=outer
- /bin/sh -fc 'echo $outer'
- }
- scope12() {
- local -x outer=inner
- /bin/sh -fc 'echo $outer'
- }
- scope13() {
- local -xT OUTER outer
- outer=(i n n e r)
- /bin/sh -fc 'echo $OUTER'
- }
-
- # Bug? `typeset -h' complains that ! # $ * - ? @ are not identifiers.
- stress00() {
- typeset -h +g -m [[:alpha:]_]*
- unset -m [[:alpha:]_]*
- typeset +m [[:alpha:]_]*
- }
-
-%test
-
- typeset +m scalar array
-0:Report types of parameters with typeset +m
->scalar
->array array
-
- scope00
- print $scalar $array
-0:Simple local declarations
->local l o c a l
->scalar a r r a y
-
- scope01
- print $scalar $array
-0:Equivalence of local and typeset in functions
->local l o c a l
->scalar a r r a y
-
- scope02
- print $scalar $array
-0:Basic equivalence of declare and typeset
->local l o c a l
->scalar a r r a y
-
- declare +m scalar
-0:declare previously lacked -m/+m options
->scalar
-
- scope10
- print $outer
-0:Global export
->outer
->outer
-
- scope11
- print $outer
-0:Equivalence of export and typeset -x
->outer
->outer
-
- scope12
- print $outer
-0:Local export
->inner
->outer
-
- float f=3.14159
- typeset +m f
- float -E3 f
- print $f
- float -F f
- print $f
-0:Floating point, adding a precision, and fixed point
->float local f
->3.14e+00
->3.142
-
- integer i=3.141
- typeset +m i
- integer -i2 i
- print $i
-0:Integer and changing the base
->integer local i
->2#11
-
- float -E3 f=3.141
- typeset +m f
- integer -i2 f
- typeset +m f
- print $f
-0:Conversion of floating point to integer
->float local f
->integer 2 local f
->2#11
-
- typeset -f
-0q:Equivalence of functions and typeset -f
->$(functions)
-
- readonly r=success
- print $r
- r=failure
-1:Readonly declaration
->success
-?(eval):3: read-only variable: r
-
- typeset r=success
- readonly r
- print $r
- r=failure
-1:Convert to readonly
->success
-?(eval):4: read-only variable: r
-
- typeset -gU array
- print $array
-0:Uniquified arrays and non-local scope
->a r y
-
- typeset -T SCALAR=l:o:c:a:l array
- print $array
- typeset -U SCALAR
- print $SCALAR $array
-0:Tied parameters and uniquified colon-arrays
->l o c a l
->l:o:c:a l o c a
-
- (setopt NO_multibyte cbases
- LC_ALL=C 2>/dev/null
- typeset -T SCALAR=$'l\x83o\x83c\x83a\x83l' array $'\x83'
- print $array
- typeset -U SCALAR
- for (( i = 1; i <= ${#SCALAR}; i++ )); do
- char=$SCALAR[i]
- print $(( [#16] #char ))
- done
- print $array)
-0:Tied parameters and uniquified arrays with meta-character as separator
->l o c a l
->0x6C
->0x83
->0x6F
->0x83
->0x63
->0x83
->0x61
->l o c a
-
- typeset -T SCALAR=$'l\000o\000c\000a\000l' array $'\000'
- typeset -U SCALAR
- print $array
- [[ $SCALAR == $'l\000o\000c\000a' ]]
-0:Tied parameters and uniquified arrays with NUL-character as separator
->l o c a
-
- typeset -T SCALAR array
- typeset +T SCALAR
-1:Untying is prohibited
-?(eval):typeset:2: use unset to remove tied variables
-
- OUTER=outer
- scope13
- print $OUTER
-0:Export of tied parameters
->i:n:n:e:r
->outer
-
- typeset -TU MORESTUFF=here-we-go-go-again morestuff '-'
- print -l $morestuff
-0:Tied arrays with separator specified
->here
->we
->go
->again
-
- typeset -T THIS will not work
-1:Tied array syntax
-?(eval):typeset:1: too many arguments for -T
-
- local array[2]=x
-1:Illegal local array element assignment
-?(eval):local:1: array[2]: can't create local array elements
-
- local -a array
- typeset array[1]=a array[2]=b array[3]=c
- print $array
-0:Legal local array element assignment
->a b c
-
- local -A assoc
- local b=1 ;: to stomp assoc[1] if assoc[b] is broken
- typeset assoc[1]=a assoc[b]=2 assoc[3]=c
- print $assoc[1] $assoc[b] $assoc[3]
-0:Legal local associative array element assignment
->a 2 c
-
- local scalar scalar[1]=a scalar[2]=b scalar[3]=c
- print $scalar
-0:Local scalar subscript assignment
->abc
-
- typeset -L 10 fools
- for fools in " once" "twice" " thrice" " oops too long here"; do
- print "'$fools'"
- done
-0:Left justification of scalars
->'once '
->'twice '
->'thrice '
->'oops too l'
-
- typeset -L 10 -F 3 foolf
- for foolf in 1.3 4.6 -2.987 -4.91031; do
- print "'$foolf'"
- done
-0:Left justification of floating point
->'1.300 '
->'4.600 '
->'-2.987 '
->'-4.910 '
-
- typeset -L 10 -Z foolzs
- for foolzs in 001.3 04.6 -2.987 -04.91231; do
- print "'$foolzs'"
- done
-0:Left justification of scalars with zero suppression
->'1.3 '
->'4.6 '
->'-2.987 '
->'-04.91231 '
-
- typeset -R 10 foors
- for foors in short longer even-longer; do
- print "'$foors'"
- done
-0:Right justification of scalars
->' short'
->' longer'
->'ven-longer'
-
- typeset -Z 10 foozs
- for foozs in 42 -42 " 43" " -43"; do
- print "'$foozs'"
- done
-0:Right justification of scalars with zeroes
->'0000000042'
->' -42'
->' 000000043'
->' -43'
-
- integer -Z 10 foozi
- for foozi in 42 -42 " 43" " -43"; do
- print "'$foozi'"
- done
-0:Right justification of integers with zero, no initial base
->'0000000042'
->'-000000042'
->'0000000043'
->'-000000043'
-# In case you hadn't twigged, the spaces are absorbed in the initial
-# math evaluation, so don't get through.
-
- unsetopt cbases
- integer -Z 10 -i 16 foozi16
- for foozi16 in 42 -42 " 43" " -43"; do
- print "'$foozi16'"
- done
-0:Right justification of integers with zero, base 16, C_BASES off
->'16#000002A'
->'-16#00002A'
->'16#000002B'
->'-16#00002B'
-
- setopt cbases
- integer -Z 10 -i 16 foozi16c
- for foozi16c in 42 -42 " 43" " -43"; do
- print "'$foozi16c'"
- done
-0:Right justification of integers with zero, base 16, C_BASES on
->'0x0000002A'
->'-0x000002A'
->'0x0000002B'
->'-0x000002B'
-
- setopt cbases
- integer -Z 10 -i 16 foozi16c
- for foozi16c in 0x1234 -0x1234; do
- for (( i = 1; i <= 5; i++ )); do
- print "'${foozi16c[i,11-i]}'"
- done
- print "'${foozi16c[-2]}'"
- done
-0:Extracting substrings from padded integers
->'0x00001234'
->'x0000123'
->'000012'
->'0001'
->'00'
->'3'
->'-0x0001234'
->'0x000123'
->'x00012'
->'0001'
->'00'
->'3'
-
- typeset -F 3 -Z 10 foozf
- for foozf in 3.14159 -3.14159 4 -4; do
- print "'$foozf'"
- done
-0:Right justification of fixed point numbers with zero
->'000003.142'
->'-00003.142'
->'000004.000'
->'-00004.000'
-
- stress00
- print $scalar $array
-0q:Stress test: all parameters are local and unset, using -m
->scalar a r y
-
- local parentenv=preserved
- fn() {
- typeset -h +g -m \*
- unset -m \*
- integer i=9
- float -H f=9
- declare -t scalar
- declare -H -a array
- typeset
- typeset +
- }
- fn
- echo $parentenv
-0:Parameter hiding and tagging, printing types and values
->array local array
->float local f
->integer local i=9
->local tagged scalar=''
->array local array
->float local f
->integer local i
->local tagged scalar
->preserved
-
- export ENVFOO=bar
- print ENVFOO in environment
- env | grep '^ENVFOO'
- print Changing ENVFOO
- ENVFOO="not bar any more"
- env | grep '^ENVFOO'
- unset ENVFOO
- print ENVFOO no longer in environment
- env | grep '^ENVFOO'
-1:Adding and removing values to and from the environment
->ENVFOO in environment
->ENVFOO=bar
->Changing ENVFOO
->ENVFOO=not bar any more
->ENVFOO no longer in environment
-
- (export FOOENV=BAR
- env | grep '^FOOENV'
- print Exec
- exec $ZTST_testdir/../Src/zsh -fc '
- print Unset
- unset FOOENV
- env | grep "^FOOENV"')
-1:Can unset environment variables after exec
->FOOENV=BAR
->Exec
->Unset
-
- local case1=upper
- typeset -u case1
- print $case1
- upper="VALUE OF \$UPPER"
- print ${(P)case1}
-0:Upper case conversion, does not apply to values used internally
->UPPER
->VALUE OF $UPPER
-
- local case2=LOWER
- typeset -l case2
- print $case2
- LOWER="value of \$lower"
- print ${(P)case2}
-0:Lower case conversion, does not apply to values used internally
->lower
->value of $lower
-
- typeset -a array
- array=(foo bar)
- fn() { typeset -p array nonexistent; }
- fn
-1:declare -p shouldn't create scoped values
->typeset -g -a array=( foo bar )
-?fn:typeset: no such variable: nonexistent
-
- unsetopt typesetsilent
- silent1(){ typeset -g silence; }
- silent2(){ local silence; silent1; }
- silent2
-0:typeset -g should be silent even without TYPESET_SILENT
-
- typeset -T TIED_SCALAR tied_array
- TIED_SCALAR=foo:bar
- print $tied_array
- typeset -T TIED_SCALAR=goo:car tied_array
- print $tied_array
- typeset -T TIED_SCALAR tied_array=(poo par)
- print $TIED_SCALAR
-0:retying arrays to same array works
->foo bar
->goo car
->poo:par
-
- (
- setopt POSIXBUILTINS
- readonly pbro
- print ${+pbro} >&2
- (typeset -g pbro=3)
- (pbro=4)
- readonly -p pbro >&2 # shows up as "readonly" although unset
- typeset -gr pbro # idempotent (no error)...
- print ${+pbro} >&2 # ...so still readonly...
- typeset -g +r pbro # ...can't turn it off
- )
-1:readonly with POSIX_BUILTINS
-?0
-?(eval):5: read-only variable: pbro
-?(eval):6: read-only variable: pbro
-?typeset -g -r pbro
-?0
-?(eval):10: read-only variable: pbro
-
- readonly foo=bar novalue
- readonly -p
-0:readonly -p output (no readonly specials)
->typeset -r foo=bar
->typeset -r novalue=''
-
- local -a a1 a2
- local -r r1=yes r2=no
- a1=(one two) a2=(three four)
- readonly a1
- typeset -pm 'a[12]'
- typeset -pm 'r[12]'
-0:readonly -p output
->typeset -ar a1=( one two )
->typeset -a a2=( three four )
->typeset -r r1=yes
->typeset -r r2=no
-
- one=hidden two=hidden three=hidden four=hidden five=hidden
- fn() {
- local bleugh="four=vier"
- typeset -R10 one=eins two=(zwei dio) three $bleugh five=(cinq cinque)
- three=drei
- print -l $one $two $three $four $five
- }
- fn
- print -l $one $two $three $four $five
-0:typeset reserved word interface: basic
-> eins
->zwei
->dio
-> drei
-> vier
->cinq
->cinque
->hidden
->hidden
->hidden
->hidden
->hidden
-
- (
- setopt glob
- mkdir -p arrayglob
- touch arrayglob/{one,two,three,four,five,six,seven}
- fn() {
- typeset array=(arrayglob/[tf]*)
- print -l ${array:t}
- #
- typeset {first,second,third}=the_same_value array=(
- extends
- over
- multiple
- lines
- )
- print -l $first $second $third "$array"
- #
- integer i=$(echo 1 + 2 + 3 + 4)
- print $i
- #
- # only noted by accident this was broken..
- # we need to turn off special recognition
- # of assignments within assignments...
- typeset careful=( i=1 j=2 k=3 )
- print -l $careful
- }
- fn
- )
-0:typeset reserved word, more complicated cases
->five
->four
->three
->two
->the_same_value
->the_same_value
->the_same_value
->extends over multiple lines
->10
->i=1
->j=2
->k=3
-
- (
- # reserved word is recognised at parsing.
- # yes, this is documented.
- # anyway, that means we need to
- # re-eval the function...
- fn='
- fn() {
- typeset foo=`echo one word=two`
- print $foo
- print $word
- }
- '
- print reserved
- eval $fn; fn
- print builtin
- disable -r typeset
- eval $fn; fn
- enable -r typeset
- disable typeset
- print reserved
- eval $fn; fn
- )
-0:reserved word and builtin interfaces
->reserved
->one word=two
->
->builtin
->one
->two
->reserved
->one word=two
->
-
- fn() {
- emulate -L zsh
- setopt typeset_silent
- local k
- typeset -A hash=(k1 v1 k2 v2)
- typeset foo=word array=(more than one word)
- for k in ${(ko)hash}; do
- print $k $hash[$k]
- done
- print -l $foo $array
- typeset -A hash
- typeset foo array
- for k in ${(ko)hash}; do
- print $k $hash[$k]
- done
- print -l $foo $array
- typeset hash=(k3 v3 k4 v4) array=(odd number here)
- for k in ${(ko)hash}; do
- print $k $hash[$k]
- done
- print -l $array
- }
- fn
-0:typeset preserves existing variable types
->k1 v1
->k2 v2
->word
->more
->than
->one
->word
->k1 v1
->k2 v2
->word
->more
->than
->one
->word
->k3 v3
->k4 v4
->odd
->number
->here
-
- fn() { typeset foo bar thing=this stuff=(that other) more=woevva; }
- which -x2 fn
- fn2() { typeset assignfirst=(why not); }
- which -x2 fn2
-0:text output from typeset
->fn () {
-> typeset foo bar thing=this stuff=(that other) more=woevva
->}
->fn2 () {
-> typeset assignfirst=(why not)
->}
-
- fn() {
- typeset array=()
- print ${(t)array} ${#array}
- typeset gnothergarray=() gnothergarray[1]=yes gnothergarray[2]=no
- print -l ${(t)gnothergarray} $gnothergarray
- }
- fn
-0:can set empty array
->array-local 0
->array-local
->yes
->no
-
- array=(nothing to see here)
- fn() {
- typeset array=(one two three four five)
- typeset array[2,4]=(umm er)
- print ${#array} $array
- typeset array[2,3]=()
- print ${#array} $array
- }
- fn
- print ${#array} $array
-0:can update array slices in typeset
->4 one umm er five
->2 one five
->4 nothing to see here
-
- array=(no really nothing here)
- fn() {
- typeset array=() array[2]=two array[4]=four
- typeset -p array
- typeset array=() array[3]=three array[1]=one
- typeset -p array
- }
- fn
- print $array
-0:setting empty array in typeset
->typeset -a array=( '' two '' four )
->typeset -a array=( one '' three )
->no really nothing here
-
- readonly isreadonly=yes
- typeset isreadonly=still
-1:typeset returns status 1 if setting readonly variable
-?(eval):2: read-only variable: isreadonly
-
- if (( UID )); then
- UID=$((UID+1)) date; echo "Status is printed, $?"
- else
- ZTST_skip="cannot test setuid error when tests run as superuser"
- fi
-0:when cannot change UID, the command isn't run
-# 'date' did not run.
->Status is printed, 1
-*?*: failed to change user ID: *
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B03print.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B03print.ztst
deleted file mode 100644
index c65568ad..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B03print.ztst
+++ /dev/null
@@ -1,336 +0,0 @@
-# Tests for the echo, print, printf and pushln builtins
-
-# Tested elsewhere:
-# Use of print -p to output to coprocess A01grammar
-# Prompt expansion with print -P D01prompt
-# -l, -r, -R and -n indirectly tested in various places
-
-# Not yet tested:
-# echo and pushln
-# print's -b -c -s -z -N options
-
-
-%test
-
- print -D "${HOME:-~}"
-0:replace directory name
->~
-
- print -u2 'error message'
-0:output to file-descriptor
-?error message
-
- print -o foo bar Baz
-0:argument sorting
->Baz bar foo
-
- print -f
-1:print -f needs a format specified
-?(eval):print:1: argument expected: -f
-
- print -Of '%s\n' foo bar baz
-0:reverse argument sorting
->foo
->baz
->bar
-
-# some locales force case-insensitive sorting
- (LC_ALL=C; print -o a B c)
-0:case-sensitive argument sorting
->B a c
-
- (LC_ALL=C; print -io a B c)
-0:case-insensitive argument sorting
->a B c
-
- print -m '[0-9]' one 2 three 4 five 6
-0:removal of non-matching arguments
->2 4 6
-
- printf '%s\n' string
-0:test s format specifier
->string
-
- printf '%b' '\t\\\n'
-0:test b format specifier
-> \
-
- printf '%q\n' '=a=b \ c!'
-0: test q format specifier
->\=a=b\ \\\ c!
-
- printf '%c\n' char
-0:test c format specifier
->c
-
- printf '%.10e%n\n' 1 count >/dev/null
- printf '%d\n' $count
-0:test n format specifier
->16
-
- printf '%5b%n\n' abc count >/dev/null; echo $count
-0:check count of width-specified %b
->5
-
- printf '%s!%5b!\n' abc
-0:ensure width is applied to empty param
->abc! !
-
- printf '%d %d\n' 123.45 678 90.1
-0:test d format specifier
->123 678
->90 0
-
- printf '%g %g\n' 123.45 678 90.1
-0:test g format specifier
->123.45 678
->90.1 0
-
- print -f 'arg: %b\n' -C2 '\x41' '\x42' '\x43'
-0:override -C when -f was given
->arg: A
->arg: B
->arg: C
-
-# Is anyone not using ASCII
- printf '%d\n' \'A
-0:initial quote to get numeric value of character with int
->65
-
- printf '%.1E\n' \'B
-0:initial quote to get numeric value of character with double
->6.6E+01
-
- printf '%x\n' $(printf '"\xf0')
-0:numeric value of high numbered character
->f0
-
- printf '\x25s\n' arg
-0:using \x25 to print a literal % in format
->%s
-
- printf '%3c\n' c
-0:width specified in format specifier
-> c
-
- printf '%.4s\n' chopped
-0:precision specified in format specifier
->chop
-
- printf '%*.*f\n' 6 2 10.2
-0:width/precision specified in arguments
-> 10.20
-
- printf '%z'
-1:use of invalid directive
-?(eval):printf:1: %z: invalid directive
-
- printf '%d\n' 3a
-1:bad arithmetic expression
-?(eval):1: bad math expression: operator expected at `a'
->0
-
- printf '%12$s' 1 2 3
-1:out of range argument specifier
-?(eval):printf:1: 12: argument specifier out of range
-
- printf '%2$s\n' 1 2 3
-1:out of range argument specifier on format reuse
-?(eval):printf:1: 2: argument specifier out of range
->2
-
- printf '%*0$d'
-1:out of range argument specifier on width
-?(eval):printf:1: 0: argument specifier out of range
-
- print -m -f 'format - %s.\n' 'z' a b c
-0:format not printed if no arguments left after -m removal
-
- print -f 'format - %s%b.\n'
-0:format printed despite lack of arguments
->format - .
-
- printf 'x%4sx\n'
-0:with no arguments empty string where string needed
->x x
-
- printf '%d\n'
-0:with no arguments, zero used where number needed
->0
-
- printf '%s\t%c:%#x%%\n' one a 1 two b 2 three c 3
-0:multiple arguments with format reused
->one a:0x1%
->two b:0x2%
->three c:0x3%
-
- printf '%d%n' 123 val val val > /dev/null
- printf '%d\n' val
-0:%n count zeroed on format reuse
->1
-
-# this may fill spec string with '%0'+- #*.*lld\0' - 14 characters
- printf '%1$0'"'+- #-08.5dx\n" 123
-0:maximal length format specification
->+00123 x
-
- printf "x:%-20s:y\n" fubar
-0:left-justification of string
->x:fubar :y
-
- printf '%*smorning\n' -5 good
-0:negative width specified
->good morning
-
- printf '%.*g\n' -1 .1
-0:negative precision specified
->0.1
-
- printf '%2$s %1$d\n' 1 2
-0:specify argument to output explicitly
->2 1
-
- printf '%3$.*1$d\n' 4 0 3
-0:specify output and precision arguments explicitly
->0003
-
- printf '%2$d%1$d\n' 1 2 3 4
-0:reuse format where arguments are explicitly specified
->21
->43
-
- printf '%1$*2$d' 1 2 3 4 5 6 7 8 9 10; echo .EoL.
-0:reuse of specified arguments
-> 1 3 5 7 9.EoL.
-
- echo -n 'Now is the time'; echo .EoL.
-0:testing -n with echo
->Now is the time.EoL.
-
- printf '%1$0+.3d\n' 3
-0:flags mixed with specified argument
->+003
-
-# Test the parsing of the \c escape.
-
- echo '1 2!\c3 4' a b c d; echo .EoL.
-0:Truncating first echo arg using backslash-c
->1 2!.EoL.
-
- echo a b '1 2?\c5 6' c d; echo .EoL.
-0:Truncating third echo arg using backslash-c
->a b 1 2?.EoL.
-
- printf '1 2!\c3 4'; echo .EoL.
-0:Truncating printf literal using backslash-c
->1 2!.EoL.
-
- printf '%s %b!\c%s %s' 1 2 3 4 5 6 7 8 9; echo .EoL.
-0:Truncating printf format using backslash-c
->1 2!.EoL.
-
- printf '%s %b!\c%s %s' '1\c' '2\n\c' 3 4 5 6 7 8 9
-0:Truncating printf early %b arg using backslash-c
->1\c 2
-
- printf '%b %b\n' 1 2 3 4 '5\c' 6 7 8 9; echo .EoL.
-0:Truncating printf late %b arg using backslash-c
->1 2
->3 4
->5.EoL.
-
-# The following usage, as stated in the manual, is not recommended and the
-# results are undefined. Tests are here anyway to ensure some form of
-# half-sane behaviour.
-
- printf '%2$s %s %3$s\n' Morning Good World
-0:mixed style of argument selection
->Good Morning World
-
- printf '%*1$.*d\n' 1 2
-0:argument specified for width only
->00
-
- print -f '%*.*1$d\n' 1 2 3
-0:argument specified for precision only
->2
->000
-
- printf -- '%s\n' str
-0:initial `--' ignored to satisfy POSIX
->str
-
- printf '%'
-1:nothing after % in format specifier
-?(eval):printf:1: %: invalid directive
-
- printf $'%\0'
-1:explicit null after % in format specifier
-?(eval):printf:1: %: invalid directive
-
- printf '%b\n' '\0123'
-0:printf handles \0... octal escapes in replacement text
->S
-
- print -lO $'a' $'a\0' $'a\0b' $'a\0b\0' $'a\0b\0a' $'a\0b\0b' $'a\0c' |
- while read -r line; do
- for (( i = 1; i <= ${#line}; i++ )); do
- foo=$line[i]
- printf "%02x" $(( #foo ))
- done
- print
- done
-0:sorting with embedded nulls
->610063
->6100620062
->6100620061
->61006200
->610062
->6100
->61
-
- foo=$'one\ttwo\tthree\tfour\n'
- foo+=$'\tone\ttwo\tthree\tfour\n'
- foo+=$'\t\tone\t\ttwo\t\tthree\t\tfour'
- print -x4 $foo
- print -X4 $foo
-0:Tab expansion by print
->one two three four
-> one two three four
-> one two three four
->one two three four
-> one two three four
-> one two three four
-
- unset foo
- print -v foo once more
- typeset -p foo
- printf -v foo "%s\0%s-" into the breach
- typeset -p foo
-0:print and printf into a variable
->typeset -g foo='once more'
->typeset -g foo=$'into\C-@the-breach\C-@-'
-
- typeset -a foo
- print -f '%2$d %4s' -v foo one 1 two 2 three 3
- typeset -p foo
-0:printf into an array variable
->typeset -a foo=( '1 one' '2 two' '3 three' )
-
- typeset -a foo
- print -f '%s' -v foo string
- typeset -p foo
-0:printf to an array variable without format string reuse
->typeset foo=string
-
- printf -
- printf - -
- printf --
- printf -- -
- printf -- --
- printf -x -v foo
- # Final print for newline on stdout
- print
-0:regression test of printf with assorted ambiguous options or formats
->------x
-?(eval):printf:3: not enough arguments
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B04read.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B04read.ztst
deleted file mode 100644
index 25c3d417..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B04read.ztst
+++ /dev/null
@@ -1,112 +0,0 @@
-# Tests for the read builtin
-
-# Tested elsewhere:
-# reading from a coprocess A01grammar, A04redirect
-
-# Not tested:
-# -c/-l/-n (options for compctl functions)
-# -q/-s (needs a tty)
-
-%test
-
- read <<<'hello world'
- print $REPLY
-0:basic read command
->hello world
-
- read -A <<<'hello world'
- print $reply[2]
-0:array read
->world
-
- read -k3 -u0 <<foo
-
- for char in y Y n N X $'\n'; do
- read -q -u0 <<<$char
- print $?
- done
-0:read yes or no, default no
->0
->0
->1
->1
->1
->1
-
- read -d: <<foo
-
- print foo:bar|IFS=: read -A
- print $reply
-0:use different, IFS separator to array
->foo bar
-
- print -z hello world; read -z
- print $REPLY
-0:read from editor buffer stack
->hello world
-
- unset REPLY
- read -E <<hello
->hello
-
- unset REPLY
- read -e <<hello
->
-
- read -e -t <<hello
-
- SECONDS=0
- read -e -t 5 <<hello
->0
-
- print -n 'Testing the\0null hypothesis\0' |
- while read -d $'\0' line; do print $line; done
-0:read with null delimiter
->Testing the
->null hypothesis
-
-# Note that trailing NULLs are not stripped even if they are in
-# $IFS; only whitespace characters contained in $IFS are stripped.
- print -n $'Aaargh, I hate nulls.\0\0\0' | read line
- print ${#line}
-0:read with trailing metafied characters
->24
-
- (typeset -r foo
- read foo) <<one
->two
->three
->one:two:three
-
- array=()
- read -Ae array <<<'four five six'
- print ${(j.:.)array}
-0:Behaviour of -A and -e combination
->four
->five
->six
->
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B05eval.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B05eval.ztst
deleted file mode 100644
index 6427d6f2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B05eval.ztst
+++ /dev/null
@@ -1,34 +0,0 @@
-# Tests for the eval builtin.
-# This is quite short; eval is widely tested throughout the test suite
-# and its basic behaviour is fairly straightforward.
-
-%prep
-
- cmd='print $?'
-
-%test
-
- false
- eval $cmd
-0:eval retains value of $?
->1
-
- # no point getting worked up over what the error message is...
- ./command_not_found 2>/dev/null
- eval $cmd
-0:eval after command not found
->127
-
- # trick the test system
- sp=
- false
- eval "
- $sp
- $sp
- $sp
- "
-0:eval with empty command resets the status
-
- false
- eval
-0:eval with empty command resets the status
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B06fc.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B06fc.ztst
deleted file mode 100644
index 922b0010..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B06fc.ztst
+++ /dev/null
@@ -1,25 +0,0 @@
-# Tests of fc command
-%prep
-
- mkdir fc.tmp
- cd fc.tmp
- print 'fc -l foo' >fcl
-
-%test
- $ZTST_testdir/../Src/zsh -f ./fcl
-1:Checking that fc -l foo doesn't core dump when history is empty
-?./fcl:fc:1: event not found: foo
-
- PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< $'fc -p /dev/null 0 0\n:'
-0:Checking that fc -p doesn't core dump when history size is zero
-*?*%*
-
- PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null a 0'
-1:Checking that fc -p rejects non-integer history size
-*?*% fc: HISTSIZE must be an integer
-*?*%*
-
- PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null 0 a'
-1:Checking that fc -p rejects non-integer history save size
-*?*% fc: SAVEHIST must be an integer
-*?*%*
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B07emulate.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B07emulate.ztst
deleted file mode 100644
index 2de097e2..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B07emulate.ztst
+++ /dev/null
@@ -1,253 +0,0 @@
-# Test the "emulate" builtin and related functions.
-
-%prep
-
- isset() {
- print -n "${1}: "
- if [[ -o $1 ]]; then print yes; else print no; fi
- }
- showopts() {
- # Set for Bourne shell emulation
- isset shwordsplit
- # Set in native mode and unless "emulate -R" is in use
- isset banghist
- }
- cshowopts() {
- showopts
- # Show a csh option, too
- isset cshnullglob
- }
-
-%test
-
- (print Before
- showopts
- fn() {
- emulate sh
- }
- fn
- print After
- showopts)
-0:Basic use of emulate
->Before
->shwordsplit: no
->banghist: yes
->After
->shwordsplit: yes
->banghist: yes
-
- fn() {
- emulate -L sh
- print During
- showopts
- }
- print Before
- showopts
- fn
- print After
- showopts
-0:Use of emulate -L
->Before
->shwordsplit: no
->banghist: yes
->During
->shwordsplit: yes
->banghist: yes
->After
->shwordsplit: no
->banghist: yes
-
- (print Before
- showopts
- emulate -R sh
- print After
- showopts)
-0:Use of emulate -R
->Before
->shwordsplit: no
->banghist: yes
->After
->shwordsplit: yes
->banghist: no
-
- print Before
- showopts
- emulate sh -c 'print During; showopts'
- print After
- showopts
-0:Use of emulate -c
->Before
->shwordsplit: no
->banghist: yes
->During
->shwordsplit: yes
->banghist: yes
->After
->shwordsplit: no
->banghist: yes
-
- print Before
- showopts
- emulate -R sh -c 'print During; showopts'
- print After
- showopts
-0:Use of emulate -R -c
->Before
->shwordsplit: no
->banghist: yes
->During
->shwordsplit: yes
->banghist: no
->After
->shwordsplit: no
->banghist: yes
-
- print Before
- showopts
- emulate -R sh -c 'shshowopts() { showopts; }'
- print After definition
- showopts
- print In sticky emulation
- shshowopts
- print After sticky emulation
- showopts
-0:Basic sticky function emulation
->Before
->shwordsplit: no
->banghist: yes
->After definition
->shwordsplit: no
->banghist: yes
->In sticky emulation
->shwordsplit: yes
->banghist: no
->After sticky emulation
->shwordsplit: no
->banghist: yes
-
- print Before
- cshowopts
- emulate -R sh -c 'shshowopts() { cshowopts; }'
- emulate csh -c 'cshshowopts() {
- cshowopts
- print In nested sh emulation
- shshowopts
- }'
- print After definition
- cshowopts
- print In sticky csh emulation
- cshshowopts
- print After sticky emulation
- cshowopts
-0:Basic sticky function emulation
->Before
->shwordsplit: no
->banghist: yes
->cshnullglob: no
->After definition
->shwordsplit: no
->banghist: yes
->cshnullglob: no
->In sticky csh emulation
->shwordsplit: no
->banghist: yes
->cshnullglob: yes
->In nested sh emulation
->shwordsplit: yes
->banghist: no
->cshnullglob: no
->After sticky emulation
->shwordsplit: no
->banghist: yes
->cshnullglob: no
-
- isalp() { if [[ -o alwayslastprompt ]]; then print on; else print off; fi; }
- emulate sh -c 'shfunc_inner() { setopt alwayslastprompt; }'
- emulate csh -c 'cshfunc_inner() { setopt alwayslastprompt; }'
- emulate sh -c 'shfunc_outer() {
- unsetopt alwayslastprompt;
- shfunc_inner;
- isalp
- unsetopt alwayslastprompt
- cshfunc_inner
- isalp
- }'
- shfunc_outer
-0:Sticky emulation not triggered if sticky emulation unchanged
->on
->off
-
- (
- setopt ignorebraces
- emulate zsh -o extendedglob -c '
- [[ -o ignorebraces ]] || print "Yay, ignorebraces was reset"
- [[ -o extendedglob ]] && print "Yay, extendedglob is set"
- '
- )
-0:emulate -c with options
->Yay, ignorebraces was reset
->Yay, extendedglob is set
-
- (
- setopt ignorebraces
- emulate zsh -o extendedglob
- [[ -o ignorebraces ]] || print "Yay, ignorebraces is no longer set"
- [[ -o extendedglob ]] && print "Yay, extendedglob is set"
- )
-0:emulate with options but no -c
->Yay, ignorebraces is no longer set
->Yay, extendedglob is set
-
- emulate zsh -o fixallmybugs 'print This was executed, bad'
-1:emulate -c with incorrect options
-?(eval):emulate:1: no such option: fixallmybugs
-
- emulate zsh -c '
- func() { [[ -o extendedglob ]] || print extendedglob is off }
- '
- func
- emulate zsh -o extendedglob -c '
- func() { [[ -o extendedglob ]] && print extendedglob is on }
- '
- func
-0:options specified alongside emulation are also sticky
->extendedglob is off
->extendedglob is on
-
- emulate zsh -o extendedglob -c '
- func_inner() { setopt nobareglobqual }
- '
- emulate zsh -o extendedglob -c '
- func_outer() {
- func_inner
- [[ -o bareglobqual ]] || print bareglobqual was turned off
- [[ -o extendedglob ]] && print extendedglob is on, though
- }
- '
- [[ -o extendedglob ]] || print extendedglob is initially off
- func_outer
-0:options propagate between identical emulations
->extendedglob is initially off
->bareglobqual was turned off
->extendedglob is on, though
-
- emulate zsh -o extendedglob -c '
- func_inner() { setopt nobareglobqual }
- '
- emulate zsh -o extendedglob -o cbases -c '
- func_outer() {
- func_inner
- [[ -o bareglobqual ]] && print bareglobqual is still on
- [[ -o extendedglob ]] && print extendedglob is on, too
- }
- '
- [[ -o extendedglob ]] || print extendedglob is initially off
- func_outer
-0:options do not propagate between different emulations
->extendedglob is initially off
->bareglobqual is still on
->extendedglob is on, too
-
- emulate sh -c '[[ a == a ]]'
-0:regression test for POSIX_ALIASES reserved words
-F:Some reserved tokens are handled in alias expansion
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B08shift.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B08shift.ztst
deleted file mode 100644
index 0aa92267..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B08shift.ztst
+++ /dev/null
@@ -1,33 +0,0 @@
-# Test the shift builtin.
-
-%test
-
- set -- one two three four five six seven eight nine ten
- shift
- print $*
- shift 2
- print $*
- shift -p 3
- print $*
- shift -p
- print $*
-0:shifting positional parameters
->two three four five six seven eight nine ten
->four five six seven eight nine ten
->four five six seven
->four five six
-
- array=(yan tan tether mether pip azer sezar akker conter dick)
- shift 2 array
- print $array
- shift array
- print $array
- shift -p 3 array
- print $array
- shift -p array
- print $array
-0:shifting array
->tether mether pip azer sezar akker conter dick
->mether pip azer sezar akker conter dick
->mether pip azer sezar
->mether pip azer
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B09hash.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B09hash.ztst
deleted file mode 100644
index 7b5dfb43..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/B09hash.ztst
+++ /dev/null
@@ -1,79 +0,0 @@
-# The hash builtin is most used for the command hash table, which is
-# populated automatically. This is therefore highly system specific,
-# so mostly we'll test with the directory hash table: the logic is
-# virtually identical but with the different table, and furthermore
-# the shell doesn't care whether the directory exists unless you refer
-# to it in a context that needs one.
-
-%prep
- populate_hash() {
- hash -d one=/first/directory
- hash -d two=/directory/the/second
- hash -d three=/noch/ein/verzeichnis
- hash -d four=/bored/with/this/now
- }
-
-%test
-
- hash -d
-0:Directory hash initially empty
-
- populate_hash
- hash -d
-0:Populating directory hash and output with sort
->four=/bored/with/this/now
->one=/first/directory
->three=/noch/ein/verzeichnis
->two=/directory/the/second
-
- hash -rd
- hash -d
-0:Empty hash
-
- populate_hash
- hash -d
-0:Refill hash
->four=/bored/with/this/now
->one=/first/directory
->three=/noch/ein/verzeichnis
->two=/directory/the/second
-
- hash -dL
-0:hash -L option
->hash -d four=/bored/with/this/now
->hash -d one=/first/directory
->hash -d three=/noch/ein/verzeichnis
->hash -d two=/directory/the/second
-
- hash -dm 't*'
-0:hash -m option
->three=/noch/ein/verzeichnis
->two=/directory/the/second
-
- hash -d five=/yet/more six=/here/we/go seven=/not/yet/eight
- hash -d
-0:Multiple assignments
->five=/yet/more
->four=/bored/with/this/now
->one=/first/directory
->seven=/not/yet/eight
->six=/here/we/go
->three=/noch/ein/verzeichnis
->two=/directory/the/second
-
- hash -d one two three
-0:Multiple arguments with no assignment not in verbose mode
-
- hash -vd one two three
-0:Multiple arguments with no assignment in verbose mode
->one=/first/directory
->two=/directory/the/second
->three=/noch/ein/verzeichnis
-
- hash -d t-t=/foo
- i="~t-t"
- print ~t-t/bar
- print ${~i}/rab
-0:Dashes are untokenized in directory hash names
->/foo/bar
->/foo/rab
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C01arith.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C01arith.ztst
deleted file mode 100644
index 61da763a..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C01arith.ztst
+++ /dev/null
@@ -1,422 +0,0 @@
-# Tests corresponding to the texinfo node `Arithmetic Evaluation'
-
-%test
-
- integer light there
- (( light = 42 )) &&
- let 'there = light' &&
- print $(( there ))
-0:basic integer arithmetic
->42
-
- float light there
- integer rnd
- (( light = 3.1415 )) &&
- let 'there = light' &&
- print -- $(( rnd = there * 10000 ))
-# save rounding problems by converting to integer
-0:basic floating point arithmetic
->31415
-
- integer rnd
- (( rnd = ((29.1 % 13.0 * 10) + 0.5) ))
- print $rnd
-0:Test floating point modulo function
->31
-
- print $(( 0x10 + 0X01 + 2#1010 ))
-0:base input
->27
-
- float light
- (( light = 4 ))
- print $light
- typeset -F light
- print $light
-0:conversion to float
->4.000000000e+00
->4.0000000000
-
- integer i
- (( i = 32.5 ))
- print $i
-0:conversion to int
->32
-
- integer i
- (( i = 4 - - 3 * 7 << 1 & 7 ^ 1 | 16 ** 2 ))
- print $i
-0:precedence (arithmetic)
->1591
-
- fn() {
- setopt localoptions c_precedences
- integer i
- (( i = 4 - - 3 * 7 << 1 & 7 ^ 1 | 16 ** 2 ))
- print $i
- }
- fn
-0:precedence (arithmetic, with C_PRECEDENCES)
->259
-
- print $(( 1 < 2 || 2 < 2 && 3 > 4 ))
-0:precedence (logical)
->1
-
- print $(( 1 + 4 ? 3 + 2 ? 4 + 3 ? 5 + 6 ? 4 * 8 : 0 : 0 : 0 : 0 ))
-0:precedence (ternary)
->32
-
- print $(( 3 ? 2 ))
-1:parsing ternary (1)
-?(eval):1: bad math expression: ':' expected
-
- print $(( 3 ? 2 : 1 : 4 ))
-1:parsing ternary (2)
-?(eval):1: bad math expression: ':' without '?'
-
- print $(( 0, 4 ? 3 : 1, 5 ))
-0:comma operator
->5
-
- foo=000
- print $(( ##A + ##\C-a + #foo + $#foo ))
-0:#, ## and $#
->117
-
- print $((##))
-1:## without following character
-?(eval):1: bad math expression: character missing after ##
-
- print $((## ))
-0:## followed by a space
->32
-
- integer i
- (( i = 3 + 5 * 1.75 ))
- print $i
-0:promotion to float
->11
-
- typeset x &&
- (( x = 3.5 )) &&
- print $x &&
- (( x = 4 )) &&
- print $x
-0:use of scalars to store integers and floats
->3.5
->4
-
- (( newarray[unsetvar] = 1 ))
-2:error using unset variable as index
-?(eval):1: newarray: assignment to invalid subscript range
-
- integer setvar=1
- (( newarray[setvar]++ ))
- (( newarray[setvar]++ ))
- print ${(t)newarray} ${#newarray} ${newarray[1]}
-0:setting array elements in math context
->array 1 2
-
- xarr=()
- (( xarr = 3 ))
- print ${(t)xarr} $xarr
-0:converting type from array
->integer 3
-
- print $(( 13 = 42 ))
-1:bad lvalue
-?(eval):1: bad math expression: lvalue required
-
- x=/bar
- (( x = 32 ))
- print $x
-0:assigning to scalar which contains non-math string
->32
-
- print $(( ))
-0:empty math parse e.g. $(( )) acts like a zero
->0
-
- print $(( a = ))
-1:empty assignment
-?(eval):1: bad math expression: operand expected at end of string
-
- print $(( 3, ))
-1:empty right hand of comma
-?(eval):1: bad math expression: operand expected at end of string
-
- print $(( 3,,4 ))
-1:empty middle of comma
-?(eval):1: bad math expression: operand expected at `,4 '
-
- print $(( (3 + 7, 4), 5 ))
-0:commas and parentheses, part 1
->5
-
- print $(( 5, (3 + 7, 4) ))
-0:commas and parentheses, part 1
->4
-
- print $(( 07.5 ))
- (setopt octalzeroes; print $(( 09.5 )))
-0:leading zero doesn't affect floating point
->7.5
->9.5
-
- (setopt octalzeroes; print $(( 09 )))
-1:octalzeroes rejects invalid constants
-?(eval):1: bad math expression: operator expected at `9 '
-
- (setopt octalzeroes; print $(( 08#77 )))
-0:octalzeroes doesn't affect bases
->63
-
- print $(( 36#z ))
-0:bases up to 36 work
->35
-
- print $(( 37#z ))
-1:bases beyond 36 don't work
-?(eval):1: invalid base (must be 2 to 36 inclusive): 37
-
- print $(( 3 + "fail" ))
-1:parse failure in arithmetic
-?(eval):1: bad math expression: operand expected at `"fail" '
-
- alias 3=echo
- print $(( 3 + "OK"); echo "Worked")
-0:not a parse failure because not arithmetic
->+ OK Worked
-
- fn() {
- emulate -L zsh
- print $(( [#16] 255 ))
- print $(( [##16] 255 ))
- setopt cbases
- print $(( [#16] 255 ))
- print $(( [##16] 255 ))
- }
- fn
-0:doubled # in base removes radix
->16#FF
->FF
->0xFF
->FF
-
- array=(1)
- x=0
- (( array[++x]++ ))
- print $x
- print $#array
- print $array
-0:no double increment for subscript
->1
->1
->2
-
- # This is a bit naughty... the value of array
- # isn't well defined since there's no sequence point
- # between the increments of x, however we just want
- # to be sure that in this case, unlike the above,
- # x does get incremented twice.
- x=0
- array=(1 2)
- (( array[++x] = array[++x] + 1 ))
- print $x
-0:double increment for repeated expression
->2
-
- # Floating point. Default precision should take care of rounding errors.
- print $(( 1_0.000_000e0_1 ))
- # Integer.
- print $(( 0x_ff_ff_ ))
- # _ are parts of variable names that don't start with a digit
- __myvar__=42
- print $(( __myvar__ + $__myvar__ ))
- # _ is not part of variable name that does start with a digit
- # (which are substituted before math eval)
- set -- 6
- print $(( $1_000_000 ))
- # Underscores in expressions with no whitespace
- print $(( 3_000_+4_000_/2 ))
- # Underscores may appear in the base descriptor, for what it's worth...
- print $(( 1_6_#f_f_ ))
-0:underscores in math constants
->100.
->65535
->84
->6000000
->5000
->255
-
- # Force floating point.
- for expr in "3/4" "0x100/0x200" "0x30/0x10"; do
- print $(( $expr ))
- setopt force_float
- print $(( $expr ))
- unsetopt force_float
- done
-0:Forcing floating point constant evaluation, or not.
->0
->0.75
->0
->0.5
->3
->3.
-
- print $(( 0x30 + 0.5 ))
- print $(( 077 + 0.5 ))
- (setopt octalzeroes; print $(( 077 + 0.5 )) )
-0:Mixed float and non-decimal integer constants
->48.5
->77.5
->63.5
-
- underscore_integer() {
- setopt cbases localoptions
- print $(( [#_] 1000000 ))
- print $(( [#16_] 65536 ))
- print $(( [#16_4] 65536 * 32768 ))
- }
- underscore_integer
-0:Grouping output with underscores: integers
->1_000_000
->0x10_000
->0x8000_0000
-
- print $(( [#_] (5. ** 10) / 16. ))
-0:Grouping output with underscores: floating point
->610_351.562_5
-
- env SHLVL=1+RANDOM $ZTST_testdir/../Src/zsh -f -c 'print $SHLVL'
-0:Imported integer functions are not evaluated
->2
-
- print $(( 0b0 + 0b1 + 0b11 + 0b110 ))
-0:Binary input
->10
-
- print $(( 0b2 ))
-1:Binary numbers don't tend to have 2's in
-?(eval):1: bad math expression: operator expected at `2 '
-# ` for emacs shell mode
-
- integer varassi
- print $(( varassi = 5.5 / 2.0 ))
- print $varassi
-0:Integer variable assignment converts result to integer
->2
->2
-# It's hard to test for integer to float.
-
- integer ff1=3 ff2=4
- print $(( ff1/ff2 ))
- setopt force_float
- print $(( ff1/ff2 ))
- unsetopt force_float
-0:Variables are forced to floating point where necessary
-# 0.75 is exactly representable, don't expect rounding error.
->0
->0.75
-
- # The following tests for a bug that only happens when
- # backing up over input read a line at a time, so we'll
- # read the input from stdin.
- $ZTST_testdir/../Src/zsh -f <<<'
- print $((echo first command
- ); echo second command)
- print third command
- '
-0:Backing up a line of input when finding out it's not arithmetic
->first command second command
->third command
-
- $ZTST_testdir/../Src/zsh -f <<<'
- print $((3 +
- 4))
- print next line
- '
-0:Not needing to back up a line when reading multiline arithmetic
->7
->next line
-
- $ZTST_testdir/../Src/zsh -f <<<'
- print $((case foo in
- bar)
- echo not this no, no
- ;;
- foo)
- echo yes, this one
- ;;
- esac)
- print after case in subshell)
- '
-0:Non-arithmetic subst with command subsitution parse from hell
->yes, this one after case in subshell
-
- print "a$((echo one subst)
- (echo two subst))b"
-0:Another tricky case that is actually a command substitution
->aone subst
->two substb
-
- print "x$((echo one frob); (echo two frob))y"
-0:Same on a single line
->xone frob
->two froby
-
- # This case actually only works by accident: if it wasn't for the
- # unbalanced parenthesis this would be a valid math substitution.
- # Hence it's definitely not recommended code. However, it does give
- # the algorithm an extra check.
- print $((case foo in
- foo)
- print Worked OK
- ;;
- esac))
-0:Would-be math expansion with extra parenthesis making it a cmd subst
->Worked OK
-
- (setopt extendedglob
- set -- 32.463
- print ${$(( $1 * 100 ))%%.[0-9]#})
-0:Arithmetic substitution nested in parameter substitution
->3246
-
- print $((`:`))
-0:Null string in arithmetic evaluation after command substitution
->0
-
- print $(( 1 + $(( 2 + 3 )) ))
- print $(($((3+4))))
- print $((1*$((2*$((3))*4))*5))
-0:Nested math substitutions. Yes, I know, very useful.
->6
->7
->120
-
- foo="(1)"
- print $((foo))
- print $(($foo))
- print $(((2)))
- foo="3)"
- (print $((foo))) 2>&1
- (print $(($foo))) 2>&1
-1: Good and bad trailing parentheses
->1
->1
->2
->(eval):6: bad math expression: unexpected ')'
->(eval):7: bad math expression: unexpected ')'
-
- unset number
- (( number = 3 ))
- print ${(t)number}
- unset number
- (setopt posix_identifiers
- (( number = 3 ))
- print ${(t)number})
-0:type of variable when created in arithmetic context
->integer
->scalar
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C02cond.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C02cond.ztst
deleted file mode 100644
index 38525016..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C02cond.ztst
+++ /dev/null
@@ -1,448 +0,0 @@
-# Tests corresponding to the texinfo node `Conditional Expressions'
-
-%prep
-
- umask 077
-
- mkdir cond.tmp
-
- cd cond.tmp
-
- typeset -gi isnfs
- [[ "$(find . -prune -fstype nfs 2>/dev/null)" == "." ]] && isnfs=1
- if (( isnfs )) &&
- (cd -q ${ZTST_tmp} >/dev/null 2>&1 &&
- [[ "$(find . -prune -fstype nfs 2>/dev/null)" != "." ]]); then
- filetmpprefix=${ZTST_tmp}/condtest-$$-
- isnfs=0
- else
- filetmpprefix=
- fi
- newnewnew=${filetmpprefix}newnewnew
- unmodified=${filetmpprefix}unmodified
- zlnfs=${filetmpprefix}zlnfs
-
- touch $unmodified
-
- touch zerolength
- chgrp $EGID zerolength
-
- touch $zlnfs
- chgrp $EGID $zlnfs
-
- print 'Garbuglio' >nonzerolength
-
- mkdir modish
- chgrp $EGID modish
-
- chmod 7710 modish # g+xs,u+s,+t
- chmod g+s modish # two lines combined work around chmod bugs
-
- touch unmodish
- chmod 000 unmodish
-
- print 'MZ' > cmd.exe
- chmod +x cmd.exe
-%test
-
- [[ -a zerolength && ! -a nonexistent ]]
-0:-a cond
-
- # Find a block special file system. This is a little tricky.
- block=$(find /dev(|ices)/ -type b -print)
- if [[ -n $block ]]; then
- [[ -b $block[(f)1] && ! -b zerolength ]]
- else
- print -u$ZTST_fd 'Warning: Not testing [[ -b blockdevice ]] (no devices found)'
- [[ ! -b zerolength ]]
- fi
-0D:-b cond
-
- # Use hardcoded /dev/tty because globbing inside /dev fails on Cygwin
- char=/dev/tty
- [[ -c $char && ! -c $zerolength ]]
-0:-c cond
-
- [[ -d . && ! -d zerolength ]]
-0:-d cond
-
- [[ -e zerolength && ! -e nonexistent ]]
-0:-e cond
-
- if [[ -n $block ]]; then
- [[ -f zerolength && ! -f cond && ! -f $char && ! -f $block[(f)1] && ! -f . ]]
- else
- print -u$ZTST_fd 'Warning: Not testing [[ -f blockdevice ]] (no devices found)'
- [[ -f zerolength && ! -f cond && ! -f $char && ! -f . ]]
- fi
-0:-f cond
-
- [[ -g modish && ! -g zerolength ]]
-0:-g cond
-
- ln -s zerolength link
- [[ -h link && ! -h zerolength ]]
-0:-h cond
-
- [[ -k modish && ! -k zerolength ]]
-0:-k cond
-
- foo=foo
- bar=
- [[ -n $foo && ! -n $bar && ! -n '' ]]
-0:-n cond
-
- [[ -o rcs && ! -o norcs && -o noerrexit && ! -o errexit ]]
-0:-o cond
-
- if ! grep '#define HAVE_FIFOS' $ZTST_testdir/../config.h; then
- print -u$ZTST_fd 'Warning: Not testing [[ -p pipe ]] (FIFOs not supported)'
- [[ ! -p zerolength ]]
- else
- if whence mkfifo && mkfifo pipe || mknod pipe p; then
- [[ -p pipe && ! -p zerolength ]]
- else
- print -u$ZTST_fd 'Warning: Not testing [[ -p pipe ]] (cannot create FIFO)'
- [[ ! -p zerolength ]]
- fi
- fi
-0dD:-p cond
-
- if (( EUID == 0 )); then
- print -u$ZTST_fd 'Warning: Not testing [[ ! -r file ]] (root reads anything)'
- [[ -r zerolength && -r unmodish ]]
- elif [[ $OSTYPE = cygwin ]]; then
- print -u$ZTST_fd 'Warning: Not testing [[ ! -r file ]]
- (all files created by user may be readable)'
- [[ -r zerolength ]]
- else
- [[ -r zerolength && ! -r unmodish ]]
- fi
-0:-r cond
-
- [[ -s nonzerolength && ! -s zerolength ]]
-0:-s cond
-
-# no simple way of guaranteeing test for -t
-
- [[ -u modish && ! -u zerolength ]]
-0:-u cond
-
- [[ -x cmd.exe && ! -x zerolength ]]
-0:-x cond
-
- [[ -z $bar && -z '' && ! -z $foo ]]
-0:-z cond
-
- [[ -L link && ! -L zerolength ]]
-0:-L cond
-
-# hard to guarantee a file not owned by current uid
- [[ -O zerolength ]]
-0:-O cond
-
- [[ -G zerolength ]]
-0:-G cond
-
-# can't be bothered with -S
-
- if [[ ${mtab::="$({mount || /sbin/mount || /usr/sbin/mount} 2>/dev/null)"} = *[(]?*[)] ]]; then
- print -u $ZTST_fd 'This test takes two seconds...'
- else
- unmodified_ls="$(ls -lu $unmodified)"
- print -u $ZTST_fd 'This test takes up to 60 seconds...'
- fi
- sleep 2
- touch $newnewnew
- if [[ $OSTYPE == "cygwin" ]]; then
- ZTST_skip="[[ -N file ]] not supported on Cygwin"
- elif (( isnfs )); then
- ZTST_skip="[[ -N file ]] not supported with NFS"
- elif { (( ! $+unmodified_ls )) &&
- cat $unmodified &&
- { df -k -- ${$(print -r -- "$mtab" |
- awk '/noatime/ {print $1,$3}'):-""} | tr -s ' ' |
- fgrep -- "$(df -k . | tail -1 | tr -s ' ')" } >&/dev/null } ||
- { (( $+unmodified_ls )) && SECONDS=0 &&
- ! until (( SECONDS >= 58 )); do
- ZTST_hashmark; sleep 2; cat $unmodified
- [[ $unmodified_ls != "$(ls -lu $unmodified)" ]] && break
- done }; then
- ZTST_skip="[[ -N file ]] not supported with noatime file system"
- else
- [[ -N $newnewnew && ! -N $unmodified ]]
- fi
-0:-N cond
-F:This test can fail on NFS-mounted filesystems as the access and
-F:modification times are not updated separately. The test will fail
-F:on HFS+ (Apple Mac OS X default) filesystems because access times
-F:are not recorded. Also, Linux ext3 filesystems may be mounted
-F:with the noatime option which does not update access times.
-F:Failures in these cases do not indicate a problem in the shell.
-
- [[ $newnewnew -nt $zlnfs && ! ($unmodified -nt $zlnfs) ]]
-0:-nt cond
-
- [[ $zlnfs -ot $newnewnew && ! ($zlnfs -ot $unmodified) ]]
-0:-ot cond
-
- [[ link -ef zerolength && ! (link -ef nonzerolength) ]]
-0:-ef cond
-
- [[ foo = foo && foo != bar && foo == foo && foo != '' ]]
-0:=, == and != conds
-
- [[ bar < foo && foo > bar ]]
-0:< and > conds
-
- [[ $(( 3 + 4 )) -eq 0x07 && $(( 5 * 2 )) -ne 0x10 ]]
-0:-eq and -ne conds
-
- [[ 3 -lt 04 && 05 -gt 2 ]]
-0:-lt and -gt conds
-
- [[ 3 -le 3 && ! (4 -le 3) ]]
-0:-le cond
-
- [[ 3 -ge 3 && ! (3 -ge 4) ]]
-0:-ge cond
-
- [[ 1 -lt 2 || 2 -lt 2 && 3 -gt 4 ]]
-0:|| and && in conds
-
- if ! grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h; then
- print -u$ZTST_fd "Warning: not testing [[ -e /dev/fd/0 ]] (/dev/fd not supported)"
- true
- else
- [[ -e /dev/fd/0 ]]
- fi
-0dD:/dev/fd support in conds handled by access
-
- if ! grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h; then
- print -u$ZTST_fd "Warning: not testing [[ -O /dev/fd/0 ]] (/dev/fd not supported)"
- true
- else
- [[ -O /dev/fd/0 ]]
- fi
-0dD:/dev/fd support in conds handled by stat
-
- [[ ( -z foo && -z foo ) || -z foo ]]
-1:complex conds with skipping
-
- [ '' != bar -a '' = '' ]
-0:strings with `[' builtin
-
- [ `echo 0` -lt `echo 1` ]
-0:substitution in `[' builtin
-
- [ -n foo scrimble ]
-2:argument checking for [ builtin
-?(eval):[:1: too many arguments
-
- test -n foo scramble
-2:argument checking for test builtin
-?(eval):test:1: too many arguments
-
- [ -n foo scrimble scromble ]
-2:argument checking for [ builtin
-?(eval):[:1: too many arguments
-
- test -n foo scramble scrumble
-2:argument checking for test builtin
-?(eval):test:1: too many arguments
-
- [ -n foo -a -n bar scrimble ]
-2:argument checking for [ builtin
-?(eval):[:1: too many arguments
-
- test -n foo -a -z "" scramble
-2:argument checking for test builtin
-?(eval):test:1: too many arguments
-
- fn() {
- # careful: first file must exist to trigger bug
- [[ -e $unmodified ]] || print Where\'s my file\?
- [[ $unmodified -nt NonExistentFile ]]
- print status = $?
- }
- fn
-0:-nt shouldn't abort on non-existent files
->status = 1
-
- str='string' empty=''
- [[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]]
-0:-v cond
-
- arr=( 1 2 3 4 ) empty=()
- [[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] &&
- -v arr[(i)3] && ! -v arr[(i)x] &&
- ! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] &&
- ! -v arr[3]extra && -v empty && ! -v empty[1] ]]
-0:-v cond with array
-
- typeset -A assoc=( key val num 4 )
- [[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] &&
- ! -v assoc[x] && ! -v assoc[key][1] ]]
-0:-v cond with association
-
- () { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg ''
-0:-v cond with positional parameters
-
-# core dumps on failure
- if zmodload zsh/regex 2>/dev/null; then
- echo >regex_test.sh 'if [[ $# = 1 ]]; then
- if [[ $1 =~ /?[^/]+:[0-9]+:$ ]]; then
- :
- fi
- fi
- exit 0'
- $ZTST_testdir/../Src/zsh -f ./regex_test.sh
- fi
-0:regex tests shouldn't crash
-
- if zmodload zsh/regex 2>/dev/null; then
- ( # subshell in case coredump test failed
- string="this has stuff in it"
- bad_regex=0
- if [[ $string =~ "h([a-z]*) s([a-z]*) " ]]; then
- if [[ "$MATCH $MBEGIN $MEND" != "has stuff 6 15" ]]; then
- print -r "regex variables MATCH MBEGIN MEND:
- '$MATCH $MBEGIN $MEND'
- should be:
- 'has stuff 6 15'"
- bad_regex=1
- else
- results=("as 7 8" "tuff 11 14")
- for i in 1 2; do
- if [[ "$match[$i] $mbegin[$i] $mend[$i]" != $results[i] ]]; then
- print -r "regex variables match[$i] mbegin[$i] mend[$i]:
- '$match[$i] $mbegin[$i] $mend[$i]'
- should be
- '$results[$i]'"
- bad_regex=1
- break
- fi
- done
- fi
- (( bad_regex )) || print OK
- else
- print -r "regex failed to match '$string'"
- fi
- )
- else
- # if it didn't load, tough, but not a test error
- ZTST_skip="regexp library not found."
- fi
-0:MATCH, MBEGIN, MEND, match, mbegin, mend
->OK
-
- if zmodload zsh/regex 2>/dev/null; then
- ( # subshell because regex module may dump core, see above
- if [[ a =~ a && b == b ]]; then
- print OK
- else
- print "regex =~ inverted following test"
- fi
- )
- else
- # not a test error
- ZTST_skip="regexp library not found."
- fi
-0:regex infix operator should not invert following conditions
->OK
-
- [[ -fail badly ]]
-2:Error message for unknown prefix condition
-?(eval):1: unknown condition: -fail
-
- [[ really -fail badly ]]
-2:Error message for unknown infix condition
-?(eval):1: unknown condition: -fail
-
- crashme() {
- if [[ $1 =~ ^http:* ]]
- then
- url=${1#*=}
- fi
- }
- which crashme
-0:Regression test for examining code with regular expression match
->crashme () {
-> if [[ $1 =~ ^http:* ]]
-> then
-> url=${1#*=}
-> fi
->}
-
- weirdies=(
- '! -a !'
- '! -o !'
- '! -a'
- '! -o'
- '! -a ! -a !'
- '! = !'
- '! !'
- '= -a o'
- '! = -a o')
- for w in $weirdies; do
- eval test $w
- print $?
- done
-0:test compatability weirdness: treat ! as a string sometimes
->0
->0
->1
->0
->0
->0
->1
->0
->1
-
- foo=''
- [[ $foo ]] || print foo is empty
- foo=full
- [[ $foo ]] && print foo is full
-0:bash compatibility with single [[ ... ]] argument
->foo is empty
->foo is full
-
- test -z \( || print Not zero 1
- test -z \< || print Not zero 2
- test -n \( && print Not zero 3
- test -n \) && print Not zero 4
- [ -n \> ] && print Not zero 5
- [ -n \! ] && print Not zero 6
-0:test with two arguments and a token
->Not zero 1
->Not zero 2
->Not zero 3
->Not zero 4
->Not zero 5
->Not zero 6
-
- [ '(' = ')' ] || print OK 1
- [ '((' = '))' ] || print OK 2
- [ '(' = '(' ] && print OK 3
- [ '(' non-empty-string ')' ] && echo OK 4
- [ '(' '' ')' ] || echo OK 5
-0:yet more old-fashioned test fix ups: prefer comparison to parentheses
->OK 1
->OK 2
->OK 3
->OK 4
->OK 5
-
- fn() { [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]] }
- which -x2 fn
-0: = and == appear as input
->fn () {
-> [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]]
->}
-
-%clean
- # This works around a bug in rm -f in some versions of Cygwin
- chmod 644 unmodish
- for tmpfile in $newnewnew $unmodified $zlnfs; do
- [[ -f $tmpfile ]] && rm -f $tmpfile
- done
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C03traps.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C03traps.ztst
deleted file mode 100644
index 7bc0b486..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C03traps.ztst
+++ /dev/null
@@ -1,761 +0,0 @@
-# Tests for both trap builtin and TRAP* functions.
-
-%prep
-
- setopt localtraps
- mkdir traps.tmp && cd traps.tmp
-
-%test
-
- fn1() {
- trap 'print EXIT1' EXIT
- fn2() { trap 'print EXIT2' EXIT; }
- fn2
- }
- fn1
-0:Nested `trap ... EXIT'
->EXIT2
->EXIT1
-
- fn1() {
- TRAPEXIT() { print EXIT1; }
- fn2() { TRAPEXIT() { print EXIT2; }; }
- fn2
- }
- fn1
-0: Nested TRAPEXIT
->EXIT2
->EXIT1
-
- fn1() {
- trap 'print EXIT1' EXIT
- fn2() { trap - EXIT; }
- fn2
- }
- fn1
-0:Nested `trap - EXIT' on `trap ... EXIT'
->EXIT1
-
- fn1() {
- TRAPEXIT() { print EXIT1; }
- fn2() { trap - EXIT; }
- fn2
- }
- fn1
-0:Nested `trap - EXIT' on `TRAPEXIT'
->EXIT1
-
-# We can't test an EXIT trap for the shell as a whole, because
-# we're inside a function scope which we don't leave when the
-# subshell exits. Not sure if that's the correct behaviour, but
-# it's sort of consistent.
- ( fn1() { trap 'print Function 1 going' EXIT; exit; print Not reached; }
- fn2() { trap 'print Function 2 going' EXIT; fn1; print Not reached; }
- fn2
- )
-0:EXIT traps on functions when exiting from function
->Function 1 going
->Function 2 going
-
-# $ZTST_exe is relative to the parent directory.
-# We ought to fix this in ztst.zsh...
- (cd ..
- $ZTST_exe -fc 'TRAPEXIT() { print Exited.; }')
-0:EXIT traps on a script
->Exited.
-
- trap -
- trap
- trap int INT
- trap sigterm SIGTERM
- trap quit 3
- trap
-0: Outputting traps correctly
->trap -- int INT
->trap -- quit QUIT
->trap -- sigterm TERM
-
- fn1() {
- trap -
- trap
- trap 'print INT1' INT
- fn2() { trap 'print INT2' INT; trap; }
- trap
- fn2
- trap
- }
- fn1
-0: Nested `trap ... INT', not triggered
->trap -- 'print INT1' INT
->trap -- 'print INT2' INT
->trap -- 'print INT1' INT
-
- fn1() {
- trap -
- trap
- TRAPINT() { print INT1; }
- fn2() { TRAPINT() { print INT2; }; trap; }
- trap
- fn2
- trap
- }
- fn1
-0: Nested TRAPINT, not triggered
->TRAPINT () {
-> print INT1
->}
->TRAPINT () {
-> print INT2
->}
->TRAPINT () {
-> print INT1
->}
-
- fn1() {
- trap -
- trap 'print INT1' INT
- fn2() { trap - INT; trap; }
- trap
- fn2
- trap
- }
- fn1
-0: Nested `trap - INT' on untriggered `trap ... INT'
->trap -- 'print INT1' INT
->trap -- 'print INT1' INT
-
-# Testing the triggering of traps here is very unpleasant.
-# The delays are attempts to avoid race conditions, though there is
-# no guarantee that they will work. Note the subtlety that the
-# `sleep' in the function which receives the trap does *not* get the
-# signal, only the parent shell, which is waiting for a SIGCHILD.
-# (At least, that's what I think is happening.) Thus we have to wait at
-# least the full two seconds to make sure we have got the output from the
-# execution of the trap.
-
- print -u $ZTST_fd 'This test takes at least three seconds...'
- fn1() {
- trap 'print TERM1' TERM
- fn2() { trap 'print TERM2; return 1' TERM; sleep 2; }
- fn2 &
- sleep 1
- kill -TERM $!
- sleep 2
- }
- fn1
-0: Nested `trap ... TERM', triggered on inner loop
->TERM2
-
- print -u $ZTST_fd 'This test, too, takes at least three seconds...'
- fn1() {
- trap 'print TERM1; return 1' TERM
- fn2() { trap 'print TERM2; return 1' TERM; }
- fn2
- sleep 2
- }
- fn1 &
- sleep 1
- kill -TERM $!
- sleep 2
-0: Nested `trap ... TERM', triggered on outer loop
->TERM1
-
- TRAPZERR() { print error activated; }
- fn() { print start of fn; false; print end of fn; }
- fn
- fn() {
- setopt localoptions localtraps
- unfunction TRAPZERR
- print start of fn
- false
- print end of fn
- }
- fn
- unfunction TRAPZERR
- print finish
-0: basic localtraps handling
->start of fn
->error activated
->end of fn
->start of fn
->end of fn
->finish
-
- TRAPZERR() { print 'ERR-or!'; }
- f() { print f; false; }
- t() { print t; }
- f
- f && t
- t && f && true
- t && f
- testunset() {
- setopt localtraps
- unset -f TRAPZERR
- print testunset
- false
- true
- }
- testunset
- f
- print status $?
- unfunction TRAPZERR
-0: more sophisticated error trapping
->f
->ERR-or!
->f
->t
->f
->t
->f
->ERR-or!
->testunset
->f
->ERR-or!
->status 1
-
- f() {
- setopt localtraps
- TRAPWINCH() { print "Window changed. That wrecked the test."; }
- }
- f
- f
- functions TRAPWINCH
-1:Unsetting ordinary traps with localtraps.
-
-#
-# Returns from within traps are a perennial problem.
-# The following two apply to returns in and around standard
-# ksh-style traps. The intention is that a return value from
-# within the function is preserved (i.e. statuses set by the trap
-# are ignored) unless the trap explicitly executes `return', which makes
-# it return from the enclosing function.
-#
- fn() { trap 'true' EXIT; return 1; }
- fn
-1: ksh-style EXIT traps preserve return value
-
- inner() { trap 'return 3' EXIT; return 2; }
- outer() { inner; return 1; }
- outer
-3: ksh-style EXIT traps can force return status of enclosing function
-
-# Autoloaded traps are horrid, but unfortunately people expect
-# them to work if we support them.
- echo "print Running exit trap" >TRAPEXIT
- ${${ZTST_exe##[^/]*}:-$ZTST_testdir/$ZTST_exe} -fc '
- fpath=(. $fpath)
- autoload TRAPEXIT
- print "Exiting, attempt 1"
- exit
- print "What?"
- '
- ${${ZTST_exe##[^/]*}:-$ZTST_testdir/$ZTST_exe} -fc '
- fpath=(. $fpath)
- autoload TRAPEXIT;
- fn() { print Some function }
- fn
- print "Exiting, attempt 2"
- exit
- '
-0: autoloaded TRAPEXIT (exit status > 128 indicates an old bug is back)
->Exiting, attempt 1
->Running exit trap
->Some function
->Exiting, attempt 2
->Running exit trap
-
- print -u $ZTST_fd Another test that takes three seconds
- gotsig=0
- signal_handler() {
- echo "parent received signal"
- gotsig=1
- }
- child() {
- sleep 1
- echo "child sending signal"
- kill -15 $parentpid
- sleep 2
- echo "child exiting"
- exit 33
- }
- parentpid=$$
- child &
- childpid=$!
- trap signal_handler 15
- echo "parent waiting"
- wait $childpid
- cstatus=$?
- echo "wait #1 finished, gotsig=$gotsig, status=$cstatus"
- gotsig=0
- wait $childpid
- cstatus=$?
- echo "wait #2 finished, gotsig=$gotsig, status=$cstatus"
-0:waiting for trapped signal
->parent waiting
->child sending signal
->parent received signal
->wait #1 finished, gotsig=1, status=143
->child exiting
->wait #2 finished, gotsig=0, status=33
-
- fn1() {
- setopt errexit
- trap 'echo error1' ZERR
- false
- print Shouldn\'t get here 1a
- }
- fn2() {
- setopt errexit
- trap 'echo error2' ZERR
- return 1
- print Shouldn\'t get here 2a
- }
- fn3() {
- setopt errexit
- TRAPZERR() { echo error3; }
- false
- print Shouldn\'t get here 3a
- }
- fn4() {
- setopt errexit
- TRAPZERR() { echo error4; }
- return 1
- print Shouldn\'t get here 4a
- }
- (fn1; print Shouldn\'t get here 1b)
- (fn2; print Shouldn\'t get here 2b)
- (fn3; print Shouldn\'t get here 3b)
- (fn4; print Shouldn\'t get here 4b)
-1: Combination of ERR_EXIT and ZERR trap
->error1
->error2
->error3
->error4
-
- fn1() { TRAPZERR() { print trap; return 42; }; false; print Broken; }
- (fn1)
- print Working $?
-0: Force return of containing function from TRAPZERR.
->trap
->Working 42
-
- fn2() { trap 'print trap; return 42' ZERR; false; print Broken }
- (fn2)
- print Working $?
-0: Return with non-zero status triggered from within trap '...' ZERR.
->trap
->Working 42
-
- fn3() { TRAPZERR() { print trap; return 0; }; false; print OK this time; }
- (fn3)
- print Working $?
-0: Normal return from TRAPZERR.
->trap
->OK this time
->Working 0
-
- fn4() { trap 'print trap; return 0' ZERR; false; print Broken; }
- (fn4)
- print Working $?
-0: Return with zero status triggered from within trap '...' ZERR.
->trap
->Working 0
-
- { trap 'echo This subshell is exiting' EXIT; } | cat
-0: EXIT trap set in current shell at left of pipeline
->This subshell is exiting
-
- ( trap 'echo This subshell is also exiting' EXIT; ) | cat
-0: EXIT trap set in subshell at left of pipeline
->This subshell is also exiting
-
- ( trap 'echo Should only appear once at the end' EXIT
- ( : trap reset here ) | cat
- : trap not reset but not part of shell command list | cat
- echo nothing after this should appear $( : trap reset here too)
- )
-0: EXIT trap set in subshell reset in subsubshell
->nothing after this should appear
->Should only appear once at the end
-
- echo $( trap 'echo command substitution exited' EXIT )
-0: EXIT trap set in command substitution
->command substitution exited
-
- (cd ..; $ZTST_exe -fc 'setopt posixtraps;
- TRAPEXIT() { print Exited; }
- fn1() { trap; }
- setopt localtraps # should be ignored by EXIT
- fn2() { TRAPEXIT() { print No, really exited; } }
- fn1
- fn2
- fn1')
-0:POSIX_TRAPS option
->TRAPEXIT () {
-> print Exited
->}
->TRAPEXIT () {
-> print No, really exited
->}
->No, really exited
-
- (cd ..; $ZTST_exe -fc 'unsetopt posixtraps;
- echo start program
- emulate sh -c '\''testfn() {
- echo start function
- set -o | grep posixtraps
- trap "echo EXIT TRAP TRIGGERED" EXIT
- echo end function
- }'\''
- testfn
- echo program continuing
- echo end of program')
-0:POSIX_TRAPS effect on EXIT trap is sticky
->start program
->start function
->noposixtraps off
->end function
->program continuing
->end of program
->EXIT TRAP TRIGGERED
-
- (cd ..; $ZTST_exe -fc '
- echo entering program
- emulate sh -c '\''trap "echo POSIX exit trap triggered" EXIT'\''
- fn() {
- trap "echo native zsh function-local exit trap triggered" EXIT
- echo entering native zsh function
- }
- fn
- echo exiting program
- ')
-0:POSIX EXIT trap can have nested native mode EXIT trap
->entering program
->entering native zsh function
->native zsh function-local exit trap triggered
->exiting program
->POSIX exit trap triggered
-
- (cd ..; $ZTST_exe -fc '
- echo entering program
- emulate sh -c '\''spt() { trap "echo POSIX exit trap triggered" EXIT; }'\''
- fn() {
- trap "echo native zsh function-local exit trap triggered" EXIT
- echo entering native zsh function
- }
- spt
- fn
- echo exiting program
- ')
-0:POSIX EXIT trap not replaced if defined within function
->entering program
->entering native zsh function
->native zsh function-local exit trap triggered
->exiting program
->POSIX exit trap triggered
-
- (set -e
- printf "a\nb\n" | while read line
- do
- [[ $line = a* ]] || continue
- ((ctr++))
- [[ $line = foo ]]
- done
- echo "ctr = $ctr"
- )
-1:ERREXIT in loop with simple commands
-
- fn() {
- emulate -L zsh
- setopt errreturn
- if false; then
- false
- print No.
- else
- print Oh, yes
- fi
- }
- fn
-0:ERR_RETURN not triggered in if condition
->Oh, yes
-
- fn() {
- emulate -L zsh
- setopt errreturn
- if true; then
- false
- print No.
- else
- print No, no.
- fi
- }
- fn
-1:ERR_RETURN in "if"
-
- fn() {
- emulate -L zsh
- setopt errreturn
- if false; then
- print No.
- else
- false
- print No, no.
- fi
- }
- fn
-1:ERR_RETURN in "else" branch (regression test)
-
- $ZTST_testdir/../Src/zsh -f =(<<<"
- if false; then
- :
- else
- if [[ -n '' ]]; then
- a=2
- fi
- print Yes
- fi
- ")
-0:ERR_RETURN when false "if" is the first statement in an "else" (regression)
->Yes
-F:Must be tested with a top-level script rather than source or function
-
- fn() {
- emulate -L zsh
- setopt errreturn
- print before
- false
- print after
- }
- fn
-1:ERR_RETURN, basic case
->before
-
- fn() {
- emulate -L zsh
- setopt errreturn
- print before
- ! true
- ! false
- print after
- }
- fn
-0:ERR_RETURN with "!"
->before
->after
-
- fn() {
- emulate -L zsh
- setopt errreturn
- print before
- ! true
- ! false
- false
- print after
- }
- fn
-1:ERR_RETURN with "!" and a following false
->before
-
- fn() {
- emulate -L zsh
- setopt errreturn
- print before
- ! if true; then
- false
- fi
- print after
- }
- fn
-0:ERR_RETURN with "!" suppressed inside complex structure
->before
->after
-
- fn() {
- emulate -L zsh
- setopt errreturn
- print before
- if true; then
- false
- fi
- print after
- }
- fn
-1:ERR_RETURN with no "!" suppression (control case)
->before
-
- (setopt err_return
- fn() {
- print before-in
- false && false
- }
- print before-out
- fn
- print after-out
- )
-1:ERR_RETURN with "&&" in function (regression test)
->before-out
->before-in
-
- (setopt err_return
- fn() {
- print before-in
- false && false
- print after-in
- }
- print before-out
- fn
- print after-out
- )
-0:ERR_RETURN not triggered on LHS of "&&" in function
->before-out
->before-in
->after-in
->after-out
-
- (setopt err_return
- fn() {
- print before-in
- true && false
- print after-in
- }
- print before-out
- fn
- print after-out
- )
-1:ERR_RETURN triggered on RHS of "&&" in function
->before-out
->before-in
-
- (setopt err_exit
- for x in y; do
- false && true
- done
- print OK
- )
-0:ERR_EXIT not triggered by status 1 at end of for
->OK
-
- (setopt err_exit
- integer x=0
- while (( ! x++ )); do
- false && true
- done
- print OK
- )
-0:ERR_EXIT not triggered by status 1 at end of while
->OK
-
- (setopt err_exit
- repeat 1; do
- false && true
- done
- print OK
- )
-0:ERR_EXIT not triggered by status 1 at end of repeat
->OK
-
- (setopt err_exit
- if true; then
- false && true
- fi
- print OK
- )
-0:ERR_EXIT not triggered by status 1 at end of if
->OK
-
- (setopt err_exit
- {
- false && true
- }
- print OK
- )
-0:ERR_EXIT not triggered by status 1 at end of { }
->OK
-
- (setopt err_exit
- for x in y; do
- false
- done
- print OK
- )
-1:ERR_EXIT triggered by status 1 within for
-
- (setopt err_exit
- integer x=0
- while (( ! x++ )); do
- false
- done
- print OK
- )
-1:ERR_EXIT triggered by status 1 within while
-
- (setopt err_exit
- repeat 1; do
- false
- done
- print OK
- )
-1:ERR_EXIT triggered by status 1 within repeat
-
- (setopt err_exit
- if true; then
- false
- fi
- print OK
- )
-1:ERR_EXIT triggered by status 1 within if
-
- (setopt err_exit
- {
- false
- }
- print OK
- )
-1:ERR_EXIT triggered by status 1 within { }
-
- (setopt err_exit
- () {
- false && true
- print Still functioning
- false && true
- }
- print OK
- )
-1:ERR_EXIT triggered by status 1 at end of anon func
->Still functioning
-
- if zmodload zsh/system 2>/dev/null; then
- (
- trap 'echo TERM; exit 2' TERM
- trap 'echo EXIT' EXIT
- kill -s TERM "$sysparams[pid]"
- echo 'FATAL: we should never get here!' 1>&2
- exit 1
- )
- else
- ZTST_skip="zsh/system library not found."
- fi
-2:EXIT trap from TERM trap
->TERM
->EXIT
-
- # Should not get "hello" in the single quotes.
- (
- trap "echo hello" EXIT;
- { :; } | { read line; print "'$line'"; }
- )
-0:EXIT trap not called in LHS of pipeline: Shell construct on LHS
->''
->hello
-
- (
- trap "echo hello" EXIT;
- cat ''
->hello
-
-%clean
-
- rm -f TRAPEXIT
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C04funcdef.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C04funcdef.ztst
deleted file mode 100644
index 0cf2b58b..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C04funcdef.ztst
+++ /dev/null
@@ -1,502 +0,0 @@
-%prep
-
- mkdir funcdef.tmp
- cd funcdef.tmp
- setopt chaselinks
- cd .
- unsetopt chaselinks
- mydir=$PWD
-
-%test
-
- fn1() { return 1; }
- fn2() {
- fn1
- print $?
- return 2
- }
- fn2
-2:Basic status returns from functions
->1
-
- fnz() { }
- false
- fnz
-0:Empty function body resets status
-
- fn3() { return 3; }
- fnstat() { print $?; }
- fn3
- fnstat
-0:Status is not reset on non-empty function body
->3
-
- function f$$ () {
- print regress expansion of function names
- }
- f$$
-0:Regression test: 'function f$$ () { ... }'
->regress expansion of function names
-
- function foo () print bar
- foo
-0:Function definition without braces
->bar
-
- functions -M m1
- m1() { (( $# )) }
- print $(( m1() ))
- print $(( m1(1) ))
- print $(( m1(1,2) ))
-0:User-defined math functions, argument handling
->0
->1
->2
-
- functions -M m2
- m2() {
- integer sum
- local val
- for val in $*; do
- (( sum += $val ))
- done
- }
- print $(( m2(1) ))
- print $(( m2(1,3+3,4**2) ))
-0:User-defined math functions, complex argument handling
->1
->23
-
- functions -M m3 1 2
- m3() { (( 1 )) }
- print zero
- (print $(( m3() )))
- print one
- print $(( m3(1) ))
- print two
- print $(( m3(1,2) ))
- print three
- (print $(( m3(1,2,3) )))
-1:User-defined math functions, argument checking
->zero
->one
->1
->two
->1
->three
-?(eval):4: wrong number of arguments: m3()
-?(eval):10: wrong number of arguments: m3(1,2,3)
-
- functions -M m4 0 0 testmathfunc
- functions -M m5 0 0 testmathfunc
- testmathfunc() {
- if [[ $0 = m4 ]]; then
- (( 4 ))
- else
- (( 5 ))
- fi
- }
- print $(( m4() ))
- print $(( m5() ))
-0:User-defined math functions, multiple interfaces
->4
->5
-
- command_not_found_handler() {
- print "Great News! I've handled the command:"
- print "$1"
- print "with arguments:"
- print -l ${argv[2,-1]}
- }
- ACommandWhichHadBetterNotExistOnTheSystem and some "really useful" args
-0:Command not found handler, success
->Great News! I've handled the command:
->ACommandWhichHadBetterNotExistOnTheSystem
->with arguments:
->and
->some
->really useful
->args
-
-# ' deconfuse emacs
-
- command_not_found_handler() {
- print "Your command:" >&2
- print "$1" >&2
- print "has gone down the tubes. Sorry." >&2
- return 42
- }
- ThisCommandDoesNotExistEither
-42:Command not found handler, failure
-?Your command:
-?ThisCommandDoesNotExistEither
-?has gone down the tubes. Sorry.
-
- local variable=outside
- print "I am $variable"
- function {
- local variable=inside
- print "I am $variable"
- }
- print "I am $variable"
- () {
- local variable="inside again"
- print "I am $variable"
- }
- print "I am $variable"
-0:Anonymous function scope
->I am outside
->I am inside
->I am outside
->I am inside again
->I am outside
-
- integer i
- for (( i = 0; i < 10; i++ )); do function {
- case $i in
- ([13579])
- print $i is odd
- ;|
- ([2468])
- print $i is even
- ;|
- ([2357])
- print $i is prime
- ;;
- esac
- }; done
-0:Anonymous function with patterns in loop
->1 is odd
->2 is even
->2 is prime
->3 is odd
->3 is prime
->4 is even
->5 is odd
->5 is prime
->6 is even
->7 is odd
->7 is prime
->8 is even
->9 is odd
-
- echo stuff in file >file.in
- function {
- sed 's/stuff/rubbish/'
- } file.out
- cat file.out
-0:Anonymous function redirection
->rubbish in file
-
- variable="Do be do"
- print $variable
- function {
- print $variable
- local variable="Da de da"
- print $variable
- function {
- print $variable
- local variable="Dum da dum"
- print $variable
- }
- print $variable
- }
- print $variable
-0:Nested anonymous functions
->Do be do
->Do be do
->Da de da
->Da de da
->Dum da dum
->Da de da
->Do be do
-
- () (cat $1 $2) <(print process expanded) =(print expanded to file)
-0:Process substitution with anonymous functions
->process expanded
->expanded to file
-
- () { print This has arguments $*; } of all sorts; print After the function
- function { print More stuff $*; } and why not; print Yet more
-0:Anonymous function with arguments
->This has arguments of all sorts
->After the function
->More stuff and why not
->Yet more
-
- fn() {
- (){ print Anonymous function 1 $*; } with args
- function { print Anonymous function 2 $*; } with more args
- print Following bit
- }
- functions fn
-0:Text representation of anonymous function with arguments
->fn () {
-> () {
-> print Anonymous function 1 $*
-> } with args
-> () {
-> print Anonymous function 2 $*
-> } with more args
-> print Following bit
->}
-
- touch yes no
- () { echo $1 } (y|z)*
- (echo here)
- () { echo $* } some (y|z)*
- () { echo empty };(echo here)
-0:Anonymous function arguments and command arguments
->yes
->here
->some yes
->empty
->here
-
- if true; then f() { echo foo1; } else f() { echo bar1; } fi; f
- if false; then f() { echo foo2; } else f() { echo bar2; } fi; f
-0:Compatibility with other shells when not anonymous functions
->foo1
->bar2
-
- (
- setopt ignorebraces
- fpath=(.)
- print "{ echo OK }\n[[ -o ignorebraces ]] || print 'ignorebraces is off'" \
- >emufunctest
- (autoload -z emufunctest; emufunctest) 2>&1
- emulate zsh -c 'autoload -Uz emufunctest'
- emufunctest
- [[ -o ignorebraces ]] && print 'ignorebraces is still on here'
- )
-0:sticky emulation applies to autoloads and autoloaded function execution
->emufunctest:3: parse error near `\n'
->OK
->ignorebraces is off
->ignorebraces is still on here
-#` (matching error message for editors parsing the file)
-
-# lsfoo should not be expanded as an anonymous function argument
- alias lsfoo='This is not ls.'
- () (echo anon func; echo "$@") lsfoo
-0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway
->anon func
->lsfoo
-
- print foo | () cat
-0:Simple anonymous function should not simplify enclosing pipeline
->foo
-
- alias fooalias=barexpansion
- funcwithalias() { echo $(fooalias); }
- functions funcwithalias
- barexpansion() { print This is the correct output.; }
- funcwithalias
-0:Alias expanded in command substitution does not appear expanded in text
->funcwithalias () {
-> echo $(fooalias)
->}
->This is the correct output.
-
- unfunction command_not_found_handler # amusing but unhelpful
- alias first='firstfn1 firstfn2' second='secondfn1 secondfn2'
- function first second { print This is function $0; }
- first
- second
- firstfn1
- secondfn1
-127:No alias expansion after "function" keyword
->This is function first
->This is function second
-?(eval):6: command not found: firstfn1
-?(eval):7: command not found: secondfn1
-
- (
- fpath=(.)
- print "print oops was successfully autoloaded" >oops
- oops() { eval autoload -X }
- oops
- which -x2 oops
- )
-0:autoload containing eval
->oops was successfully autoloaded
->oops () {
-> print oops was successfully autoloaded
->}
-
- (
- fpath=(.)
- printf '%s\n' 'oops(){}' 'ninjas-earring(){}' 'oops "$@"' >oops
- autoload oops
- oops
- whence -v oops
- )
-0q:whence -v of zsh-style autoload
->oops is a shell function from $mydir/oops
-
- (
- fpath=(.)
- mkdir extra
- print 'print "I have been loaded by explicit path."' >extra/spec
- autoload -Uz $PWD/extra/spec
- spec
- )
-0:autoload with explicit path
->I have been loaded by explicit path.
-
- (
- fpath=(.)
- print 'print "I have been loaded by default path."' >def
- autoload -Uz $PWD/extra/def
- def
- )
-1:autoload with explicit path with function in normal path, no -d
-?(eval):5: def: function definition file not found
-
- (
- fpath=(.)
- autoload -dUz $PWD/extra/def
- def
- )
-0:autoload with explicit path with function in normal path, with -d
->I have been loaded by default path.
-
- (
- cd extra
- fpath=(.)
- autoload -r spec
- cd ..
- spec
- )
-0:autoload -r
->I have been loaded by explicit path.
-
- (
- cd extra
- fpath=(.)
- autoload -r def
- cd ..
- def
- )
-0:autoload -r is permissive
->I have been loaded by default path.
-
- (
- cd extra
- fpath=(.)
- autoload -R def
- )
-1:autoload -R is not permissive
-?(eval):4: def: function definition file not found
-
- (
- spec() { autoload -XUz $PWD/extra; }
- spec
- )
-0:autoload -X with path
->I have been loaded by explicit path.
-
-# The line number 1 here and in the next test seems suspect,
-# but this example proves it's not down to the new features
-# being tested here.
- (
- fpath=(.)
- cod() { autoload -XUz; }
- cod
- )
-1:autoload -X with no path, failure
-?(eval):1: cod: function definition file not found
-
- (
- fpath=(.)
- def() { autoload -XUz $PWD/extra; }
- def
- )
-1:autoload -X with wrong path and no -d
-?(eval):1: def: function definition file not found
-
- (
- fpath=(.)
- def() { autoload -dXUz $PWD/extra; }
- def
- )
-0:autoload -dX with path
->I have been loaded by default path.
-
- (
- fpath=(.)
- print 'loadthisfunc() { autoload -X }' >loadthisfunc_sourceme
- print 'print Function was loaded correctly.' >loadthisfunc
- source $PWD/loadthisfunc_sourceme
- loadthisfunc
- )
-0: autoload -X interaction with absolute filename used for source location
->Function was loaded correctly.
-
- (
- fpath=()
- mkdir extra2
- for f in fun2a fun2b; do
- print "print $f" >extra2/$f
- done
- repeat 3; do
- autoload $PWD/extra2/fun2{a,b} $PWD/extra/spec
- fun2a
- fun2b
- spec
- unfunction fun2a fun2b spec
- autoload $PWD/extra2/fun2{a,b} $PWD/extra/spec
- spec
- fun2b
- fun2a
- unfunction fun2a fun2b spec
- done
- )
-0: Exercise the directory name cache for autoloads
->fun2a
->fun2b
->I have been loaded by explicit path.
->I have been loaded by explicit path.
->fun2b
->fun2a
->fun2a
->fun2b
->I have been loaded by explicit path.
->I have been loaded by explicit path.
->fun2b
->fun2a
->fun2a
->fun2b
->I have been loaded by explicit path.
->I have been loaded by explicit path.
->fun2b
->fun2a
-
- not_trashed() { print This function was not trashed; }
- autoload -Uz /foo/bar/not_trashed
- not_trashed
-0:autoload with absolute path doesn't trash loaded function
->This function was not trashed
-
- # keep spec from getting loaded in parent shell for simplicity
- (
- if whence spec; then print spec already loaded >&2; exit 1; fi
- autoload -Uz $PWD/spec
- autoload -Uz $PWD/extra/spec
- spec
- )
-0:autoload with absolute path can be overridden if not yet loaded
->I have been loaded by explicit path.
-
- (
- if whence spec; then print spec already loaded >&2; exit 1; fi
- autoload -Uz $PWD/extra/spec
- autoload spec
- spec
- )
-0:autoload with absolute path not cancelled by bare autoload
->I have been loaded by explicit path.
-
-%clean
-
- rm -f file.in file.out
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C05debug.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C05debug.ztst
deleted file mode 100644
index 9a8df1da..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/C05debug.ztst
+++ /dev/null
@@ -1,159 +0,0 @@
-%prep
-
- setopt localtraps
-
-%test
-
- unsetopt DEBUG_BEFORE_CMD
- debug-trap-bug1() {
- setopt localtraps
- print "print bug file here" >bug-file
- print "print this is line one
- print this is line two
- print this is line three
- print and this is line fifty-nine." >bug-file2
- function debug_trap_handler {
- print $functrace[1]
- do_bug
- }
- function do_bug {
- . ./bug-file
- }
- trap 'echo EXIT hit' EXIT
- trap 'debug_trap_handler' DEBUG
- . ./bug-file2
- }
- debug-trap-bug1
-0: Relationship between traps and sources
->debug-trap-bug1:15
->bug file here
->this is line one
->./bug-file2:1
->bug file here
->this is line two
->./bug-file2:2
->bug file here
->this is line three
->./bug-file2:3
->bug file here
->and this is line fifty-nine.
->./bug-file2:4
->bug file here
->debug-trap-bug1:16
->bug file here
->EXIT hit
-
- cat >zsh-trapreturn-bug2 <<-'HERE'
- cmd='./fdasfsdafd'
- [[ -x $cmd ]] && rm $cmd
- set -o DEBUG_BEFORE_CMD
- trap '[[ $? -ne 0 ]] && exit 0' DEBUG
- $cmd # invalid command
- # Failure
- exit 10
- HERE
- $ZTST_testdir/../Src/zsh -f ./zsh-trapreturn-bug2 2>erroutput.dif
- mystat=$?
- (
- setopt extendedglob
- print ${"$(< erroutput.dif)"%%:[^:]#: ./fdasfsdafd}
- )
- (( mystat == 0 ))
-0: trapreturn handling bug is properly fixed
->./zsh-trapreturn-bug2:5
-
- fn() {
- setopt localtraps localoptions debugbeforecmd
- trap '(( LINENO == 4 )) && setopt errexit' DEBUG
- print $LINENO three
- print $LINENO four
- print $LINENO five
- [[ -o errexit ]] && print "Hey, ERREXIT is set!"
- }
- fn
-1:Skip line from DEBUG trap
->3 three
->5 five
-
- # Assignments are a special case, since they use a simpler
- # wordcode type, so we need to test skipping them separately.
- fn() {
- setopt localtraps localoptions debugbeforecmd
- trap '(( LINENO == 4 )) && setopt errexit' DEBUG
- x=three
- x=four
- print $LINENO $x
- [[ -o errexit ]] && print "Hey, ERREXIT is set!"
- }
- fn
-1:Skip assignment from DEBUG trap
->5 three
-
- fn() {
- setopt localtraps localoptions debugbeforecmd
- trap 'print $LINENO' DEBUG
- [[ a = a ]] && print a is ok
- }
- fn
-0:line numbers of complex sublists
->3
->a is ok
-
- fn() {
- setopt localtraps localoptions debugbeforecmd
- trap 'print $LINENO' DEBUG
- print before
- x=' first
- second
- third'
- print $x
- }
- fn
-0:line numbers of multiline assignments
->3
->before
->4
->7
-> first
-> second
-> third
-
- fn() {
- emulate -L zsh; setopt debugbeforecmd
- trap 'print "$LINENO: '\''$ZSH_DEBUG_CMD'\''"' DEBUG
- print foo &&
- print bar ||
- print rod
- x=y
- print $x
- fn2() { echo wow }
- fn2
- }
- fn
-0:ZSH_DEBUG_CMD in debug traps
->3: 'print foo && print bar || print rod'
->foo
->bar
->6: 'x=y '
->7: 'print $x'
->y
->8: 'fn2 () {
-> echo wow
->}'
->9: 'fn2'
->0: 'echo wow'
->wow
-
- foo() {
- emulate -L zsh; setopt debugbeforecmd
- trap '[[ $ZSH_DEBUG_CMD == *bar* ]] && return 2' DEBUG
- echo foo
- echo bar
- }
- foo
-2:Status of forced return from eval-style DEBUG trap
->foo
-
-%clean
-
- rm -f bug-file bug-file2 erroutput.dif zsh-trapreturn-bug2
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D01prompt.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D01prompt.ztst
deleted file mode 100644
index 607ffb69..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D01prompt.ztst
+++ /dev/null
@@ -1,203 +0,0 @@
-%prep
-
- mkdir prompt.tmp
- cd prompt.tmp
- mydir=$PWD
- SHLVL=2
- setopt extendedglob
-
-%test
-
- hash -d mydir=$mydir
- print -P ' %%%): %)
- %%~: %~
- %%d: %d
- %%1/: %1/
- %%h: %h
- %%L: %L
- %%M: %M
- %%m: %m
- %%n: %n
- %%N: %N
- %%i: %i
- a%%{...%%}b: a%{%}b
- '
-0q:Basic prompt escapes as shown.
-> %): )
-> %~: ~mydir
-> %d: $mydir
-> %1/: ${mydir:t}
-> %h: 0
-> %L: 2
-> %M: $HOST
-> %m: ${HOST%%.*}
-> %n: $USERNAME
-> %N: (eval)
-> %i: 2
-> a%{...%}b: ab
->
-
- true
- print -P '%?'
- false
- print -P '%?'
-0:`%?' prompt escape
->0
->1
-
- PS4="%_> "
- setopt xtrace
- if true; then true; else false; fi
- unsetopt xtrace
-0:`%_' prompt escape
-?if> true
-?then> true
-?> unsetopt xtrace
-
- diff =(print -P '%#') =(print -P '%(!.#.%%)')
-0:`%#' prompt escape and its equivalent
-
- psvar=(caesar adsum jam forte)
- print -P '%v' '%4v'
-0:`%v' prompt escape
->caesar forte
-
- true
- print -P '%(?.true.false)'
- false
- print -P '%(?.true.false)'
-0:ternary prompt escapes
->true
->false
-
- print -P 'start %10<......>truncated at 10%>> Not truncated%3> ...>Not shown'
-0:prompt truncation
->start ...d at 10 Not truncated ...
->start truncat... Not truncated ...
-
-# It's hard to check the time and date as they are moving targets.
-# We therefore just check that various forms of the date are consistent.
-# In fact, if you perform this at midnight it can still fail.
-# We could test for that, but we can't be bothered.
-# I hope LC_ALL is enough to make the format what's expected.
-
- LC_ALL=C
- date1=$(print -P %w)
- date2=$(print -P %W)
- date3=$(print -P %D)
- if [[ $date1 != [A-Z][a-z][a-z][[:blank:]]##[0-9]## ]]; then
- print "Date \`$date1' is not in the form \`Day DD' (e.g. \`Mon 1'"
- fi
- if [[ $date2 != [0-9][0-9]/[0-9][0-9]/[0-9][0-9] ]]; then
- print "Date \`$date2' is not in the form \`DD/MM/YYYY'"
- fi
- if [[ $date3 != [0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
- print "Date \`$date3' is not in the form \`YY-MM-DD'"
- fi
- if (( $date1[5,-1] != $date2[4,5] )) || (( $date2[4,5] != $date3[7,8] ))
- then
- print "Days of month do not agree in $date1, $date2, $date3"
- fi
- if (( $date2[1,2] != $date3[4,5] )); then
- print "Months do not agree in $date2, $date3"
- fi
- if (( $date2[7,8] != $date3[1,2] )); then
- print "Years do not agree in $date2, $date3"
- fi
-0:Dates produced by prompt escapes
-
- mkdir foo
- mkdir foo/bar
- mkdir foo/bar/rod
- (zsh_directory_name() {
- emulate -L zsh
- setopt extendedglob
- local -a match mbegin mend
- if [[ $1 = d ]]; then
- if [[ $2 = (#b)(*bar)/rod ]]; then
- reply=(barmy ${#match[1]})
- else
- return 1
- fi
- else
- if [[ $2 = barmy ]]; then
- reply=($mydir/foo/bar)
- else
- return 1
- fi
- fi
- }
- # success
- print ~[barmy]/anything
- cd foo/bar/rod
- print -P %~
- # failure
- setopt nonomatch
- print ~[scuzzy]/rubbish
- cd ../..
- print -P %~
- # catastrophic failure
- unsetopt nonomatch
- print ~[scuzzy]/rubbish
- )
-1q:Dynamic named directories
->$mydir/foo/bar/anything
->~[barmy]/rod
->~[scuzzy]/rubbish
->~mydir/foo
-?(eval):33: no directory expansion: ~[scuzzy]
-
- (
- zsh_directory_name() {
- emulate -L zsh
- setopt extendedglob
- local -a match mbegin mend
- if [[ $1 = n ]]; then
- if [[ $2 = *:l ]]; then
- reply=(${2%%:l}/very_long_directory_name)
- return 0
- else
- return 1
- fi
- else
- if [[ $2 = (#b)(*)/very_long_directory_name ]]; then
- reply=(${match[1]}:l ${#2})
- return 0
- else
- return 1
- fi
- fi
- }
- parent=$PWD
- dir=$parent/very_long_directory_name
- mkdir $dir
- cd $dir
- fn() {
- PS4='+%N:%i> '
- setopt localoptions xtrace
- # The following is the key to the test.
- # It invokes zsh_directory_name which does PS4 output stuff
- # while we're doing prompt handling for the parameter
- # substitution. This checks recursion works OK.
- local d=${(%):-%~}
- print ${d//$parent/\}
- }
- fn 2>stderr
- # post process error to remove variable contents
- while read line; do
- # tricky: reply is set to include directory length which is variable
- [[ $line = *reply* ]] && continue
- print ${line//$parent/\}
- done &2
- )
-0:Recursive use of prompts
->~[:l]
-?+zsh_directory_name:1> emulate -L zsh
-?+zsh_directory_name:2> setopt extendedglob
-?+zsh_directory_name:3> local -a match mbegin mend
-?+zsh_directory_name:4> [[ d = n ]]
-?+zsh_directory_name:12> [[ /very_long_directory_name = (#b)(*)/very_long_directory_name ]]
-?+zsh_directory_name:14> return 0
-?+fn:7> local d='~[:l]'
-?+fn:8> print '~[:l]'
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D02glob.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D02glob.ztst
deleted file mode 100644
index 1385d57d..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D02glob.ztst
+++ /dev/null
@@ -1,688 +0,0 @@
-# Tests for globbing
-
-%prep
- mkdir glob.tmp
- mkdir glob.tmp/dir{1,2,3,4}
- mkdir glob.tmp/dir3/subdir
- : >glob.tmp/{,{dir1,dir2}/}{a,b,c}
-
- globtest () {
- $ZTST_testdir/../Src/zsh -f $ZTST_srcdir/../Misc/$1
- }
-
- regress_absolute_path_and_core_dump() {
- local absolute_dir=$(cd glob.tmp && pwd -P)
- [[ -n $absolute_dir ]] || return 1
- setopt localoptions extendedglob nullglob
- print $absolute_dir/**/*~/*
- setopt nonullglob nomatch
- print glob.tmp/**/*~(.)#
- }
-
-%test
-
- globtest globtests
-0:zsh globbing
->0: [[ foo~ = foo~ ]]
->0: [[ foo~ = (foo~) ]]
->0: [[ foo~ = (foo~|) ]]
->0: [[ foo.c = *.c~boo* ]]
->1: [[ foo.c = *.c~boo*~foo* ]]
->0: [[ fofo = (fo#)# ]]
->0: [[ ffo = (fo#)# ]]
->0: [[ foooofo = (fo#)# ]]
->0: [[ foooofof = (fo#)# ]]
->0: [[ fooofoofofooo = (fo#)# ]]
->1: [[ foooofof = (fo##)# ]]
->1: [[ xfoooofof = (fo#)# ]]
->1: [[ foooofofx = (fo#)# ]]
->0: [[ ofxoofxo = ((ofo#x)#o)# ]]
->1: [[ ofooofoofofooo = (fo#)# ]]
->0: [[ foooxfooxfoxfooox = (fo#x)# ]]
->1: [[ foooxfooxofoxfooox = (fo#x)# ]]
->0: [[ foooxfooxfxfooox = (fo#x)# ]]
->0: [[ ofxoofxo = ((ofo#x)#o)# ]]
->0: [[ ofoooxoofxo = ((ofo#x)#o)# ]]
->0: [[ ofoooxoofxoofoooxoofxo = ((ofo#x)#o)# ]]
->0: [[ ofoooxoofxoofoooxoofxoo = ((ofo#x)#o)# ]]
->1: [[ ofoooxoofxoofoooxoofxofo = ((ofo#x)#o)# ]]
->0: [[ ofoooxoofxoofoooxoofxooofxofxo = ((ofo#x)#o)# ]]
->0: [[ aac = ((a))#a(c) ]]
->0: [[ ac = ((a))#a(c) ]]
->1: [[ c = ((a))#a(c) ]]
->0: [[ aaac = ((a))#a(c) ]]
->1: [[ baaac = ((a))#a(c) ]]
->0: [[ abcd = ?(a|b)c#d ]]
->0: [[ abcd = (ab|ab#)c#d ]]
->0: [[ acd = (ab|ab#)c#d ]]
->0: [[ abbcd = (ab|ab#)c#d ]]
->0: [[ effgz = (bc##d|ef#g?|(h|)i(j|k)) ]]
->0: [[ efgz = (bc##d|ef#g?|(h|)i(j|k)) ]]
->0: [[ egz = (bc##d|ef#g?|(h|)i(j|k)) ]]
->0: [[ egzefffgzbcdij = (bc##d|ef#g?|(h|)i(j|k))# ]]
->1: [[ egz = (bc##d|ef##g?|(h|)i(j|k)) ]]
->0: [[ ofoofo = (ofo##)# ]]
->0: [[ oxfoxoxfox = (oxf(ox)##)# ]]
->1: [[ oxfoxfox = (oxf(ox)##)# ]]
->0: [[ ofoofo = (ofo##|f)# ]]
->0: [[ foofoofo = (foo|f|fo)(f|ofo##)# ]]
->0: [[ oofooofo = (of|oofo##)# ]]
->0: [[ fffooofoooooffoofffooofff = (f#o#)# ]]
->1: [[ fffooofoooooffoofffooofffx = (f#o#)# ]]
->0: [[ fofoofoofofoo = (fo|foo)# ]]
->0: [[ foo = ((^x)) ]]
->0: [[ foo = ((^x)*) ]]
->1: [[ foo = ((^foo)) ]]
->0: [[ foo = ((^foo)*) ]]
->0: [[ foobar = ((^foo)) ]]
->0: [[ foobar = ((^foo)*) ]]
->1: [[ foot = z*~*x ]]
->0: [[ zoot = z*~*x ]]
->1: [[ foox = z*~*x ]]
->1: [[ zoox = z*~*x ]]
->0: [[ moo.cow = (*~*.*).(*~*.*) ]]
->1: [[ mad.moo.cow = (*~*.*).(*~*.*) ]]
->0: [[ moo.cow = (^*.*).(^*.*) ]]
->1: [[ sane.moo.cow = (^*.*).(^*.*) ]]
->1: [[ mucca.pazza = mu(^c#)?.pa(^z#)? ]]
->1: [[ _foo~ = _(|*[^~]) ]]
->0: [[ fff = ((^f)) ]]
->0: [[ fff = ((^f)#) ]]
->0: [[ fff = ((^f)##) ]]
->0: [[ ooo = ((^f)) ]]
->0: [[ ooo = ((^f)#) ]]
->0: [[ ooo = ((^f)##) ]]
->0: [[ foo = ((^f)) ]]
->0: [[ foo = ((^f)#) ]]
->0: [[ foo = ((^f)##) ]]
->1: [[ f = ((^f)) ]]
->1: [[ f = ((^f)#) ]]
->1: [[ f = ((^f)##) ]]
->0: [[ foot = (^z*|*x) ]]
->1: [[ zoot = (^z*|*x) ]]
->0: [[ foox = (^z*|*x) ]]
->0: [[ zoox = (^z*|*x) ]]
->0: [[ foo = (^foo)# ]]
->1: [[ foob = (^foo)b* ]]
->0: [[ foobb = (^foo)b* ]]
->1: [[ foob = (*~foo)b* ]]
->0: [[ foobb = (*~foo)b* ]]
->1: [[ zsh = ^z* ]]
->0: [[ a%1X = [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] ]]
->1: [[ a%1 = [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] ]]
->0: [[ [: = [[:]# ]]
->0: [[ :] = []:]# ]]
->0: [[ :] = [:]]# ]]
->0: [[ [ = [[] ]]
->0: [[ ] = []] ]]
->0: [[ [] = [^]]] ]]
->0: [[ fooxx = (#i)FOOXX ]]
->1: [[ fooxx = (#l)FOOXX ]]
->0: [[ FOOXX = (#l)fooxx ]]
->1: [[ fooxx = (#i)FOO(#I)X(#i)X ]]
->0: [[ fooXx = (#i)FOO(#I)X(#i)X ]]
->0: [[ fooxx = ((#i)FOOX)x ]]
->1: [[ fooxx = ((#i)FOOX)X ]]
->1: [[ BAR = (bar|(#i)foo) ]]
->0: [[ FOO = (bar|(#i)foo) ]]
->0: [[ Modules = (#i)*m* ]]
->0: [[ fooGRUD = (#i)(bar|(#I)foo|(#i)rod)grud ]]
->1: [[ FOOGRUD = (#i)(bar|(#I)foo|(#i)rod)grud ]]
->0: [[ readme = (#i)readme~README|readme ]]
->0: [[ readme = (#i)readme~README|readme~README ]]
->0: [[ 633 = <1-1000>33 ]]
->0: [[ 633 = <-1000>33 ]]
->0: [[ 633 = <1->33 ]]
->0: [[ 633 = <->33 ]]
->0: [[ 12345678901234567890123456789012345678901234567890123456789012345678901234567890foo = <42->foo ]]
->0: [[ READ.ME = (#ia1)readme ]]
->1: [[ READ..ME = (#ia1)readme ]]
->0: [[ README = (#ia1)readm ]]
->0: [[ READM = (#ia1)readme ]]
->0: [[ README = (#ia1)eadme ]]
->0: [[ EADME = (#ia1)readme ]]
->0: [[ READEM = (#ia1)readme ]]
->1: [[ ADME = (#ia1)readme ]]
->1: [[ README = (#ia1)read ]]
->0: [[ bob = (#a1)[b][b] ]]
->1: [[ bob = (#a1)[b][b]a ]]
->0: [[ bob = (#a1)[b]o[b]a ]]
->1: [[ bob = (#a1)[c]o[b] ]]
->0: [[ abcd = (#a2)XbcX ]]
->0: [[ abcd = (#a2)ad ]]
->0: [[ ad = (#a2)abcd ]]
->0: [[ abcd = (#a2)bd ]]
->0: [[ bd = (#a2)abcd ]]
->0: [[ badc = (#a2)abcd ]]
->0: [[ adbc = (#a2)abcd ]]
->1: [[ dcba = (#a2)abcd ]]
->0: [[ dcba = (#a3)abcd ]]
->0: [[ aabaXaaabY = (#a1)(a#b)#Y ]]
->0: [[ aabaXaaabY = (#a1)(a#b)(a#b)Y ]]
->0: [[ aaXaaaaabY = (#a1)(a#b)(a#b)Y ]]
->0: [[ aaaXaaabY = (#a1)(a##b)##Y ]]
->0: [[ aaaXbaabY = (#a1)(a##b)##Y ]]
->1: [[ read.me = (#ia1)README~READ.ME ]]
->0: [[ read.me = (#ia1)README~READ_ME ]]
->1: [[ read.me = (#ia1)README~(#a1)READ_ME ]]
->0: [[ test = *((#s)|/)test((#e)|/)* ]]
->0: [[ test/path = *((#s)|/)test((#e)|/)* ]]
->0: [[ path/test = *((#s)|/)test((#e)|/)* ]]
->0: [[ path/test/ohyes = *((#s)|/)test((#e)|/)* ]]
->1: [[ atest = *((#s)|/)test((#e)|/)* ]]
->1: [[ testy = *((#s)|/)test((#e)|/)* ]]
->1: [[ testy/path = *((#s)|/)test((#e)|/)* ]]
->1: [[ path/atest = *((#s)|/)test((#e)|/)* ]]
->1: [[ atest/path = *((#s)|/)test((#e)|/)* ]]
->1: [[ path/testy = *((#s)|/)test((#e)|/)* ]]
->1: [[ path/testy/ohyes = *((#s)|/)test((#e)|/)* ]]
->1: [[ path/atest/ohyes = *((#s)|/)test((#e)|/)* ]]
->0: [[ XabcdabcY = X(ab|c|d)(#c5)Y ]]
->0: [[ XabcdabcY = X(ab|c|d)(#c1,5)Y ]]
->0: [[ XabcdabcY = X(ab|c|d)(#c5,8)Y ]]
->0: [[ XabcdabcY = X(ab|c|d)(#c4,)Y ]]
->1: [[ XabcdabcY = X(ab|c|d)(#c6,)Y ]]
->1: [[ XabcdabcY = X(ab|c|d)(#c1,4)Y ]]
->0: [[ ZX = Z(|)(#c1)X ]]
->0: [[ froofroo = (fro(#c2))(#c2) ]]
->1: [[ froofroofroo = (fro(#c2))(#c2) ]]
->1: [[ froofro = (fro(#c2))(#c2) ]]
->0: [[ ax = ?(#c1,2)x ]]
->0: [[ ax = ?(#c1,)x ]]
->0: [[ ax = ?(#c0,1)x ]]
->1: [[ ax = ?(#c0,0)x ]]
->1: [[ ax = ?(#c2,)x ]]
->0: [[ aa = a(#c1,2)a ]]
->0: [[ aa = a(#c1,)a ]]
->0: [[ aa = a(#c0,1)a ]]
->1: [[ aa = a(#c0,0)a ]]
->1: [[ aa = a(#c2,)a ]]
->0: [[ test.zsh = *.?(#c1)sh ]]
->0: [[ test.bash = *.?(#c2)sh ]]
->0: [[ test.bash = *.?(#c1,2)sh ]]
->0: [[ test.bash = *.?(#c1,)sh ]]
->0: [[ test.zsh = *.?(#c1,)sh ]]
->0 tests failed.
-
- globtest globtests.ksh
-0:ksh compatibility
->0: [[ fofo = *(f*(o)) ]]
->0: [[ ffo = *(f*(o)) ]]
->0: [[ foooofo = *(f*(o)) ]]
->0: [[ foooofof = *(f*(o)) ]]
->0: [[ fooofoofofooo = *(f*(o)) ]]
->1: [[ foooofof = *(f+(o)) ]]
->1: [[ xfoooofof = *(f*(o)) ]]
->1: [[ foooofofx = *(f*(o)) ]]
->0: [[ ofxoofxo = *(*(of*(o)x)o) ]]
->1: [[ ofooofoofofooo = *(f*(o)) ]]
->0: [[ foooxfooxfoxfooox = *(f*(o)x) ]]
->1: [[ foooxfooxofoxfooox = *(f*(o)x) ]]
->0: [[ foooxfooxfxfooox = *(f*(o)x) ]]
->0: [[ ofxoofxo = *(*(of*(o)x)o) ]]
->0: [[ ofoooxoofxo = *(*(of*(o)x)o) ]]
->0: [[ ofoooxoofxoofoooxoofxo = *(*(of*(o)x)o) ]]
->0: [[ ofoooxoofxoofoooxoofxoo = *(*(of*(o)x)o) ]]
->1: [[ ofoooxoofxoofoooxoofxofo = *(*(of*(o)x)o) ]]
->0: [[ ofoooxoofxoofoooxoofxooofxofxo = *(*(of*(o)x)o) ]]
->0: [[ aac = *(@(a))a@(c) ]]
->0: [[ ac = *(@(a))a@(c) ]]
->1: [[ c = *(@(a))a@(c) ]]
->0: [[ aaac = *(@(a))a@(c) ]]
->1: [[ baaac = *(@(a))a@(c) ]]
->0: [[ abcd = ?@(a|b)*@(c)d ]]
->0: [[ abcd = @(ab|a*@(b))*(c)d ]]
->0: [[ acd = @(ab|a*(b))*(c)d ]]
->0: [[ abbcd = @(ab|a*(b))*(c)d ]]
->0: [[ effgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
->0: [[ efgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
->0: [[ egz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
->0: [[ egzefffgzbcdij = *(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]]
->1: [[ egz = @(b+(c)d|e+(f)g?|?(h)i@(j|k)) ]]
->0: [[ ofoofo = *(of+(o)) ]]
->0: [[ oxfoxoxfox = *(oxf+(ox)) ]]
->1: [[ oxfoxfox = *(oxf+(ox)) ]]
->0: [[ ofoofo = *(of+(o)|f) ]]
->0: [[ foofoofo = @(foo|f|fo)*(f|of+(o)) ]]
->0: [[ oofooofo = *(of|oof+(o)) ]]
->0: [[ fffooofoooooffoofffooofff = *(*(f)*(o)) ]]
->1: [[ fffooofoooooffoofffooofffx = *(*(f)*(o)) ]]
->0: [[ fofoofoofofoo = *(fo|foo) ]]
->0: [[ foo = !(x) ]]
->0: [[ foo = !(x)* ]]
->1: [[ foo = !(foo) ]]
->0: [[ foo = !(foo)* ]]
->0: [[ foobar = !(foo) ]]
->0: [[ foobar = !(foo)* ]]
->0: [[ moo.cow = !(*.*).!(*.*) ]]
->1: [[ mad.moo.cow = !(*.*).!(*.*) ]]
->1: [[ mucca.pazza = mu!(*(c))?.pa!(*(z))? ]]
->1: [[ _foo~ = _?(*[^~]) ]]
->0: [[ fff = !(f) ]]
->0: [[ fff = *(!(f)) ]]
->0: [[ fff = +(!(f)) ]]
->0: [[ ooo = !(f) ]]
->0: [[ ooo = *(!(f)) ]]
->0: [[ ooo = +(!(f)) ]]
->0: [[ foo = !(f) ]]
->0: [[ foo = *(!(f)) ]]
->0: [[ foo = +(!(f)) ]]
->1: [[ f = !(f) ]]
->1: [[ f = *(!(f)) ]]
->1: [[ f = +(!(f)) ]]
->0: [[ foot = @(!(z*)|*x) ]]
->1: [[ zoot = @(!(z*)|*x) ]]
->0: [[ foox = @(!(z*)|*x) ]]
->0: [[ zoox = @(!(z*)|*x) ]]
->0: [[ foo = *(!(foo)) ]]
->1: [[ foob = !(foo)b* ]]
->0: [[ foobb = !(foo)b* ]]
->0: [[ fooxx = (#i)FOOXX ]]
->1: [[ fooxx = (#l)FOOXX ]]
->0: [[ FOOXX = (#l)fooxx ]]
->1: [[ fooxx = (#i)FOO@(#I)X@(#i)X ]]
->0: [[ fooXx = (#i)FOO@(#I)X@(#i)X ]]
->0: [[ fooxx = @((#i)FOOX)x ]]
->1: [[ fooxx = @((#i)FOOX)X ]]
->1: [[ BAR = @(bar|(#i)foo) ]]
->0: [[ FOO = @(bar|(#i)foo) ]]
->0: [[ Modules = (#i)*m* ]]
->0 tests failed.
-
- (unsetopt multibyte
- [[ bjrn = *[]* ]])
-0:single byte match with top bit set
-
- ( regress_absolute_path_and_core_dump )
-0:exclusions regression test
->
->glob.tmp/a glob.tmp/b glob.tmp/c glob.tmp/dir1 glob.tmp/dir1/a glob.tmp/dir1/b glob.tmp/dir1/c glob.tmp/dir2 glob.tmp/dir2/a glob.tmp/dir2/b glob.tmp/dir2/c glob.tmp/dir3 glob.tmp/dir3/subdir glob.tmp/dir4
-
- print glob.tmp/*(/)
-0:Just directories
->glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir3 glob.tmp/dir4
-
- print glob.tmp/*(.)
-0:Just files
->glob.tmp/a glob.tmp/b glob.tmp/c
-
- print glob.tmp/*(.e^'reply=( glob.tmp/*/${REPLY:t} )'^:t)
-0:Globbing used recursively (inside e glob qualifier)
->a a b b c c
-
- print glob.tmp/*/*(e:'reply=( glob.tmp/**/*([1]) )'::t)
-0:Recursive globbing used recursively (inside e glob qualifier)
->a a a a a a a
-
- print glob.tmp/**/(:h)
-0:Head modifier
->. glob.tmp glob.tmp glob.tmp glob.tmp glob.tmp/dir3
-
- print glob.tmp(:r)
-0:Remove extension modifier
->glob
-
- print glob.tmp/*(:s/./_/)
-0:Substitute modifier
->glob_tmp/a glob_tmp/b glob_tmp/c glob_tmp/dir1 glob_tmp/dir2 glob_tmp/dir3 glob_tmp/dir4
-
- print glob.tmp/*(F)
-0:Just full dirs
->glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir3
-
- print glob.tmp/*(^F)
-0:Omit full dirs
->glob.tmp/a glob.tmp/b glob.tmp/c glob.tmp/dir4
-
- print glob.tmp/*(/^F)
-0:Just empty dirs
->glob.tmp/dir4
-
- setopt extendedglob
- print glob.tmp/**/*~*/dir3(/*|(#e))(/)
-0:Exclusions with complicated path specifications
->glob.tmp/dir1 glob.tmp/dir2 glob.tmp/dir4
-
- print -l -- glob.tmp/*(P:-f:)
-0:Prepending words to each argument
->-f
->glob.tmp/a
->-f
->glob.tmp/b
->-f
->glob.tmp/c
->-f
->glob.tmp/dir1
->-f
->glob.tmp/dir2
->-f
->glob.tmp/dir3
->-f
->glob.tmp/dir4
-
- print -l -- glob.tmp/*(P:one word:P:another word:)
-0:Prepending two words to each argument
->one word
->another word
->glob.tmp/a
->one word
->another word
->glob.tmp/b
->one word
->another word
->glob.tmp/c
->one word
->another word
->glob.tmp/dir1
->one word
->another word
->glob.tmp/dir2
->one word
->another word
->glob.tmp/dir3
->one word
->another word
->glob.tmp/dir4
-
- [[ "" = "" ]] && echo OK
-0:Empty strings
->OK
-
- foo="this string has a : colon in it"
- print ${foo%% #:*}
-0:Must-match arguments in complex patterns
->this string has a
-
- mkdir glob.tmp/ra=1.0_et=3.5
- touch glob.tmp/ra=1.0_et=3.5/foo
- print glob.tmp/ra=1.0_et=3.5/???
-0:Bug with intermediate paths with plain strings but tokenized characters
->glob.tmp/ra=1.0_et=3.5/foo
-
- doesmatch() {
- setopt localoptions extendedglob
- print -n $1 $2\
- if [[ $1 = $~2 ]]; then print yes; else print no; fi;
- }
- doesmatch MY_IDENTIFIER '[[:IDENT:]]##'
- doesmatch YOUR:IDENTIFIER '[[:IDENT:]]##'
- IFS=$'\n' doesmatch $'\n' '[[:IFS:]]'
- IFS=' ' doesmatch $'\n' '[[:IFS:]]'
- IFS=':' doesmatch : '[[:IFSSPACE:]]'
- IFS=' ' doesmatch ' ' '[[:IFSSPACE:]]'
- WORDCHARS="" doesmatch / '[[:WORD:]]'
- WORDCHARS="/" doesmatch / '[[:WORD:]]'
-0:Named character sets handled internally
->MY_IDENTIFIER [[:IDENT:]]## yes
->YOUR:IDENTIFIER [[:IDENT:]]## no
->
-> [[:IFS:]] yes
->
-> [[:IFS:]] no
->: [[:IFSSPACE:]] no
-> [[:IFSSPACE:]] yes
->/ [[:WORD:]] no
->/ [[:WORD:]] yes
-
- [[ foo = (#c0)foo ]]
-2:Misplaced (#c...) flag
-?(eval):1: bad pattern: (#c0)foo
-
- mkdir glob.tmp/dir5
- touch glob.tmp/dir5/N123
- print glob.tmp/dir5/N<->(N)
- rm -rf glob.tmp/dir5
-0:Numeric glob is not usurped by process substitution.
->glob.tmp/dir5/N123
-
- tpd() {
- [[ $1 = $~2 ]]
- print -r "$1, $2: $?"
- }
- test_pattern_disables() {
- emulate -L zsh
- tpd 'forthcoming' 'f*g'
- disable -p '*'
- tpd 'forthcoming' 'f*g'
- tpd 'f*g' 'f*g'
- tpd '[frog]' '[frog]'
- tpd '[frog]' '\[[f]rog\]'
- disable -p '['
- tpd '[frog]' '[frog]'
- tpd '[frog]' '\[[f]rog\]'
- setopt extendedglob
- tpd 'foo' '^bar'
- disable -p '^'
- tpd 'foo' '^bar'
- tpd '^bar' '^bar'
- tpd 'rumble' '(rumble|bluster)'
- tpd '(thunder)' '(thunder)'
- disable -p '('
- tpd 'rumble' '(rumble|bluster)'
- tpd '(thunder)' '(thunder)'
- setopt kshglob
- tpd 'scramble' '@(panic|frenzy|scramble)'
- tpd '@(scrimf)' '@(scrimf)'
- disable -p '@('
- tpd 'scramble' '@(panic|frenzy|scramble)'
- tpd '@(scrimf)' '@(scrimf)'
- disable -p
- }
- test_pattern_disables
- print Nothing should be disabled.
- disable -p
-0:disable -p
->forthcoming, f*g: 0
->forthcoming, f*g: 1
->f*g, f*g: 0
->[frog], [frog]: 1
->[frog], \[[f]rog\]: 0
->[frog], [frog]: 0
->[frog], \[[f]rog\]: 1
->foo, ^bar: 0
->foo, ^bar: 1
->^bar, ^bar: 0
->rumble, (rumble|bluster): 0
->(thunder), (thunder): 1
->rumble, (rumble|bluster): 1
->(thunder), (thunder): 0
->scramble, @(panic|frenzy|scramble): 0
->@(scrimf), @(scrimf): 1
->scramble, @(panic|frenzy|scramble): 1
->@(scrimf), @(scrimf): 0
->'(' '*' '[' '^' '@('
->Nothing should be disabled.
-
- (
- setopt nomatch
- x=( '' )
- print $^x(N)
- )
-0:No error with empty null glob with (N).
->
-
- (setopt kshglob
- test_array=(
- '+fours' '+*'
- '@titude' '@*'
- '!bang' '!*'
- # and check they work in the real kshglob cases too...
- '+bus+bus' '+(+bus|-car)'
- '@sinhats' '@(@sinhats|wrensinfens)'
- '!kerror' '!(!somethingelse)'
- # and these don't match, to be sure
- '+more' '+(+less)'
- '@all@all' '@(@all)'
- '!goesitall' '!(!goesitall)'
- )
- for str pat in $test_array; do
- eval "[[ $str = $pat ]]" && print "$str matches $pat"
- done
- true
- )
-0:kshglob option does not break +, @, ! without following open parenthesis
->+fours matches +*
->@titude matches @*
->!bang matches !*
->+bus+bus matches +(+bus|-car)
->@sinhats matches @(@sinhats|wrensinfens)
->!kerror matches !(!somethingelse)
-
- (
- setopt extendedglob
- cd glob.tmp
- [[ -n a*(#qN) ]] && print File beginning with a
- [[ -z z*(#qN) ]] && print No file beginning with z
- setopt nonomatch
- [[ -n z*(#q) ]] && print Normal string if nullglob not set
- )
-0:Force glob expansion in conditions using (#q)
->File beginning with a
->No file beginning with z
->Normal string if nullglob not set
-
- (){ print $#@ } glob.tmp/dir*(Y1)
- (){ print $#@ } glob.tmp/file*(NY1)
- (){ [[ "$*" == */dir?\ */dir? ]] && print Returns matching filenames } glob.tmp/dir*(Y2)
- (){ print "Limit is upper bound:" ${(o)@:t} } glob.tmp/dir*(Y5)
- (){ print "Negated:" $@:t } glob.tmp/dir*(Y1^Y)
- (){ print "Sorting:" $@:t } glob.tmp/dir*(Y4On)
- (){ [[ $#@ -eq 1 ]] && print Globs before last path component } glob.tmp/dir?/subdir(NY1)
- (){ [[ $1 == glob.tmp/a ]] } glob.tmp/**/a(Y1) && print Breadth first
- (){ [[ $#@ -eq 0 ]] && print Respects qualifiers } glob.tmp/dir*(NY1.)
- (print -- *(Y)) 2>/dev/null || print "Argument required"
-0:short-circuit modifier
->1
->0
->Returns matching filenames
->Limit is upper bound: dir1 dir2 dir3 dir4
->Negated: dir1 dir2 dir3 dir4
->Sorting: dir4 dir3 dir2 dir1
->Globs before last path component
->Breadth first
->Respects qualifiers
->Argument required
-
- [[ "ce fichier n'existe pas" = (#b)ce\ (f[^ ]#)\ *s(#q./) ]]
- print $match[1]
-0:(#q) is ignored completely in conditional pattern matching
->fichier
-
-# The following should not cause excessive slowdown.
- print glob.tmp/*.*
- print glob.tmp/**************************.*************************
-0:Optimisation to squeeze multiple *'s used as ordinary glob wildcards.
->glob.tmp/ra=1.0_et=3.5
->glob.tmp/ra=1.0_et=3.5
-
- [[ 1_2_ = (*_)(#c1) ]] && print 1 OK # because * matches 1_2
- [[ 1_2_ = (*_)(#c2) ]] && print 2 OK
- [[ 1_2_ = (*_)(#c3) ]] || print 3 OK
-0:Some more complicated backtracking with match counts.
->1 OK
->2 OK
->3 OK
-
- [[ foo = 'f'\o"o" ]]
-0:Stripping of quotes from patterns (1)
-
- [[ foo = 'f'('o'|'a')('o'|'b') ]]
-0:Stripping of quotes from patterns (2)
-
- [[ fob = 'f'('o'|'a')('o'|'b') ]]
-0:Stripping of quotes from patterns (3)
-
- [[ fab = 'f'('o'|'a')('o'|'b') ]]
-0:Stripping of quotes from patterns (4)
-
- [[ fib != 'f'('o'|'a')('o'|'b') ]]
-0:Stripping of quotes from patterns (4)
-
- [[ - != [a-z] ]]
-0:- is a special character in ranges
-
- [[ - = ['a-z'] ]]
-0:- is not a special character in ranges if quoted
-
- [[ b-1 = [a-z]-[0-9] ]]
-0:- untokenized following a bracketed subexpression
-
- [[ b-1 = []a-z]-[]0-9] ]]
-0:- "]" after "[" is normal range character and - still works
-
- headremove="bcdef"
- print ${headremove#[a-z]}
-0:active - works in pattern in parameter
->cdef
-
- headremove="bcdef"
- print ${headremove#['a-z']}
- headremove="-cdef"
- print ${headremove#['a-z']}
-0:quoted - works in pattern in parameter
->bcdef
->cdef
-
- [[ a != [^a] ]]
-0:^ active in character class if not quoted
-
- [[ a = ['^a'] ]]
-0:^ not active in character class if quoted
-
- [[ a != [!a] ]]
-0:! active in character class if not quoted
-
- [[ a = ['!a'] ]]
-0:! not active in character class if quoted
-
- # Actually, we don't need the quoting here,
- # c.f. the next test. This just makes it look
- # more standard.
- cset="^a-z"
- [[ "^" = ["$cset"] ]] || print Fail 1
- [[ "a" = ["$cset"] ]] || print Fail 2
- [[ "-" = ["$cset"] ]] || print Fail 3
- [[ "z" = ["$cset"] ]] || print Fail 4
- [[ "1" != ["$cset"] ]] || print Fail 5
- [[ "b" != ["$cset"] ]] || print Fail 6
-0:character set specified as quoted variable
-
- cset="^a-z"
- [[ "^" = [$~cset] ]] || print Fail 1
- [[ "a" != [$~cset] ]] || print Fail 2
- [[ "-" = [$~cset] ]] || print Fail 3
- [[ "z" != [$~cset] ]] || print Fail 4
- [[ "1" = [$~cset] ]] || print Fail 5
- [[ "b" != [$~cset] ]] || print Fail 6
-0:character set specified as active variable
-
- () { print -l -- $@:a } / /..{,/} /1 /nonexistent/..{,/} /deeper/nonexistent/..{,/}
-0:modifier ':a' doesn't require existence
->/
->/
->/
->/1
->/
->/
->/deeper
->/deeper
-
- () { set -- ${PWD}/$^@; print -l -- $@:A } glob.tmp/nonexistent/foo/bar/baz
-0:modifier ':A' doesn't require existence
-*>*/glob.tmp/nonexistent/foo/bar/baz
-
- ln -s dir3/subdir glob.tmp/link
- () {
- print ${1:A} | grep glob.tmp
- } glob.tmp/link/../../hello
- rm glob.tmp/link
-0:modifier ':A' resolves '..' components before symlinks
-# There should be no output
-
- ln -s dir3/subdir glob.tmp/link
- () {
- print ${1:P}
- } glob.tmp/link/../../hello/world
- rm glob.tmp/link
-0:modifier ':P' resolves symlinks before '..' components
-*>*glob.tmp/hello/world
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D03procsubst.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D03procsubst.ztst
deleted file mode 100644
index ca8d56ff..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D03procsubst.ztst
+++ /dev/null
@@ -1,151 +0,0 @@
-# Tests for process substitution: <(...), >(...) and =(...).
-
-%prep
- if grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h > /dev/null 2>&1 ||
- grep '#define HAVE_FIFOS' $ZTST_testdir/../config.h > /dev/null 2>&1; then
- mkdir procsubst.tmp
- cd procsubst.tmp
- print 'First\tSecond\tThird\tFourth' >FILE1
- print 'Erste\tZweite\tDritte\tVierte' >FILE2
- else
- ZTST_unimplemented="process substitution is not supported"
- true
- fi
-
- function copycat { cat "$@" }
-
-%test
- paste <(cut -f1 FILE1) <(cut -f3 FILE2)
-0:<(...) substitution
->First Dritte
-
-# slightly desperate hack to force >(...) to be synchronous
- { paste <(cut -f2 FILE1) <(cut -f4 FILE2) } > >(sed 's/e/E/g' >OUTFILE)
- cat OUTFILE
-0:>(...) substitution
->SEcond ViErtE
-
- diff =(cat FILE1) =(cat FILE2)
-1:=(...) substituion
->1c1
->< First Second Third Fourth
->---
->> Erste Zweite Dritte Vierte
-
- copycat <(print First) <(print Zweite)
-0:FDs remain open for external commands called from functions
->First
->Zweite
-
- catfield2() {
- local -a args
- args=(${(s.,.)1})
- print $args[1]
- cat $args[2]
- print $args[3]
- }
- catfield2 up,<(print $'\x64'own),sideways
-0:<(...) when embedded within an argument
->up
->down
->sideways
-
- outputfield2() {
- local -a args
- args=(${(s.,.)1})
- print $args[1]
- echo 'How sweet the moonlight sits upon the bank' >$args[2]
- print $args[3]
- }
- outputfield2 muddy,>(sed -e s/s/th/g >outputfield2.txt),vesture
- # yuk
- while [[ ! -e outputfield2.txt || ! -s outputfield2.txt ]]; do :; done
- cat outputfield2.txt
-0:>(...) when embedded within an argument
->muddy
->vesture
->How thweet the moonlight thitth upon the bank
-
- catfield1() {
- local -a args
- args=(${(s.,.)1})
- cat $args[1]
- print $args[2]
- }
- catfield1 =(echo s$'\x69't),jessica
-0:=(...) followed by something else without a break
->sit
->jessica
-
- (
- setopt nonomatch
- # er... why is this treated as a glob?
- print everything,=(here is left),alone
- )
-0:=(...) preceded by other stuff has no special effect
->everything,=(here is left),alone
-
- print something=${:-=(echo 'C,D),(F,G)'}
-1: Graceful handling of bad substitution in enclosed context
-?(eval):1: unterminated `=(...)'
-# '`
-
- () {
- print -n "first: "
- cat $1
- print -n "second: "
- cat $2
- } =(echo This becomes argument one) =(echo and this argument two)
- function {
- print -n "third: "
- cat $1
- print -n "fourth: "
- cat $2
- } =(echo This becomes argument three) =(echo and this argument four)
-0:Process environment of anonymous functions
->first: This becomes argument one
->second: and this argument two
->third: This becomes argument three
->fourth: and this argument four
-
- () {
- # Make sure we don't close the file descriptor too early
- eval 'print "Execute a complicated command first" | sed s/command/order/'
- cat $1
- } <(echo This line was brought to you by the letters F and D)
-0:Process substitution as anonymous function argument
->Execute a complicated order first
->This line was brought to you by the letters F and D
-
- alias foo='cat <('
- eval 'foo echo this is bound to work)'
-0:backtacking within command string parsing with alias still pending
->this is bound to work
-
- alias foo='cat <( print'
- eval 'foo here is some output)'
-0:full alias expanded when substitution starts in alias
->here is some output
-
- if ! (mkfifo test_pipe >/dev/null 2>&1); then
- ZTST_skip="mkfifo not available"
- else
- echo 1 | tee >(cat > test_pipe) | (){
- local pipein
- read pipein 1
->1
-
- if [[ ! -e test_pipe ]]; then
- ZTST_skip="mkfifo not available"
- else
- echo 1 | tee >(cat > test_pipe) | paste - test_pipe
- fi
-0:proc subst fd in forked subshell closed in parent (external command)
->1 1
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D04parameter.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D04parameter.ztst
deleted file mode 100644
index 9128c3c3..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D04parameter.ztst
+++ /dev/null
@@ -1,2058 +0,0 @@
-# Test parameter expansion. Phew.
-# (By the way, did I say "phew"?)
-
-%prep
-
- mkdir parameter.tmp
-
- cd parameter.tmp
-
- touch boringfile evenmoreboringfile
-
-%test
-
- foo='the first parameter'
- bar='the second parameter'
- print -l $foo ${bar}
-0:Basic scalar parameter substitution
->the first parameter
->the second parameter
-
- array1=(the first array)
- array2=(the second array)
- print -l $array1 ${array2}
-0:Basic array parameter substitution
->the
->first
->array
->the
->second
->array
-
- setopt ksharrays
- print -l $array1 ${array2}
- unsetopt ksharrays
-0:Basic ksharray substitution
->the
->the
-
- setopt shwordsplit
- print -l $foo ${bar}
- print -l ${==bar}
- unsetopt shwordsplit
-0:Basic shwordsplit option handling
->the
->first
->parameter
->the
->second
->parameter
->the second parameter
-
- print $+foo ${+foo} $+notappearinginthistest ${+notappearinginthistest}
-0:$+...
->1 1 0 0
-
- x=()
- print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]}
- x=(foo)
- print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]}
-0:$+... with arrays
->1 0 0 0
->1 1 1 0
-
- set1=set1v
- null1=
- print ${set1:-set1d} ${set1-set2d} ${null1:-null1d} ${null1-null2d} x
- print ${unset1:-unset1d} ${unset1-unset2d} x
-0:${...:-...} and ${...-...}
->set1v set1v null1d x
->unset1d unset2d x
-
- set2=irrelevant
- print ${set1:=set1d} ${set2::=set2d}
- print $set2
- wasnull1=
- wasnull2=
- print ${wasnull1=wasnull1d} ${wasnull2:=wasnull2d}
- print $wasnull1 $wasnull2
-0:${...:=...}, ${...::=...}, ${...=...}
->set1v set2d
->set2d
->wasnull2d
->wasnull2d
-
- unset array
- print ${#${(A)=array=word}}
-0:${#${(A)=array=word}} counts array elements
->1
-
- (print ${set1:?okhere}; print ${unset1:?exiting1}; print not reached;)
- (print ${null1?okhere}; print ${null1:?exiting2}; print not reached;)
-1:${...:?...}, ${...?...}
->set1v
->
-?(eval):1: unset1: exiting1
-?(eval):2: null1: exiting2
-
- PROMPT="" $ZTST_testdir/../Src/zsh -fis <<<'
- unsetopt PROMPT_SP
- PS1="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
- exec 2>&1
- foo() {
- print ${1:?no arguments given}
- print not reached
- }
- foo
- print reached
- ' 2>/dev/null
-0:interactive shell returns to top level on ${...?...} error
-*>*foo:1: 1: no arguments given
->reached
-
- print ${set1:+word1} ${set1+word2} ${null1:+word3} ${null1+word4}
- print ${unset1:+word5} ${unset1+word6}
-0:${...:+...}, ${...+...}
->word1 word2 word4
->
-
- str1='This is very boring indeed.'
- print ${str1#*s}
- print ${str1##*s}
- print $str1##s
-0:${...#...}, ${...##...}
-> is very boring indeed.
-> very boring indeed.
->This is very boring indeed.##s
-
- str2='If you'\''re reading this you should go and fix some bugs instead.'
- print ${str2%d*}
- print ${str2%%d*}
-0:${...%...}, ${...%%...}
->If you're reading this you should go and fix some bugs instea
->If you're rea
-
- str1='does match'
- str2='does not match'
- print ${str1:#does * match}
- print ${str2:#does * match}
-0:${...:#...}
->does match
->
-
- array1=(arthur boldly claws dogs every fight)
- print ${array1:#[aeiou]*}
- print ${(M)array1:#[aeiou]*}
-0:${...:#...}, ${(M)...:#...} with array
->boldly claws dogs fight
->arthur every
-
- str1="$array1"
- print ${str1/[aeiou]*g/a braw bricht moonlicht nicht the nic}
- print ${(S)str1/[aeiou]*g/relishe}
-0:scalar ${.../.../...}, ${(S).../.../...}
->a braw bricht moonlicht nicht the nicht
->relishes every fight
-
- print ${array1/[aeiou]*/Y}
- print ${(S)array1/[aeiou]*/Y}
-0:array ${.../.../...}, ${(S).../.../...}
->Y bY clY dY Y fY
->Yrthur bYldly clYws dYgs Yvery fYght
-
- str1='o this is so, so so very dull'
- print ${str1//o*/Please no}
- print ${(S)str1//o*/Please no}
-0:scalar ${...//.../...}, ${(S)...//.../...}
->Please no
->Please no this is sPlease no, sPlease no sPlease no very dull
-
- print ${array1//[aeiou]*/Y}
- print ${(S)array1//[aeiou]*/Y}
-0:array ${...//.../...}, ${(S)...//.../...}
->Y bY clY dY Y fY
->YrthYr bYldly clYws dYgs YvYry fYght
-
- print ${array1:/[aeiou]*/expletive deleted}
-0:array ${...:/...}
->expletive deleted boldly claws dogs expletive deleted fight
-
- str1='a\string\with\backslashes'
- str2='a/string/with/slashes'
- print "${str1//\\/-}"
- print ${str1//\\/-}
- print "${str2//\//-}"
- print ${str2//\//-}
-0:use of backslashes in //-substitutions
->a-string-with-backslashes
->a-string-with-backslashes
->a-string-with-slashes
->a-string-with-slashes
-
- args=('one' '#foo' '(bar' "'three'" two)
- mod=('#foo' '(bar' "'three'" sir_not_appearing_in_this_film)
- print ${args:|mod}
- print ${args:*mod}
- print "${(@)args:|mod}"
- print "${(@)args:*mod}"
- args=(two words)
- mod=('one word' 'two words')
- print "${args:|mod}"
- print "${args:*mod}"
- scalar='two words'
- print ${scalar:|mod}
- print ${scalar:*mod}
- print ${args:*nonexistent}
- empty=
- print ${args:*empty}
-0:"|" array exclusion and "*" array intersection
->one two
->#foo (bar 'three'
->one two
->#foo (bar 'three'
->
->two words
->
->two words
->
->
-
- str1='twocubed'
- array=(the number of protons in an oxygen nucleus)
- print $#str1 ${#str1} "$#str1 ${#str1}" $#array ${#array} "$#array ${#array}"
-0:${#...}, $#...
->8 8 8 8 8 8 8 8
-
- set 1 2 3 4 5 6 7 8 9
- print ${##}
- set 1 2 3 4 5 6 7 8 9 10
- print ${##}
- print ${##""}
- print ${##1}
- print ${##2}
- print ${###<->} # oh, for pete's sake...
-0:${##} is length of $#, and other tales of hash horror
->1
->2
->10
->0
->10
->
-
- array=(once bitten twice shy)
- print IF${array}THEN
- print IF${^array}THEN
-0:basic ${^...}
->IFonce bitten twice shyTHEN
->IFonceTHEN IFbittenTHEN IFtwiceTHEN IFshyTHEN
-
- # Quote ${array} here because {...,...} doesn't like unquoted spaces.
- print IF{"${array}",THEN}ELSE
- print IF{${^array},THEN}ELSE
-0:combined ${^...} and {...,...}
->IFonce bitten twice shyELSE IFTHENELSE
->IFonceELSE IFTHENELSE IFbittenELSE IFTHENELSE IFtwiceELSE IFTHENELSE IFshyELSE IFTHENELSE
-
- str1='one word'
- print -l $str1 ${=str1} "split ${=str1}wise"
-0:${=...}
->one word
->one
->word
->split one
->wordwise
-
- str1='*'
- print $str1 ${~str1} $~str1
- setopt globsubst
- print $str1
- unsetopt globsubst
-0:${~...} and globsubst
->* boringfile evenmoreboringfile boringfile evenmoreboringfile
->boringfile evenmoreboringfile
-
-# The following tests a bug where globsubst didn't preserve
-# backslashes when printing out the original string.
- str1='\\*\\'
- (
- setopt globsubst nonomatch
- [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1
- [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1
- [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1
- )
-0:globsubst with backslashes
->\\ matched by \\*\\
->\\foo matched by \\*\\
->a\\b not matched by \\*\\
-
- (
- setopt globsubst
- foo="boring*"
- print ${foo+$foo}
- print ${foo+"$foo"}
- print ${~foo+"$foo"}
- )
-0:globsubst together with nested quoted expansion
->boringfile
->boring*
->boringfile
-
- print -l "${$(print one word)}" "${=$(print two words)}"
-0:splitting of $(...) inside ${...}
->one word
->two
->words
-
- (setopt shwordsplit # ensure this doesn't get set in main shell...
- test_splitting ()
- {
- array="one two three"
- for e in $array; do
- echo "'$e'"
- done
- }
- test_split_var=
- echo _${test_split_var:=$(test_splitting)}_
- echo "_${test_split_var}_")
-0:SH_WORD_SPLIT inside $(...) inside ${...}
->_'one' 'two' 'three'_
->_'one'
->'two'
->'three'_
-
- print -l "${(f)$(print first line\\nsecond line\\nthird line)}"
-0:${(f)$(...)}
->first line
->second line
->third line
-
- array1=( uno )
- print -l ${(A)newarray=splitting by numbers}
- print -l ${(t)newarray}
- print -l ${(A)=newarray::=splitting by spaces, actually}
- print -l ${(t)newarray}
- print -l ${(A)newarray::=$array1}
- print -l ${(t)newarray}
- print -l ${newarray::=$array1}
- print -l ${(t)newarray}
- print -l ${newarray::=$array2}
- print -l ${(t)newarray}
-0:${(A)...=...}, ${(A)...::=...}, ${scalar=$array}
->splitting by numbers
->array
->splitting
->by
->spaces,
->actually
->array
->uno
->array
->uno
->scalar
->the second array
->scalar
-
- newarray=("split me" "split me" "I\'m yours")
- print -l "${(@)newarray}"
-0:"${(@)...}"
->split me
->split me
->I'm yours
-
- foo='$(print Howzat usay)'
- print -l ${(e)foo}
-0:${(e)...}
->Howzat
->usay
-
- foo='`print Howzat usay`'
- print -l ${(e)foo}
-0:Regress ${(e)...} with backticks (see zsh-workers/15871)
->Howzat
->usay
-
- foo='\u65\123'
- print -r ${(g:o:)foo}
- foo='\u65\0123^X\C-x'
- print -r ${(g::)foo}
- foo='^X'
- bar='\C-\130'
- [[ ${(g:c:)foo} == ${(g:oe:)bar} ]]
- echo $?
-0:${(g)...}
->eS
->eS^X\C-x
->0
-
- foo='I'\''m nearly out of my mind with tedium'
- bar=foo
- print ${(P)bar}
-0:${(P)...}
->I'm nearly out of my mind with tedium
-#' deconfuse emacs
-
- foo=(I could be watching that programme I recorded)
- print ${(o)foo}
- print ${(oi)foo}
- print ${(O)foo}
- print ${(Oi)foo}
-0:${(o)...}, ${(O)...}
->I I be could programme recorded that watching
->be could I I programme recorded that watching
->watching that recorded programme could be I I
->watching that recorded programme I I could be
-
- foo=(yOU KNOW, THE ONE WITH wILLIAM dALRYMPLE)
- bar=(doing that tour of India.)
- print ${(L)foo}
- print ${(U)bar}
-0:${(L)...}, ${(U)...}
->you know, the one with william dalrymple
->DOING THAT TOUR OF INDIA.
-
- foo='instead here I am stuck by the computer'
- print ${(C)foo}
-0:${(C)...}
->Instead Here I Am Stuck By The Computer
-
- foo=$'\x7f\x00'
- print -r -- ${(V)foo}
-0:${(V)...}
->^?^@
-
- foo='playing '\''stupid'\'' "games" \w\i\t\h $quoting.'
- print -r ${(q)foo}
- print -r ${(qq)foo}
- print -r ${(qqq)foo}
- print -r ${(qqqq)foo}
- print -r ${(q-)foo}
-0:${(q...)...}
->playing\ \'stupid\'\ \"games\"\ \\w\\i\\t\\h\ \$quoting.
->'playing '\''stupid'\'' "games" \w\i\t\h $quoting.'
->"playing 'stupid' \"games\" \\w\\i\\t\\h \$quoting."
->$'playing \'stupid\' "games" \\w\\i\\t\\h $quoting.'
->'playing '\'stupid\'' "games" \w\i\t\h $quoting.'
-
- print -r ${(qqqq):-""}
-0:workers/36551: literal empty string in ${(qqqq)...}
->$''
-
- x=( a '' '\b' 'c d' '$e' )
- print -r ${(q)x}
- print -r ${(q-)x}
-0:Another ${(q...)...} test
->a '' \\b c\ d \$e
->a '' '\b' 'c d' '$e'
-
- print -r -- ${(q-):-foo}
- print -r -- ${(q-):-foo bar}
- print -r -- ${(q-):-"*(.)"}
- print -r -- ${(q-):-"wow 'this is cool' or is it?"}
- print -r -- ${(q-):-"no-it's-not"}
-0:${(q-)...} minimal single quoting
->foo
->'foo bar'
->'*(.)'
->'wow '\''this is cool'\'' or is it?'
->no-it\'s-not
-
- foo="'and now' \"even the pubs\" \\a\\r\\e shut."
- print -r ${(Q)foo}
-0:${(Q)...}
->and now even the pubs are shut.
-
- foo="X$'\x41'$'\x42'Y"
- print -r ${(Q)foo}
-0:${(Q)...} with handling of $'...'
->XABY
-
- # The following may look a bit random.
- # For the split we are checking that anything that
- # would normally be followed by a different word has
- # an argument break after it and anything that wouldn't doesn't.
- # For the (Q) we are simply checking that nothing disappears
- # in the parsing.
- foo=' {six} (seven) >eight< }nine{ |forty-two| $many$ )ten( more'
- array=(${(z)foo})
- print -l ${(Q)array}
-0:${(z)...} and ${(Q)...} for some hard to parse cases
-><
->five
->>
->{six}
->(
->seven
->)
->>
->eight
-><
->}nine{
->|
->forty-two
->|
->$many$
->)
->ten( more
-
- strings=(
- 'foo=(1 2 3)'
- '(( 3 + 1 == 8 / 2 ))'
- 'for (( i = 1 ; i < 10 ; i++ ))'
- '((0.25542 * 60) - 15)*60'
- 'repeat 3 (x)'
- 'repeat 3 (echo foo; echo bar)'
- 'repeat $(( 2 + 4 )) (x)'
- 'repeat $( : foo bar; echo 4) (x)'
- 'repeat "1"'\''2'\''$(( 3 + 0 ))$((echo 4);)\ 5 (x)'
- )
- for string in $strings; do
- array=(${(z)string})
- for (( i = 1; i <= ${#array}; i++ )); do
- print -r -- "${i}:${array[i]}:"
- done
- done
-0:Some syntactical expressions that are hard to split into words with (z).
->1:foo=(:
->2:1:
->3:2:
->4:3:
->5:):
->1:(( 3 + 1 == 8 / 2 )):
->1:for:
->2:((:
-# Leading whitespace is removed, because the word proper hasn't started;
-# trailing whitespace is left because the word is terminated by the
-# semicolon or double parentheses. Bit confusing but sort of consistent.
->3:i = 1 ;:
->4:i < 10 ;:
->5:i++ :
->6:)):
-# This one needs resolving between a math expression and
-# a command, which causes interesting effects internally.
->1:(:
->2:(:
->3:0.25542:
->4:*:
->5:60:
->6:):
->7:-:
->8:15:
->9:):
->10:*60:
->1:repeat:
->2:3:
->3:(:
->4:x:
->5:):
->1:repeat:
->2:3:
->3:(:
->4:echo:
->5:foo:
->6:;:
->7:echo:
->8:bar:
->9:):
->1:repeat:
->2:$(( 2 + 4 )):
->3:(:
->4:x:
->5:):
->1:repeat:
->2:$( : foo bar; echo 4):
->3:(:
->4:x:
->5:):
->1:repeat:
->2:"1"'2'$(( 3 + 0 ))$((echo 4);)\ 5:
->3:(:
->4:x:
->5:):
-
-
- line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one'
- print "*** Normal ***"
- print -l ${(z)line}
- print "*** Kept ***"
- print -l ${(Z+c+)line}
- print "*** Removed ***"
- print -l ${(Z+C+)line}
-0:Comments with (z)
->*** Normal ***
->A
->line
->with
->#
->someone's comment
->another line # (1 more
->another one
->*** Kept ***
->A
->line
->with
-># someone's comment
->;
->another
->line
-># (1 more
->;
->another
->one
->*** Removed ***
->A
->line
->with
->;
->another
->line
->;
->another
->one
-
- line='with comment # at the end'
- print -l ${(Z+C+)line}
-0:Test we don't get an additional newline token
->with
->comment
-
- line=$'echo one\necho two # with a comment\necho three'
- print -l ${(Z+nc+)line}
-0:Treating zplit newlines as ordinary whitespace
->echo
->one
->echo
->two
-># with a comment
->echo
->three
-
- print -rl - ${(z):-":;(( echo 42 "}
-0:${(z)} with incomplete math expressions
->:
->;
->(( echo 42
-
- # From parse error on it's not possible to split.
- # Just check we get the complete string.
- foo='echo $(|||) bar'
- print -rl ${(z)foo}
-0:$($(z)} with parse error in command substitution.
->echo
->$(|||) bar
-
- psvar=(dog)
- setopt promptsubst
- foo='It shouldn'\''t $(happen) to a %1v.'
- bar='But `echo what can you do\?`'
- print -r ${(%)foo}
- print -r ${(%%)bar}
-0:${(%)...}
->It shouldn't $(happen) to a dog.
->But what can you do?
-
- foo='unmatched "'
- print ${(QX)foo}
-1:${(QX)...}
-?(eval):2: unmatched "
-# " deconfuse emacs
-
- array=(characters in an array)
- print ${(c)#array}
-0:${(c)#...}
->22
-
- print ${(w)#array}
- str='colon::bolon::solon'
- print ${(ws.:.)#str}
- print ${(Ws.:.)#str}
-0:${(w)...}, ${(W)...}
->4
->3
->5
-
- typeset -A assoc
- assoc=(key1 val1 key2 val2)
- print ${(o)assoc}
- print ${(ok)assoc}
- print ${(ov)assoc}
- print ${(okv)assoc}
-0:${(k)...}, ${(v)...}
->val1 val2
->key1 key2
->val1 val2
->key1 key2 val1 val2
-
- word="obfuscatory"
- print !${(l.16.)word}! +${(r.16.)word}+
-0:simple padding
->! obfuscatory! +obfuscatory +
-
- foo=(resulting words uproariously padded)
- print ${(pl.10..\x22..X.)foo}
-0:${(pl...)...}
->Xresulting """"Xwords roariously """Xpadded
-#" deconfuse emacs
-
- print ${(l.5..X.r.5..Y.)foo}
- print ${(l.6..X.r.4..Y.)foo}
- print ${(l.7..X.r.3..Y.)foo}
- print ${(l.6..X..A.r.6..Y..B.)foo}
- print ${(l.6..X..AROOGA.r.6..Y..BARSOOM.)foo}
-0:simultaneous left and right padding
->Xresulting XXXwordsYY proariousl XXpaddedYY
->XXresultin XXXXwordsY uproarious XXXpaddedY
->XXXresulti XXXXXwords Xuproariou XXXXpadded
->XAresultingB XXXAwordsBYY uproariously XXApaddedBYY
->GAresultingB OOGAwordsBAR uproariously OGApaddedBAR
-
- foo=(why in goodness name am I doing this)
- print ${(r.5..!..?.)foo}
-0:${(r...)...}
->why?! in?!! goodn name? am?!! I?!!! doing this?
-
- array=(I\'m simply putting a brave face on)
- print ${(j:--:)array}
-0:${(j)...}
->I'm--simply--putting--a--brave--face--on
-
- print ${(F)array}
-0:${(F)...}
->I'm
->simply
->putting
->a
->brave
->face
->on
-
- string='zometimez zis getz zplit on a z'
- print -l ${(s?z?)string}
-0:${(s...)...}
->ometime
->
->is get
->
->plit on a
-
- str=s
- arr=(a)
- typeset -A ass
- ass=(a a)
- integer i
- float f
- print ${(t)str} ${(t)arr} ${(t)ass} ${(t)i} ${(t)f}
-0:${(t)...}
->scalar array association-local integer-local float-local
-
- # it's not quite clear that these are actually right unless you know
- # the algorithm: search along the string for the point at which the
- # first (last) match occurs, for ## (%%), then take the shortest possible
- # version of that for # (%). it's as good a definition as anything.
- string='where is the white windmill, whispered walter wisely'
- print ${(S)string#h*e}
- print ${(S)string##h*e}
- print ${(S)string%h*e}
- print ${(S)string%%h*e}
-0:${(S)...#...} etc.
->wre is the white windmill, whispered walter wisely
->wly
->where is the white windmill, wred walter wisely
->where is the white windmill, wly
-
- setopt extendedglob
- print ${(SI:1:)string##w[^[:space:]]# }
- print ${(SI:1+1:)string##w[^[:space:]]# }
- print ${(SI:1+1+1:)string##w[^[:space:]]# }
- print ${(SI:1+1+1+1:)string##w[^[:space:]]# }
-0:${(I:...:)...}
->is the white windmill, whispered walter wisely
->where is the windmill, whispered walter wisely
->where is the white whispered walter wisely
->where is the white windmill, walter wisely
-
- print ${(MSI:1:)string##w[^[:space:]]# }
-0:${(M...)...}
->where
-
- print ${(R)string//w[a-z]# #}
-0:${(R)...}
->is the ,
-
- # This (1) doesn't work with // or /
- # (2) perhaps ought to be 18, to be consistent with normal zsh
- # substring indexing and with backreferences.
- print ${(BES)string##white}
-0:${(BE...)...}
->14 19
-
- print ${(NS)string##white}
-0:${(N)...}
->5
-
- string='abcdefghijklmnopqrstuvwxyz'
- print ${${string%[aeiou]*}/(#m)?(#e)/${(U)MATCH}}
-0:Rule 1: Nested substitutions
->abcdefghijklmnopqrsT
-
- array=(et Swann avec cette muflerie intermittente)
- string="qui reparaissait chez lui"
- print ${array[4,5]}
- print ${array[4,5][1]}
- print ${array[4,5][1][2,3]}
- print ${string[4,5]}
- print ${string[4,5][1]}
-0:Rule 2: Parameter subscripting
->cette muflerie
->cette
->et
-> r
->
-
- foo=stringalongamax
- print ${${(P)foo[1,6]}[1,3]}
-0:Rule 3: Parameter Name Replacement
->qui
-
- print "${array[5,6]}"
- print "${(j.:.)array[1,2]}"
-0:Rule 4: Double-Quoted Joining
->muflerie intermittente
->et:Swann
-
- print "${${array}[5,7]}"
- print "${${(@)array}[1,2]}"
-0:Rule 5: Nested Subscripting
->wan
->et Swann
-
- print "${${(@)array}[1,2]#?}"
- print "${(@)${(@)array}[1,2]#?}"
-0:Rule 6: Modifiers
->t Swann
->t wann
-
- array=(she sells z shells by the z shore)
- (IFS='+'; print ${(s.s.)array})
-0:Rule 7: Forced Joining, and 8: Forced splitting
->he+ ell +z+ hell +by+the+z+ hore
-
- setopt shwordsplit
- string='another poxy boring string'
- print -l ${${string}/o/ }
- unsetopt shwordsplit
-0:Rule 9: Shell Word Splitting
->an
->ther
->p
->xy
->b
->ring
->string
-
- setopt nonomatch
- foo='b* e*'
- print ${(e)~foo}
- print ${(e)~=foo}
- setopt nomatch
-0:Rule 10: Re-Evaluation
->b* e*
->boringfile evenmoreboringfile
-
- # ${bar} -> $bar here would yield "bad substitution".
- bar=confinement
- print ${(el.20..X.)${bar}}
-0:Rule 11: Padding
->XXXXXXXXXconfinement
-
- foo=(bar baz)
- bar=(ax1 bx1)
- print "${(@)${foo}[1]}"
- print "${${(@)foo}[1]}"
- print -l ${(s/x/)bar}
- print -l ${(j/x/s/x/)bar}
- print -l ${(s/x/)bar%%1*}
-0:Examples in manual on parameter expansion
->b
->bar
->a
->1 b
->1
->a
->1
->b
->1
->a
-> b
-
- set If "this test fails" "we have broken" the shell again
- print -l ${1+"$@"}
-0:Regression test of ${1+"$@"} bug
->If
->this test fails
->we have broken
->the
->shell
->again
-
- set If "this test fails" "we have broken" the shell again
- print -l "${(A)foo::=$@}"
- print -l ${(t)foo}
- print -l $foo
-0:Regression test of "${(A)foo=$@}" bug
->If this test fails we have broken the shell again
->array
->If
->this test fails
->we have broken
->the
->shell
->again
-
- local sure_that='sure that' varieties_of='varieties of' one=1 two=2
- extra=(5 4 3)
- unset foo
- set Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace
- print -l ${=1+"$@"}
- print -l ${(A)=foo=Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace}
- print ${(t)foo}
- print -l ${=1+$one $two}
- print -l ${1+$extra$two$one}
-0:Regression test of ${=1+"$@"} bug and some related expansions
->Make
->sure that
->this test keeps
->on
->preserving all
->varieties of
->quoted
->whitespace
->Make
->sure
->that
->this test keeps
->on
->preserving all
->varieties of
->quoted
->whitespace
->array
->1
->2
->5
->4
->321
-
- splitfn() {
- emulate -L sh
- local HOME="/differs from/bash" foo='1 2' bar='3 4'
- print -l ${1:-~}
- touch has\ space
- print -l ${1:-*[ ]*}
- print -l ${1:-*[\ ]*}
- print -l ${1:-*}
- print -l ${1:-"$foo" $bar}
- print -l ${==1:-$foo $bar}
- rm has\ space
- }
- splitfn
-0:More bourne-shell-compatible nested word-splitting with wildcards and ~
->/differs from/bash
->*[
->]*
->has space
->boringfile
->evenmoreboringfile
->has space
->1 2
->3
->4
->1 2 3 4
-
- splitfn() {
- local IFS=.-
- local foo=1-2.3-4
- #
- print "Called with argument '$1'"
- print "No quotes"
- print -l ${=1:-1-2.3-4} ${=1:-$foo}
- print "With quotes on default argument only"
- print -l ${=1:-"1-2.3-4"} ${=1:-"$foo"}
- }
- print 'Using "="'
- splitfn
- splitfn 5.6-7.8
- #
- splitfn() {
- emulate -L zsh
- setopt shwordsplit
- local IFS=.-
- local foo=1-2.3-4
- #
- print "Called with argument '$1'"
- print "No quotes"
- print -l ${1:-1-2.3-4} ${1:-$foo}
- print "With quotes on default argument only"
- print -l ${1:-"1-2.3-4"} ${1:-"$foo"}
- }
- print Using shwordsplit
- splitfn
- splitfn 5.6-7.8
-0:Test of nested word splitting with and without quotes
->Using "="
->Called with argument ''
->No quotes
->1
->2
->3
->4
->1
->2
->3
->4
->With quotes on default argument only
->1-2.3-4
->1-2.3-4
->Called with argument '5.6-7.8'
->No quotes
->5
->6
->7
->8
->5
->6
->7
->8
->With quotes on default argument only
->5
->6
->7
->8
->5
->6
->7
->8
->Using shwordsplit
->Called with argument ''
->No quotes
->1
->2
->3
->4
->1
->2
->3
->4
->With quotes on default argument only
->1-2.3-4
->1-2.3-4
->Called with argument '5.6-7.8'
->No quotes
->5
->6
->7
->8
->5
->6
->7
->8
->With quotes on default argument only
->5
->6
->7
->8
->5
->6
->7
->8
-
-# Tests a long-standing bug with joining on metafied characters in IFS
- (array=(one two three)
- IFS=$'\0'
- foo="$array"
- for (( i = 1; i <= ${#foo}; i++ )); do
- char=${foo[i]}
- print $(( #char ))
- done)
-0:Joining with NULL character from IFS
->111
->110
->101
->0
->116
->119
->111
->0
->116
->104
->114
->101
->101
-
- unset SHLVL
- (( SHLVL++ ))
- print $SHLVL
-0:Unsetting and recreation of numerical special parameters
->1
-
- unset manpath
- print $+MANPATH
- manpath=(/here /there)
- print $MANPATH
- unset MANPATH
- print $+manpath
- MANPATH=/elsewhere:/somewhere
- print $manpath
-0:Unsetting and recreation of tied special parameters
->0
->/here:/there
->0
->/elsewhere /somewhere
-
- local STRING=a:b
- typeset -T STRING string
- print $STRING $string
- unset STRING
- set -A string x y z
- print $STRING $string
- STRING=a:b
- typeset -T STRING string
- print $STRING $string
- unset STRING
- set -A string x y z
- print $STRING $string
- STRING=a:b
- typeset -T STRING string
- print $STRING $string
- unset string
- STRING=x:y:z
- print $STRING $string
- STRING=a:b
- typeset -T STRING string
- print $STRING $string
- unset string
- STRING=x:y:z
- print $STRING $string
-0:Unsetting and recreation of tied normal parameters
->a:b a b
->x y z
->a:b a b
->x y z
->a:b a b
->x:y:z
->a:b a b
->x:y:z
-
- typeset -T tied1 tied2 +
- typeset -T tied2 tied1 +
-1:Attempts to swap tied variables are safe but futile
-?(eval):typeset:2: already tied as non-scalar: tied2
-
- string='look for a match in here'
- if [[ ${string%%(#b)(match)*} = "look for a " ]]; then
- print $match[1] $mbegin[1] $mend[1] $string[$mbegin[1],$mend[1]]
- print $#match $#mbegin $#mend
- else
- print That didn\'t work.
- fi
-0:Parameters associated with backreferences
->match 12 16 match
->1 1 1
-#' deconfuse emacs
-
- string='and look for a MATCH in here'
- if [[ ${(S)string%%(#m)M*H} = "and look for a in here" ]]; then
- print $MATCH $MBEGIN $MEND $string[$MBEGIN,$MEND]
- print $#MATCH
- else
- print Oh, dear. Back to the drawing board.
- fi
-0:Parameters associated with (#m) flag
->MATCH 16 20 MATCH
->5
-
- string='this is a string'
- print ${string//(#m)s/$MATCH $MBEGIN $MEND}
-0:(#m) flag with pure string
->this 4 4 is 7 7 a s 11 11tring
-
- print ${${~:-*}//(#m)*/$MATCH=$MATCH}
-0:(#m) flag with tokenized input
->*=*
-
- print -l JAMES${(u)${=:-$(echo yes yes)}}JOYCE
- print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes)}}JOYCE
-0:Bug with (u) flag reducing arrays to one element
->JAMESyesJOYCE
->JAMESyes
->she
->said
->i
->willJOYCE
-
- print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes she said she will and yes she did yes)}}JOYCE
-0:New hash seive unique algorithm for arrays of more than 10 elements
->JAMESyes
->she
->said
->i
->will
->and
->didJOYCE
-
- foo=
- print "${${foo}/?*/replacement}"
-0:Quoted zero-length strings are handled properly
->
-
- file=aleftkept
- print ${file//(#b)(*)left/${match/a/andsome}}
- print ${file//(#b)(*)left/${match//a/andsome}}
-0:Substitutions where $match is itself substituted in the replacement
->andsomekept
->andsomekept
-
- file=/one/two/three/four
- print ${file:fh}
- print ${file:F.1.h}
- print ${file:F+2+h}
- print ${file:F(3)h}
- print ${file:F<4>h}
- print ${file:F{5}h}
-0:Modifiers with repetition
->/
->/one/two/three
->/one/two
->/one
->/
->/
-
- baz=foo/bar
- zab=oof+rab
- print ${baz:s/\//+/}
- print "${baz:s/\//+/}"
- print ${zab:s/+/\//}
- print "${zab:s/+/\//}"
-0:Quoting of separator in substitution modifier
->foo+bar
->foo+bar
->oof/rab
->oof/rab
-
- bsbs='X\\\\Y'
- print -r -- ${bsbs:s/\\/\\/}
- print -r -- "${bsbs:s/\\/\\/}"
- print -r -- ${bsbs:s/\\\\/\\\\/}
- print -r -- "${bsbs:s/\\\\/\\\\/}"
- print -r -- ${bsbs:gs/\\/\\/}
- print -r -- "${bsbs:gs/\\/\\/}"
- print -r -- ${bsbs:gs/\\\\/\\\\/}
- print -r -- "${bsbs:gs/\\\\/\\\\/}"
-0:Handling of backslashed backslashes in substitution modifier
->X\\\\Y
->X\\\\Y
->X\\\\Y
->X\\\\Y
->X\\\\Y
->X\\\\Y
->X\\\\Y
->X\\\\Y
-
- print -r ${${:-one/two}:s,/,X&Y,}
- print -r ${${:-one/two}:s,/,X\&Y,}
- print -r ${${:-one/two}:s,/,X\\&Y,}
- print -r "${${:-one/two}:s,/,X&Y,}"
- print -r "${${:-one/two}:s,/,X\&Y,}"
- print -r "${${:-one/two}:s,/,X\\&Y,}"
-0:Quoting of ampersand in substitution modifier RHS
->oneX/Ytwo
->oneX&Ytwo
->oneX\/Ytwo
->oneX/Ytwo
->oneX&Ytwo
->oneX\/Ytwo
-
- nully=($'a\0c' $'a\0b\0b' $'a\0b\0a' $'a\0b\0' $'a\0b' $'a\0' $'a')
- for string in ${(o)nully}; do
- for (( i = 1; i <= ${#string}; i++ )); do
- foo=$string[i]
- printf "%02x" $(( #foo ))
- done
- print
- done
-0:Sorting arrays with embedded nulls
->61
->6100
->610062
->61006200
->6100620061
->6100620062
->610063
-
- array=(X)
- patterns=("*X*" "spong" "a[b")
- for pat in $patterns; do
- print A${array[(r)$pat]}B C${array[(I)$pat]}D
- done
-0:Bad patterns should never match array elements
->AXB C1D
->AB C0D
->AB C0D
-
- foo=(a6 a117 a17 b6 b117 b17)
- print ${(n)foo}
- print ${(On)foo}
-0:Numeric sorting
->a6 a17 a117 b6 b17 b117
->b117 b17 b6 a117 a17 a6
-
- x=sprodj
- x[-10]=scrumf
- print $x
-0:Out of range negative scalar subscripts
->scrumfsprodj
-
- a=(some sunny day)
- a[-10]=(we\'ll meet again)
- print -l $a
-0:Out of range negative array subscripts
->we'll
->meet
->again
->some
->sunny
->day
-
-# ' emacs likes this close quote
-
- a=(sping spang spong bumble)
- print ${a[(i)spong]}
- print ${a[(i)spung]}
- print ${a[(ib.1.)spong]}
- print ${a[(ib.4.)spong]}
- print ${a[(ib.10.)spong]}
-0:In and out of range reverse matched indices without and with b: arrays
->3
->5
->3
->5
->5
-
- a="thrimblewuddlefrong"
- print ${a[(i)w]}
- print ${a[(i)x]}
- print ${a[(ib.3.)w]}
- print ${a[(ib.10.)w]}
- print ${a[(ib.30.)w]}
-0:In and out of range reverse matched indices without and with b: strings
->9
->20
->9
->20
->20
-
- foo="line:with::missing::fields:in:it"
- print -l ${(s.:.)foo}
-0:Removal of empty fields in unquoted splitting
->line
->with
->missing
->fields
->in
->it
-
- foo="line:with::missing::fields:in:it"
- print -l "${(s.:.)foo}"
-0:Hacky removal of empty fields in quoted splitting with no "@"
->line
->with
->missing
->fields
->in
->it
-
- foo="line:with::missing::fields:in:it:"
- print -l "${(@s.:.)foo}"
-0:Retention of empty fields in quoted splitting with "@"
->line
->with
->
->missing
->
->fields
->in
->it
->
-
- str=abcd
- print -l ${(s..)str}
- print -l "${(s..)str}"
-0:splitting of strings into characters
->a
->b
->c
->d
->a
->b
->c
->d
-
- array=('%' '$' 'j' '*' '$foo')
- print ${array[(i)*]} "${array[(i)*]}"
- print ${array[(ie)*]} "${array[(ie)*]}"
- key='$foo'
- print ${array[(ie)$key]} "${array[(ie)$key]}"
- key='*'
- print ${array[(ie)$key]} "${array[(ie)$key]}"
-0:Matching array indices with and without quoting
->1 1
->4 4
->5 5
->4 4
-
-# Ordering of associative arrays is arbitrary, so we need to use
-# patterns that only match one element.
- typeset -A assoc_r
- assoc_r=(star '*' of '*this*' and '!that!' or '(the|other)')
- print ${(kv)assoc_r[(re)*]}
- print ${(kv)assoc_r[(re)*this*]}
- print ${(kv)assoc_r[(re)!that!]}
- print ${(kv)assoc_r[(re)(the|other)]}
- print ${(kv)assoc_r[(r)*at*]}
- print ${(kv)assoc_r[(r)*(ywis|bliss|kiss|miss|this)*]}
- print ${(kv)assoc_r[(r)(this|that|\(the\|other\))]}
-0:Reverse subscripting associative arrays with literal matching
->star *
->of *this*
->and !that!
->or (the|other)
->and !that!
->of *this*
->or (the|other)
-
- print $ZSH_SUBSHELL
- (print $ZSH_SUBSHELL)
- ( (print $ZSH_SUBSHELL) )
- ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL )
- print $(print $ZSH_SUBSHELL)
- cat =(print $ZSH_SUBSHELL)
-0:ZSH_SUBSHELL
->0
->1
->2
->2
->1
->1
->1
-
- foo=("|" "?")
- [[ "|" = ${(j.|.)foo} ]] && print yes || print no
- [[ "|" = ${(j.|.)~foo} ]] && print yes || print no
- [[ "|" = ${(~j.|.)foo} ]] && print yes || print no
- [[ "|" = ${(~~j.|.)foo} ]] && print yes || print no
- [[ "|" = ${(j.|.~)foo} ]] && print yes || print no
- [[ "x" = ${(j.|.)foo} ]] && print yes || print no
- [[ "x" = ${(j.|.)~foo} ]] && print yes || print no
- [[ "x" = ${(~j.|.)foo} ]] && print yes || print no
- [[ "x" = ${(~~j.|.)foo} ]] && print yes || print no
- [[ "x" = ${(j.|.~)foo} ]] && print yes || print no
-0:GLOBSUBST only on parameter substitution arguments
->no
->yes
->yes
->no
->no
->no
->yes
->no
->no
->no
-
- rcexbug() {
- emulate -L zsh
- setopt rcexpandparam
- local -A hash
- local -a full empty
- full=(X x)
- hash=(X x)
- print ORDINARY ARRAYS
- : The following behaves as documented in zshoptions
- print FULL expand=$full
- : Empty arrays remove the adjacent argument
- print EMPTY expand=$empty
- print ASSOCIATIVE ARRAY
- print Subscript flags returning many values
- print FOUND key=$hash[(I)X] val=$hash[(R)x]
- : This should behave like $empty, and does
- print LOST key=$hash[(I)y] val=$hash[(R)Y]
- print Subscript flags returning single values
- : Doc says "substitutes ... empty string"
- : so must not behave like an empty array
- print STRING key=$hash[(i)y] val=$hash[(r)Y]
- }
- rcexbug
-0:Lookup failures on elements of arrays with RC_EXPAND_PARAM
->ORDINARY ARRAYS
->FULL expand=X expand=x
->EMPTY
->ASSOCIATIVE ARRAY
->Subscript flags returning many values
->FOUND key=X val=x
->LOST
->Subscript flags returning single values
->STRING key= val=
-
- print $zsh_eval_context[1]
- [[ $ZSH_EVAL_CONTEXT = ${(j.:.)zsh_eval_context} ]] || print Not equal!
- (( icontext = ${#zsh_eval_context} + 1 ))
- contextfn() { print $(print $zsh_eval_context[icontext,-1]); }
- contextfn
-0:$ZSH_EVAL_CONTEXT and $zsh_eval_context
->toplevel
->shfunc cmdsubst
-
- foo="123456789"
- print ${foo:3}
- print ${foo: 1 + 3}
- print ${foo:$(( 2 + 3))}
- print ${foo:$(echo 3 + 3)}
- print ${foo:3:1}
- print ${foo: 1 + 3:(4-2)/2}
- print ${foo:$(( 2 + 3)):$(( 7 - 6 ))}
- print ${foo:$(echo 3 + 3):`echo 4 - 3`}
- print ${foo: -1}
- print ${foo: -10}
- print ${foo:5:-2}
-0:Bash-style offsets, scalar
->456789
->56789
->6789
->789
->4
->5
->6
->7
->9
->123456789
->67
-
- foo=(1 2 3 4 5 6 7 8 9)
- print ${foo:3}
- print ${foo: 1 + 3}
- print ${foo:$(( 2 + 3))}
- print ${foo:$(echo 3 + 3)}
- print ${foo:3:1}
- print ${foo: 1 + 3:(4-2)/2}
- print ${foo:$(( 2 + 3)):$(( 7 - 6 ))}
- print ${foo:$(echo 3 + 3):`echo 4 - 3`}
- print ${foo: -1}
- print ${foo: -10}
- print ${foo:5:-2}
-0:Bash-style offsets, array
->4 5 6 7 8 9
->5 6 7 8 9
->6 7 8 9
->7 8 9
->4
->5
->6
->7
->9
->1 2 3 4 5 6 7 8 9
->6 7
-
- testfn() {
- emulate -L sh
- set -A foo 1 2 3
- set -- 1 2 3
- str=abc
- echo ${foo[*]:0:1}
- echo ${foo[*]:1:1}
- echo ${foo[*]: -1:1}
- :
- echo ${*:0:1}
- echo ${*:1:1}
- echo ${*: -1:1}
- :
- echo ${str:0:1}
- echo ${str:1:1}
- echo ${str: -1:1}
- }
- testfn
-0:Bash-style offsets, Bourne-style indexing
->1
->2
->3
->testfn
->1
->3
->a
->b
->c
-
- printf "%n" '[0]'
-1:Regression test for identifier test
-?(eval):1: not an identifier: [0]
-
- str=rts
- print ${str:0:}
-1:Regression test for missing length after offset
-?(eval):2: unrecognized modifier
-
- foo="123456789"
- print ${foo:5:-6}
-1:Regression test for total length < 0 in string
-?(eval):2: substring expression: 3 < 5
-
- foo=(1 2 3 4 5 6 7 8 9)
- print ${foo:5:-6}
-1:Regression test for total length < 0 in array
-?(eval):2: substring expression: 3 < 5
-
- foo=(${(0)"$(print -n)"})
- print ${#foo}
-0:Nularg removed from split empty string
->0
-
- (set -- a b c
- setopt shwordsplit
- IFS=
- print -rl "$*"
- unset IFS
- print -rl "$*")
-0:Regression test for shwordsplit with null or unset IFS and quoted array
->abc
->a b c
-
- foo=
- print ${foo:wq}
- print ${:wq}
-0:Empty parameter should not cause modifiers to crash the shell
->
->
-
-# This used to cause uncontrolled behaviour, but at best
-# you got the wrong output so the check is worth it.
- args() { print $#; }
- args ${:*}
- args ${:|}
-0:Intersection and disjunction with empty parameters
->0
->0
-
- foo=(a b c)
- bar=(1 2 3)
- print ${foo:^bar}
- print ${foo:^^bar}
- foo=(a b c d)
- bar=(1 2)
- print ${foo:^bar}
- print ${foo:^^bar}
- foo=('a a' b)
- bar=(1 '2 2')
- print -l "${foo:^bar}"
- print -l "${(@)foo:^bar}"
-0:Zipping arrays, correct output
->a 1 b 2 c 3
->a 1 b 2 c 3
->a 1 b 2
->a 1 b 2 c 1 d 2
-# maybe this should be changed to output "a a b 1"
->a a b
->1
->a a
->1
->b
->2 2
-
- foo=(a b c)
- bar=()
- print ${foo:^bar}
- print ${foo:^^bar}
- print ${bar:^foo}
- print ${bar:^^foo}
- print ${bar:^bar}
- print ${bar:^^bar}
-0:Zipping arrays, one or both inputs empty
->
->a b c
->
->a b c
->
->
-
- foo=text
- bar=()
- print ${foo:^bar}
- print ${bar:^^foo}
- bar=other
- print ${foo:^bar}
- bar=(array elements)
- print ${foo:^bar}
- print ${foo:^^bar}
- print ${bar:^foo}
- print ${bar:^^foo}
-0:Zipping arrays, scalar input
->
->text
->text other
->text array
->text array text elements
->array text
->array text elements text
-
- foo=(a b c)
- print ${foo:^^^bar}
-1:Zipping arrays, parsing
-?(eval):2: not an identifier: ^bar
-
- (setopt nounset
- print ${foo:^noexist})
-1:Zipping arrays, NO_UNSET part 1
-?(eval):2: noexist: parameter not set
-
- (setopt nounset
- print ${noexist:^foo})
-1:Zipping arrays, NO_UNSET part 2
-?(eval):2: noexist: parameter not set
-
- expr="a@b,c@d:e@f,g@h:i@j,k@l"
- for sep in : , @; do
- print -l ${(ps.$sep.)expr}
- done
-0:Use of variable to get separator when splitting parameter
->a@b,c@d
->e@f,g@h
->i@j,k@l
->a@b
->c@d:e@f
->g@h:i@j
->k@l
->a
->b,c
->d:e
->f,g
->h:i
->j,k
->l
-
- SHLVL=1
- $ZTST_testdir/../Src/zsh -fc 'echo $SHLVL'
- $ZTST_testdir/../Src/zsh -fc '(echo $SHLVL)'
-0:SHLVL appears sensible when about to exit shell
->2
->2
-
- # SHLVL is incremented twice and decremented once in between.
- SHLVL=1
- $ZTST_testdir/../Src/zsh -fc $ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"'
- $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL")'
- $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"))'
-0:SHLVL decremented upon implicit exec optimisation
->2
->2
->2
-
- # SHLVL is incremented twice with no decrement in between.
- SHLVL=1
- $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit'
- $ZTST_testdir/../Src/zsh -fc '(exec '$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit'
- $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit)'
-0:SHLVL not decremented upon exec in subshells
->3
->3
->3
-
-# The following tests the return behaviour of parsestr/parsestrnoerr
- alias param-test-alias='print $'\''\x45xpanded in substitution'\'
- param='$(param-test-alias)'
- print ${(e)param}
-0:Alias expansion in command substitution in parameter evaluation
->Expanded in substitution
-
- a=1 b=2 c=3
- : One;
- function {
- : Two
- echo $_
- print -l $argv
- } $_ Three
- print -l $_ Four;
-0:$_ with anonymous function
->Two
->One
->Three
->Three
->Four
-
- a=1 b=2 c=3
- : One
- function {
- : Two
- echo $_
- print -l $argv
- }
- print -l "$_" Four
-0:$_ with anonymous function without arguments
->Two
->
->
->Four
-
- funnychars='The qu*nk br!wan f@x j/mps o[]r \(e la~# ^"&;'
- [[ $funnychars = ${~${(b)funnychars}} ]]
-0:${(b)...} quoting protects from GLOB_SUBST
-
- set -- foo
- echo $(( $#*3 ))
- emulate sh -c 'nolenwithoutbrace() { echo $#-1; }'
- nolenwithoutbrace
-0:Avoid confusion after overloaded characters in braceless substitution in sh
->13
->0-1
-
- a="aaa bab cac"
- b=d
- echo $a:gs/a/${b}/
- a=(aaa bab cac)
- echo $a:gs/a/${b}/
-0:History modifier works the same for scalar and array substitution
->ddd bdb cdc
->ddd bdb cdc
-
- a=1_2_3_4_5_6
- print ${a#(*_)(#c2)}
- print ${a#(*_)(#c5)}
- print ${a#(*_)(#c7)}
-0:Complicated backtracking with match counts
->3_4_5_6
->6
->1_2_3_4_5_6
-
- (setopt shwordsplit
- do_test() {
- print $#: "$@"
- }
- foo=bar
- foo2="bar bar"
- do_test ${:- foo }
- do_test ${:- foo bar }
- do_test ${:- $foo }
- do_test ${:- $foo2 }
- do_test x${:- foo }y
- do_test x${:- foo bar }y
- do_test x${:- $foo }y
- do_test x${:- $foo2 }y
- do_test x${foo:+ $foo }y
- )
-0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst
->1: foo
->2: foo bar
->1: bar
->2: bar bar
->3: x foo y
->4: x foo bar y
->3: x bar y
->4: x bar bar y
->3: x bar y
-
- (unsetopt shwordsplit # default, for clarity
- do_test() {
- print $#: "$@"
- }
- foo=bar
- foo2="bar bar"
- do_test ${:- foo }
- do_test ${:- foo bar }
- do_test ${:- $foo }
- do_test ${:- $foo2 }
- do_test x${:- foo }y
- do_test x${:- foo bar }y
- do_test x${:- $foo }y
- do_test x${:- $foo2 }y
- do_test x${foo:+ $foo }y
- )
-0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check
->1: foo
->1: foo bar
->1: bar
->1: bar bar
->1: x foo y
->1: x foo bar y
->1: x bar y
->1: x bar bar y
->1: x bar y
-
- testfn() {
- local scalar=obfuscation
- local -a array=(alpha bravo charlie delta echo foxtrot)
- local -A assoc=(one eins two zwei three drei four vier)
- local name subscript
- for name subscript in scalar 3 array 5 assoc three; do
- print ${${(P)name}[$subscript]}
- done
- }
- testfn
-0:${(P)...} with normal subscripting
->f
->echo
->drei
-
- testfn() {
- local s1=foo s2=bar
- local -a val=(s1)
- print ${${(P)val}[1,3]}
- val=(s1 s2)
- print ${${(P)val}[1,3]}
- }
- testfn
-1:${(P)...} with array as name
->foo
-?testfn:5: parameter name reference used with array
-
- testfn() {
- local -A assoc=(one buckle two show three knock four door)
- local name='assoc[two]'
- print ${${(P)name}[2,3]}
- }
- testfn
-0:${(P)...} with internal subscripting
->ho
-
- testfn() {
- local one=two
- local two=three
- local three=four
- local -a four=(all these worlds belong to foo)
- print ${(P)${(P)${(P)one}}}
- print ${${(P)${(P)${(P)one}}}[3]}
- }
- testfn
-0:nested parameter name references
->all these worlds belong to foo
->worlds
-
- (
- path=(/random /value)
- testfn1() {
- local path=
- print $#path
- }
- testfn1
- testfn2() {
- local path=/somewhere
- print $#path $path
- }
- testfn2
- print $#path $path
- )
-0:Local special variables with loose typing
->0
->1 /somewhere
->2 /random /value
-
- print -r -- ${(q+):-}
- print -r -- ${(q+)IFS}
- print -r -- ${(q+):-oneword}
- print -r -- ${(q+):-two words}
- print -r -- ${(q+):-three so-called \'words\'}
- (setopt rcquotes; print -r -- ${(q+):-three so-called \'words\'})
-0:${(q+)...}
->''
->$' \t\n\C-@'
->oneword
->'two words'
->'three so-called '\''words'\'
->'three so-called ''words'''
-
- array=(one two three)
- array[1]=${nonexistent:-foo}
- print $array
-0:"-" works after "[" in same expression (Dash problem)
->foo two three
-
- (
- setopt shwordsplit
- set -- whim:wham:whom
- IFS=:
- print -l $@
- )
-0:Splitting of $@ on IFS: single element
->whim
->wham
->whom
-
- (
- setopt shwordsplit
- set -- one:two bucklemy:shoe
- IFS=:
- print -l $@
- )
-0:Splitting of $@ on IFS: multiple elements
-# No forced joining in this case
->one
->two
->bucklemy
->shoe
-
- (
- set -- one:two bucklemy:shoe
- print -l ${(s.:.)@}
- )
-0:Splitting of $@ on (s): multiple elements
-# Forced joining in this case
->one
->two bucklemy
->shoe
-
- (
- set -- one:two bucklemy:shoe
- print -l ${(@s.:.)@}
- )
-0:Splitting of $@ on (@s): multiple elements
-# Forced non-joining in this case
->one
->two
->bucklemy
->shoe
-
- (
- set -- one:two bucklemy:shoe
- IFS=
- setopt shwordsplit
- print -l ${@} ${(s.:.)*} ${(s.:.j.-.)*}
- )
-0:Joining of $@ does not happen when IFS is empty, but splitting $* does
->one:two
->bucklemy:shoe
->one
->twobucklemy
->shoe
->one
->two-bucklemy
->shoe
-
- (
- set -- "one two" "bucklemy shoe"
- IFS=
- setopt shwordsplit rcexpandparam
- print -l "X${(@j.-.)*}"
- )
-0:Use of @ does not prevent forced join with j
->Xone two-bucklemy shoe
-
- () { print -r -- "${(q)1}" "${(b)1}" "${(qq)1}" } '=foo'
-0:(q) and (b) quoting deal with the EQUALS option
->\=foo =foo '=foo'
-
- args() { print $#; }
- a=(foo)
- args "${a[3,-1]}"
- args "${(@)a[3,-1]}"
-0:Out-of-range multiple array subscripts with quoting, with and without (@)
->1
->0
-
- a='~-/'; echo $~a
-0:Regression: "-" became Dash in workers/37689, breaking ~- expansion
-*>*
-F:We do not care what $OLDPWD is, as long as it doesn't cause an error
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D05array.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D05array.ztst
deleted file mode 100644
index 1fa607dd..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D05array.ztst
+++ /dev/null
@@ -1,112 +0,0 @@
-# Tests for array indexing
-
-%prep
-
- foo=(a b c d e f g)
- arr=(foo bar baz)
- mkdir array.tmp
- touch array.tmp/{1..9}
-
-%test
-
- echo .$foo[1].
-0:The first element
->.a.
-
- echo .$foo[1,4].
-0:Normal multi-item indexing
->.a b c d.
-
- echo .$foo[1,0].
-0:This should be empty
->..
-
- echo .$foo[4,1].
-0:Another empty slice
->..
-
- echo .$foo[1,-8].
-0:An empty slice with a negative end
->..
-
- echo .$foo[0].
-0:Treat 0 as empty
->..
-
- echo .$foo[0,0].
-0:Treat 0,0 as empty
->..
-
- echo .$foo[0,1].
-0:Another weird way to access the first element
->.a.
-
- echo .$foo[3].
-0:An inner element
->.c.
-
- echo .$foo[2,2].
-0:Another inner element
->.b.
-
- echo .$foo[2,-4].
-0:A slice with a negative end
->.b c d.
-
- echo .$foo[-4,5].
-0:A slice with a negative start
->.d e.
-
- echo .$foo[-6,-2].
-0:A slice with a negative start and end
->.b c d e f.
-
- echo .${${arr[2]}[1]}.
- echo .${${arr[-2]}[1]}.
- echo .${${arr[2,2]}[1]}.
- echo .${${arr[-2,-2]}[1]}.
- echo .${${arr[2,-2]}[1]}.
- echo .${${arr[-2,2]}[1]}.
-0:Slices should return an array, elements a scalar
->.b.
->.b.
->.bar.
->.bar.
->.bar.
->.bar.
-
- setopt ksh_arrays
- echo .${foo[1,2]}.
- unsetopt ksh_arrays
-0:Ksh array indexing
->.b c.
-
- setopt ksh_arrays
- echo .${foo[0,1]}.
- unsetopt ksh_arrays
-0:Ksh array indexing (ii)
->.a b.
-
- setopt ksh_arrays
- echo .${foo[1,-1]}.
- unsetopt ksh_arrays
-0:Ksh array indexing (iii)
->.b c d e f g.
-
- cd array.tmp
- echo . ?([3,5]) .
- cd ..
-0:Glob array indexing
->. 3 4 5 .
-
- cd array.tmp
- echo . ?([2,-2]) .
- cd ..
-0:Glob array indexing (ii)
->. 2 3 4 5 6 7 8 .
-
- cd array.tmp
- echo . ?([-6,-4]) .
- cd ..
-0:Glob array indexing (iii)
->. 4 5 6 .
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D06subscript.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D06subscript.ztst
deleted file mode 100644
index 14492366..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D06subscript.ztst
+++ /dev/null
@@ -1,268 +0,0 @@
-# Test parameter subscripting.
-
-%prep
-
- s='Twinkle, twinkle, little *, [how] I [wonder] what? You are!'
- a=('1' ']' '?' '\2' '\]' '\?' '\\3' '\\]' '\\?' '\\\4' '\\\]' '\\\?')
- typeset -g -A A
- A=($a)
-
-%test
-
- x=','
- print $s[(i)winkle] $s[(I)winkle]
- print ${s[(i)You are]} $#s
- print ${s[(r)$x,(R)$x]}
-0:Scalar pattern subscripts without wildcards
->2 11
->53 60
->, twinkle, little *,
-
- x='*'
- print $s[(i)*] $s[(i)\*] $s[(i)$x*] $s[(i)${(q)x}*] $s[(I)$x\*]
- print $s[(r)?,(R)\?] $s[(r)\?,(R)?]
- print $s[(r)\*,(R)*]
- print $s[(r)\],(R)\[]
-0:Scalar pattern subscripts with wildcards
->1 26 1 26 26
->Twinkle, twinkle, little *, [how] I [wonder] what? ? You are!
->*, [how] I [wonder] what? You are!
->] I [
-
- print $s[(i)x] : $s[(I)x]
- print $s[(r)x] : $s[(R)x]
-0:Scalar pattern subscripts that do not match
->61 : 0
->:
-
- print -R $s[$s[(i)\[]] $s[(i)$s[(r)\*]] $s[(i)${(q)s[(r)\]]}]
-0:Scalar subscripting using a pattern subscript to get the index
->[ 1 33
-
- print -R $a[(r)?] $a[(R)?]
- print $a[(n:2:i)?] $a[(n:2:I)?]
- print $a[(i)\?] $a[(I)\?]
- print $a[(i)*] $a[(i)\*]
-0:Array pattern subscripts
->1 ?
->2 2
->3 3
->1 13
-
- # It'd be nice to do some of the following with (r), but we run into
- # limitations of the ztst script parsing of backslashes in the output.
- print -R $a[(i)\\\\?] $a[(i)\\\\\?]
- print -R $a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]
- print -R ${a[(i)\\\\\\\\?]} ${a[(i)\\\\\\\\\?]}
- print -R "$a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]"
- print -R $a[(i)\]] $a[(i)\\\\\]] $a[(i)\\\\\\\\\]] $a[(i)\\\\\\\\\\\\\]]
- print -R $a[(i)${(q)a[5]}] $a[(i)${(q)a[8]}] $a[(i)${(q)a[11]}]
- print -R $a[(i)${a[3]}] $a[(i)${a[6]}] $a[(i)${a[9]}] $a[(i)${a[12]}]
-0:Array pattern subscripts with multiple backslashes
->4 6
->7 9
->7 9
->7 9
->2 5 8 11
->5 8 11
->1 3 4 6
-
- print -R $A[1] $A[?] $A[\\\\3] $A[\\\]]
- print -R $A[$a[11]]
- print -R $A[${(q)a[5]}]
-0:Associative array lookup (direct subscripting)
->] \2 \\] \?
->\\\?
->\\\?
-
- # The (o) is necessary here for predictable output ordering
- print -R $A[(I)\?] ${(o)A[(I)?]}
- print -R $A[(i)\\\\\\\\3]
- print -R $A[(I)\\\\\\\\\?] ${(o)A[(I)\\\\\\\\?]}
-0:Associative array lookup (pattern subscripting)
->? 1 ?
->\\3
->\\? \\3 \\?
-
- print -R $A[(R)\?] : ${(o)A[(R)?]}
- print -R $A[(R)\\\\\?] ${(o)A[(R)\\\\?]} ${(o)A[(R)\\\\\?]}
- print -R ${(o)A[(R)\\\\\\\\\]]}
-0:Associative array lookup (reverse subscripting)
->: ]
->\? \2 \? \?
->\\]
-
- eval 'A[*]=star'
-1:Illegal associative array assignment
-?(eval):1: A: attempt to set slice of associative array
-
- x='*'
- A[$x]=xstar
- A[${(q)x}]=qxstar
- print -R ${(k)A[(r)xstar]} $A[$x]
- print -R ${(k)A[(r)qxstar]} $A[${(q)x}]
- A[(e)*]=star
- A[\*]=backstar
- print -R ${(k)A[(r)star]} $A[(e)*]
- print -R ${(k)A[(r)backstar]} $A[\*]
-0:Associative array assignment
->* xstar
->\* qxstar
->* star
->\* backstar
-
- o='['
- c=']'
- A[\]]=cbrack
- A[\[]=obrack
- A[\\\[]=backobrack
- A[\\\]]=backcbrack
- print -R $A[$o] $A[$c] $A[\[] $A[\]] $A[\\\[] $A[\\\]]
- print -R $A[(i)\[] $A[(i)\]] $A[(i)\\\\\[] $A[(i)\\\\\]]
-0:Associative array keys with open and close brackets
->obrack cbrack obrack cbrack backobrack backcbrack
->[ ] \[ \]
-
- print -R $A[$o] $A[$s[(r)\[]]
- print -R $A[(r)$c] $A[(r)$s[(r)\]]]
- print -R $A[$A[(i)\\\\\]]]
-0:Associative array lookup using a pattern subscript to get the key
->obrack obrack
->] ]
->backcbrack
-
- print -R ${A[${A[(r)\\\\\\\\\]]}]::=zounds}
- print -R ${A[${A[(r)\\\\\\\\\]]}]}
- print -R $A[\\\\\]]
-0:Associative array substitution-assignment with reverse pattern subscript key
->zounds
->zounds
->zounds
-
- print -R ${(o)A[(K)\]]}
- print -R ${(o)A[(K)\\\]]}
-0:Associative array keys interpreted as patterns
->\2 backcbrack cbrack star
->\\\4 \\\? star zounds
-
-# It doesn't matter which element we get, since we never guarantee
-# ordering of an associative array. So just test the number of matches.
- array=(${(o)A[(k)\]]})
- print ${#array}
- array=(${(o)A[(k)\\\]]})
- print ${#array}
-0:Associative array keys interpreted as patterns, single match
->1
->1
-
- typeset -g "A[one\"two\"three\"quotes]"=QQQ
- typeset -g 'A[one\"two\"three\"quotes]'=qqq
- print -R "$A[one\"two\"three\"quotes]"
- print -R $A[one\"two\"three\"quotes]
- A[one"two"three"four"quotes]=QqQq
- print -R $A[one"two"three"four"quotes]
- print -R $A[$A[(i)one\"two\"three\"quotes]]
- print -R "$A[$A[(i)one\"two\"three\"quotes]]"
-0:Associative array keys with double quotes
->QQQ
->qqq
->QqQq
->qqq
->QQQ
-
- print ${x::=$A[$A[(i)one\"two\"three\"quotes]]}
- print $x
- print ${x::="$A[$A[(i)one\"two\"three\"quotes]]"}
- print $x
-0:More keys with double quotes, used in assignment-expansion
->qqq
->qqq
->QQQ
->QQQ
-
- qqq=lower
- QQQ=upper
- print ${(P)A[one\"two\"three\"quotes]}
- print "${(P)A[$A[(i)one\"two\"three\"quotes]]}"
-0:Keys with double quotes and the (P) expansion flag
->lower
->upper
-
- typeset -ga empty
- echo X${${empty##*}[-1]}X
-0:Negative index applied to substition result from empty array
->XX
-
- print $empty[(i)] $empty[(I)]
-0:(i) returns 1 for empty array, (I) returns 0.
->1 0
-
- array=(one two three four)
- print X$array[0]X
-0:Element zero is empty if KSH_ZERO_SUBSCRIPT is off.
->XX
-
- array[0]=fumble
-1:Can't set element zero if KSH_ZERO_SUBSCRIPT is off.
-?(eval):1: array: assignment to invalid subscript range
-
- print X$array[(R)notfound]X
-0:(R) returns empty if not found if KSH_ZERO_SUBSCRIPT is off.
->XX
-
- setopt KSH_ZERO_SUBSCRIPT
- print X$array[0]X
-0:Element zero is element one if KSH_ZERO_SUBSCRIPT is on.
->XoneX
-
- array[0]=fimble
- print $array
-0:Can set element zero if KSH_ZERO_SUBSCRIPT is on.
->fimble two three four
-
- print X$array[(R)notfound]X
-0:(R) yuckily returns the first element on failure withe KSH_ZERO_SUBSCRIPT
->XfimbleX
-
- unsetopt KSH_ZERO_SUBSCRIPT
- array[(R)notfound,(r)notfound]=(help help here come the seventies retreads)
- print $array
-0:[(R)notfound,(r)notfound] replaces the whole array
->help help here come the seventies retreads
-
- string="Why, if it isn't Officer Dibble"
- print "[${string[0]}][${string[1]}][${string[0,3]}]"
-0:String subscripts with KSH_ZERO_SUBSCRIPT unset
->[][W][Why]
-
- setopt KSH_ZERO_SUBSCRIPT
- print "[${string[0]}][${string[1]}][${string[0,3]}]"
-0:String subscripts with KSH_ZERO_SUBSCRIPT set
->[W][W][Why]
-
- unsetopt KSH_ZERO_SUBSCRIPT
- string[0,3]="Goodness"
- print $string
-0:Assignment to chunk of string ignores element 0
->Goodness, if it isn't Officer Dibble
-
- string[0]=!
-1:Can't set only element zero of string
-?(eval):1: string: assignment to invalid subscript range
-
- typeset -A assoc=(leader topcat officer dibble sidekick choochoo)
- alias myind='echo leader' myletter='echo 1' myletter2='echo 4'
- print ${assoc[$(myind)]}
- print $assoc[$(myind)]
- print ${assoc[$(myind)][$(myletter)]}${assoc[$(myind)][$(myletter2)]}
- assoc[$(myind)]='of the gang'
- print ${assoc[$(myind)]}
- print $assoc[$(myind)]
- print $assoc[leader]
-0: Parsing subscript with non-trivial tokenisation
->topcat
->topcat
->tc
->of the gang
->of the gang
->of the gang
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D07multibyte.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D07multibyte.ztst
deleted file mode 100644
index e2031534..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D07multibyte.ztst
+++ /dev/null
@@ -1,587 +0,0 @@
-%prep
-
-# Find a UTF-8 locale.
- setopt multibyte
-# Don't let LC_* override our choice of locale.
- unset -m LC_\*
- mb_ok=
- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8
- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8'))
- for LANG in $langs; do
- if [[ é = ? ]]; then
- mb_ok=1
- break;
- fi
- done
- if [[ -z $mb_ok ]]; then
- ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented"
- else
- print -u $ZTST_fd Testing multibyte with locale $LANG
- mkdir multibyte.tmp && cd multibyte.tmp
- fi
-
-%test
-
- a=ténébreux
- for i in {1..9}; do
- print ${a[i]}
- for j in {$i..9}; do
- print $i $j ${a[i,j]} ${a[-j,-i]}
- done
- done
-0:Basic indexing with multibyte characters
->t
->1 1 t x
->1 2 té ux
->1 3 tén eux
->1 4 téné reux
->1 5 ténéb breux
->1 6 ténébr ébreux
->1 7 ténébre nébreux
->1 8 ténébreu énébreux
->1 9 ténébreux ténébreux
->é
->2 2 é u
->2 3 én eu
->2 4 éné reu
->2 5 énéb breu
->2 6 énébr ébreu
->2 7 énébre nébreu
->2 8 énébreu énébreu
->2 9 énébreux ténébreu
->n
->3 3 n e
->3 4 né re
->3 5 néb bre
->3 6 nébr ébre
->3 7 nébre nébre
->3 8 nébreu énébre
->3 9 nébreux ténébre
->é
->4 4 é r
->4 5 éb br
->4 6 ébr ébr
->4 7 ébre nébr
->4 8 ébreu énébr
->4 9 ébreux ténébr
->b
->5 5 b b
->5 6 br éb
->5 7 bre néb
->5 8 breu énéb
->5 9 breux ténéb
->r
->6 6 r é
->6 7 re né
->6 8 reu éné
->6 9 reux téné
->e
->7 7 e n
->7 8 eu én
->7 9 eux tén
->u
->8 8 u é
->8 9 ux té
->x
->9 9 x t
-
- s=é
- print A${s[-2]}A B${s[-1]}B C${s[0]}C D${s[1]}D E${s[2]}E
-0:Out of range subscripts with multibyte characters
->AA BéB CC DéD EE
-
- print ${a[(i)é]} ${a[(I)é]} ${a[${a[(i)é]},${a[(I)é]}]}
-0:Reverse indexing with multibyte characters
->2 4 éné
-
- print ${a[(r)én,(r)éb]}
-0:Subscript searching with multibyte characters
->énéb
-
- print ${a[(rb:1:)é,-1]}
- print ${a[(rb:2:)é,-1]}
- print ${a[(rb:3:)é,-1]}
- print ${a[(rb:4:)é,-1]}
- print ${a[(rb:5:)é,-1]}
-0:Subscript searching with initial offset
->énébreux
->énébreux
->ébreux
->ébreux
->
-
- print ${a[(rn:1:)é,-1]}
- print ${a[(rn:2:)é,-1]}
- print ${a[(rn:3:)é,-1]}
-0:Subscript searching with count
->énébreux
->ébreux
->
-
- print ${a[(R)én,(R)éb]}
-0:Backward subscript searching with multibyte characters
->énéb
-
-# Starting offsets with (R) seem to be so strange as to be hardly
-# worth testing.
-
- setopt extendedglob
- [[ $a = (#b)t(én)(éb)reux ]] || print "Failed to match." >&2
- for i in {1..${#match}}; do
- print $match[i] $mbegin[i] $mend[i] ${a[$mbegin[i],$mend[i]]}
- done
-0:Multibyte offsets in pattern tests
->én 2 3 én
->éb 4 5 éb
-
- b=${(U)a}
- print $b
- print ${(L)b}
- desdichado="Je suis le $a, le veuf, l'inconsolé"
- print ${(C)desdichado}
- lxiv="l'état c'est moi"
- print ${(C)lxiv}
-0:Case modification of multibyte strings
->TÉNÉBREUX
->ténébreux
->Je Suis Le Ténébreux, Le Veuf, L'Inconsolé
->L'État C'Est Moi
-
- array=(ølaf ødd øpened án encyclopædia)
- barray=(${(U)array})
- print $barray
- print ${(L)barray}
- print ${(C)array}
- print ${(C)barray}
-0:Case modification of arrays with multibyte strings
->ØLAF ØDD ØPENED ÁN ENCYCLOPÆDIA
->ølaf ødd øpened án encyclopædia
->Ølaf Ødd Øpened Án Encyclopædia
->Ølaf Ødd Øpened Án Encyclopædia
-
- print $(( ##¥ ))
- pound=£
- print $(( #pound ))
- alpha=α
- print $(( ##α )) $(( #alpha ))
-0:Conversion to Unicode in mathematical expressions
->165
->163
->945 945
-
- unsetopt posix_identifiers
- expr='hähä=3 || exit 1; print $hähä'
- eval $expr
- setopt posix_identifiers
- (eval $expr)
-1:POSIX_IDENTIFIERS option
->3
-?(eval):1: command not found: hähä=3
-
- foo="Ølaf«Ødd«øpénëd«ån«àpple"
- print -l ${(s.«.)foo}
- ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος."
- print -l ${=ioh}
- print ${(w)#ioh}
-0:Splitting with multibyte characters
->Ølaf
->Ødd
->øpénëd
->ån
->àpple
->Ἐν
->ἀρχῇ
->ἦν
->ὁ
->λόγος,
->καὶ
->ὁ
->λόγος
->ἦν
->πρὸς
->τὸν
->θεόν,
->καὶ
->θεὸς
->ἦν
->ὁ
->λόγος.
->17
-
- read -d £ one
- read -d £ two
- print $one
- print $two
-0:read with multibyte delimiter
-first
->second
-
- (IFS=«
- read -d » -A array
- print -l $array)
-0:read -A with multibyte IFS
-dominus
->illuminatio
->mea
-
- read -k2 -u0 twochars
- print $twochars
-0:read multibyte characters
-<«»ignored
->«»
-
- read -q -u0 mb
- print $?
-0:multibyte character makes read -q return false
-<«
->1
-
- # See if the system grokks first-century Greek...
- ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος."
- for (( i = 1; i <= ${#ioh}; i++ )); do
- # FC3 doesn't recognise ῇ (U+1FC7: Greek small letter eta with
- # perispomeni and ypogegrammeni, of course) as a lower case character.
- if [[ $ioh[i] != [[:lower:]] && $i != 7 ]]; then
- for tp in upper space punct invalid; do
- if [[ $tp = invalid || $ioh[i] = [[:${tp}:]] ]]; then
- print "$i: $tp"
- break
- fi
- done
- fi
- done
-0:isw* functions on non-ASCII wide characters
->1: upper
->3: space
->8: space
->11: space
->13: space
->19: punct
->20: space
->24: space
->26: space
->32: space
->35: space
->40: space
->44: space
->49: punct
->50: space
->54: space
->59: space
->62: space
->64: space
->70: punct
-
- ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος"
- print ${ioh#[[:alpha:]]##}
- print ${ioh##[[:alpha:]]##}
- print ${ioh%[[:alpha:]]##}
- print ${ioh%%[[:alpha:]]##}
- print ${(S)ioh#λ*ς}
- print ${(S)ioh##λ*ς}
- print ${(S)ioh%θ*ς}
- print ${(S)ioh%%θ*ς}
-0:Parameter #, ##, %, %% with multibyte characters
->ν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
-> ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
->Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγο
->Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ
->Ἐν ἀρχῇ ἦν ὁ , καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος
->Ἐν ἀρχῇ ἦν ὁ
->Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ ἦν ὁ λόγος
->Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ
-
- a="1ë34ë6"
- print ${(BEN)a#*4}
- print ${(BEN)a##*ë}
- print ${(BEN)a%4*}
- print ${(BEN)a%%ë*}
- print ${(SBEN)a#ë3}
- print ${(SBEN)a%4ë}
-0:Flags B, E, N and S in ${...#...} and ${...%...}
->1 5 4
->1 6 5
->4 7 3
->2 7 5
->2 4 2
->4 6 2
-
- foo=(κατέβην χθὲς εἰς Πειραιᾶ)
- print ${(l.3..¥.r.3..£.)foo}
- print ${(l.4..¥.r.2..£.)foo}
- print ${(l.5..¥.r.1..£.)foo}
- print ${(l.4..¥..«.r.4..£..».)foo}
- print ${(l.4..¥..Σωκράτης.r.4..£..Γλαύκωνος.)foo}
-0:simultaneous left and right padding
->κατέβη ¥χθὲς£ ¥¥εἰς£ Πειραι
->¥κατέβ ¥¥χθὲς ¥¥¥εἰς ¥Πειρα
->¥¥κατέ ¥¥¥χθὲ ¥¥¥¥εἰ ¥¥Πειρ
->«κατέβην ¥«χθὲς»£ ¥¥«εἰς»£ «Πειραιᾶ
->ςκατέβην ηςχθὲςΓλ τηςεἰςΓλ ςΠειραιᾶ
-# er... yeah, that looks right...
-
- foo=picobarn
- print ${foo:s£bar£rod£:s¥rod¥stick¥}
-0:Delimiters in modifiers
->picostickn
-
-# TODO: if we get paired multibyte bracket delimiters to work
-# (as Emacs does, the smug so-and-so), the following should change.
- foo=bar
- print ${(r£5££X£)foo}
- print ${(l«10««Y««HI«)foo}
-0:Delimiters in parameter flags
->barXX
->YYYYYHIbar
-
- printf "%4.3s\n" főobar
-0:Multibyte characters in printf widths
-> főo
-
-# We ask for case-insensitive sorting here (and supply upper case
-# characters) so that we exercise the logic in the shell that lowers the
-# case of the string for case-insensitive sorting.
- print -oi HÛH HÔH HÎH HÊH HÂH
- (LC_ALL=C; print -oi HAH HUH HEH HÉH HÈH)
-0:Multibyte characters in print sorting
->HÂH HÊH HÎH HÔH HÛH
->HAH HEH HUH HÈH HÉH
-
-# These are control characters in Unicode, so don't show up.
-# We just want to check they're not being treated as tokens.
- for x in {128..150}; do
- print ${(#)x}
- done | while read line; do
- print ${#line} $(( #line ))
- done
-0:evaluated character number with multibyte characters
->1 128
->1 129
->1 130
->1 131
->1 132
->1 133
->1 134
->1 135
->1 136
->1 137
->1 138
->1 139
->1 140
->1 141
->1 142
->1 143
->1 144
->1 145
->1 146
->1 147
->1 148
->1 149
->1 150
-
- touch ngs1txt ngs2txt ngs10txt ngs20txt ngs100txt ngs200txt
- setopt numericglobsort
- print -l ngs*
-0:NUMERIC_GLOB_SORT option in UTF-8 locale
->ngs1txt
->ngs2txt
->ngs10txt
->ngs20txt
->ngs100txt
->ngs200txt
-
-# Not strictly multibyte, but gives us a well-defined locale for testing.
- foo=$'X\xc0Y\x07Z\x7fT'
- print -r ${(q)foo}
-0:Backslash-quoting of unprintable/invalid characters uses $'...'
->X$'\300'Y$'\a'Z$'\177'T
-
-# This also isn't strictly multibyte and is here to reduce the
-# likelihood of a "cannot do character set conversion" error.
- (print $'\u00e9') 2>&1 | read
- if [[ $REPLY != é ]]; then
- print "warning: your system can't do simple Unicode conversion." >&$ZTST_fd
- print "Check you have a correctly installed iconv library." >&$ZTST_fd
- # cheat
- repeat 4 print OK
- else
- testfn() { (LC_ALL=C; print $'\u00e9') }
- repeat 4 testfn 2>&1 | while read line; do
- if [[ $line = *"character not in range"* ]]; then
- print OK
- elif [[ $line = "?" ]]; then
- print OK
- else
- print Failed: no error message and no question mark
- fi
- done
- fi
- true
-0:error handling in Unicode quoting
->OK
->OK
->OK
->OK
-
- tmp1='glob/\(\)Ą/*'
- [[ glob/'()Ą'/foo == $~tmp1 ]] && print "Matched against $tmp1"
- tmp1='glob/\(\)Ā/*'
- [[ glob/'()Ā'/bar == $~tmp1 ]] && print "Matched against $tmp1"
-0:Backslashes and metafied characters in patterns
->Matched against glob/()Ą/*
->Matched against glob/()Ā/*
-
- mkdir 梶浦由記 'Пётр Ильич Чайковский'
- (cd 梶浦由記; print ${${(%):-%~}:t})
- (cd 'Пётр Ильич Чайковский'; print ${${(%):-%~}:t})
-0:Metafied characters in prompt expansion
->梶浦由記
->Пётр Ильич Чайковский
-
- (
- setopt nonomatch
- tmp1=Ą
- tmpA=(Ą 'Пётр Ильич Чайковский' 梶浦由記)
- print ${tmp1} ${(%)tmp1} ${(%%)tmp1}
- print ${#tmp1} ${#${(%)tmp1}} ${#${(%%)tmp1}}
- print ${tmpA}
- print ${(%)tmpA}
- print ${(%%)tmpA}
- )
-0:More metafied characters in prompt expansion
->Ą Ą Ą
->1 1 1
->Ą Пётр Ильич Чайковский 梶浦由記
->Ą Пётр Ильич Чайковский 梶浦由記
->Ą Пётр Ильич Чайковский 梶浦由記
-
- setopt cbases
- print $'\xc5' | read
- print $(( [#16] #REPLY ))
-0:read passes through invalid multibyte characters
->0xC5
-
- word=abcま
- word[-1]=
- print $word
- word=abcま
- word[-2]=
- print $word
- word=abcま
- word[4]=d
- print $word
- word=abcま
- word[3]=not_c
- print $word
-0:assignment with negative indices
->abc
->abま
->abcd
->abnot_cま
-
- # The following doesn't necessarily need UTF-8, but this gives
- # us the full effect --- if we parse this wrongly the \xe9
- # in combination with the tokenized input afterwards looks like a
- # valid UTF-8 character. But it isn't.
- print $'$\xe9#``' >test_bad_param
- (setopt nonomatch
- . ./test_bad_param)
-127:Invalid parameter name with following tokenized input
-?./test_bad_param:1: command not found: $\M-i#
-
- lines=$'one\tZSH\tthree\nfour\tfive\tsix'
- print -X8 -r -- $lines
-0:Tab expansion with extra-wide characters
->one ZSH three
->four five six
-# This doesn't look aligned in my editor because actually the characters
-# aren't quite double width, but the arithmetic is correct.
-# It appears just to be an effect of the font.
-
- () {
- emulate -L zsh
- setopt errreturn
- local cdpath=(.)
- mkdir ホ
- cd ホ
- cd ..
- cd ./ホ
- cd ..
- }
-0:cd with special characters
-
- test_array=(
- '[[ \xcc = \xcc ]]'
- '[[ \xcc != \xcd ]]'
- '[[ \xcc != \ucc ]]'
- '[[ \ucc = \ucc ]]'
- '[[ \ucc = [\ucc] ]]'
- '[[ \xcc != [\ucc] ]]'
- # Not clear how useful the following is...
- '[[ \xcc = [\xcc] ]]'
- )
- for test in $test_array; do
- if ! eval ${(g::)test} ; then
- print -rl "Test $test failed" >&2
- fi
- done
-0:Invalid characters in pattern matching
-
- [[ $'\xe3' == [[:INCOMPLETE:]] ]] || print fail 1
- [[ $'\xe3\x83' == [[:INCOMPLETE:]][[:INVALID:]] ]] || print fail 2
- [[ $'\xe3\x83\x9b' != [[:INCOMPLETE:][:INVALID:]] ]] || print fail 3
- [[ $'\xe3\x83\x9b' = ? ]] || print fail 4
-0:Testing incomplete and invalid multibyte character components
-
- print -r -- ${(q+):-ホ}
- foo='She said "ホ". I said "You can'\''t '\''ホ'\'' me!'
- print -r -- ${(q+)foo}
-0:${(q+)...} with printable multibyte characters
->ホ
->'She said "ホ". I said "You can'\''t '\''ホ'\'' me!'
-
-# This will silently succeed if zsh/parameter isn't available
- (zmodload zsh/parameter >/dev/null 2>&1
- f() {
- : $(:)
- "↓"
- }
- : $functions)
-0:Multibyte handling of functions parameter
-
-# c1=U+0104 (Ą) and c2=U+0120 (Ġ) are chosen so that
-# u1 = utf8(c1) = c4 84 < u2 = utf8(c2) = c4 a0
-# metafy(u1) = c4 83 a4 > metafy(u2) = c4 83 80
-# in both UTF-8 and ASCII collations (the latter is used in macOS
-# and some versions of BSDs).
- local -a names=( $'\u0104' $'\u0120' )
- print -o $names
- mkdir -p colltest
- cd colltest
- touch $names
- print ?
-0:Sorting of metafied characters
->Ą Ġ
->Ą Ġ
-
- printf '%q%q\n' 你你
-0:printf %q and quotestring and general metafy / token madness
->你你
-
-# This test is kept last as it introduces an additional
-# dependency on the system regex library.
- if zmodload zsh/regex 2>/dev/null; then
- [[ $'\ua0' =~ '^.$' ]] && print OK
- [[ $'\ua0' =~ $'^\ua0$' ]] && print OK
- [[ $'\ua0'X =~ '^X$' ]] || print OK
- else
- ZTST_skip="regexp library not found."
- fi
-0:Ensure no confusion on metafied input to regex module
->OK
->OK
->OK
-F:A failure here may indicate the system regex library does not
-F:support character sets outside the portable 7-bit range.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D08cmdsubst.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D08cmdsubst.ztst
deleted file mode 100644
index 36253734..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D08cmdsubst.ztst
+++ /dev/null
@@ -1,169 +0,0 @@
-# Tests for command substitution.
-
-%prep
- mkdir cmdsubst.tmp
- touch cmdsubst.tmp/file{1,2}.txt
-
-%test
- foo="two words"
- print -l `echo $foo bar`
-0:Basic `...` substitution
->two
->words
->bar
-
- foo="two words"
- print -l $(echo $foo bar)
-0:Basic $(...) substitution
->two
->words
->bar
-
- foo='intricate buffoonery'
- print -l "`echo $foo and licentiousness`"
-0:Quoted `...` substitution
->intricate buffoonery and licentiousness
-
- foo="more words"
- print -l "$(echo $foo here)"
-0:Quoted $(...) substitution
->more words here
-
-# we used never to get this one right, but I think it is now...
- print -r "`print -r \\\\\\\\`"
-0:Stripping of backslasshes in quoted `...`
->\\
-
- print -r "$(print -r \\\\\\\\)"
-0:Stripping of backslashes in quoted $(...)
->\\\\
-
- fnify() { print \"$*\"; }
- print `fnify \`fnify understatement\``
-0:Nested `...`
->""understatement""
-
- print $(fnify $(fnify overboard))
-0:Nested $(...)
->""overboard""
-
- fructify() { print \'$*\'; }
- print "`fructify \`fructify indolence\``"
-0:Nested quoted `...`
->''indolence''
-
- print "$(fructify $(fructify obtuseness))"
-0:Nested quoted $(...)
->''obtuseness''
-
- gesticulate() { print \!$*\!; }
- print $((gesticulate wildly); gesticulate calmly)
-0:$(( ... ) ... ) is not arithmetic
->!wildly! !calmly!
-
- commencify() { print +$*+; }
- print "$((commencify output); commencify input)"
-0:quoted $(( ... ) .. ) is not arithmetic
->+output+
->+input+
-
- (
- cd cmdsubst.tmp
- print first: ${$(print \*)}
- print second: ${~$(print \*)}
- print third: ${$(print *)}
- print fourth: "${~$(print \*)}"
- print fifth: ${~"$(print \*)"}
- )
-0:mixing $(...) with parameter substitution and globbing
->first: *
->second: file1.txt file2.txt
->third: file1.txt file2.txt
->fourth: *
->fifth: file1.txt file2.txt
-
- $(exit 0) $(exit 3) || print $?
-0:empty command uses exit value of last substitution
->3
-
- X=$(exit 2) $(exit 0) || print $?
-0:variable assignments processed after other substitutions
->2
-
- false
- ``
-0:Empty command substitution resets status
-
- false
- echo `echo $?`
-0:Non-empty command substitution inherits status
->1
-
- echo $(( ##\" ))
- echo $(echo \")
- echo $((echo \"); echo OK)
-0:Handling of backslash double quote in parenthesised substitutions
->34
->"
->" OK
-
- echo $(case foo in
- foo)
- echo This test worked.
- ;;
- bar)
- echo This test failed in a rather bizarre way.
- ;;
- *)
- echo This test failed.
- ;;
- esac)
-0:Parsing of command substitution with unmatched parentheses: case, basic
->This test worked.
-
- echo "$(case bar in
- foo)
- echo This test spoobed.
- ;;
- bar)
- echo This test plurbled.
- ;;
- *)
- echo This test bzonked.
- ;;
- esac)"
-0:Parsing of command substitution with unmatched parentheses: case with quotes
->This test plurbled.
-
- echo before $(
- echo start; echo unpretentious |
- while read line; do
- case $line in
- u*)
- print Word began with u
- print and ended with a crunch
- ;;
- esac
- done | sed -e 's/Word/Universe/'; echo end
- ) after
-0:Parsing of command substitution with ummatched parentheses: with frills
->before start Universe began with u and ended with a crunch end after
-
- alias foo='echo $('
- eval 'foo echo this just works, OK\?)'
-0:backtracking within command string parsing with alias still pending
->this just works, OK?
-
- (
- set errexit
- show_nargs() { print $#; }
- print a $() b
- print c "$()" d
- )
-0:Empty $() is a valid empty substitution.
->a b
->c d
-
- empty=$() && print "'$empty'"
-0:Empty $() is a valid assignment
->''
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D09brace.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D09brace.ztst
deleted file mode 100644
index 3e667a8d..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/D09brace.ztst
+++ /dev/null
@@ -1,114 +0,0 @@
-# Tests for brace expansion
-
-%prep
-
- foo=(a b c)
- arr=(foo bar baz)
-
-%test
-
- print X{1,2,{3..6},7,8}Y
-0:Basic brace expansion
->X1Y X2Y X3Y X4Y X5Y X6Y X7Y X8Y
-
- print ${foo}{one,two,three}$arr
-0:Brace expansion with arrays, no RC_EXPAND_PARAM
->a b conefoo ctwofoo cthreefoo bar baz
-
- print ${^foo}{one,two,three}$arr
-0:Brace expansion with arrays, with RC_EXPAND_PARAM (1)
->aonefoo atwofoo athreefoo bonefoo btwofoo bthreefoo conefoo ctwofoo cthreefoo bar baz
-
- print ${foo}{one,two,three}$^arr
-0:Brace expansion with arrays, with RC_EXPAND_PARAM (2)
->a b conefoo ctwofoo cthreefoo conebar ctwobar cthreebar conebaz ctwobaz cthreebaz
-
- print ${^foo}{one,two,three}$^arr
-0:Brace expansion with arrays, with RC_EXPAND_PARAM (3)
->aonefoo atwofoo athreefoo aonebar atwobar athreebar aonebaz atwobaz athreebaz bonefoo btwofoo bthreefoo bonebar btwobar bthreebar bonebaz btwobaz bthreebaz conefoo ctwofoo cthreefoo conebar ctwobar cthreebar conebaz ctwobaz cthreebaz
-
- print X{01..4}Y
-0:Numeric range expansion, padding (1)
->X01Y X02Y X03Y X04Y
-
- print X{1..04}Y
-0:Numeric range expansion, padding (2)
->X01Y X02Y X03Y X04Y
-
- print X{7..12}Y
-0:Numeric range expansion, padding (or not) (3)
->X7Y X8Y X9Y X10Y X11Y X12Y
-
- print X{07..12}Y
-0:Numeric range expansion, padding (4)
->X07Y X08Y X09Y X10Y X11Y X12Y
-
- print X{7..012}Y
-0:Numeric range expansion, padding (5)
->X007Y X008Y X009Y X010Y X011Y X012Y
-
- print X{4..1}Y
-0:Numeric range expansion, decreasing
->X4Y X3Y X2Y X1Y
-
- print X{1..4}{1..4}Y
-0:Numeric range expansion, combined braces
->X11Y X12Y X13Y X14Y X21Y X22Y X23Y X24Y X31Y X32Y X33Y X34Y X41Y X42Y X43Y X44Y
-
- print X{-4..4}Y
-0:Numeric range expansion, negative numbers (1)
->X-4Y X-3Y X-2Y X-1Y X0Y X1Y X2Y X3Y X4Y
-
- print X{4..-4}Y
-0:Numeric range expansion, negative numbers (2)
->X4Y X3Y X2Y X1Y X0Y X-1Y X-2Y X-3Y X-4Y
-
- print X{004..-4..2}Y
-0:Numeric range expansion, stepping and padding (1)
->X004Y X002Y X000Y X-02Y X-04Y
-
- print X{4..-4..02}Y
-0:Numeric range expansion, stepping and padding (1)
->X04Y X02Y X00Y X-2Y X-4Y
-
- print X{1..32..3}Y
-0:Numeric range expansion, step alignment (1)
->X1Y X4Y X7Y X10Y X13Y X16Y X19Y X22Y X25Y X28Y X31Y
-
- print X{1..32..-3}Y
-0:Numeric range expansion, step alignment (2)
->X31Y X28Y X25Y X22Y X19Y X16Y X13Y X10Y X7Y X4Y X1Y
-
- print X{32..1..3}Y
-0:Numeric range expansion, step alignment (3)
->X32Y X29Y X26Y X23Y X20Y X17Y X14Y X11Y X8Y X5Y X2Y
-
- print X{32..1..-3}Y
-0:Numeric range expansion, step alignment (4)
->X2Y X5Y X8Y X11Y X14Y X17Y X20Y X23Y X26Y X29Y X32Y
-
- setopt brace_ccl
- print X{za-q521}Y
- unsetopt brace_ccl
-0:BRACE_CCL on
->X1Y X2Y X5Y XaY XbY XcY XdY XeY XfY XgY XhY XiY XjY XkY XlY XmY XnY XoY XpY XqY XzY
-
- print X{za-q521}Y
-0:BRACE_CCL off
->X{za-q521}Y
-
- print -r hey{a..j}there
-0:{char..char} ranges, simple case
->heyathere heybthere heycthere heydthere heyethere heyfthere heygthere heyhthere heyithere heyjthere
-
- print -r gosh{1,{Z..a},2}cripes
-0:{char..char} ranges, ASCII ordering
->gosh1cripes goshZcripes gosh[cripes gosh\cripes gosh]cripes gosh^cripes gosh_cripes gosh`cripes goshacripes gosh2cripes
-
- print -r crumbs{y..p}ooh
-0:{char..char} ranges, reverse
->crumbsyooh crumbsxooh crumbswooh crumbsvooh crumbsuooh crumbstooh crumbssooh crumbsrooh crumbsqooh crumbspooh
-
- print -r left{[..]}right
-0:{char..char} ranges with tokenized characters
->left[right left\right left]right
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E01options.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E01options.ztst
deleted file mode 100644
index 2bd4fdb1..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E01options.ztst
+++ /dev/null
@@ -1,1313 +0,0 @@
-# Test various shell options.
-# Interactive options not tested here:
-# ALWAYS_LAST_PROMPT
-# ALWAYS_TO_END
-# APPEND_HISTORY (history not maintained)
-# AUTO_LIST
-# AUTO_MENU
-# AUTO_NAME_DIRS (named directory table not maintained)
-# AUTO_PARAM_KEYS
-# AUTO_PARAM_SLASH
-# AUTO_REMOVE_SLASH
-# AUTO_RESUME
-# BANG_HIST
-# BASH_AUTO_LIST
-# BEEP (!)
-# BG_NICE
-# CHECK_JOBS
-# COMPLETE_ALIASES
-# COMPLETE_IN_WORD
-# CORRECT
-# CORRECT_ALL
-# CSH_JUNKIE_HISTORY
-# DVORAK
-# EXTENDED_HISTORY
-# FLOW_CONTROL
-# GLOB_COMPLETE
-# HIST_ALLOW_CLOBBER
-# HIST_BEEP
-# HIST_EXPIRE_DUPS_FIRST
-# HIST_FIND_NO_DUPS
-# HIST_IGNORE_ALL_DUPS
-# HIST_IGNORE_DUPS (-h)
-# HIST_IGNORE_SPACE (-g)
-# HIST_NO_FUNCTIONS
-# HIST_NO_STORE
-# HIST_REDUCE_BLANKS
-# HIST_SAVE_NO_DUPS
-# HIST_VERIFY
-# HUP
-# IGNORE_EOF
-# INC_APPEND_HISTORY
-# INTERACTIVE
-# INTERACTIVE_COMMENTS
-# LIST_AMBIGUOUS
-# LIST_BEEP
-# LIST_PACKED
-# LIST_ROWS_FIRST
-# LIST_TYPES
-# LOGIN
-# LONG_LIST_JOBS
-# MAIL_WARNING
-# MENU_COMPLETE
-# MONITOR
-# NOTIFY
-# OVERSTRIKE
-# PRINT_EIGHT_BIT
-# PROMPT_CR
-# PUSHD_SILENT
-# REC_EXACT
-# RM_STAR_SILENT
-# RM_STAR_WAIT
-# SHARE_HISTORY
-# SINGLE_LINE_ZLE
-# SUN_KEYBOARD_HACK
-# ZLE
-# The following require SHINSTDIN and are not (yet) tested:
-# AUTO_CD
-# SHINSTDIN
-#
-# Other difficult things I haven't done:
-# GLOBAL_RCS (uses fixed files outside build area)
-# HASH_CMDS )
-# HASH_DIRS ) fairly seriously internal, hard to test at all
-# HASH_LIST_ALL )
-# PRINT_EXIT_STATUS haven't worked out what this does yet, although
-# Bart suggested a fix.
-# PRIVILEGED (similar to GLOBAL_RCS)
-# RCS ( " " " " )
-# SH_OPTION_LETTERS even I found this too dull to set up a test for
-# SINGLE_COMMAND kills shell
-# VERBOSE hard because done on input (c.f. SHINSTDIN).
-
-%prep
- mkdir options.tmp && cd options.tmp
-
- mkdir tmpcd homedir
-
- touch tmpfile1 tmpfile2
-
- mydir=$PWD
- mydirt=`print -P %~`
- mydirhome=`export HOME=$mydir/homedir; print -P %~`
- catpath=$(which cat)
- lspath==ls
-
-%test
-
- alias echo='print foo'
- unsetopt aliases
- # use eval else aliases are all parsed at start
- eval echo bar
- setopt aliases
- eval echo bar
- unalias echo
-0:ALIASES option
->bar
->foo bar
-
- setopt allexport
- testpm1=exported
- unsetopt allexport
- testpm2=unexported
- print ${(t)testpm1}
- print ${(t)testpm2}
-0:ALL_EXPORT option
->scalar-export
->scalar
-
- # Count the number of directories on the stack. Don't care what they are.
- dircount() { dirs -v | tail -1 | awk '{ print $1 + 1}'; }
- unsetopt autopushd
- cd tmpcd
- dircount
- cd ..
- setopt autopushd
- cd tmpcd
- dircount
- unsetopt autopushd
- popd >/dev/null
-0:AUTO_PUSHD option
->1
->2
-
- unsetopt badpattern
- print [a
- setopt badpattern
- print [b
-1:BAD_PATTERN option
->[a
-?(eval):4: bad pattern: [b
-
- unsetopt bareglobqual nomatch
- print *(.)
- setopt bareglobqual nomatch
- print *(.)
-0:BARE_GLOB_QUAL option
->*(.)
->tmpfile1 tmpfile2
-
- setopt braceccl
- print {abcd}
- unsetopt braceccl
- print {abcd}
-0:BRACE_CCL option
->a b c d
->{abcd}
-
-# Don't use NUL as a field separator in the following.
- setopt braceccl
- print {$'\0'-$'\5'} | IFS=' ' read -A chars
- for c in $chars; do print $(( #c )); done
- unsetopt braceccl
-0:BRACE_CCL option starting from NUL
->0
->1
->2
->3
->4
->5
-
- setopt bsdecho
- echo "histon\nimpington"
- echo -e "girton\ncottenham"
- unsetopt bsdecho
- echo "newnham\ncomberton"
-0:BSD_ECHO option
->histon\nimpington
->girton
->cottenham
->newnham
->comberton
-
- unsetopt c_bases
- print $(( [#16]15 ))
- print $(( [#8]9 ))
- setopt c_bases
- print $(( [#16]31 ))
- print $(( [#8]17 ))
- setopt octal_zeroes
- print $(( [#8]19 ))
- unsetopt c_bases octal_zeroes
-0:C_BASES option
->16#F
->8#11
->0x1F
->8#21
->023
-
- setopt cdablevars
- # only absolute paths are eligible for ~-expansion
- cdablevar1=tmpcd
- (cd cdablevar1)
- cdablevar2=$PWD/tmpcd
- cd cdablevar2
- cd ..
- print back in ${PWD:t}
- unsetopt cdablevars
- cd cdablevar2
-1q:CDABLE_VARS option
->back in options.tmp
-?(eval):cd:4: no such file or directory: cdablevar1
-?(eval):cd:10: no such file or directory: cdablevar2
-
-# CHASE_DOTS should go with CHASE_LINKS in B01cd.ztst
-# which saves me having to write it here.
-
- setopt noclobber
- rm -f foo1 bar1 rod1
- echo waterbeach >foo1
- (echo landbeach >foo1)
- cat foo1
- (echo lode >>bar1)
- [[ -f bar1 ]] && print That shouldn\'t be there.
- echo denny >rod1
- echo wicken >>rod1
- cat rod1
- unsetopt noclobber
- rm -f foo2 bar2 rod2
- echo ely >foo2
- echo march >foo2
- cat foo2
- echo wimpole >>bar2
- cat bar2
- echo royston >rod2
- echo foxton >>rod2
- cat rod2
- rm -f foo* bar* rod*
-0:CLOBBER option
->waterbeach
->denny
->wicken
->march
->wimpole
->royston
->foxton
-?(eval):4: file exists: foo1
-?(eval):6: no such file or directory: bar1
-
- setopt cshjunkieloops
- eval 'for f in swaffham bulbeck; print $f; end'
- print next one should fail >&2
- unsetopt cshjunkieloops
- eval 'for f in chesterton arbury; print $f; end'
-1:CSH_JUNKIE_LOOPS option (for loop)
->swaffham
->bulbeck
-?next one should fail
-?(eval):1: parse error near `end'
-
-# ` emacs deconfusion
-
- setopt cshjunkiequotes
- print this should cause an error >&2
- eval "print 'line one
- line two'"
- print this should not >&2
- eval "print 'line three\\
- line four'"
- unsetopt cshjunkiequotes
-0:CSH_JUNKIE_QUOTES option
->line three
-> line four
-?this should cause an error
-?(eval):1: unmatched '
-?this should not
-
-# ' emacs deconfusion
-
- nullcmd() { print '$NULLCMD run'; }
- readnullcmd() { print 'Running $READNULLCMD'; cat; }
- NULLCMD=nullcmd
- READNULLCMD=readnullcmd
- setopt cshnullcmd
- rm -f foo
- print "This should fail" >&2
- (>foo)
- print "This should succeed" >&2
- print "These are the contents of foo" >foo
- cat foo
- print "This should also fail" >&2
- (foo
- These are the contents of foo
->Running $READNULLCMD
->$NULLCMD run
-?This should fail
-?(eval):8: redirection with no command
-?This should succeed
-?This should also fail
-?(eval):13: redirection with no command
-
-# nomatch should be overridden by cshnullglob
- setopt nomatch cshnullglob
- print tmp* nothing* blah
- print -n 'hoping for no match: ' >&2
- (print nothing* blah)
- print >&2
- unsetopt cshnullglob nomatch
- print tmp* nothing* blah
- print nothing* blah
-0:CSH_NULL_GLOB option
->tmpcd tmpfile1 tmpfile2 blah
->tmpcd tmpfile1 tmpfile2 nothing* blah
->nothing* blah
-?hoping for no match: (eval):4: no match
-?
-
-# The trick is to avoid =cat being expanded in the output while $catpath is.
- setopt NO_equals
- print -n trick; print =cat
- setopt equals
- print -n trick; print =cat
-0q:EQUALS option
->trick=cat
->trick$catpath
-
-# explanation of expected TRAPZERR output: from false and from
-# testfn() with ERR_EXIT on (hmm, should we really get a second one from
-# the function exiting?), then from the false only with ERR_EXIT off.
- TRAPZERR() { print ZERR trapped; }
- testfn() { setopt localoptions $2; print $1 before; false; print $1 after; }
- (testfn on errexit)
- testfn off
- unfunction TRAPZERR testfn
-0:ERR_EXIT option
->on before
->ZERR trapped
->ZERR trapped
->off before
->ZERR trapped
->off after
-
- (print before; setopt noexec; print after)
-0:NO_EXEC option
->before
-
- (setopt noexec
- typeset -A hash
- hash['this is a string'])
-0:NO_EXEC option should not attempt to parse subscripts
-
- (setopt noexec nomatch
- echo *NonExistentFile*)
-0:NO_EXEC option should not do globbing
-
- (setopt noexec
- echo ${unset_var?Not an error})
-0:NO_EXEC should not test for unset variables
-
- (setopt noexec
- : ${${string%[aeiou]*}/(#m)?(#e)/${(U)MATCH}} Rule 1
- : ${array[4,5][1][2,3]} Rule 2
- : ${${(P)foo[1,6]}[1,3]} Rule 3
- : "${${(@)array}[1,2]}" Rule 5
- : "${(@)${(@)array}[1,2]#?}" Rule 6
- : ${(el.20..X.)${bar}} Rule 11 success case)
-0:NO_EXEC handles parameter substitution examples
-
- (setopt noexec
- : ${(el.20..X.)$bar} Rule 11 failure case)
-1:NO_EXEC does recognize bad substitution syntax
-*?* bad substitution
-
- setopt NO_eval_lineno
- eval 'print $LINENO'
- setopt eval_lineno
- eval 'print $LINENO'
-0:EVAL_LINENO option
->2
->1
-
- # The EXTENDED_GLOB test doesn't test globbing fully --- it just tests
- # that certain patterns are treated literally with the option off
- # and as patterns with the option on.
- testfn() { print -n "$1 $2 $3 "; if [[ $1 = ${~2} ]];
- then print yes; else print no; fi; }
- tests=('a#' '?~b' '^aa')
- strings=('a' 'aa' 'b' 'a#' '?~b' '^aa')
- for opt in noextendedglob extendedglob; do
- setopt $opt
- for test in $tests; do
- for string in $strings; do
- testfn $string $test $opt
- done
- done
- done
-0:EXTENDED_GLOB option
->a a# noextendedglob no
->aa a# noextendedglob no
->b a# noextendedglob no
->a# a# noextendedglob yes
->?~b a# noextendedglob no
->^aa a# noextendedglob no
->a ?~b noextendedglob no
->aa ?~b noextendedglob no
->b ?~b noextendedglob no
->a# ?~b noextendedglob no
->?~b ?~b noextendedglob yes
->^aa ?~b noextendedglob no
->a ^aa noextendedglob no
->aa ^aa noextendedglob no
->b ^aa noextendedglob no
->a# ^aa noextendedglob no
->?~b ^aa noextendedglob no
->^aa ^aa noextendedglob yes
->a a# extendedglob yes
->aa a# extendedglob yes
->b a# extendedglob no
->a# a# extendedglob no
->?~b a# extendedglob no
->^aa a# extendedglob no
->a ?~b extendedglob yes
->aa ?~b extendedglob no
->b ?~b extendedglob no
->a# ?~b extendedglob no
->?~b ?~b extendedglob no
->^aa ?~b extendedglob no
->a ^aa extendedglob yes
->aa ^aa extendedglob no
->b ^aa extendedglob yes
->a# ^aa extendedglob yes
->?~b ^aa extendedglob yes
->^aa ^aa extendedglob yes
-
- foo() { print My name is $0; }
- unsetopt functionargzero
- foo
- setopt functionargzero
- foo
- unfunction foo
-0:FUNCTION_ARGZERO option
->My name is (anon)
->My name is foo
-
- setopt _NO_glob_
- print tmp*
- set -o glob
- print tmp*
-0:GLOB option
->tmp*
->tmpcd tmpfile1 tmpfile2
-
- showit() { local v;
- for v in first second third; do
- eval print \$$v \$\{\(t\)$v\}
- done;
- }
- setit() { typeset -x first=inside1;
- typeset +g -x second=inside2;
- typeset -g -x third=inside3;
- showit;
- }
- first=outside1 second=outside2 third=outside3
- unsetopt globalexport
- setit
- showit
- setopt globalexport
- setit
- showit
- unfunction setit showit
-0:GLOBAL_EXPORT option
->inside1 scalar-local-export
->inside2 scalar-local-export
->inside3 scalar-export
->outside1 scalar
->outside2 scalar
->inside3 scalar-export
->inside1 scalar-export
->inside2 scalar-local-export
->inside3 scalar-export
->inside1 scalar-export
->outside2 scalar
->inside3 scalar-export
-
-# GLOB_ASSIGN is tested in A06assign.ztst.
-
- mkdir onlysomefiles
- touch onlysomefiles/.thisfile onlysomefiles/thatfile
- setopt globdots
- print onlysomefiles/*
- unsetopt globdots
- print onlysomefiles/*
- rm -rf onlysomefiles
-0:GLOB_DOTS option
->onlysomefiles/.thisfile onlysomefiles/thatfile
->onlysomefiles/thatfile
-
- # we've tested this enough times already...
- # could add some stuff for other sorts of expansion
- foo='tmp*'
- setopt globsubst
- print ${foo}
- unsetopt globsubst
- print ${foo}
-0:GLOB_SUBST option
->tmpcd tmpfile1 tmpfile2
->tmp*
-
- setopt histsubstpattern
- print *(:s/t??/TING/)
- foo=(tmp*)
- print ${foo:s/??p/THUMP/}
- foo=(one.c two.c three.c)
- print ${foo:s/#%(#b)t(*).c/T${match[1]}.X/}
- print *(#q:s/#(#b)tmp(*e)/'scrunchy${match[1]}'/)
- unsetopt histsubstpattern
-0:HIST_SUBST_PATTERN option
->TINGcd TINGfile1 TINGfile2 homedir
->THUMPcd THUMPfile1 THUMPfile2
->one.c Two.X Three.X
->homedir scrunchyfile1 scrunchyfile2 tmpcd
-
- setopt ignorebraces
- echo X{a,b}Y
- unsetopt ignorebraces
- echo X{a,b}Y
-0:IGNORE_BRACES option
->X{a,b}Y
->XaY XbY
-
- setopt ksh_arrays
- array=(one two three)
- print $array $array[2]
- print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
- unsetopt ksh_arrays
- print $array $array[2]
- print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
- unset array
-0:KSH_ARRAYS option
->one one[2]
->one two three
->one two three two
->one two three
-
- fpath=(.)
- echo >foo 'echo foo loaded; foo() { echo foo run; }'
- echo >bar 'bar() { echo bar run; }'
- setopt kshautoload
- autoload foo bar
- foo
- bar
- unfunction foo bar
- unsetopt kshautoload
- autoload foo bar
- foo
- bar
-0:KSH_AUTOLOAD option
->foo loaded
->foo run
->bar run
->foo loaded
->bar run
-
-# ksh_glob is tested by the glob tests.
-
- setopt kshoptionprint globassign
- print set
- setopt | grep kshoptionprint
- setopt | grep globassign
- unsetopt kshoptionprint
- print unset
- setopt | grep kshoptionprint
- setopt | grep globassign
- unsetopt globassign
-0:KSH_OPTION_PRINT option
->set
->kshoptionprint on
->globassign on
->unset
->globassign
-
- # This test is now somewhat artificial as
- # KSH_TYPESET only applies to the builtin
- # interface. Tests to the more standard
- # reserved word interface appear elsewhere.
- (
- # reserved words are handled during parsing,
- # hence eval...
- disable -r typeset
- eval '
- setopt kshtypeset
- ktvars=(ktv1 ktv2)
- typeset ktfoo=`echo arg1 arg2` $ktvars
- print $+ktv1 $+ktv2 $+ktv3
- print $ktfoo
- unsetopt kshtypeset
- typeset noktfoo=`echo noktarg1 noktarg2`
- print $noktfoo
- print $+noktarg1 $+noktarg2
- unset ktfoo ktv1 ktv2 noktfoo noktarg2
- '
- )
-0:KSH_TYPESET option
->1 1 0
->arg1 arg2
->noktarg1
->0 1
-
- showopt() { setopt | egrep 'localoptions|ksharrays'; }
- f1() { setopt localoptions ksharrays; showopt }
- f2() { setopt ksharrays; showopt }
- setopt kshoptionprint
- showopt
- f1
- showopt
- f2
- showopt
- unsetopt ksh_arrays
-0:LOCAL_OPTIONS option
->ksharrays off
->localoptions off
->ksharrays on
->localoptions on
->ksharrays off
->localoptions off
->ksharrays on
->localoptions off
->ksharrays on
->localoptions off
-
-# LOCAL_TRAPS was tested in C03traps (phew).
-
- fn() {
- local HOME=/any/old/name
- print -l var=~ 'anything goes/here'=~ split=`echo maybe not`;
- }
- setopt magicequalsubst
- fn
- setopt kshtypeset
- fn
- unsetopt magicequalsubst kshtypeset
- fn
-0:MAGIC_EQUAL_SUBST option
->var=/any/old/name
->anything goes/here=/any/old/name
->split=maybe
->not
->var=/any/old/name
->anything goes/here=/any/old/name
->split=maybe not
->var=~
->anything goes/here=~
->split=maybe
->not
-
- setopt MARK_DIRS
- print tmp*
- unsetopt MARK_DIRS
- print tmp*
-0:MARK_DIRS option
->tmpcd/ tmpfile1 tmpfile2
->tmpcd tmpfile1 tmpfile2
-
-# maybe should be in A04redirect
- print "This is in1" >in1
- print "This is in2" >in2
- unsetopt multios
- print Test message >foo1 >foo2
- print foo1: $(foo1 >foo2
- sleep 1 # damn, race in multios
- print foo1: $(foo1:
->foo2: Test message
->This is in2
->foo1: Test message
->foo2: Test message
->This is in1
->This is in2
-
-# This is trickier than it looks. There's a hack at the end of
-# execcmd() to catch the multio processes attached to the
-# subshell, which otherwise sort of get lost in the general turmoil.
-# Without that, the multios aren't synchronous with the subshell
-# or the main shell starting the "cat", so the output files appear
-# empty.
- setopt multios
- ( echo hello ) >multio_out1 >multio_out2 && cat multio_out*
-0:Multios attached to a subshell
->hello
->hello
-
-# This tests for another race in multios.
- print -u $ZTST_fd 'This test hangs the shell when it fails...'
- setopt multios
- echo These are the contents of the file >multio_race.out
- multio_race_fn() { cat; }
- multio_race_fn <$(echo multio_race.out multio_race.out)
-0:Fix for race with input multios
->These are the contents of the file
->These are the contents of the file
-
-# tried this with other things, but not on its own, so much.
- unsetopt nomatch
- print with nonomatch: flooble*
- setopt nomatch
- print with nomatch flooble*
-1:NOMATCH option
->with nonomatch: flooble*
-?(eval):4: no matches found: flooble*
-
-# NULL_GLOB should override NONOMATCH...
- setopt nullglob nomatch
- print frooble* tmp*
- unsetopt nullglob nomatch
- print frooble* tmp*
-0:NULL_GLOB option
->tmpcd tmpfile1 tmpfile2
->frooble* tmpcd tmpfile1 tmpfile2
-
- touch ngs1.txt ngs2.txt ngs10.txt ngs20.txt ngs100.txt ngs200.txt
- setopt numericglobsort
- print -l ngs*
- unsetopt numericglobsort
- print -l ngs*
-0:NUMERIC_GLOB_SORT option
->ngs1.txt
->ngs2.txt
->ngs10.txt
->ngs20.txt
->ngs100.txt
->ngs200.txt
->ngs1.txt
->ngs10.txt
->ngs100.txt
->ngs2.txt
->ngs20.txt
->ngs200.txt
-
- typeset -i 10 oznum
- setopt octalzeroes
- (( oznum = 012 + 013 ))
- print $oznum
- unsetopt octalzeroes
- (( oznum = 012 + 013 ))
- print $oznum
- unset oznum
-0:OCTAL_ZEROES options
->21
->25
-
- typeset -a oldpath
- oldpath=($path)
- mkdir pdt_topdir pathtestdir pdt_topdir/pathtestdir
- print "#!/bin/sh\necho File in upper dir" >pathtestdir/findme
- print "#!/bin/sh\necho File in lower dir" >pdt_topdir/pathtestdir/findme
- chmod u+x pathtestdir/findme pdt_topdir/pathtestdir/findme
- pathtestdir/findme
- rm -f pathtestdir/findme
- setopt pathdirs
- path=($PWD $PWD/pdt_topdir)
- pathtestdir/findme
- print unsetting option...
- unsetopt pathdirs
- pathtestdir/findme
- path=($oldpath)
- unset oldpath
- rm -rf pdt_topdir pathtestdir
-0:PATH_DIRS option
->File in upper dir
->File in lower dir
->unsetting option...
-?(eval):14: no such file or directory: pathtestdir/findme
-
- (setopt pathdirs; path+=( /usr/bin ); type ./env)
-1:whence honours PATH_DIRS option
->./env not found
-
- setopt posixbuiltins
- PATH= command -v print
- PATH= command -V print
- PATH= command print foo
- unsetopt posixbuiltins
- print unsetting...
- PATH= command -V print
- PATH= command print foo
-127:POSIX_BUILTINS option
->print
->print is a shell builtin
->foo
->unsetting...
->print is a shell builtin
-?(eval):8: command not found: print
-
- # With non-special command: original value restored
- # With special builtin: new value kept
- # With special builtin preceeded by "command": original value restored.
- (setopt posixbuiltins
- FOO=val0
- FOO=val1 true; echo $FOO
- FOO=val2 times 1>/dev/null 2>&1; echo $FOO
- FOO=val3 command times 1>/dev/null 2>&1; echo $FOO)
-0:POSIX_BUILTINS and restoring variables
->val0
->val2
->val2
-
-# PRINTEXITVALUE only works if shell input is coming from standard input.
-# Goodness only knows why.
- $ZTST_testdir/../Src/zsh -f <<<'
- setopt printexitvalue
- func() {
- false
- }
- func
- '
-1:PRINT_EXIT_VALUE option
-?zsh: exit 1
-
- $ZTST_testdir/../Src/zsh -f <<<'
- setopt printexitvalue
- () { false; }
- '
-1:PRINT_EXIT_VALUE option for anonymous function
-?zsh: exit 1
-
- setopt promptbang
- print -P !
- setopt nopromptbang
- print -P !
-0:PROMPT_BANG option
->0
->!
-
- unsetopt promptpercent
- print -P '%/'
- setopt promptpercent
- print -P '%/'
-0q:PROMPT_PERCENT option
->%/
->$mydir
-
- setopt promptsubst
- print -P '`echo waaah`'
- unsetopt promptsubst
- print -P '`echo waaah`'
-0:PROMPT_SUBST option
->waaah
->`echo waaah`
-
- dirs
- pushd $mydir/tmpcd
- dirs
- pushd $mydir/tmpcd
- dirs
- setopt pushdignoredups
- pushd $mydir/tmpcd
- dirs
- unsetopt pushdignoredups
- popd >/dev/null
- popd >/dev/null
-0q:PUSHD_IGNOREDUPS option
->$mydirt
->$mydirt/tmpcd $mydirt
->$mydirt/tmpcd $mydirt/tmpcd $mydirt
->$mydirt/tmpcd $mydirt/tmpcd $mydirt
-
- mkdir newcd
- cd $mydir
- pushd $mydir/tmpcd
- pushd $mydir/newcd
- dirs
- pushd -0
- dirs
- setopt pushdminus pushdsilent
- pushd -0
- dirs
- unsetopt pushdminus
- popd >/dev/null
- popd >/dev/null
- cd $mydir
-0q:PUSHD_MINUS option
->$mydirt/newcd $mydirt/tmpcd $mydirt
->$mydirt $mydirt/newcd $mydirt/tmpcd
->$mydirt $mydirt/newcd $mydirt/tmpcd
-
-# Do you have any idea how dull this is?
-
- (export HOME=$mydir/homedir
- pushd $mydir/tmpcd
- pushd
- dirs
- setopt pushdtohome
- pushd
- dirs
- unsetopt pushdtohome
- popd
- pushd
- popd
- dirs)
-0q:PUSHD_TO_HOME option
->$mydirhome $mydirhome/tmpcd
->~ $mydirhome $mydirhome/tmpcd
->$mydirhome
-
- array=(one two three four)
- setopt rcexpandparam
- print aa${array}bb
- unsetopt rcexpandparam
- print aa${array}bb
-0:RC_EXPAND_PARAM option
->aaonebb aatwobb aathreebb aafourbb
->aaone two three fourbb
-
- setopt rcquotes
- # careful, this is done when parsing a complete block
- eval "print 'one''quoted''expression'"
- unsetopt rcquotes
- eval "print 'another''quoted''expression'"
-0:RC_QUOTES option
->one'quoted'expression
->anotherquotedexpression
-
-# too lazy to test jobs -Z and ARGV0.
- (setopt restricted; cd /)
- (setopt restricted; PATH=/bin:/usr/bin)
- (setopt restricted; /bin/ls)
- (setopt restricted; hash ls=/bin/ls)
- (setopt restricted; print ha >outputfile)
- (setopt restricted; exec ls)
- (setopt restricted; unsetopt restricted)
- :
-0:RESTRICTED option
-?(eval):cd:1: restricted
-?(eval):2: PATH: restricted
-?(eval):3: /bin/ls: restricted
-?(eval):hash:4: restricted: /bin/ls
-?(eval):5: writing redirection not allowed in restricted mode
-?(eval):exec:6: ls: restricted
-?(eval):unsetopt:7: can't change option: restricted
-
-# ' emacs deconfusion
-
- fn() {
- print =ls ={ls,}
- local foo='=ls'
- print ${~foo}
- }
- setopt shfileexpansion
- fn
- unsetopt shfileexpansion
- fn
-0q:SH_FILE_EXPANSION option
->$lspath =ls =
->=ls
->$lspath $lspath =
->$lspath
-
- testpat() {
- if [[ $1 = ${~2} ]]; then print $1 $2 yes; else print $1 $2 no; fi
- }
- print option on
- setopt shglob
- repeat 2; do
- for str in 'a(b|c)' ab; do
- testpat $str 'a(b|c)'
- done
- for str in 'a<1-10>' a9; do
- testpat $str 'a<1-10>'
- done
- [[ ! -o shglob ]] && break
- print option off
- unsetopt shglob
- done
-0:SH_GLOB option
->option on
->a(b|c) a(b|c) yes
->ab a(b|c) no
->a<1-10> a<1-10> yes
->a9 a<1-10> no
->option off
->a(b|c) a(b|c) no
->ab a(b|c) yes
->a<1-10> a<1-10> no
->a9 a<1-10> yes
-
- print this is bar >bar
- fn() {
- local NULLCMD=cat READNULLCMD=cat
- { echo hello | >foo } 2>/dev/null
- cat foo
- option set
->option unset
->hello
->this is bar
-
- fn() {
- eval 'for f in foo bar; print $f'
- eval 'for f (word1 word2) print $f'
- eval 'repeat 3 print nonsense'
- }
- unsetopt shortloops
- print option unset
- fn
- setopt shortloops
- print option set
- fn
-0:SHORT_LOOPS option
->option unset
->option set
->foo
->bar
->word1
->word2
->nonsense
->nonsense
->nonsense
-?(eval):1: parse error near `print'
-?(eval):1: parse error near `print'
-?(eval):1: parse error near `print'
-
- fn() { print -l $*; }
- setopt shwordsplit
- print option set
- repeat 2; do
- foo='two words'
- fn $foo
- fn "${=foo}"
- [[ ! -o shwordsplit ]] && break
- unsetopt shwordsplit
- print option unset
- done
-0:SH_WORD_SPLIT option
->option set
->two
->words
->two
->words
->option unset
->two words
->two
->words
-
- fn() { unset foo; print value is $foo; }
- setopt nounset
- print option unset unset by setting nounset
- eval fn
- print option unset reset
- setopt unset
- fn
-0:UNSET option
->option unset unset by setting nounset
->option unset reset
->value is
-?fn: foo: parameter not set
-
- fn1() { unset foo; print value 1 is ${foo#bar}; }
- fn2() { unset foo; print value 2 is ${foo%bar}; }
- fn3() { unset foo; print value 3 is ${foo/bar}; }
- setopt nounset
- print option unset unset by setting nounset
- eval fn1
- eval fn2
- eval fn3
- print option unset reset
- setopt unset
- fn1
- fn2
- fn3
-0:UNSET option with operators
->option unset unset by setting nounset
->option unset reset
->value 1 is
->value 2 is
->value 3 is
-?fn1: foo: parameter not set
-?fn2: foo: parameter not set
-?fn3: foo: parameter not set
-
- fn() {
- emulate -L zsh
- setopt warncreateglobal
- foo1=bar1
- unset foo1
- foo1=bar2
- local foo2=bar3
- unset foo2
- foo2=bar4
- typeset -g foo3
- foo3=bar5
- fn2() {
- foo3=bar6
- }
- foo4=bar7 =true
- (( foo5=8 ))
- integer foo6=9
- (( foo6=10 ))
- }
- # don't pollute the test environment with the variables...
- (fn)
-0:WARN_CREATE_GLOBAL option
-?fn:3: scalar parameter foo1 created globally in function fn
-?fn:5: scalar parameter foo1 created globally in function fn
-?fn:15: numeric parameter foo5 created globally in function fn
-
- fn() {
- emulate -L zsh
- setopt warncreateglobal
- TZ=UTC date >&/dev/null
- local um=$(TZ=UTC date 2>/dev/null)
- }
- fn
-0:WARN_CREATE_GLOBAL negative cases
-
- (
- foo1=global1 foo2=global2 foo3=global3 foo4=global4
- integer foo5=5
- # skip foo6, defined in fn_wnv
- foo7=(one two)
- fn_wnv() {
- # warns
- foo1=bar1
- # doesn't warn
- local foo2=bar3
- unset foo2
- # still doesn't warn
- foo2=bar4
- # doesn't warn
- typeset -g foo3=bar5
- # warns
- foo3=bar6
- fn2() {
- # warns if global option, not attribute
- foo3=bar6
- }
- fn2
- # doesn't warn
- foo4=bar7 =true
- # warns
- (( foo5=8 ))
- integer foo6=9
- # doesn't warn
- (( foo6=10 ))
- foo7[3]=three
- foo7[4]=(four)
- }
- print option off >&2
- fn_wnv
- print option on >&2
- setopt warnnestedvar
- fn_wnv
- unsetopt warnnestedvar
- print function attribute on >&2
- functions -W fn_wnv
- fn_wnv
- print all off again >&2
- functions +W fn_wnv
- fn_wnv
- )
-0:WARN_NESTED_VAR option
-?option off
-?option on
-?fn_wnv:2: scalar parameter foo1 set in enclosing scope in function fn_wnv
-?fn_wnv:11: scalar parameter foo3 set in enclosing scope in function fn_wnv
-?fn2:2: scalar parameter foo3 set in enclosing scope in function fn2
-?fn_wnv:20: numeric parameter foo5 set in enclosing scope in function fn_wnv
-?function attribute on
-?fn_wnv:2: scalar parameter foo1 set in enclosing scope in function fn_wnv
-?fn_wnv:11: scalar parameter foo3 set in enclosing scope in function fn_wnv
-?fn_wnv:20: numeric parameter foo5 set in enclosing scope in function fn_wnv
-?all off again
-
-
- (
- setopt warnnestedvar
- () {
- typeset -A a
- : ${a[hello world]::=foo}
- print ${(t)a}
- key="hello world"
- print $a[$key]
- }
- )
-0:No false positive on parameter used with subscripted assignment
->association-local
->foo
-
- (
- setopt warnnestedvar
- () {
- local var=(one two)
- () { var=three; }
- print $var
- }
- )
-0:Warn when changing type of nested variable: array to scalar.
-?(anon): scalar parameter var set in enclosing scope in function (anon)
->three
-
- (
- setopt warnnestedvar
- () {
- local var=three
- () { var=(one two); }
- print $var
- }
- )
-0:Warn when changing type of nested variable: scalar to array.
-?(anon): array parameter var set in enclosing scope in function (anon)
->one two
-
-# This really just tests if XTRACE is egregiously broken.
-# To test it properly would need a full set of its own.
- fn() { print message; }
- PS4='+%N:%i> '
- setopt xtrace
- fn
- unsetopt xtrace
- fn
-0:XTRACE option
->message
->message
-?+(eval):4> fn
-?+fn:0> print message
-?+(eval):5> unsetopt xtrace
-
- setopt ignoreclosebraces
- eval "icb_test() { echo this is OK; }"
- icb_test
- icb_args() { print $#; }
- eval "icb_args { this, is, ok, too }"
-0:IGNORE_CLOSE_BRACES option
->this is OK
->6
-
- (setopt pipefail
- true | true | true
- print $?
- true | false | true
- print $?
- exit 2 | false | true
- print $?
- false | exit 2 | true
- print $?)
-0:PIPE_FAIL option
->0
->1
->1
->2
-
- for (( i = 0; i < 10; i++ )); do
- () {
- print $i
- break
- }
- done
-0:NO_LOCAL_LOOPS
->0
-
- () {
- emulate -L zsh
- setopt localloops
- for (( i = 0; i < 10; i++ )); do
- () {
- setopt nolocalloops # ignored in parent
- print $i
- break
- }
- done
- }
-0:LOCAL_LOOPS
->0
->1
->2
->3
->4
->5
->6
->7
->8
->9
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
-?(anon):4: `break' active at end of function scope
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E02xtrace.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E02xtrace.ztst
deleted file mode 100644
index da6191cd..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/E02xtrace.ztst
+++ /dev/null
@@ -1,148 +0,0 @@
-# Test that xtrace output is correctly generated
-
-%prep
- mkdir xtrace.tmp && cd xtrace.tmp
-
- function xtf {
- local regression_test_dummy_variable
- print "$*"
- }
- function xtfx {
- local regression_test_dummy_variable
- print "Tracing: (){ builtin 2>file }" 2>>xtrace.err
- { print "Tracing: (){ { builtin } 2>file }" } 2>>xtrace.err
- }
- echo 'print "$*"' > xt.in
-
-%test
-
- PS4='+%N:%i> '
- set -x
- print 'Tracing: builtin'
- print 'Tracing: builtin 2>file' 2>xtrace.err
- cat <<<'Tracing: external'
- cat <<<'Tracing: external 2>file' 2>>xtrace.err
- ( print 'Tracing: ( builtin )' )
- ( print 'Tracing: ( builtin ) 2>file' ) 2>>xtrace.err
- ( cat <<<'Tracing: ( external )' )
- ( cat <<<'Tracing: ( external ) 2>file' ) 2>>xtrace.err
- { print 'Tracing: { builtin }' }
- { print 'Tracing: { builtin } 2>file' } 2>>xtrace.err
- { cat <<<'Tracing: { external }' }
- { cat <<<'Tracing: { external } 2>file' } 2>>xtrace.err
- repeat 1 do print 'Tracing: do builtin done'; done
- repeat 1 do print 'Tracing: do builtin done 2>file'; done 2>>xtrace.err
- repeat 1 do cat <<<'Tracing: do external done'; done
- repeat 1 do cat <<<'Tracing: do external done 2>file'; done 2>>xtrace.err
- xtf 'Tracing: function'
- xtf 'Tracing: function 2>file' 2>>xtrace.err
- xtfx
- . ./xt.in 'Tracing: source'
- . ./xt.in 'Tracing: source 2>file' 2>>xtrace.err
- set +x
- cat xtrace.err
-0:xtrace with and without redirection
->Tracing: builtin
->Tracing: builtin 2>file
->Tracing: external
->Tracing: external 2>file
->Tracing: ( builtin )
->Tracing: ( builtin ) 2>file
->Tracing: ( external )
->Tracing: ( external ) 2>file
->Tracing: { builtin }
->Tracing: { builtin } 2>file
->Tracing: { external }
->Tracing: { external } 2>file
->Tracing: do builtin done
->Tracing: do builtin done 2>file
->Tracing: do external done
->Tracing: do external done 2>file
->Tracing: function
->Tracing: function 2>file
->Tracing: (){ builtin 2>file }
->Tracing: (){ { builtin } 2>file }
->Tracing: source
->Tracing: source 2>file
->+(eval):8> print 'Tracing: ( builtin ) 2>file'
->+(eval):10> cat
->+(eval):12> print 'Tracing: { builtin } 2>file'
->+(eval):14> cat
->+(eval):16> print 'Tracing: do builtin done 2>file'
->+(eval):18> cat
->+xtf:1> local regression_test_dummy_variable
->+xtf:2> print 'Tracing: function 2>file'
->+xtfx:3> print 'Tracing: (){ { builtin } 2>file }'
-?+(eval):3> print 'Tracing: builtin'
-?+(eval):4> print 'Tracing: builtin 2>file'
-?+(eval):5> cat
-?+(eval):6> cat
-?+(eval):7> print 'Tracing: ( builtin )'
-?+(eval):9> cat
-?+(eval):11> print 'Tracing: { builtin }'
-?+(eval):13> cat
-?+(eval):15> print 'Tracing: do builtin done'
-?+(eval):17> cat
-?+(eval):19> xtf 'Tracing: function'
-?+xtf:1> local regression_test_dummy_variable
-?+xtf:2> print 'Tracing: function'
-?+(eval):20> xtf 'Tracing: function 2>file'
-?+(eval):21> xtfx
-?+xtfx:1> local regression_test_dummy_variable
-?+xtfx:2> print 'Tracing: (){ builtin 2>file }'
-?+(eval):22> . ./xt.in 'Tracing: source'
-?+./xt.in:1> print 'Tracing: source'
-?+(eval):23> . ./xt.in 'Tracing: source 2>file'
-?+./xt.in:1> print 'Tracing: source 2>file'
-?+(eval):24> set +x
-
- typeset -ft xtf
- xtf 'Tracing: function'
-0:tracing function
->Tracing: function
-?+xtf:1> local regression_test_dummy_variable
-?+xtf:2> print 'Tracing: function'
-
- echo 'PS4="+%x:%I> "
- fn() {
- print This is fn.
- }
- :
- fn
- ' >fnfile
- $ZTST_testdir/../Src/zsh -fx ./fnfile 2>errfile
- grep '\./fnfile' errfile 1>&2
-0:Trace output with sourcefile and line number.
->This is fn.
-?+./fnfile:1> PS4='+%x:%I> '
-?+./fnfile:5> :
-?+./fnfile:6> fn
-?+./fnfile:3> print This is fn.
-
- set -x
- [[ 'f o' == 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
- [[ 'f o' = 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
- [[ -e nonexistentfile || ( -z '' && -t 3 ) ]]
- set +x
-0:Trace for conditions
-?+(eval):2> [[ 'f o' == f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
-?+(eval):3> [[ 'f o' = f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
-?+(eval):4> [[ -e nonexistentfile || -z '' && -t 3 ]]
-?+(eval):5> set +x
-
- # Part 1: Recurses into nested anonymous functions
- fn() {
- () { () { true } }
- }
- functions -T fn
- fn
- # Part 2: Doesn't recurse into named functions
- gn() { true }
- fn() { gn }
- functions -T fn
- fn
-0:tracing recurses into anonymous functions
-?+fn:1> '(anon)'
-?+(anon):0> '(anon)'
-?+(anon):0> true
-?+fn:0> gn
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/Makefile.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/Makefile.in
deleted file mode 100644
index 083df494..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/Makefile.in
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# Makefile for Test subdirectory
-#
-# Copyright (c) 1999 Peter Stephensons
-# 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.
-#
-
-subdir = Test
-dir_top = ..
-SUBDIRS =
-
-@VERSION_MK@
-
-# source/build directories
-VPATH = @srcdir@
-sdir = @srcdir@
-sdir_top = @top_srcdir@
-INSTALL = @INSTALL@
-
-@DEFS_MK@
-
-# ========== DEPENDENCIES FOR TESTING ==========
-
-check test:
- if test -n "$(DLLD)"; then \
- cd $(dir_top) && DESTDIR= \
- $(MAKE) MODDIR=`pwd`/$(subdir)/Modules install.modules > /dev/null; \
- fi
- if ZTST_testlist="`for f in $(sdir)/$(TESTNUM)*.ztst; \
- do echo $$f; done`" \
- ZTST_srcdir="$(sdir)" \
- ZTST_exe=$(dir_top)/Src/zsh@EXEEXT@ \
- $(dir_top)/Src/zsh@EXEEXT@ +Z -f $(sdir)/runtests.zsh; then \
- stat=0; \
- else \
- stat=1; \
- fi; \
- sleep 1; \
- rm -rf Modules .zcompdump; \
- exit $$stat
-
-# ========== DEPENDENCIES FOR CLEANUP ==========
-
-@CLEAN_MK@
-
-mostlyclean-here:
- rm -rf Modules .zcompdump *.tmp
-
-distclean-here:
- rm -f Makefile
-
-realclean-here:
-
-# ========== DEPENDENCIES FOR MAINTENANCE ==========
-
-@CONFIG_MK@
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/README b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/README
deleted file mode 100644
index d012277c..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/README
+++ /dev/null
@@ -1,30 +0,0 @@
-There are now different sections, expressed by the first letter in the
-scripts names:
-
- A: basic command parsing and execution
- B: builtins
- C: shell commands with special syntax
- D: substititution
- E: options
- V: modules
- W: builtin interactive commands and constructs
- X: line editing
- Y: completion
- Z: separate systems and user contributions
-
-You will need to run these by using `make test' in the Test subdirectory of
-the build area for your system (which may or may not be the same as the
-Test subdirectory of the source tree), or the directory above. You can get
-more information about the tests being performed with
- ZTST_verbose=1 make check
-(`test' is equivalent to `check') or change 1 to 2 for even more detail.
-
-Individual or groups of tests can be performed with
- make TESTNUM=C02 check
-or
- make TESTNUM=C check
-to perform just the test beginning C02, or all tests beginning C,
-respectively.
-
-Instructions on how to write tests are given in B01cd.ztst, which acts as a
-model.
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V02zregexparse.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V02zregexparse.ztst
deleted file mode 100644
index b4cec424..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V02zregexparse.ztst
+++ /dev/null
@@ -1,382 +0,0 @@
-# Tests corresponding to the texinfo node `Conditional Expressions'
-
-%prep
-
- if ! zmodload zsh/zutil 2>/dev/null; then
- ZTST_unimplemented="can't load the zsh/zutil module for testing"
- fi
-
-%test
-
- zregexparse p1 p2 ''
-0:empty
-
- zregexparse p1 p2 a /a/
-0:element
-
- zregexparse p1 p2 aaaaaa /a/ \#
-0:closure
-
- zregexparse p1 p2 ab /a/ /b/
-0:concatenation
-
- zregexparse p1 p2 a /a/ \| /b/
-0:alternation 1
-
- zregexparse p1 p2 b /a/ \| /b/
-0:alternation 2
-
- zregexparse p1 p2 a \( /a/ \)
-0:grouping
-
- zregexparse p1 p2 abbaaab \( /a/ \| /b/ \) \#
-0:alternation, grouping and closure
-
- zregexparse p1 p2 abcdef /ab/ %cd% /cdef/
-0:lookahead 1
-
- zregexparse p1 p2 abcdef /ab/ %ZZ% /cdef/
-1:lookahead 2
-
- zregexparse p1 p2 abcd /ab/ %cd% '-print guard' ':print caction' /cd/
-0:pattern, lookahead, guard and completion action
->guard
-
- zregexparse p1 p2 abcd /ab/ %cd% '-print guard; false' ':print caction' /cd/
-1:guard failure
->guard
->caction
-
- zregexparse p1 p2 abcdef /ab/ '{print AB}' /cd/ '{print CD}' /ef/ '{print EF}'
-0:action
->AB
->CD
->EF
-
- zregexparse p1 p2 aaa
- print $? $p1 $p2
-0:aaa
->2 0 0
-
- zregexparse p1 p2 aaa /a/
- print $? $p1 $p2
-0:aaa /a/
->2 1 1
-
- zregexparse p1 p2 aaa /a/ /a/
- print $? $p1 $p2
-0:aaa 2*/a/
->2 2 2
-
- zregexparse p1 p2 aaa /a/ /a/ /a/
- print $? $p1 $p2
-0:aaa 3*/a/
->0 3 3
-
- zregexparse p1 p2 aaa /a/ /a/ /a/ /a/
- print $? $p1 $p2
-0:aaa 4*/a/
->1 3 3
-
- zregexparse p1 p2 aaa /a/ /a/ /a/ /a/ /a/
- print $? $p1 $p2
-0:aaa 5*/a/
->1 3 3
-
- zregexparse p1 p2 aaa /aaa/
- print $? $p1 $p2
-0:aaa /aaa/
->0 3 3
-
- zregexparse p1 p2 aaa /aaa/ /a/
- print $? $p1 $p2
-0:aaa /aaa/ /a/
->1 3 3
-
- zregexparse p1 p2 aaa /a/ \#
- print $? $p1 $p2
-0:aaa /aaa/ #
->0 3 3
-
- zregexparse p1 p2 aaa /a/ \# \#
- print $? $p1 $p2
-0:aaa /aaa/ # #
->0 3 3
-
- zregexparse p1 p2 aaa \( /a/ \)
- print $? $p1 $p2
-0:aaa ( /a/ )
->2 1 1
-
- zregexparse p1 p2 aaa \( /a/ \) \#
- print $? $p1 $p2
-0:aaa ( /a/ ) #
->0 3 3
-
- zregexparse p1 p2 aaa /a/ /b/
- print $? $p1 $p2
-0:aaa /a/ /b/
->1 1 1
-
- zregexparse p1 p2 a /a/ '{print A}'
- print $? $p1 $p2
-0:a /a/ '{A}'
->A
->0 1 1
-
- zregexparse p1 p2 a /b/ '{print A}'
- print $? $p1 $p2
-0:a /b/ '{A}'
->1 0 0
-
- zregexparse p1 p2 a /b/ ':print A' '{print B}'
- print $? $p1 $p2
-0:a /b/ ':A' '{B}'
->A
->1 0 0
-
- zregexparse p1 p2 ab /a/ '{print A}'
- print $? $p1 $p2
-0:ab /a/ '{A}'
->2 1 1
-
- zregexparse p1 p2 ab /a/ '{print A}' /b/ '{print B}'
- print $? $p1 $p2
-0:ab /a/ '{A}' /b/ '{B}'
->A
->B
->0 2 2
-
- zregexparse p1 p2 ab /a/ ':print A' '{print B}' /b/ ':print C' '{print D}'
- print $? $p1 $p2
-0:ab /a/ ':A' '{B}' /b/ ':C' '{D}'
->B
->D
->0 2 2
-
- zregexparse p1 p2 abc /a/ '{print A}' /b/ '{print B}' /c/ '{print C}'
- print $? $p1 $p2
-0:abc /a/ '{A}' /b/ '{B}' /c/ '{C}'
->A
->B
->C
->0 3 3
-
- zregexparse p1 p2 abz /a/ '{print A}' /b/ '{print B}' /c/ '{print C}'
- print $? $p1 $p2
-0:abz /a/ '{A}' /b/ '{B}' /c/ '{C}'
->A
->1 2 2
-
- zregexparse p1 p2 azz /a/ '{print A}' /b/ '{print B}' /c/ '{print C}'
- print $? $p1 $p2
-0:azz /a/ '{A}' /b/ '{B}' /c/ '{C}'
->1 1 1
-
- zregexparse p1 p2 aba '{print A}' /a/ '{print B}' /b/ '{print C}' /c/ '{print D}'
- print $? $p1 $p2
-0:aba '{A}' /a/ '{B}' /b/ '{C}' /c/ '{D}'
->A
->B
->1 2 2
-
- zregexparse p1 p2 a /a/ '{print "$match[1]"}'
- print $? $p1 $p2
-0:a /a/ '{M1}'
->a
->0 1 1
-
- zregexparse p1 p2 aaa /a/ '{print A}' //
- print $? $p1 $p2
-0:aaa /a/ '{A}' //
->A
->2 1 1
-
- zregexparse p1 p2 aaa /a/ '{print "$match[1]"}' // '{print A}'
- print $? $p1 $p2
-0:aaa /a/ '{M1}' // '{A}'
->a
->2 1 1
-
- zregexparse p1 p2 abcdef /a/ '{print $match[1]}' /b/ '{print $match[1]}' /c/ '{print $match[1]}' // '{print A}'
- print $? $p1 $p2
-0:abcdef /a/ '{M1}' /b/ '{M1}' /c/ '{M1}' // '{A}'
->a
->b
->c
->2 3 3
-
- zregexparse p1 p2 abcdef /a/ '{print A}' /b/ '{print B}' /c/ '{print C}' // '{print D}'
- print $? $p1 $p2
-0:abcdef /a/ '{A}' /b/ '{B}' /c/ '{C}' // '{D}'
->A
->B
->C
->2 3 3
-
- zregexparse p1 p2 a /a/ '{print A}' /b/ '{print B}'
- print $? $p1 $p2
-0:a /a/ {A} /b/ {B}
->1 1 1
-
- zregexparse p1 p2 abcdef \
- /a/ '-print Ga:$p1:$p2:$match[1]' '{print Aa:$p1:$p2:$match[1]}' \
- /b/ '-print Gb:$p1:$p2:$match[1]' '{print Ab:$p1:$p2:$match[1]}' \
- /c/ '-print Gc:$p1:$p2:$match[1]' '{print Ac:$p1:$p2:$match[1]}' \
- //
- print $? $p1 $p2
-0:abcdef /a/ -Ga {Aa} /b/ -Gb {Aa} /c/ -Gc {Ac} //
->Ga:0:0:a
->Gb:1:1:b
->Aa:1:1:a
->Gc:2:2:c
->Ab:2:2:b
->Ac:3:3:c
->2 3 3
-
- zregexparse p1 p2 abcdef \
- /a/ '-print Ga:$p1:$p2:$match[1]' '{print Aa:$p1:$p2:$match[1]}' \
- /b/ '-print Gb:$p1:$p2:$match[1]' '{print Ab:$p1:$p2:$match[1]}' \
- /c/ '-print Gc:$p1:$p2:$match[1]' '{print Ac:$p1:$p2:$match[1]}' \
- '/[]/' ':print F:$p1:$p2'
- print $? $p1 $p2
-0:abcdef /a/ -Ga {Aa} /b/ -Gb {Ab} /c/ -Gc {Ac} /[]/ :F
->Ga:0:0:a
->Gb:1:1:b
->Aa:1:1:a
->Gc:2:2:c
->Ab:2:2:b
->F:3:3
->1 3 3
-
- zregexparse p1 p2 abcdef \
- /a/ '-print Ga:$p1:$p2:$match[1]' '{print Aa:$p1:$p2:$match[1]}' \
- /b/ '-print Gb:$p1:$p2:$match[1]' '{print Ab:$p1:$p2:$match[1]}' \
- /c/ '-print Gc:$p1:$p2:$match[1]' '{print Ac:$p1:$p2:$match[1]}' \
- \( '/[]/' ':print F1:$p1:$p2' \| /z/ ':print F2' \)
- print $? $p1 $p2
-0:abcdef /a/ -Ga {Aa} /b/ -Gb {Ab} /c/ -Gc {Ac} ( /[]/ :F1 | /z/ :F2 )
->Ga:0:0:a
->Gb:1:1:b
->Aa:1:1:a
->Gc:2:2:c
->Ab:2:2:b
->F1:3:3
->F2
->1 3 3
-
- zregexparse p1 p2 a '/[]/' ':print A'
- print $? $p1 $p2
-0:a /[]/ :A
->A
->1 0 0
-
- zregexparse p1 p2 $'\0' $'/\0/' '{print A}'
- print $? $p1 $p2
-0:"\0" /\0/ {A}
->A
->0 1 1
-
- zregexparse p1 p2 $'\0' $'/\0/' '{print A}' '/ /' '{print B}'
- print $? $p1 $p2
-0:"\0" /\0/ {A} / / {B}
->1 1 1
-
- zregexparse p1 p2 abcdef \( '/?/' '{print $match[1]}' \) \#
- print $? $p1 $p2
-0:abcdef ( /?/ {M1} ) #
->a
->b
->c
->d
->e
->f
->0 6 6
-
- zregexparse p1 p2 abcdef \( '/c?|?/' '{print $match[1]}' \) \#
- print $? $p1 $p2
-0:abcdef ( /c?|?/ {M1} ) #
->a
->b
->cd
->e
->f
->0 6 6
-
- zregexparse p1 p2 abcacdef \( /a/ '{print $match[1]}' \| /b/ '{print $match[1]}' \| /c/ '{print $match[1]}' \) \#
- print $? $p1 $p2
-0:abcacdef ( /a/ {M1} | /b/ {M1} | /c/ {M1} ) #
->a
->b
->c
->a
->1 5 5
-
- zregexparse p1 p2 abcdef \( /a/ ':print A' \| /b/ ':print B' \| /c/ ':print C' \) \#
- print $? $p1 $p2
-0:abcdef ( /a/ :A | /b/ :B | /c/ :C ) #
->A
->B
->C
->1 3 3
-
- zregexparse p1 p2 abcdef \( /a/ ':print A' '{print $match[1]}' \| /b/ ':print B' '{print $match[1]}' \| /c/ ':print C' '{print $match[1]}' \) \#
- print $? $p1 $p2
-0:abcdef ( /a/ :A {M1} | /b/ :B {M1} | /c/ :C {M1} ) #
->a
->b
->A
->B
->C
->1 3 3
-
- zregexparse p1 p2 $'com\0xx' /$'[^\0]#\0'/ \( /$'[^\0]#\0'/ :'print A' /$'[^\0]#\0'/ :'print B' \) \#
- print $? $p1 $p2
-0:"com\0xx" /W/ ( /W/ :A /W/ :B ) #
->A
->1 4 4
-
- zregexparse p1 p2 $'com\0xx\0yy' /$'[^\0]#\0'/ \( /$'[^\0]#\0'/ :'print A' /$'[^\0]#\0'/ :'print B' \) \#
- print $? $p1 $p2
-0:"com\0xx\0yy" /W/ ( /W/ :A /W/ :B ) #
->B
->1 7 7
-
- zregexparse p1 p2 $'com\0xx\0yy\0zz' /$'[^\0]#\0'/ \( /$'[^\0]#\0'/ :'print A' /$'[^\0]#\0'/ :'print B' \) \#
- print $? $p1 $p2
-0:"com\0xx\0yy\0zz" /W/ ( /W/ :A /W/ :B ) #
->A
->1 10 10
-
- zregexparse p1 p2 abcdez /abc/ ':print A:$p1:$p2' /def/ ':print B:$p1:$p2'
- print $? $p1 $p2
-0:abcdez /abc/ :A /def/ :B
->B:3:3
->1 3 3
-
- zregexparse p1 p2 abcdez /abc/+ ':print A:$p1:$p2' /def/ ':print B:$p1:$p2'
- print $? $p1 $p2
-0:abcdez /abc/+ :A /def/ :B
->A:0:3
->B:0:3
->1 0 3
-
- zregexparse p1 p2 abcdez /abc/+ ':print A:$p1:$p2' // /def/ ':print B:$p1:$p2'
- print $? $p1 $p2
-0:abcdez /abc/+ :A // /def/ :B
->A:0:3
->B:0:3
->1 0 3
-
- zregexparse p1 p2 abcdez /abc/+ ':print A:$p1:$p2' //- /def/ ':print B:$p1:$p2'
- print $? $p1 $p2
-0:abcdez /abc/+ :A //- /def/ :B
->B:3:3
->1 3 3
-
- zregexparse p1 p2 $'ZZZZ\0abcdef' $'/ZZZZ\0/' /abc/+ ':print A:$p1:$p2' /dee/ ':print B:$p1:$p2'
- print $? $p1 $p2
-0:"ZZZZ\0abcdef" /ZZZZ\0/ /abc/+ :A /dee/ :B
->A:5:8
->B:5:8
->1 5 8
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V03mathfunc.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V03mathfunc.ztst
deleted file mode 100644
index 1edb7a27..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V03mathfunc.ztst
+++ /dev/null
@@ -1,141 +0,0 @@
-# Tests for the module zsh/mathfunc
-
-%prep
- if ! zmodload zsh/mathfunc 2>/dev/null; then
- ZTST_unimplemented="The module zsh/mathfunc is not available."
- fi
-
-%test
- # -g makes pi available in later tests
- float -gF 5 pi
- (( pi = 4 * atan(1.0) ))
- print $pi
-0:Basic operation with atan
->3.14159
-
- float -F 5 result
- (( result = atan(3,2) ))
- print $result
-0:atan with two arguments
->0.98279
-
- print $(( atan(1,2,3) ))
-1:atan can't take three arguments
-?(eval):1: wrong number of arguments: atan(1,2,3)
-
- float r1=$(( rand48() ))
- float r2=$(( rand48() ))
- float r3=$(( rand48() ))
- # Yes, this is a floating point equality test like they tell
- # you not to do. As the pseudrandom sequence is deterministic,
- # this is the right thing to do in this case.
- if (( r1 == r2 )); then
- print "Seed not updated correctly the first time"
- else
- print "First two random numbers differ, OK"
- fi
- if (( r2 == r3 )); then
- print "Seed not updated correctly the second time"
- else
- print "Second two random numbers differ, OK"
- fi
-0:rand48 with default initialisation
-F:This test fails if your math library doesn't have erand48().
->First two random numbers differ, OK
->Second two random numbers differ, OK
-
- seed=f45677a6cbe4
- float r1=$(( rand48(seed) ))
- float r2=$(( rand48(seed) ))
- seed2=$seed
- float r3=$(( rand48(seed) ))
- float r4=$(( rand48(seed2) ))
- # Yes, this is a floating point equality test like they tell
- # you not to do. As the pseudrandom sequence is deterministic,
- # this is the right thing to do in this case.
- if (( r1 == r2 )); then
- print "Seed not updated correctly the first time"
- else
- print "First two random numbers differ, OK"
- fi
- if (( r2 == r3 )); then
- print "Seed not updated correctly the second time"
- else
- print "Second two random numbers differ, OK"
- fi
- if (( r3 == r4 )); then
- print "Identical seeds generate identical numbers, OK"
- else
- print "Indeterminate result from identical seeds"
- fi
-0:rand48 with pre-generated seed
-F:This test fails if your math library doesn't have erand48().
->First two random numbers differ, OK
->Second two random numbers differ, OK
->Identical seeds generate identical numbers, OK
-
- float -F 5 pitest
- (( pitest = 4.0 * atan(1) ))
- # This is a string test of the output to 5 digits.
- if [[ $pi = $pitest ]]; then
- print "OK, atan on an integer seemed to work"
- else
- print "BAD: got $pitest instead of $pi"
- fi
-0:Conversion of arguments from integer
->OK, atan on an integer seemed to work
-
- float -F 5 result
- typeset str
- for str in 0 0.0 1 1.5 -1 -1.5; do
- (( result = abs($str) ))
- print $result
- done
-0:Use of abs on various numbers
->0.00000
->0.00000
->1.00000
->1.50000
->1.00000
->1.50000
-
- print $(( sqrt(-1) ))
-1:Non-negative argument checking for square roots.
-?(eval):1: math: argument to sqrt out of range
-
-# Simple test that the pseudorandom number generators are producing
-# something that could conceivably be pseudorandom numbers in a
-# linear range. Not a detailed quantitative verification.
- integer N=10000 isource ok=1
- float -F f sum sumsq max max2 av sd
- typeset -a randoms
- randoms=('f = RANDOM' 'f = rand48()')
- for isource in 1 2; do
- (( sum = sumsq = max = 0 ))
- repeat $N; do
- let $randoms[$isource]
- (( f > max )) && (( max = f ))
- (( sum += f, sumsq += f * f ))
- done
- (( av = sum / N ))
- (( sd = sqrt((sumsq - N * av * av) / (N-1)) ))
- (( max2 = 0.5 * max ))
- if (( av > max2 * 1.1 )) || (( av < max2 * 0.9 )); then
- print "WARNING: average of random numbers is suspicious.
- Was testing: $randoms[$isource]"
- (( ok = 0 ))
- fi
- if (( sd < max / 4 )); then
- print "WARNING: distribution of random numbers is suspicious.
- Was testing: $randoms[$isource]"
- (( ok = 0 ))
- fi
- done
- (( ok ))
-0:Test random number generator distributions are not grossly broken
-
- float -F 5 g l
- (( g = gamma(2), l = lgamma(2) ))
- print $g, $l
-0:Test Gamma function gamma and lgamma
->1.00000, 0.00000
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V04features.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V04features.ztst
deleted file mode 100644
index 6939053e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V04features.ztst
+++ /dev/null
@@ -1,172 +0,0 @@
-%prep
-
-# Do some tests on handling of features.
-# This also does some slightly more sophisticated loading and
-# unloading tests than we did in V01zmodload.ztst.
-#
-# We use zsh/datetime because it has a list of features that is short
-# but contains two types.
-
- # Subshell for prep test so we can load individual features later
- if ! (zmodload zsh/datetime 2>/dev/null); then
- ZTST_unimplemented="can't load the zsh/datetime module for testing"
- fi
-
-%test
- zmodload -F zsh/datetime
- zmodload -lF zsh/datetime
-0:Loading modules with no features
->-b:strftime
->-p:EPOCHSECONDS
->-p:EPOCHREALTIME
->-p:epochtime
-
- zmodload -F zsh/datetime b:strftime
- zmodload -lF zsh/datetime
-0:Enabling features
->+b:strftime
->-p:EPOCHSECONDS
->-p:EPOCHREALTIME
->-p:epochtime
-
- zmodload -F zsh/datetime +p:EPOCHSECONDS -b:strftime
- zmodload -lF zsh/datetime
-0:Disabling features
->-b:strftime
->+p:EPOCHSECONDS
->-p:EPOCHREALTIME
->-p:epochtime
-
- zmodload -Fe zsh/datetime p:EPOCHSECONDS b:strftime
-0:Testing existing features
-
- zmodload -Fe zsh/datetime +p:EPOCHSECONDS
-0:Testing features are in given state (on feature is on)
-
- zmodload -Fe zsh/datetime -p:EPOCHSECONDS
-1:Testing features are in given state (on feature is not off
-
- zmodload -Fe zsh/datetime +p:strftime
-1:Testing features are in given state (off feature is not on)
-
- zmodload -Fe zsh/datetime -b:strftime
-0:Testing features are in given state (off feature is off
-
- zmodload -Fe zsh/datetime p:EPOCHSECONDS b:strftime b:mktimebetter
-1:Testing non-existent features
-
- zmodload -FlP dtf zsh/datetime
- for feature in b:strftime p:EPOCHSECONDS; do
- if [[ ${${dtf[(R)?$feature]}[1]} = + ]]; then
- print $feature is enabled
- else
- print $feature is disabled
- fi
- done
-0:Testing features via array parameter
->b:strftime is disabled
->p:EPOCHSECONDS is enabled
-
- fn() {
- local EPOCHSECONDS=scruts
- print $EPOCHSECONDS
- print ${(t)EPOCHSECONDS}
- }
- fn
- if [[ $EPOCHSECONDS = <-> ]]; then
- print EPOCHSECONDS is a number
- else
- print EPOCHSECONDS is some random piece of junk
- fi
- print ${(t)EPOCHSECONDS}
-0:Module special parameter is hidden by a local parameter
->scruts
->scalar-local
->EPOCHSECONDS is a number
->integer-readonly-hide-hideval-special
-
- typeset +h EPOCHSECONDS
- fn() {
- local EPOCHSECONDS=scruts
- print Didn\'t get here >&2
- }
- fn
-1:Unhidden readonly special can't be assigned to when made local
-?fn:1: read-only variable: EPOCHSECONDS
-
- zmodload -u zsh/datetime
-0:Module unloaded
-
- zmodload -e zsh/datetime
-1:Module doesn't exist when unloaded
-
- zmodload -Fe zsh/datetime p:EPOCHSECONDS
-1:Module doesn't have features when unloaded
-
- fn() {
- local EPOCHSECONDS=scrimf
- zmodload zsh/datetime
- }
- fn
-2:Failed to add parameter if local parameter present
-?fn:2: Can't add module parameter `EPOCHSECONDS': local parameter exists
-?fn:zsh/datetime:2: error when adding parameter `EPOCHSECONDS'
-
- zmodload -lF zsh/datetime
-0:Feature state with loading after error enabling
->+b:strftime
->-p:EPOCHSECONDS
->+p:EPOCHREALTIME
->+p:epochtime
-
- zmodload -F zsh/datetime p:EPOCHSECONDS
- zmodload -Fe zsh/datetime +p:EPOCHSECONDS
-0:Successfully added feature parameter that previously failed
-
- fn() {
- local EPOCHSECONDS=scrooble
- zmodload -u zsh/datetime
- print $EPOCHSECONDS
- }
- fn
- print ${+EPOCHSECONDS}
-0:Successfully unloaded a module despite a parameter being hidden
->scrooble
->0
-
- EPOCHSECONDS=(any old parameter)
- print -l $EPOCHSECONDS
-0:Using parameter as normal after unloading is OK
->any
->old
->parameter
-
- print strftime is ${builtins[strftime]:-undefined}
- zmodload -F zsh/datetime b:strftime
- print strftime is ${builtins[strftime]:-undefined}
- zmodload -F zsh/datetime -b:strftime
- print strftime is ${builtins[strftime]:-undefined}
-0:Enabling and disabling of builtins as features
->strftime is undefined
->strftime is defined
->strftime is undefined
-
- zmodload -u zsh/datetime
- zmodload zsh/datetime
-2:Loading won't override global parameter
-?(eval):2: Can't add module parameter `EPOCHSECONDS': parameter already exists
-?(eval):zsh/datetime:2: error when adding parameter `EPOCHSECONDS'
-
- unset EPOCHSECONDS
- zmodload -F zsh/datetime p:EPOCHSECONDS
- zmodload -Fe zsh/datetime +p:EPOCHSECONDS
-0:unsetting a global parameter allows feature parameter to be enabled
-
- zmodload -F zsh/datetime -b:strftime -p:EPOCHSECONDS
- zmodload zsh/datetime
- zmodload -lF zsh/datetime
-0:zmodload with no -F enables all features
->+b:strftime
->+p:EPOCHSECONDS
->+p:EPOCHREALTIME
->+p:epochtime
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V05styles.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V05styles.ztst
deleted file mode 100644
index ca95b634..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V05styles.ztst
+++ /dev/null
@@ -1,143 +0,0 @@
-%prep
-
-# Test the use of styles, if the zsh/zutil module is available.
-
- if ! zmodload zsh/zutil 2>/dev/null; then
- ZTST_unimplemented="can't load the zsh/zutil module for testing"
- fi
-
-%test
- zstyle :random:stuff any-old-style with any old value
- zstyle :randomly:chosen some-other-style I can go on and on
- zstyle -d
- zstyle
-0:zstyle -d restores a pristine state
-
-# patterns should be ordered by weight, so add in reverse order to check
- zstyle ':ztst:context*' scalar-style other-scalar-value
- zstyle ':ztst:context:*' scalar-style second-scalar-value
- zstyle ':ztst:context:sub1' scalar-style scalar-value
- zstyle ':ztst:context:sub1' array-style array value elements 'with spaces'
- zstyle ':ztst:context*' boolean-style false
- zstyle ':ztst:context:sub1' boolean-style true
-0:defining styles
-
-# styles are now sorted, but patterns are in order of definition
- zstyle
-0:listing styles in default format
->array-style
-> :ztst:context:sub1 array value elements 'with spaces'
->boolean-style
-> :ztst:context:sub1 true
-> :ztst:context* false
->scalar-style
-> :ztst:context:sub1 scalar-value
-> :ztst:context:* second-scalar-value
-> :ztst:context* other-scalar-value
-
- zstyle -L
-0:listing styles in zstyle format
->zstyle :ztst:context:sub1 array-style array value elements 'with spaces'
->zstyle :ztst:context:sub1 boolean-style true
->zstyle ':ztst:context*' boolean-style false
->zstyle :ztst:context:sub1 scalar-style scalar-value
->zstyle ':ztst:context:*' scalar-style second-scalar-value
->zstyle ':ztst:context*' scalar-style other-scalar-value
-
- zstyle -b :ztst:context:sub1 boolean-style bool; print $bool
- zstyle -t :ztst:context:sub1 boolean-style
-0:boolean test -b/-t + true
->yes
-
- zstyle -b :ztst:context:sub2 boolean-style bool; print $bool
- zstyle -t :ztst:context:sub2 boolean-style
-1:boolean test -b/-t + false
->no
-
- zstyle -b :ztst:context:sub1 boolean-unset-style bool; print $bool
- zstyle -t :ztst:context:sub1 boolean-unset-style
-2:boolean test -b/-t + unset
->no
-
- zstyle -T :ztst:context:sub1 boolean-style
-0:boolean test -T + true
-
- zstyle -T :ztst:context:sub2 boolean-style
-1:boolean test -T + false
-
- zstyle -T :ztst:context:sub1 boolean-unset-style
-0:boolean test -T + unset
-
- zstyle -s :ztst:context:sub1 scalar-style scalar && print $scalar
- zstyle -s :ztst:context:sub2 scalar-style scalar && print $scalar
- zstyle -s :ztst:contextual-psychedelia scalar-style scalar && print $scalar
- zstyle -s :ztst:contemplative scalar-style scalar || print no match
-0:pattern matching rules
->scalar-value
->second-scalar-value
->other-scalar-value
->no match
-
- zstyle -s :ztst:context:sub1 array-style scalar + && print $scalar
-0:scalar with separator
->array+value+elements+with spaces
-
- zstyle -e :ztst:\* eval-style 'reply=($something)'
- something=(one two three)
- zstyle -a :ztst:eval eval-style array && print -l $array
-0:zstyle -e evaluations
->one
->two
->three
-
-# pattern ordering on output is not specified, so although in the
-# current implementation it's deterministic we shouldn't
-# assume it's always the same. Thus we sort the array.
-# (It might be a nice touch to order patterns by weight, which is
-# the way they are stored for each separate style.)
- zstyle -g array && print -l ${(o)array}
-0:retrieving patterns
->:ztst:*
->:ztst:context*
->:ztst:context:*
->:ztst:context:sub1
-
- zstyle -m :ztst:context:sub1 array-style 'w* *s'
-0:positive pattern match
-
- zstyle -m :ztst:context:sub1 array-style 'v'
-1:negative pattern match
-
- zstyle -g array ':ztst:context*' && print -l $array
-0:retrieving styles by pattern
->boolean-style
->scalar-style
-
- zstyle -g array ':ztst:context:sub1' array-style && print -l $array
-0:retrieving values by pattern and name
->array
->value
->elements
->with spaces
-
- zstyle -d :ztst:context:sub1
- zstyle
-0:deleting styles by pattern only
->boolean-style
-> :ztst:context* false
->eval-style
->(eval) :ztst:* 'reply=($something)'
->scalar-style
-> :ztst:context:* second-scalar-value
-> :ztst:context* other-scalar-value
-
- zstyle -d :ztst:context\* scalar-style
- zstyle
-0:deleting styles by pattern and style name
->boolean-style
-> :ztst:context* false
->eval-style
->(eval) :ztst:* 'reply=($something)'
->scalar-style
-> :ztst:context:* second-scalar-value
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V07pcre.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V07pcre.ztst
deleted file mode 100644
index ad177071..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V07pcre.ztst
+++ /dev/null
@@ -1,139 +0,0 @@
-%prep
-
- if ! zmodload -F zsh/pcre C:pcre-match 2>/dev/null
- then
- ZTST_unimplemented="the zsh/pcre module is not available"
- return 0
- fi
-# Load the rest of the builtins
- zmodload zsh/pcre
- setopt rematch_pcre
-# Find a UTF-8 locale.
- setopt multibyte
-# Don't let LC_* override our choice of locale.
- unset -m LC_\*
- mb_ok=
- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8
- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8'))
- for LANG in $langs; do
- if [[ é = ? ]]; then
- mb_ok=1
- break;
- fi
- done
- if [[ -z $mb_ok ]]; then
- ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented"
- else
- print -u $ZTST_fd Testing PCRE multibyte with locale $LANG
- mkdir multibyte.tmp && cd multibyte.tmp
- fi
-
-%test
-
- [[ 'foo→bar' =~ .([^[:ascii:]]). ]]
- print $MATCH
- print $match[1]
-0:Basic non-ASCII regexp matching
->o→b
->→
-
- unset match mend
- s=$'\u00a0'
- [[ $s =~ '^.$' ]] && print OK
- [[ A${s}B =~ .(.). && $match[1] == $s ]] && print OK
- [[ A${s}${s}B =~ A([^[:ascii:]]*)B && $mend[1] == 3 ]] && print OK
- unset s
-0:Raw IMETA characters in input string
->OK
->OK
->OK
-
- [[ foo =~ f.+ ]] ; print $?
- [[ foo =~ x.+ ]] ; print $?
- [[ ! foo =~ f.+ ]] ; print $?
- [[ ! foo =~ x.+ ]] ; print $?
- [[ foo =~ f.+ && bar =~ b.+ ]] ; print $?
- [[ foo =~ x.+ && bar =~ b.+ ]] ; print $?
- [[ foo =~ f.+ && bar =~ x.+ ]] ; print $?
- [[ ! foo =~ f.+ && bar =~ b.+ ]] ; print $?
- [[ foo =~ f.+ && ! bar =~ b.+ ]] ; print $?
- [[ ! ( foo =~ f.+ && bar =~ b.+ ) ]] ; print $?
- [[ ! foo =~ x.+ && bar =~ b.+ ]] ; print $?
- [[ foo =~ x.+ && ! bar =~ b.+ ]] ; print $?
- [[ ! ( foo =~ x.+ && bar =~ b.+ ) ]] ; print $?
-0:Regex result inversion detection
->0
->1
->1
->0
->0
->1
->1
->1
->1
->1
->0
->1
->0
-
-# Note that PCRE_ANCHORED only means anchored at the start
-# Also note that we don't unset MATCH/match on failed match (and it's an
-# open issue as to whether or not we should)
- pcre_compile '.(→.)'
- pcre_match foo→bar
- print $? $MATCH $match ; unset MATCH match
- pcre_match foo.bar
- print $? $MATCH $match ; unset MATCH match
- pcre_match foo†bar
- print $? $MATCH $match ; unset MATCH match
- pcre_match foo→†ar
- print $? $MATCH $match ; unset MATCH match
- pcre_study
- pcre_match foo→bar
- print $? $MATCH $match ; unset MATCH match
- pcre_compile -a '.(→.)'
- pcre_match foo→bar
- print $? $MATCH $match ; unset MATCH match
- pcre_match o→bar
- print $? $MATCH $match ; unset MATCH match
- pcre_match o→b
- print $? $MATCH $match ; unset MATCH match
- pcre_compile 'x.(→.)'
- pcre_match xo→t
- print $? $MATCH $match ; unset MATCH match
- pcre_match Xo→t
- print $? $MATCH $match ; unset MATCH match
- pcre_compile -i 'x.(→.)'
- pcre_match xo→t
- print $? $MATCH $match ; unset MATCH match
- pcre_match Xo→t
- print $? $MATCH $match ; unset MATCH match
-0:pcre_compile interface testing: basic, anchored & case-insensitive
->0 o→b →b
->1
->1
->0 o→† →†
->0 o→b →b
->1
->0 o→b →b
->0 o→b →b
->0 xo→t →t
->1
->0 xo→t →t
->0 Xo→t →t
-
- string="The following zip codes: 78884 90210 99513"
- pcre_compile -m "\d{5}"
- pcre_match -b -- $string && print "$MATCH; ZPCRE_OP: $ZPCRE_OP"
- pcre_match -b -n $ZPCRE_OP[(w)2] -- $string || print failed
- print "$MATCH; ZPCRE_OP: $ZPCRE_OP"
-0:pcre_match -b and pcre_match -n
->78884; ZPCRE_OP: 25 30
->90210; ZPCRE_OP: 31 36
-
-# Subshell because crash on failure
- ( setopt re_match_pcre
- [[ test.txt =~ '^(.*_)?(test)' ]]
- echo $match[2] )
-0:regression for segmentation fault, workers/38307
->test
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V08zpty.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V08zpty.ztst
deleted file mode 100644
index b0cbfa05..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V08zpty.ztst
+++ /dev/null
@@ -1,29 +0,0 @@
-# zpty is required by tests of interactive modes of the shell itself.
-# This tests some extra things.
-
-%prep
-
- if ! zmodload zsh/zpty 2>/dev/null
- then
- ZTST_unimplemented="the zsh/zpty module is not available"
- elif [[ $OSTYPE = cygwin ]]; then
- ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
- fi
-
-%test
-
- zpty cat cat
- zpty -w cat a line of text
- var=
- zpty -r cat var && print -r -- ${var%%$'\r\n'}
- zpty -d cat
-0:zpty with a process that does not set up the terminal: internal write
->a line of text
-
- zpty cat cat
- print a line of text | zpty -w cat
- var=
- zpty -r cat var && print -r -- ${var%%$'\r\n'}
- zpty -d cat
-0:zpty with a process that does not set up the terminal: write via stdin
->a line of text
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V09datetime.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V09datetime.ztst
deleted file mode 100644
index 7905155d..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V09datetime.ztst
+++ /dev/null
@@ -1,74 +0,0 @@
-%prep
-
- if zmodload zsh/datetime 2>/dev/null; then
- setopt multibyte
- unset LC_ALL
- LC_TIME=C
- TZ=UTC+0
- # It's not clear this skip_extensions is correct, but the
- # format in question is causing problems on Solaris.
- # We'll revist this after the release.
- [[ "$(strftime %^_10B 0)" = " JANUARY" ]] || skip_extensions=1
- [[ "$(LC_TIME=ja_JP.UTF-8 strftime %OS 1)" = 一 ]] || skip_japanese=1
- else
- ZTST_unimplemented="can't load the zsh/datetime module for testing"
- fi
-
-%test
-
- strftime %y 0
- strftime %Y 1000000000
- strftime %x 1200000000
- strftime %X 1200000001
-0:basic format specifiers
->70
->2001
->01/10/08
->21:20:01
-
- strftime %-m_%f_%K_%L 1181100000
- strftime %6. 0
-0:zsh extensions
->6_6_3_3
->000000
-
- if [[ $skip_extensions = 1 ]]; then
- ZTST_skip="strftime extensions not supported"
- elif [[ $skip_japanese = 1 ]]; then
- ZTST_skip="Japanese UTF-8 locale not supported"
- else
- (
- LC_TIME=ja_JP.UTF-8
- strftime %Ey 1000000000
- strftime %Oy 1000000000
- strftime %Ex 1000000000
- strftime %OS 1000000000
- strftime %03Ey 650000000
- )
- fi
-0:alternate format extensions
->13
->一
->平成13年09月09日
->四十
->002
-
- if [[ $skip_extensions = 1 ]]; then
- ZTST_skip="strftime extensions not supported"
- else
- (
- strftime '%#A' 0
- strftime '%^_10B' 0
- strftime %03Ey 650000000
- strftime %-Oe 0
- )
- fi
-0:various extensions
->THURSDAY
-> JANUARY
->090
->1
-
- print -r -- ${(V)"$(strftime $'%Y\0%m\0%d' 100000000)"}
-0:Embedded nulls
->1973^@03^@03
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V10private.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V10private.ztst
deleted file mode 100644
index 78ecd48e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/V10private.ztst
+++ /dev/null
@@ -1,304 +0,0 @@
-# Tests for the zsh/param/private module
-
-%prep
-
- if ! zmodload zsh/param/private 2>/dev/null; then
- ZTST_unimplemented="can't load the zsh/param/private module for testing"
- else
- # Do not use .tmp here, ztst.zsh will remove it too soon (see %cleanup)
- mkdir private.TMP
- sed -e 's,# test_zsh_param_private,zmodload zsh/param/private,' < $ZTST_srcdir/B02typeset.ztst > private.TMP/B02
- fi
-
-%test
-
- (zmodload -u zsh/param/private && zmodload zsh/param/private)
-0:unload and reload the module without crashing
-
- typeset scalar_test=toplevel
- () {
- print $scalar_test
- private scalar_test
- print $+scalar_test
- unset scalar_test
- print $+scalar_test
- }
- print $scalar_test
-0:basic scope hiding
->toplevel
->1
->0
->toplevel
-
- typeset scalar_test=toplevel
- print $scalar_test
- () {
- private scalar_test=function
- print $scalar_test
- }
- print $scalar_test
-0:enter and exit a scope
->toplevel
->function
->toplevel
-
- print $+unset_test
- () {
- private unset_test
- print $+unset_test
- unset_test=setme
- print $unset_test
- }
- print $+unset_test
-0:variable defined only in scope
->0
->1
->setme
->0
-
- # Depends on zsh-5.0.9 typeset keyword
- typeset -a array_test=(top level)
- () {
- local -Pa array_test=(in function)
- () {
- private array_test
- print $+array_test
- }
- print $array_test
- }
- print $array_test
-0:nested scope with different type, correctly restored
->1
->in function
->top level
-
- typeset -a array_test=(top level)
- () {
- private array_test
- array_test=(in function)
- }
-1:type of private may not be changed by assignment
-?(anon):2: array_test: attempt to assign array value to non-array
-
- typeset -A hash_test=(top level)
- () {
- setopt localoptions noglob
- private hash_test[top]
- }
-1:associative array fields may not be private
-?(anon):private:2: hash_test[top]: can't create local array elements
-
- () {
- private path
- }
-1:tied params may not be private, part 1
-?(anon):private:1: can't change scope of existing param: path
-
- () {
- private PATH
- }
-1:tied params may not be private, part 2
-?(anon):private:1: can't change scope of existing param: PATH
-
- () {
- private -h path
- print X$path
- }
-0:privates may hide tied paramters
->X
-
- # Deliberate type mismatch here
- typeset -a hash_test=(top level)
- typeset -p hash_test
- inner () {
- private -p hash_test
- print ${(t)hash_test} ${(kv)hash_test}
- }
- outer () {
- local -PA hash_test=(in function)
- typeset -p hash_test
- inner
- }
- outer
- print ${(kv)hash_test}
-0:private hides value from surrounding scope in nested scope
->typeset -a hash_test=( top level )
->typeset -A hash_test=( in function )
->typeset -g -a hash_test=( top level )
->array-local top level
->top level
-F:note "typeset" rather than "private" in output from outer
-
- () {
- private -a array_test
- local array_test=scalar
- }
-1:private cannot be re-declared as local
-?(anon):local:2: array_test: inconsistent type for assignment
-
- () {
- local hash_test=scalar
- private -A hash_test
- }
-1:local cannot be re-declared as private
-?(anon):private:2: can't change scope of existing param: hash_test
-
- inner () {
- print $+scalar_test
- $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
- }
- () {
- private -x scalar_test=whaat
- $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
- inner
- print Y $scalar_test
- }
-0:exported private behaves like a local, part 1
->X whaat
->0
->X whaat
->Y whaat
-
- inner () {
- typeset -p array_test
- $ZTST_testdir/../Src/zsh -fc 'print X $array_test'
- }
- () {
- local -Pax array_test=(whaat)
- print Y $array_test
- $ZTST_testdir/../Src/zsh -fc 'print X $array_test'
- inner
- }
-0:exported private behaves like a local, part 2 (arrays do not export)
-?inner:typeset:1: no such variable: array_test
->Y whaat
->X
->X
-
- inner () {
- print $+scalar_test
- $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
- }
- () {
- private scalar_test=whaat
- export scalar_test
- $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
- inner
- () {
- print $+scalar_test
- $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test'
- }
- print Y $scalar_test
- }
-0:exported private behaves like a local, part 3 (export does not change scope)
->X whaat
->0
->X whaat
->0
->X whaat
->Y whaat
-
- typeset -A hash_test=(top level)
- () {
- local -PA hash_test=(in function)
- () {
- print X ${(kv)hash_test}
- }
- print Y ${(kv)hash_test}
- }
- print ${(kv)hash_test}
-0:privates are not visible in anonymous functions, part 1
->X top level
->Y in function
->top level
-
- typeset -A hash_test=(top level)
- () {
- local -PA hash_test=(in function)
- () {
- print X ${(kv)hash_test}
- hash_test[in]=deeper
- }
- print Y ${(kv)hash_test}
- }
- print ${(okv)hash_test}
-0:privates are not visible in anonymous functions, part 2
->X top level
->Y in function
->deeper in level top
-
- typeset -A hash_test=(top level)
- () {
- local -Pa array_test=(in function)
- local -PA hash_test=($array_test)
- () {
- print X ${(kv)hash_test}
- hash_test=(even deeper)
- {
- array_test+=(${(kv)hash_test})
- } always {
- print ${array_test-array_test not set} ${(t)array_test}
- }
- }
- print Y ${(kv)hash_test} Z $array_test
- }
- print ${(kv)hash_test} ${(t)array_test}
-1:privates are not visible in anonymous functions, part 3
->X top level
->array_test not set
-?(anon):4: array_test: attempt to assign private in nested scope
-F:future revision will create a global with this assignment
-
- typeset -a array_test
- typeset -A hash_test=(top level)
- () {
- local -Pa array_test=(in function)
- local -PA hash_test=($array_test)
- () {
- print X ${(kv)hash_test}
- hash_test=(even deeper)
- array_test+=(${(kv)hash_test})
- }
- print Y ${(kv)hash_test} Z $array_test
- }
- print ${(kv)hash_test} $array_test
-0:privates are not visible in anonymous functions, part 4
->X top level
->Y in function Z in function
->even deeper even deeper
-
- typeset -A hash_test=(top level)
- () {
- local -PA hash_test=(in function)
- () {
- print X ${(kv)hash_test}
- unset hash_test
- }
- print Y ${(kv)hash_test}
- }
- print ${(t)hash_test} ${(kv)hash_test}
-0:privates are not visible in anonymous functions, part 5
->X top level
->Y in function
->
-
- # Subshell because otherwise this silently dumps core when broken
- ( () { private SECONDS } )
-1:special parameters cannot be made private
-?(anon):private: can't change scope of existing param: SECONDS
-
- () { private -h SECONDS }
-0:private parameter may hide a special parameter
-
- if (( UID )); then
- ZTST_verbose=0 $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh private.TMP/B02
- else
- ZTST_skip="cannot re-run typeset tests when tests run as superuser"
- fi
-0:typeset still works with zsh/param/private module loaded
-*>*
-*>*
-
-%clean
-
- rm -r private.TMP
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/W01history.ztst b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/W01history.ztst
deleted file mode 100644
index 6ef9b11c..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/W01history.ztst
+++ /dev/null
@@ -1,60 +0,0 @@
-# Tests for BANG_HIST replacements
-
-%prep
-
- if [[ -t 0 ]]; then print -u $ZTST_fd History tests write to /dev/tty; fi
-
-%test
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- print one two three four five six seven eight nine ten
- print !:$ !:10 !:9 !:1 !:0
- print one two three four five six seven eight nine ten
- print !:0-$ !:1-2
- ' 2>/dev/null
-0:History word references
->one two three four five six seven eight nine ten
->ten ten nine one print
->one two three four five six seven eight nine ten
->print one two three four five six seven eight nine ten one two
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- print line one of an arbitrary series
- print issue two for some mystery sequence
- print !-1:5-$
- print !1:2
- print !2:2
- print !-3:1-$
- ' 2>/dev/null
-0:History line numbering
->line one of an arbitrary series
->issue two for some mystery sequence
->mystery sequence
->one
->two
->mystery sequence
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- print All metaphor, Malachi, stilts and all
- print !1:2:s/,/\\\\?/ !1:2:s/m/shm/:s/,/\!/
- print !1:2:&
- print -l !1:2-3:gs/a/o/
- ' 2>/dev/null
-0:History substitution
->All metaphor, Malachi, stilts and all
->metaphor? shmetaphor!
->metaphor!
->metophor,
->Molochi,
-
- $ZTST_testdir/../Src/zsh -fis <<<'
- echo foo bar
- echo $(!!) again
- echo more $( !! )' 2>/dev/null
-0:Regression test for history references in command substitution
->foo bar
->foo bar again
->more foo bar again
-*?*
-F:Check that a history bug introduced by workers/34160 is working again.
-# Discarded line of error output consumes prompts printed by "zsh -i".
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/comptest b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/comptest
deleted file mode 100644
index 166d0b40..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/comptest
+++ /dev/null
@@ -1,177 +0,0 @@
-comptestinit () {
- setopt extendedglob
- [[ -d $ZTST_testdir/Modules/zsh ]] && module_path=( $ZTST_testdir/Modules )
- fpath=( $ZTST_srcdir/../Functions/*~*/CVS(/)
- $ZTST_srcdir/../Completion
- $ZTST_srcdir/../Completion/*/*~*/CVS(/) )
-
- zmodload zsh/zpty || return $?
-
- comptest_zsh=${ZSH:-zsh}
- comptest_keymap=e
-
- while getopts vz: opt; do
- case $opt in
- z) comptest_zsh="$OPTARG";;
- v) comptest_keymap="v";;
- esac
- done
- (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
-
- export PS1=""
- zpty zsh "$comptest_zsh -f +Z"
-
- zpty -r zsh log1 "**" || {
- print "first prompt hasn't appeared."
- return 1
- }
-
- comptesteval \
-"export LC_ALL=${ZSH_TEST_LANG:-C}" \
-"emulate -R zsh" \
-"export ZDOTDIR=$ZTST_testdir" \
-"module_path=( $module_path )" \
-"fpath=( $fpath )" \
-"bindkey -$comptest_keymap" \
-'LISTMAX=10000000
-stty 38400 columns 80 rows 24 tabs -icanon -iexten
-TERM=vt100
-KEYTIMEOUT=1
-setopt zle
-autoload -U compinit
-compinit -u
-zstyle ":completion:*:default" list-colors "no=" "fi=" "di=" "ln=" "pi=" "so=" "bd=" "cd=" "ex=" "mi=" "tc=" "sp=" "lc=" "ec=\n" "rc="
-zstyle ":completion:*" group-name ""
-zstyle ":completion:*:messages" format "%d
-"
-zstyle ":completion:*:descriptions" format "%d
-"
-zstyle ":completion:*:options" verbose yes
-zstyle ":completion:*:values" verbose yes
-setopt noalwayslastprompt listrowsfirst completeinword
-zmodload zsh/complist
-expand-or-complete-with-report () {
- print -lr ""
- zle expand-or-complete
- print -lr - "$LBUFFER" "$RBUFFER"
- zle clear-screen
- zle -R
-}
-list-choices-with-report () {
- print -lr ""
- zle list-choices
- zle clear-screen
- zle -R
-}
-comp-finish () {
- print ""
- zle kill-whole-line
- zle clear-screen
- zle -R
-}
-zle-finish () {
- local buffer="$BUFFER" cursor="$CURSOR" mark="$MARK"
- (( region_active)) || unset mark
- BUFFER=""
- zle -I
- zle clear-screen
- zle redisplay
- print -lr "" "BUFFER: $buffer" "CURSOR: $cursor"
- (( $+mark )) && print -lr "MARK: $mark"
- zle accept-line
-}
-zle -N expand-or-complete-with-report
-zle -N list-choices-with-report
-zle -N comp-finish
-zle -N zle-finish
-bindkey "^I" expand-or-complete-with-report
-bindkey "^D" list-choices-with-report
-bindkey "^Z" comp-finish
-bindkey "^X" zle-finish
-bindkey -a "^X" zle-finish
-'
-}
-
-zpty_flush() {
- local junk
- if zpty -r -t zsh junk \*; then
- (( ZTST_verbose > 2 )) && print -n -u $ZTST_fd "$*: ${(V)junk}"
- while zpty -r -t zsh junk \* ; do
- (( ZTST_verbose > 2 )) && print -n -u $ZTST_fd "${(V)junk}"
- done
- (( ZTST_verbose > 2 )) && print -u $ZTST_fd ''
- fi
-}
-
-zpty_run() {
- zpty -w zsh "$*"
- zpty -r -m zsh log "**" || {
- print "prompt hasn't appeared."
- return 1
- }
-}
-
-comptesteval () {
- local tmp=/tmp/comptest.$$
-
- print -lr - "$@" > $tmp
- # zpty_flush Before comptesteval
- zpty -w zsh ". $tmp"
- zpty -r -m zsh log_eval "**" || {
- print "prompt hasn't appeared."
- return 1
- }
- zpty_flush After comptesteval
- rm $tmp
-}
-
-comptest () {
- input="$*"
- zpty -n -w zsh "$input"$'\C-Z'
- zpty -r -m zsh log "***" || {
- print "failed to invoke finish widget."
- return 1
- }
-
- logs=(${(s::)log})
- shift logs
-
- for log in "$logs[@]"; do
- if [[ "$log" = (#b)*$''(*)$'\r\n'(*)$''* ]]; then
- print -lr "line: {$match[1]}{$match[2]}"
- fi
- while (( ${(N)log#*(#b)(<(??)>(*)|(*)|(*)|(*)|(*))} )); do
- log="${log[$mend[1]+1,-1]}"
- if (( 0 <= $mbegin[2] )); then
- if [[ $match[2] != TC && $match[3] != \ # ]]; then
- print -lr "$match[2]:{${match[3]%${(%):-%E}}}"
- fi
- elif (( 0 <= $mbegin[4] )); then
- print -lr "DESCRIPTION:{$match[4]}"
- elif (( 0 <= $mbegin[5] )); then
- print -lr "MESSAGE:{$match[5]}"
- elif (( 0 <= $mbegin[6] )); then
- print -lr "COMPADD:{${${match[6]}//[$'\r\n']/}}"
- elif (( 0 <= $mbegin[7] )); then
- print -lr "INSERT_POSITIONS:{${${match[7]}//[$'\r\n']/}}"
- fi
- done
- done
-}
-
-zletest () {
- local first=0
- for input; do
- # zpty_flush Before zletest
- # sleep for $KEYTIMEOUT
- (( first++ )) && { sleep 2 & } | read -t 0.011 -u 0 -k 1
- zpty -n -w zsh "$input"
- done
- zpty -n -w zsh $'\C-X'
- zpty -r -m zsh log "***" || {
- print "failed to invoke finish widget."
- return 1
- }
- # zpty_flush After zletest
- print -lr "${(@)${(@ps:\r\n:)log##*}[2,-2]}"
-}
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/runtests.zsh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/runtests.zsh
deleted file mode 100644
index 562234d9..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/runtests.zsh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/zsh -f
-
-emulate zsh
-
-# Run all specified tests, keeping count of which succeeded.
-# The reason for this extra layer above the test script is to
-# protect from catastrophic failure of an individual test.
-# We could probably do that with subshells instead.
-
-integer success failure skipped retval
-for file in "${(f)ZTST_testlist}"; do
- $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh $file
- retval=$?
- if (( $retval == 2 )); then
- (( skipped++ ))
- elif (( $retval )); then
- (( failure++ ))
- else
- (( success++ ))
- fi
-done
-print "**************************************
-$success successful test script${${success:#1}:+s}, \
-$failure failure${${failure:#1}:+s}, \
-$skipped skipped
-**************************************"
-return $(( failure ? 1 : 0 ))
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/ztst.zsh b/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/ztst.zsh
deleted file mode 100755
index f172ae14..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/Test/ztst.zsh
+++ /dev/null
@@ -1,547 +0,0 @@
-#!/bin/zsh -f
-# The line above is just for convenience. Normally tests will be run using
-# a specified version of zsh. With dynamic loading, any required libraries
-# must already have been installed in that case.
-#
-# Takes one argument: the name of the test file. Currently only one such
-# file will be processed each time ztst.zsh is run. This is slower, but
-# much safer in terms of preserving the correct status.
-# To avoid namespace pollution, all functions and parameters used
-# only by the script begin with ZTST_.
-#
-# Options (without arguments) may precede the test file argument; these
-# are interpreted as shell options to set. -x is probably the most useful.
-
-# Produce verbose messages if non-zero.
-# If 1, produce reports of tests executed; if 2, also report on progress.
-# Defined in such a way that any value from the environment is used.
-: ${ZTST_verbose:=0}
-
-# We require all options to be reset, not just emulation options.
-# Unfortunately, due to the crud which may be in /etc/zshenv this might
-# still not be good enough. Maybe we should trick it somehow.
-emulate -R zsh
-
-# Ensure the locale does not screw up sorting. Don't supply a locale
-# unless there's one set, to minimise problems.
-[[ -n $LC_ALL ]] && LC_ALL=C
-[[ -n $LC_COLLATE ]] && LC_COLLATE=C
-[[ -n $LC_NUMERIC ]] && LC_NUMERIC=C
-[[ -n $LC_MESSAGES ]] && LC_MESSAGES=C
-[[ -n $LANG ]] && LANG=C
-
-# Don't propagate variables that are set by default in the shell.
-typeset +x WORDCHARS
-
-# Set the module load path to correspond to this build of zsh.
-# This Modules directory should have been created by "make check".
-[[ -d Modules/zsh ]] && module_path=( $PWD/Modules )
-# Allow this to be passed down.
-export MODULE_PATH
-
-# We need to be able to save and restore the options used in the test.
-# We use the $options variable of the parameter module for this.
-zmodload zsh/parameter
-
-# Note that both the following are regular arrays, since we only use them
-# in whole array assignments to/from $options.
-# Options set in test code (i.e. by default all standard options)
-ZTST_testopts=(${(kv)options})
-
-setopt extendedglob nonomatch
-while [[ $1 = [-+]* ]]; do
- set $1
- shift
-done
-# Options set in main script
-ZTST_mainopts=(${(kv)options})
-
-# We run in the current directory, so remember it.
-ZTST_testdir=$PWD
-ZTST_testname=$1
-
-integer ZTST_testfailed
-
-# This is POSIX nonsense. Because of the vague feeling someone, somewhere
-# may one day need to examine the arguments of "tail" using a standard
-# option parser, every Unix user in the world is expected to switch
-# to using "tail -n NUM" instead of "tail -NUM". Older versions of
-# tail don't support this.
-tail() {
- emulate -L zsh
-
- if [[ -z $TAIL_SUPPORTS_MINUS_N ]]; then
- local test
- test=$(echo "foo\nbar" | command tail -n 1 2>/dev/null)
- if [[ $test = bar ]]; then
- TAIL_SUPPORTS_MINUS_N=1
- else
- TAIL_SUPPORTS_MINUS_N=0
- fi
- fi
-
- integer argi=${argv[(i)-<->]}
-
- if [[ $argi -le $# && $TAIL_SUPPORTS_MINUS_N = 1 ]]; then
- argv[$argi]=(-n ${argv[$argi][2,-1]})
- fi
-
- command tail "$argv[@]"
-}
-
-# The source directory is not necessarily the current directory,
-# but if $0 doesn't contain a `/' assume it is.
-if [[ $0 = */* ]]; then
- ZTST_srcdir=${0%/*}
-else
- ZTST_srcdir=$PWD
-fi
-[[ $ZTST_srcdir = /* ]] || ZTST_srcdir="$ZTST_testdir/$ZTST_srcdir"
-
-# Set the function autoload paths to correspond to this build of zsh.
-fpath=( $ZTST_srcdir/../Functions/*~*/CVS(/)
- $ZTST_srcdir/../Completion
- $ZTST_srcdir/../Completion/*/*~*/CVS(/) )
-
-: ${TMPPREFIX:=/tmp/zsh}
-ZTST_tmp=${TMPPREFIX}.ztst.$$
-if ! rm -f $ZTST_tmp || ! mkdir -p $ZTST_tmp || ! chmod go-w $ZTST_tmp; then
- print "Can't create $ZTST_tmp for exclusive use." >&2
- exit 1
-fi
-# Temporary files for redirection inside tests.
-ZTST_in=${ZTST_tmp}/ztst.in
-# hold the expected output
-ZTST_out=${ZTST_tmp}/ztst.out
-ZTST_err=${ZTST_tmp}/ztst.err
-# hold the actual output from the test
-ZTST_tout=${ZTST_tmp}/ztst.tout
-ZTST_terr=${ZTST_tmp}/ztst.terr
-
-ZTST_cleanup() {
- cd $ZTST_testdir
- rm -rf $ZTST_testdir/dummy.tmp $ZTST_testdir/*.tmp(N) ${ZTST_tmp}
-}
-
-# This cleanup always gets performed, even if we abort. Later,
-# we should try and arrange that any test-specific cleanup
-# always gets called as well.
-##trap 'print cleaning up...
-##ZTST_cleanup' INT QUIT TERM
-# Make sure it's clean now.
-rm -rf dummy.tmp *.tmp
-
-# Report failure. Note that all output regarding the tests goes to stdout.
-# That saves an unpleasant mixture of stdout and stderr to sort out.
-ZTST_testfailed() {
- print -r "Test $ZTST_testname failed: $1"
- if [[ -n $ZTST_message ]]; then
- print -r "Was testing: $ZTST_message"
- fi
- print -r "$ZTST_testname: test failed."
- if [[ -n $ZTST_failmsg ]]; then
- print -r "The following may (or may not) help identifying the cause:
-$ZTST_failmsg"
- fi
- ZTST_testfailed=1
- return 1
-}
-
-# Print messages if $ZTST_verbose is non-empty
-ZTST_verbose() {
- local lev=$1
- shift
- if [[ -n $ZTST_verbose && $ZTST_verbose -ge $lev ]]; then
- print -r -u $ZTST_fd -- $*
- fi
-}
-ZTST_hashmark() {
- if [[ ZTST_verbose -le 0 && -t $ZTST_fd ]]; then
- print -n -u$ZTST_fd -- ${(pl:SECONDS::\#::\#\r:)}
- fi
- (( SECONDS > COLUMNS+1 && (SECONDS -= COLUMNS) ))
-}
-
-if [[ ! -r $ZTST_testname ]]; then
- ZTST_testfailed "can't read test file."
- exit 1
-fi
-
-exec {ZTST_fd}>&1
-exec {ZTST_input}<$ZTST_testname
-
-# The current line read from the test file.
-ZTST_curline=''
-# The current section being run
-ZTST_cursect=''
-
-# Get a new input line. Don't mangle spaces; set IFS locally to empty.
-# We shall skip comments at this level.
-ZTST_getline() {
- local IFS=
- while true; do
- read -u $ZTST_input -r ZTST_curline || return 1
- [[ $ZTST_curline == \#* ]] || return 0
- done
-}
-
-# Get the name of the section. It may already have been read into
-# $curline, or we may have to skip some initial comments to find it.
-# If argument present, it's OK to skip the reset of the current section,
-# so no error if we find garbage.
-ZTST_getsect() {
- local match mbegin mend
-
- while [[ $ZTST_curline != '%'(#b)([[:alnum:]]##)* ]]; do
- ZTST_getline || return 1
- [[ $ZTST_curline = [[:blank:]]# ]] && continue
- if [[ $# -eq 0 && $ZTST_curline != '%'[[:alnum:]]##* ]]; then
- ZTST_testfailed "bad line found before or after section:
-$ZTST_curline"
- exit 1
- fi
- done
- # have the next line ready waiting
- ZTST_getline
- ZTST_cursect=${match[1]}
- ZTST_verbose 2 "ZTST_getsect: read section name: $ZTST_cursect"
- return 0
-}
-
-# Read in an indented code chunk for execution
-ZTST_getchunk() {
- # Code chunks are always separated by blank lines or the
- # end of a section, so if we already have a piece of code,
- # we keep it. Currently that shouldn't actually happen.
- ZTST_code=''
- # First find the chunk.
- while [[ $ZTST_curline = [[:blank:]]# ]]; do
- ZTST_getline || break
- done
- while [[ $ZTST_curline = [[:blank:]]##[^[:blank:]]* ]]; do
- ZTST_code="${ZTST_code:+${ZTST_code}
-}${ZTST_curline}"
- ZTST_getline || break
- done
- ZTST_verbose 2 "ZTST_getchunk: read code chunk:
-$ZTST_code"
- [[ -n $ZTST_code ]]
-}
-
-# Read in a piece for redirection.
-ZTST_getredir() {
- local char=${ZTST_curline[1]} fn
- ZTST_redir=${ZTST_curline[2,-1]}
- while ZTST_getline; do
- [[ $ZTST_curline[1] = $char ]] || break
- ZTST_redir="${ZTST_redir}
-${ZTST_curline[2,-1]}"
- done
- ZTST_verbose 2 "ZTST_getredir: read redir for '$char':
-$ZTST_redir"
-
- case $char in
- ('<') fn=$ZTST_in
- ;;
- ('>') fn=$ZTST_out
- ;;
- ('?') fn=$ZTST_err
- ;;
- (*) ZTST_testfailed "bad redir operator: $char"
- return 1
- ;;
- esac
- if [[ $ZTST_flags = *q* && $char = '<' ]]; then
- # delay substituting output until variables are set
- print -r -- "${(e)ZTST_redir}" >>$fn
- else
- print -r -- "$ZTST_redir" >>$fn
- fi
-
- return 0
-}
-
-# Execute an indented chunk. Redirections will already have
-# been set up, but we need to handle the options.
-ZTST_execchunk() {
- setopt localloops # don't let continue & break propagate out
- options=($ZTST_testopts)
- () {
- unsetopt localloops
- eval "$ZTST_code"
- }
- ZTST_status=$?
- # careful... ksh_arrays may be in effect.
- ZTST_testopts=(${(kv)options[*]})
- options=(${ZTST_mainopts[*]})
- ZTST_verbose 2 "ZTST_execchunk: status $ZTST_status"
- return $ZTST_status
-}
-
-# Functions for preparation and cleaning.
-# When cleaning up (non-zero string argument), we ignore status.
-ZTST_prepclean() {
- # Execute indented code chunks.
- while ZTST_getchunk; do
- ZTST_execchunk >/dev/null || [[ -n $1 ]] || {
- [[ -n "$ZTST_unimplemented" ]] ||
- ZTST_testfailed "non-zero status from preparation code:
-$ZTST_code" && return 0
- }
- done
-}
-
-# diff wrapper
-ZTST_diff() {
- emulate -L zsh
- setopt extendedglob
-
- local diff_out
- integer diff_pat diff_ret
-
- case $1 in
- (p)
- diff_pat=1
- ;;
-
- (d)
- ;;
-
- (*)
- print "Bad ZTST_diff code: d for diff, p for pattern match"
- ;;
- esac
- shift
-
- if (( diff_pat )); then
- local -a diff_lines1 diff_lines2
- integer failed i
-
- diff_lines1=("${(f)$(<$argv[-2])}")
- diff_lines2=("${(f)$(<$argv[-1])}")
- if (( ${#diff_lines1} != ${#diff_lines2} )); then
- failed=1
- else
- for (( i = 1; i <= ${#diff_lines1}; i++ )); do
- if [[ ${diff_lines2[i]} != ${~diff_lines1[i]} ]]; then
- failed=1
- break
- fi
- done
- fi
- if (( failed )); then
- print -rl "Pattern match failed:" \<${^diff_lines1} \>${^diff_lines2}
- diff_ret=1
- fi
- else
- diff_out=$(diff "$@")
- diff_ret="$?"
- if [[ "$diff_ret" != "0" ]]; then
- print -r -- "$diff_out"
- fi
- fi
-
- return "$diff_ret"
-}
-
-ZTST_test() {
- local last match mbegin mend found substlines
- local diff_out diff_err
- local ZTST_skip
-
- while true; do
- rm -f $ZTST_in $ZTST_out $ZTST_err
- touch $ZTST_in $ZTST_out $ZTST_err
- ZTST_message=''
- ZTST_failmsg=''
- found=0
- diff_out=d
- diff_err=d
-
- ZTST_verbose 2 "ZTST_test: looking for new test"
-
- while true; do
- ZTST_verbose 2 "ZTST_test: examining line:
-$ZTST_curline"
- case $ZTST_curline in
- (%*) if [[ $found = 0 ]]; then
- break 2
- else
- last=1
- break
- fi
- ;;
- ([[:space:]]#)
- if [[ $found = 0 ]]; then
- ZTST_getline || break 2
- continue
- else
- break
- fi
- ;;
- ([[:space:]]##[^[:space:]]*) ZTST_getchunk
- if [[ $ZTST_curline == (#b)([-0-9]##)([[:alpha:]]#)(:*)# ]]; then
- ZTST_xstatus=$match[1]
- ZTST_flags=$match[2]
- ZTST_message=${match[3]:+${match[3][2,-1]}}
- else
- ZTST_testfailed "expecting test status at:
-$ZTST_curline"
- return 1
- fi
- ZTST_getline
- found=1
- ;;
- ('<'*) ZTST_getredir || return 1
- found=1
- ;;
- ('*>'*)
- ZTST_curline=${ZTST_curline[2,-1]}
- diff_out=p
- ;&
- ('>'*)
- ZTST_getredir || return 1
- found=1
- ;;
- ('*?'*)
- ZTST_curline=${ZTST_curline[2,-1]}
- diff_err=p
- ;&
- ('?'*)
- ZTST_getredir || return 1
- found=1
- ;;
- ('F:'*) ZTST_failmsg="${ZTST_failmsg:+${ZTST_failmsg}
-} ${ZTST_curline[3,-1]}"
- ZTST_getline
- found=1
- ;;
- (*) ZTST_testfailed "bad line in test block:
-$ZTST_curline"
- return 1
- ;;
- esac
- done
-
- # If we found some code to execute...
- if [[ -n $ZTST_code ]]; then
- ZTST_hashmark
- ZTST_verbose 1 "Running test: $ZTST_message"
- ZTST_verbose 2 "ZTST_test: expecting status: $ZTST_xstatus"
- ZTST_verbose 2 "Input: $ZTST_in, output: $ZTST_out, error: $ZTST_terr"
-
- ZTST_execchunk <$ZTST_in >$ZTST_tout 2>$ZTST_terr
-
- if [[ -n $ZTST_skip ]]; then
- ZTST_verbose 0 "Test case skipped: $ZTST_skip"
- ZTST_skip=
- if [[ -n $last ]]; then
- break
- else
- continue
- fi
- fi
-
- # First check we got the right status, if specified.
- if [[ $ZTST_xstatus != - && $ZTST_xstatus != $ZTST_status ]]; then
- ZTST_testfailed "bad status $ZTST_status, expected $ZTST_xstatus from:
-$ZTST_code${$(<$ZTST_terr):+
-Error output:
-$(<$ZTST_terr)}"
- return 1
- fi
-
- ZTST_verbose 2 "ZTST_test: test produced standard output:
-$(<$ZTST_tout)
-ZTST_test: and standard error:
-$(<$ZTST_terr)"
-
- # Now check output and error.
- if [[ $ZTST_flags = *q* && -s $ZTST_out ]]; then
- substlines="$(<$ZTST_out)"
- rm -rf $ZTST_out
- print -r -- "${(e)substlines}" >$ZTST_out
- fi
- if [[ $ZTST_flags != *d* ]] && ! ZTST_diff $diff_out -u $ZTST_out $ZTST_tout; then
- ZTST_testfailed "output differs from expected as shown above for:
-$ZTST_code${$(<$ZTST_terr):+
-Error output:
-$(<$ZTST_terr)}"
- return 1
- fi
- if [[ $ZTST_flags = *q* && -s $ZTST_err ]]; then
- substlines="$(<$ZTST_err)"
- rm -rf $ZTST_err
- print -r -- "${(e)substlines}" >$ZTST_err
- fi
- if [[ $ZTST_flags != *D* ]] && ! ZTST_diff $diff_err -u $ZTST_err $ZTST_terr; then
- ZTST_testfailed "error output differs from expected as shown above for:
-$ZTST_code"
- return 1
- fi
- fi
- ZTST_verbose 1 "Test successful."
- [[ -n $last ]] && break
- done
-
- ZTST_verbose 2 "ZTST_test: all tests successful"
-
- # reset message to keep ZTST_testfailed output correct
- ZTST_message=''
-}
-
-
-# Remember which sections we've done.
-typeset -A ZTST_sects
-ZTST_sects=(prep 0 test 0 clean 0)
-
-print "$ZTST_testname: starting."
-
-# Now go through all the different sections until the end.
-# prep section may set ZTST_unimplemented, in this case the actual
-# tests will be skipped
-ZTST_skipok=
-ZTST_unimplemented=
-while [[ -z "$ZTST_unimplemented" ]] && ZTST_getsect $ZTST_skipok; do
- case $ZTST_cursect in
- (prep) if (( ${ZTST_sects[prep]} + ${ZTST_sects[test]} + \
- ${ZTST_sects[clean]} )); then
- ZTST_testfailed "\`prep' section must come first"
- exit 1
- fi
- ZTST_prepclean
- ZTST_sects[prep]=1
- ;;
- (test)
- if (( ${ZTST_sects[test]} + ${ZTST_sects[clean]} )); then
- ZTST_testfailed "bad placement of \`test' section"
- exit 1
- fi
- # careful here: we can't execute ZTST_test before || or &&
- # because that affects the behaviour of traps in the tests.
- ZTST_test
- (( $? )) && ZTST_skipok=1
- ZTST_sects[test]=1
- ;;
- (clean)
- if (( ${ZTST_sects[test]} == 0 || ${ZTST_sects[clean]} )); then
- ZTST_testfailed "bad use of \`clean' section"
- else
- ZTST_prepclean 1
- ZTST_sects[clean]=1
- fi
- ZTST_skipok=
- ;;
- *) ZTST_testfailed "bad section name: $ZTST_cursect"
- ;;
- esac
-done
-
-if [[ -n "$ZTST_unimplemented" ]]; then
- print "$ZTST_testname: skipped ($ZTST_unimplemented)"
- ZTST_testfailed=2
-elif (( ! $ZTST_testfailed )); then
- print "$ZTST_testname: all tests successful."
-fi
-ZTST_cleanup
-exit $(( ZTST_testfailed ))
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/aclocal.m4 b/dots/.config/zsh/config/plugins/fzf-tab/modules/aclocal.m4
deleted file mode 100644
index e91be3c0..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/aclocal.m4
+++ /dev/null
@@ -1,77 +0,0 @@
-# Local additions to Autoconf macros.
-# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
-# Francois Pinard , 1992.
-
-# @defmac fp_PROG_CC_STDC
-# @maindex PROG_CC_STDC
-# @ovindex CC
-# If the C compiler in not in ANSI C mode by default, try to add an option
-# to output variable @code{CC} to make it so. This macro tries various
-# options that select ANSI C on some system or another. It considers the
-# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
-# handles function prototypes correctly.
-#
-# If you use this macro, you should check after calling it whether the C
-# compiler has been set to accept ANSI C; if not, the shell variable
-# @code{fp_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
-# code in ANSI C, you can make an un-ANSIfied copy of it by using the
-# program @code{ansi2knr}, which comes with Ghostscript.
-# @end defmac
-
-define(fp_PROG_CC_STDC,
-[AC_CACHE_CHECK(for ${CC-cc} option to accept ANSI C,
-fp_cv_prog_cc_stdc,
-[fp_cv_prog_cc_stdc=no
-ac_save_CFLAGS="$CFLAGS"
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX -Ae or -Aa -D_HPUX_SOURCE
-# SVR4 -Xc
-# For HP-UX, we try -Ae first; this turns on ANSI but also extensions,
-# as well as defining _HPUX_SOURCE, and we can then use long long.
-# We keep the old version for backward compatibility.
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" -Xc
-do
- CFLAGS="$ac_save_CFLAGS $ac_arg"
- AC_TRY_COMPILE(
-[#ifndef __STDC__
-choke me
-#endif
-], [int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};],
-[fp_cv_prog_cc_stdc="$ac_arg"; break])
-done
-CFLAGS="$ac_save_CFLAGS"
-])
-case "x$fp_cv_prog_cc_stdc" in
- x|xno) ;;
- *) CC="$CC $fp_cv_prog_cc_stdc" ;;
-esac
-])
-
-AC_DEFUN(AC_PROG_LN,
-[AC_MSG_CHECKING(whether ln works)
-AC_CACHE_VAL(ac_cv_prog_LN,
-[rm -f conftestdata conftestlink
-echo > conftestdata
-if ln conftestdata conftestlink 2>/dev/null
-then
- rm -f conftestdata conftestlink
- ac_cv_prog_LN="ln"
-else
- rm -f conftestdata
- ac_cv_prog_LN="cp"
-fi])dnl
-LN="$ac_cv_prog_LN"
-if test "$ac_cv_prog_LN" = "ln"; then
- AC_MSG_RESULT(yes)
-else
- AC_MSG_RESULT(no)
-fi
-AC_SUBST(LN)dnl
-])
-
-builtin(include, aczsh.m4)
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/aczsh.m4 b/dots/.config/zsh/config/plugins/fzf-tab/modules/aczsh.m4
deleted file mode 100644
index 0219ae2f..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/aczsh.m4
+++ /dev/null
@@ -1,690 +0,0 @@
-dnl
-dnl Autconf tests for zsh.
-dnl
-dnl Copyright (c) 1995-1997 Richard Coleman
-dnl All rights reserved.
-dnl
-dnl Permission is hereby granted, without written agreement and without
-dnl license or royalty fees, to use, copy, modify, and distribute this
-dnl software and to distribute modified versions of this software for any
-dnl purpose, provided that the above copyright notice and the following
-dnl two paragraphs appear in all copies of this software.
-dnl
-dnl In no event shall Richard Coleman or the Zsh Development Group be liable
-dnl to any party for direct, indirect, special, incidental, or consequential
-dnl damages arising out of the use of this software and its documentation,
-dnl even if Richard Coleman and the Zsh Development Group have been advised of
-dnl the possibility of such damage.
-dnl
-dnl Richard Coleman and the Zsh Development Group specifically disclaim any
-dnl warranties, including, but not limited to, the implied warranties of
-dnl merchantability and fitness for a particular purpose. The software
-dnl provided hereunder is on an "as is" basis, and Richard Coleman and the
-dnl Zsh Development Group have no obligation to provide maintenance,
-dnl support, updates, enhancements, or modifications.
-dnl
-
-dnl
-dnl zsh_64_BIT_TYPE
-dnl Check whether the first argument works as a 64-bit type.
-dnl If there is a non-zero third argument, we just assume it works
-dnl when we're cross compiling. This is to allow a type to be
-dnl specified directly as --enable-lfs="long long".
-dnl Sets the variable given in the second argument to the first argument
-dnl if the test worked, `no' otherwise. Be careful testing this, as it
-dnl may produce two words `long long' on an unquoted substitution.
-dnl Also check that the compiler does not mind it being cast to int.
-dnl This macro does not produce messages as it may be run several times
-dnl before finding the right type.
-dnl
-
-AC_DEFUN(zsh_64_BIT_TYPE,
-[AC_TRY_RUN([
-#ifdef HAVE_SYS_TYPES_H
-#include
-#endif
-
-main()
-{
- $1 foo = 0;
- int bar = (int) foo;
- return sizeof($1) != 8;
-}
-], $2="$1", $2=no,
- [if test x$3 != x ; then
- $2="$1"
- else
- $2=no
- fi])
-])
-
-
-dnl
-dnl zsh_SHARED_FUNCTION
-dnl
-dnl This is just a frontend to zsh_SHARED_SYMBOL
-dnl
-dnl Usage: zsh_SHARED_FUNCTION(name[,rettype[,paramtype]])
-dnl
-
-AC_DEFUN(zsh_SHARED_FUNCTION,
-[zsh_SHARED_SYMBOL($1, ifelse([$2], ,[int ],[$2]) $1 [(]ifelse([$3], ,[ ],[$3])[)], $1)])
-
-dnl
-dnl zsh_SHARED_VARIABLE
-dnl
-dnl This is just a frontend to zsh_SHARED_SYMBOL
-dnl
-dnl Usage: zsh_SHARED_VARIABLE(name[,type])
-dnl
-
-AC_DEFUN(zsh_SHARED_VARIABLE,
-[zsh_SHARED_SYMBOL($1, ifelse([$2], ,[int ],[$2]) $1, [&$1])])
-
-dnl
-dnl zsh_SHARED_SYMBOL
-dnl Check whether symbol is available in static or shared library
-dnl
-dnl On some systems, static modifiable library symbols (such as environ)
-dnl may appear only in statically linked libraries. If this is the case,
-dnl then two shared libraries that reference the same symbol, each linked
-dnl with the static library, could be given distinct copies of the symbol.
-dnl
-dnl Usage: zsh_SHARED_SYMBOL(name,declaration,address)
-dnl Sets zsh_cv_shared_$1 cache variable to yes/no
-dnl
-
-AC_DEFUN(zsh_SHARED_SYMBOL,
-[AC_CACHE_CHECK([if $1 is available in shared libraries],
-zsh_cv_shared_$1,
-[if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
-else
- us=
-fi
-echo '
-void *zsh_getaddr1()
-{
-#ifdef __CYGWIN__
- __attribute__((__dllimport__))
-#endif
- extern $2;
- return $3;
-};
-' > conftest1.c
-sed 's/zsh_getaddr1/zsh_getaddr2/' < conftest1.c > conftest2.c
-if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AC_FD_CC); then
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-main()
-{
- void *handle1, *handle2;
- void *(*zsh_getaddr1)(), *(*zsh_getaddr2)();
- void *sym1, *sym2;
- handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle1) exit(1);
- handle2 = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle2) exit(1);
- zsh_getaddr1 = (void *(*)()) dlsym(handle1, "${us}zsh_getaddr1");
- zsh_getaddr2 = (void *(*)()) dlsym(handle2, "${us}zsh_getaddr2");
- sym1 = zsh_getaddr1();
- sym2 = zsh_getaddr2();
- if(!sym1 || !sym2) exit(1);
- if(sym1 != sym2) exit(1);
- dlclose(handle1);
- handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle1) exit(1);
- zsh_getaddr1 = (void *(*)()) dlsym(handle1, "${us}zsh_getaddr1");
- sym1 = zsh_getaddr1();
- if(!sym1) exit(1);
- if(sym1 != sym2) exit(1);
- exit(0);
-}
-], [zsh_cv_shared_$1=yes],
-[zsh_cv_shared_$1=no],
-[zsh_cv_shared_$1=no]
-)
-else
- zsh_cv_shared_$1=no
-fi
-])
-])
-
-dnl
-dnl zsh_SYS_DYNAMIC_CLASH
-dnl Check whether symbol name clashes in shared libraries are acceptable.
-dnl
-
-AC_DEFUN(zsh_SYS_DYNAMIC_CLASH,
-[AC_CACHE_CHECK([if name clashes in shared objects are OK],
-zsh_cv_sys_dynamic_clash_ok,
-[if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
-else
- us=
-fi
-echo 'int fred () { return 42; }' > conftest1.c
-echo 'int fred () { return 69; }' > conftest2.c
-if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AC_FD_CC); then
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-
-main()
-{
- void *handle1, *handle2;
- int (*fred1)(), (*fred2)();
- handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle1) exit(1);
- handle2 = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle2) exit(1);
- fred1 = (int (*)()) dlsym(handle1, "${us}fred");
- fred2 = (int (*)()) dlsym(handle2, "${us}fred");
- if(!fred1 || !fred2) exit(1);
- exit((*fred1)() != 42 || (*fred2)() != 69);
-}
-], [zsh_cv_sys_dynamic_clash_ok=yes],
-[zsh_cv_sys_dynamic_clash_ok=no],
-[zsh_cv_sys_dynamic_clash_ok=no]
-)
-else
- zsh_cv_sys_dynamic_clash_ok=no
-fi
-])
-if test "$zsh_cv_sys_dynamic_clash_ok" = yes; then
- AC_DEFINE(DYNAMIC_NAME_CLASH_OK)
-fi
-])
-
-dnl
-dnl zsh_SYS_DYNAMIC_GLOBAL
-dnl Check whether symbols in one dynamically loaded library are
-dnl available to another dynamically loaded library.
-dnl
-
-AC_DEFUN(zsh_SYS_DYNAMIC_GLOBAL,
-[AC_CACHE_CHECK([for working RTLD_GLOBAL],
-zsh_cv_sys_dynamic_rtld_global,
-[if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
-else
- us=
-fi
-echo 'int fred () { return 42; }' > conftest1.c
-echo 'extern int fred(); int barney () { return fred() + 27; }' > conftest2.c
-if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AC_FD_CC); then
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-main()
-{
- void *handle;
- int (*barneysym)();
- handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle) exit(1);
- handle = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle) exit(1);
- barneysym = (int (*)()) dlsym(handle, "${us}barney");
- if(!barneysym) exit(1);
- exit((*barneysym)() != 69);
-}
-], [zsh_cv_sys_dynamic_rtld_global=yes],
-[zsh_cv_sys_dynamic_rtld_global=no],
-[zsh_cv_sys_dynamic_rtld_global=no]
-)
-else
- zsh_cv_sys_dynamic_rtld_global=no
-fi
-])
-])
-
-dnl
-dnl zsh_SYS_DYNAMIC_EXECSYMS
-dnl Check whether symbols in the executable are available to dynamically
-dnl loaded libraries.
-dnl
-
-AC_DEFUN(zsh_SYS_DYNAMIC_EXECSYMS,
-[AC_CACHE_CHECK([whether symbols in the executable are available],
-zsh_cv_sys_dynamic_execsyms,
-[if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
-else
- us=
-fi
-echo 'extern int fred(); int barney () { return fred() + 27; }' > conftest1.c
-if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&AC_FD_CC); then
- save_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS"
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-main()
-{
- void *handle;
- int (*barneysym)();
- handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle) exit(1);
- barneysym = (int (*)()) dlsym(handle, "${us}barney");
- if(!barneysym) exit(1);
- exit((*barneysym)() != 69);
-}
-
-int fred () { return 42; }
-], [zsh_cv_sys_dynamic_execsyms=yes],
-[zsh_cv_sys_dynamic_execsyms=no],
-[zsh_cv_sys_dynamic_execsyms=no]
-)
- LDFLAGS=$save_ldflags
-else
- zsh_cv_sys_dynamic_execsyms=no
-fi
-])
-])
-
-dnl
-dnl zsh_SYS_DYNAMIC_STRIP_EXE
-dnl Check whether it is safe to strip executables.
-dnl
-
-AC_DEFUN(zsh_SYS_DYNAMIC_STRIP_EXE,
-[AC_REQUIRE([zsh_SYS_DYNAMIC_EXECSYMS])
-AC_CACHE_CHECK([whether executables can be stripped],
-zsh_cv_sys_dynamic_strip_exe,
-[if test "$zsh_cv_sys_dynamic_execsyms" != yes; then
- zsh_cv_sys_dynamic_strip_exe=yes
-elif
- if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
- else
- us=
- fi
- echo 'extern int fred(); int barney() { return fred() + 27; }' > conftest1.c
- AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
- AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS 1>&AC_FD_CC); then
- save_ldflags=$LDFLAGS
- LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS -s"
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-main()
-{
- void *handle;
- int (*barneysym)();
- handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle) exit(1);
- barneysym = (int (*)()) dlsym(handle, "${us}barney");
- if(!barneysym) exit(1);
- exit((*barneysym)() != 69);
-}
-
-int fred () { return 42; }
-], [zsh_cv_sys_dynamic_strip_exe=yes],
-[zsh_cv_sys_dynamic_strip_exe=no],
-[zsh_cv_sys_dynamic_strip_exe=no]
-)
- LDFLAGS=$save_ldflags
-else
- zsh_cv_sys_dynamic_strip_exe=no
-fi
-])
-])
-
-dnl
-dnl zsh_SYS_DYNAMIC_STRIP_EXE
-dnl Check whether it is safe to strip dynamically loaded libraries.
-dnl
-
-AC_DEFUN(zsh_SYS_DYNAMIC_STRIP_LIB,
-[AC_CACHE_CHECK([whether libraries can be stripped],
-zsh_cv_sys_dynamic_strip_lib,
-[if test "$zsh_cv_func_dlsym_needs_underscore" = yes; then
- us=_
-else
- us=
-fi
-echo 'int fred () { return 42; }' > conftest1.c
-if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AC_FD_CC) &&
-AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS -s conftest1.o $LIBS 1>&AC_FD_CC); then
- AC_TRY_RUN([
-#ifdef HPUX10DYNAMIC
-#include
-#define RTLD_LAZY BIND_DEFERRED
-#define RTLD_GLOBAL DYNAMIC_PATH
-
-char *zsh_gl_sym_addr ;
-
-#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
-#define dlclose(handle) shl_unload((shl_t)(handle))
-#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
-#define dlerror() 0
-#else
-#ifdef HAVE_DLFCN_H
-#include
-#else
-#include
-#include
-#include
-#endif
-#endif
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 1
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-
-main()
-{
- void *handle;
- int (*fredsym)();
- handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL);
- if(!handle) exit(1);
- fredsym = (int (*)()) dlsym(handle, "${us}fred");
- if(!fredsym) exit(1);
- exit((*fredsym)() != 42);
-}
-], [zsh_cv_sys_dynamic_strip_lib=yes],
-[zsh_cv_sys_dynamic_strip_lib=no],
-[zsh_cv_sys_dynamic_strip_lib=no]
-)
-else
- zsh_cv_sys_dynamic_strip_lib=no
-fi
-])
-])
-
-dnl
-dnl zsh_PATH_UTMP(filename)
-dnl Search for a specified utmp-type file.
-dnl
-
-AC_DEFUN(zsh_PATH_UTMP,
-[AC_CACHE_CHECK([for $1 file], [zsh_cv_path_$1],
-[for dir in /etc /usr/etc /var/adm /usr/adm /var/run /var/log ./conftest; do
- zsh_cv_path_$1=${dir}/$1
- test -f $zsh_cv_path_$1 && break
- zsh_cv_path_$1=no
-done
-])
-AH_TEMPLATE([PATH_]translit($1, [a-z], [A-Z])[_FILE],
-[Define to be location of ]$1[ file.])
-if test $zsh_cv_path_$1 != no; then
- AC_DEFINE_UNQUOTED([PATH_]translit($1, [a-z], [A-Z])[_FILE],
- "$zsh_cv_path_$1")
-fi
-])
-
-dnl
-dnl zsh_TYPE_EXISTS(#includes, type name)
-dnl Check whether a specified type exists.
-dnl
-
-AC_DEFUN(zsh_TYPE_EXISTS,
-[AC_CACHE_CHECK([for $2], [zsh_cv_type_exists_[]translit($2, [ ], [_])],
-[AC_TRY_COMPILE([$1], [$2 testvar;],
-[zsh_cv_type_exists_[]translit($2, [ ], [_])=yes],
-[zsh_cv_type_exists_[]translit($2, [ ], [_])=no])
-])
-AH_TEMPLATE([HAVE_]translit($2, [ a-z], [_A-Z]),
-[Define to 1 if ]$2[ is defined by a system header])
-if test $zsh_cv_type_exists_[]translit($2, [ ], [_]) = yes; then
- AC_DEFINE([HAVE_]translit($2, [ a-z], [_A-Z]))
-fi
-])
-
-dnl
-dnl zsh_STRUCT_MEMBER(#includes, type name, member name)
-dnl Check whether a specified aggregate type exists and contains
-dnl a specified member.
-dnl
-
-AC_DEFUN(zsh_STRUCT_MEMBER,
-[AC_CACHE_CHECK([for $3 in $2], [zsh_cv_struct_member_[]translit($2, [ ], [_])_$3],
-[AC_TRY_COMPILE([$1], [$2 testvar; testvar.$3;],
-[zsh_cv_struct_member_[]translit($2, [ ], [_])_$3=yes],
-[zsh_cv_struct_member_[]translit($2, [ ], [_])_$3=no])
-])
-AH_TEMPLATE([HAVE_]translit($2_$3, [ a-z], [_A-Z]),
-[Define if your system's ]$2[ has a member named ]$3[.])
-if test $zsh_cv_struct_member_[]translit($2, [ ], [_])_$3 = yes; then
- AC_DEFINE([HAVE_]translit($2_$3, [ a-z], [_A-Z]))
-fi
-])
-
-dnl
-dnl zsh_ARG_PROGRAM
-dnl Handle AC_ARG_PROGRAM substitutions into other zsh configure macros.
-dnl After processing this macro, the configure script may refer to
-dnl and $tzsh_name, and @tzsh@ is defined for make substitutions.
-dnl
-
-AC_DEFUN(zsh_ARG_PROGRAM,
-[AC_ARG_PROGRAM
-# Un-double any \ or $ (doubled by AC_ARG_PROGRAM).
-cat <<\EOF_SED > conftestsed
-s,\\\\,\\,g; s,\$\$,$,g
-EOF_SED
-zsh_transform_name=`echo "${program_transform_name}" | sed -f conftestsed`
-rm -f conftestsed
-tzsh_name=`echo zsh | sed -e "${zsh_transform_name}"`
-# Double any \ or $ in the transformed name that results.
-cat <<\EOF_SED >> conftestsed
-s,\\,\\\\,g; s,\$,$$,g
-EOF_SED
-tzsh=`echo ${tzsh_name} | sed -f conftestsed`
-rm -f conftestsed
-AC_SUBST(tzsh)dnl
-])
-
-AC_DEFUN(zsh_COMPILE_FLAGS,
- [AC_ARG_ENABLE(cppflags,
- AC_HELP_STRING([--enable-cppflags=...], [specify C preprocessor flags]),
- if test "$enableval" = "yes"
- then CPPFLAGS="$1"
- else CPPFLAGS="$enable_cppflags"
- fi)
- AC_ARG_ENABLE(cflags,
- AC_HELP_STRING([--enable-cflags=...], [specify C compiler flags]),
- if test "$enableval" = "yes"
- then CFLAGS="$2"
- else CFLAGS="$enable_cflags"
- fi)
- AC_ARG_ENABLE(ldflags,
- AC_HELP_STRING([--enable-ldflags=...], [specify linker flags]),
- if test "$enableval" = "yes"
- then LDFLAGS="$3"
- else LDFLAGS="$enable_ldflags"
- fi)
- AC_ARG_ENABLE(libs,
- AC_HELP_STRING([--enable-libs=...], [specify link libraries]),
- if test "$enableval" = "yes"
- then LIBS="$4"
- else LIBS="$enable_libs"
- fi)])
-
-dnl
-dnl zsh_CHECK_SOCKLEN_T
-dnl
-dnl check type of third argument of some network functions; currently
-dnl tested are size_t *, unsigned long *, int *.
-dnl call the result ZSOCKLEN_T since some systems have SOCKLEN_T already
-dnl
-AC_DEFUN([zsh_CHECK_SOCKLEN_T],[
- AC_CACHE_CHECK(
- [base type of the third argument to accept],
- [zsh_cv_type_socklen_t],
- [zsh_cv_type_socklen_t=
- for zsh_type in socklen_t int "unsigned long" size_t ; do
- AC_TRY_COMPILE(
- [#include
- #include ],
- [extern int accept (int, struct sockaddr *, $zsh_type *);],
- [zsh_cv_type_socklen_t="$zsh_type"; break],
- []
- )
- done
- if test -z "$zsh_cv_type_socklen_t"; then
- zsh_cv_type_socklen_t=int
- fi]
- )
- AC_DEFINE_UNQUOTED([ZSOCKLEN_T], [$zsh_cv_type_socklen_t],
- [Define to the base type of the third argument of accept])]
-)
-
-dnl Check for limit $1 e.g. RLIMIT_RSS.
-AC_DEFUN(zsh_LIMIT_PRESENT,
-[AH_TEMPLATE([HAVE_]$1,
-[Define to 1 if ]$1[ is present (whether or not as a macro).])
-AC_CACHE_CHECK([for limit $1],
-zsh_cv_have_$1,
-[AC_TRY_COMPILE([
-#include
-#ifdef HAVE_SYS_TIME_H
-#include
-#endif
-#include ],
-[$1],
- zsh_cv_have_$1=yes,
- zsh_cv_have_$1=no)])
-
-if test $zsh_cv_have_$1 = yes; then
- AC_DEFINE(HAVE_$1)
-fi])
-
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/config.guess b/dots/.config/zsh/config/plugins/fzf-tab/modules/config.guess
deleted file mode 100755
index dc84c68e..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/config.guess
+++ /dev/null
@@ -1,1501 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-# Free Software Foundation, Inc.
-
-timestamp='2009-11-20'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner. Please send patches (context
-# diff format) to and include a ChangeLog
-# entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to ."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- sh5el) machine=sh5le-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ELF__
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
- *:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
- exit ;;
- macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Pn.n version is a patched version.
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
- *:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
- s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
- exit ;;
- i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
- SUN_ARCH="i386"
- # If there is a compiler, see if it is configured for 64-bit objects.
- # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
- # This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- SUN_ARCH="x86_64"
- fi
- fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
- then
- echo "$SYSTEM_NAME"
- else
- echo rs6000-ibm-aix3.2.5
- fi
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit ;;
- *:AIX:*:[456])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include
- #include
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- eval $set_cc_for_build
-
- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
- # generating 64-bit code. GNU and HP use different nomenclature:
- #
- # $ CC_FOR_BUILD=cc ./config.guess
- # => hppa2.0w-hp-hpux11.23
- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
- # => hppa64-hp-hpux11.23
-
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep -q __LP64__
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:FreeBSD:*:*)
- case ${UNAME_MACHINE} in
- pc98)
- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- esac
- exit ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
- *:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
- *:Interix*:*)
- case ${UNAME_MACHINE} in
- x86)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
- authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
- IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
- exit ;;
- esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- *:GNU:*:*)
- # the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit ;;
- arm*:Linux:*:*)
- eval $set_cc_for_build
- if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_EABI__
- then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
- fi
- exit ;;
- avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- cris:Linux:*:*)
- echo cris-axis-linux-gnu
- exit ;;
- crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
- exit ;;
- frv:Linux:*:*)
- echo frv-unknown-linux-gnu
- exit ;;
- i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
- ;;
- or32:Linux:*:*)
- echo or32-unknown-linux-gnu
- exit ;;
- padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
- exit ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
- esac
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
- exit ;;
- x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
- exit ;;
- xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit ;;
- i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i586.
- # Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
- # this is a cross-build.
- echo i586-pc-msdosdjgpp
- exit ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
- NCR*:*:4.2:* | MPRAS*:*:4.2:*)
- OS_REL='.3'
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes .
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
- BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
- esac ;;
- *:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
- i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
- i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
- exit ;;
- i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
- exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <
-# include
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
-
-cat >&2 < in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/dots/.config/zsh/config/plugins/fzf-tab/modules/config.h.in b/dots/.config/zsh/config/plugins/fzf-tab/modules/config.h.in
deleted file mode 100644
index 89a65b7c..00000000
--- a/dots/.config/zsh/config/plugins/fzf-tab/modules/config.h.in
+++ /dev/null
@@ -1,1242 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/***** begin user configuration section *****/
-
-/* Define this to be the location of your password file */
-#define PASSWD_FILE "/etc/passwd"
-
-/* Define this to be the name of your NIS/YP password *
- * map (if applicable) */
-#define PASSWD_MAP "passwd.byname"
-
-/* Define to 1 if you want user names to be cached */
-#define CACHE_USERNAMES 1
-
-/* Define to 1 if system supports job control */
-#define JOB_CONTROL 1
-
-/* Define this if you use "suspended" instead of "stopped" */
-#define USE_SUSPENDED 1
-
-/* The default history buffer size in lines */
-#define DEFAULT_HISTSIZE 30
-
-/* The default editor for the fc builtin */
-#define DEFAULT_FCEDIT "vi"
-
-/* The default prefix for temporary files */
-#define DEFAULT_TMPPREFIX "/tmp/zsh"
-
-/***** end of user configuration section *****/
-/***** shouldn't have to change anything below here *****/
-
-
-
-/* Define to 1 if you want to use dynamically loaded modules on AIX. */
-#undef AIXDYNAMIC
-
-/* Define to 1 if the isprint() function is broken under UTF-8 locale. */
-#undef BROKEN_ISPRINT
-
-/* Define to 1 if kill(pid, 0) doesn't return ESRCH, ie BeOS R4.51. */
-#undef BROKEN_KILL_ESRCH
-
-/* Define to 1 if sigsuspend() is broken */
-#undef BROKEN_POSIX_SIGSUSPEND
-
-/* Define to 1 if compiler incorrectly cast signed to unsigned. */
-#undef BROKEN_SIGNED_TO_UNSIGNED_CASTING
-
-/* Define to 1 if tcsetpgrp() doesn't work, ie BeOS R4.51. */
-#undef BROKEN_TCSETPGRP
-
-/* Define to 1 if you use BSD style signal handling (and can block signals).
- */
-#undef BSD_SIGNALS
-
-/* Undefine if you don't want local features. By default this is defined. */
-#undef CONFIG_LOCALE
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-#undef CRAY_STACKSEG_END
-
-/* Define to a custom value for the ZSH_PATCHLEVEL parameter */
-#undef CUSTOM_PATCHLEVEL
-
-/* Define to 1 if using `alloca.c'. */
-#undef C_ALLOCA
-
-/* Define to 1 if you want to debug zsh. */
-#undef DEBUG
-
-/* The default path; used when running commands with command -p */
-#undef DEFAULT_PATH
-
-/* Define default pager used by readnullcmd */
-#undef DEFAULT_READNULLCMD
-
-/* Define to 1 if you want to avoid calling functions that will require
- dynamic NSS modules. */
-#undef DISABLE_DYNAMIC_NSS
-
-/* Define to 1 if an underscore has to be prepended to dlsym() argument. */
-#undef DLSYM_NEEDS_UNDERSCORE
-
-/* The extension used for dynamically loaded modules. */
-#undef DL_EXT
-
-/* Define to 1 if you want to use dynamically loaded modules. */
-#undef DYNAMIC
-
-/* Define to 1 if multiple modules defining the same symbol are OK. */
-#undef DYNAMIC_NAME_CLASH_OK
-
-/* Define to 1 if you want use unicode9 character widths. */
-#undef ENABLE_UNICODE9
-
-/* Define to 1 if getcwd() calls malloc to allocate memory. */
-#undef GETCWD_CALLS_MALLOC
-
-/* Define to 1 if the `getpgrp' function requires zero arguments. */
-#undef GETPGRP_VOID
-
-/* Define to 1 if getpwnam() is faked, ie BeOS R4.51. */
-#undef GETPWNAM_FAKED
-
-/* The global file to source whenever zsh is run as a login shell; if
- undefined, don't source anything */
-#undef GLOBAL_ZLOGIN
-
-/* The global file to source whenever zsh was run as a login shell. This is
- sourced right before exiting. If undefined, don't source anything. */
-#undef GLOBAL_ZLOGOUT
-
-/* The global file to source whenever zsh is run as a login shell, before
- zshrc is read; if undefined, don't source anything. */
-#undef GLOBAL_ZPROFILE
-
-/* The global file to source absolutely first whenever zsh is run; if
- undefined, don't source anything. */
-#undef GLOBAL_ZSHENV
-
-/* The global file to source whenever zsh is run; if undefined, don't source
- anything */
-#undef GLOBAL_ZSHRC
-
-/* Define if TIOCGWINSZ is defined in sys/ioctl.h but not in termios.h. */
-#undef GWINSZ_IN_SYS_IOCTL
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#undef HAVE_ALLOCA
-
-/* Define to 1 if you have and it should be used (not on Ultrix).
- */
-#undef HAVE_ALLOCA_H
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_BIND_NETDB_H
-
-/* Define if you have the termcap boolcodes symbol. */
-#undef HAVE_BOOLCODES
-
-/* Define if you have the terminfo boolnames symbol. */
-#undef HAVE_BOOLNAMES
-
-/* Define to 1 if you have the `brk' function. */
-#undef HAVE_BRK
-
-/* Define to 1 if there is a prototype defined for brk() on your system. */
-#undef HAVE_BRK_PROTO
-
-/* Define to 1 if you have the `canonicalize_file_name' function. */
-#undef HAVE_CANONICALIZE_FILE_NAME
-
-/* Define to 1 if you have the `cap_get_proc' function. */
-#undef HAVE_CAP_GET_PROC
-
-/* Define to 1 if you have the `clock_gettime' function. */
-#undef HAVE_CLOCK_GETTIME
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_CURSES_H
-
-/* Define to 1 if you have the `cygwin_conv_path' function. */
-#undef HAVE_CYGWIN_CONV_PATH
-
-/* Define to 1 if you have the `difftime' function. */
-#undef HAVE_DIFFTIME
-
-/* Define to 1 if you have the header file, and it defines `DIR'.
- */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the `dlclose' function. */
-#undef HAVE_DLCLOSE
-
-/* Define to 1 if you have the `dlerror' function. */
-#undef HAVE_DLERROR
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the `dlopen' function. */
-#undef HAVE_DLOPEN
-
-/* Define to 1 if you have the `dlsym' function. */
-#undef HAVE_DLSYM
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_DL_H
-
-/* Define to 1 if you have the `endutxent' function. */
-#undef HAVE_ENDUTXENT
-
-/* Define to 1 if you have the `erand48' function. */
-#undef HAVE_ERAND48
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_ERRNO_H
-
-/* Define to 1 if you have the `faccessx' function. */
-#undef HAVE_FACCESSX
-
-/* Define to 1 if you have the `fchdir' function. */
-#undef HAVE_FCHDIR
-
-/* Define to 1 if you have the `fchmod' function. */
-#undef HAVE_FCHMOD
-
-/* Define to 1 if you have the `fchown' function. */
-#undef HAVE_FCHOWN
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if system has working FIFOs. */
-#undef HAVE_FIFOS
-
-/* Define to 1 if you have the `fseeko' function. */
-#undef HAVE_FSEEKO
-
-/* Define to 1 if you have the `fstat' function. */
-#undef HAVE_FSTAT
-
-/* Define to 1 if you have the `ftello' function. */
-#undef HAVE_FTELLO
-
-/* Define to 1 if you have the `ftruncate' function. */
-#undef HAVE_FTRUNCATE
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_GDBM_H
-
-/* Define to 1 if you have the `gdbm_open' function. */
-#undef HAVE_GDBM_OPEN
-
-/* Define to 1 if you have the `getcchar' function. */
-#undef HAVE_GETCCHAR
-
-/* Define to 1 if you have the `getcwd' function. */
-#undef HAVE_GETCWD
-
-/* Define to 1 if you have the `getenv' function. */
-#undef HAVE_GETENV
-
-/* Define to 1 if you have the `getgrgid' function. */
-#undef HAVE_GETGRGID
-
-/* Define to 1 if you have the `getgrnam' function. */
-#undef HAVE_GETGRNAM
-
-/* Define to 1 if you have the `gethostbyname2' function. */
-#undef HAVE_GETHOSTBYNAME2
-
-/* Define to 1 if you have the `gethostname' function. */
-#undef HAVE_GETHOSTNAME
-
-/* Define to 1 if you have the `getipnodebyname' function. */
-#undef HAVE_GETIPNODEBYNAME
-
-/* Define to 1 if you have the `getline' function. */
-#undef HAVE_GETLINE
-
-/* Define to 1 if you have the `getlogin' function. */
-#undef HAVE_GETLOGIN
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the `getpwent' function. */
-#undef HAVE_GETPWENT
-
-/* Define to 1 if you have the `getpwnam' function. */
-#undef HAVE_GETPWNAM
-
-/* Define to 1 if you have the `getpwuid' function. */
-#undef HAVE_GETPWUID
-
-/* Define to 1 if you have the `getrlimit' function. */
-#undef HAVE_GETRLIMIT
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define to 1 if you have the `getutent' function. */
-#undef HAVE_GETUTENT
-
-/* Define to 1 if you have the `getutxent' function. */
-#undef HAVE_GETUTXENT
-
-/* Define to 1 if you have the `getxattr' function. */
-#undef HAVE_GETXATTR
-
-/* Define to 1 if you have the `grantpt' function. */
-#undef HAVE_GRANTPT
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the `htons' function. */
-#undef HAVE_HTONS
-
-/* Define to 1 if you have the `iconv' function. */
-#undef HAVE_ICONV
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_ICONV_H
-
-/* Define to 1 if you have the `inet_aton' function. */
-#undef HAVE_INET_ATON
-
-/* Define to 1 if you have the `inet_ntop' function. */
-#undef HAVE_INET_NTOP
-
-/* Define to 1 if you have the `inet_pton' function. */
-#undef HAVE_INET_PTON
-
-/* Define to 1 if you have the `initgroups' function. */
-#undef HAVE_INITGROUPS
-
-/* Define to 1 if you have the `initscr' function. */
-#undef HAVE_INITSCR
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if there is a prototype defined for ioctl() on your system. */
-#undef HAVE_IOCTL_PROTO
-
-/* Define to 1 if you have the `isblank' function. */
-#undef HAVE_ISBLANK
-
-/* Define to 1 if you have the `isinf' function. */
-#undef HAVE_ISINF
-
-/* Define to 1 if you have the `isnan' function. */
-#undef HAVE_ISNAN
-
-/* Define to 1 if you have the `iswblank' function. */
-#undef HAVE_ISWBLANK
-
-/* Define to 1 if you have the `killpg' function. */
-#undef HAVE_KILLPG
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_LANGINFO_H
-
-/* Define to 1 if you have the `lchown' function. */
-#undef HAVE_LCHOWN
-
-/* Define to 1 if you have the `cap' library (-lcap). */
-#undef HAVE_LIBCAP
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_LIBC_H
-
-/* Define to 1 if you have the `dl' library (-ldl). */
-#undef HAVE_LIBDL
-
-/* Define to 1 if you have the `gdbm' library (-lgdbm). */
-#undef HAVE_LIBGDBM
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#undef HAVE_LIBRT
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_LIMITS_H
-
-/* Define to 1 if system has working link(). */
-#undef HAVE_LINK
-
-/* Define to 1 if you have the `load' function. */
-#undef HAVE_LOAD
-
-/* Define to 1 if you have the `loadbind' function. */
-#undef HAVE_LOADBIND
-
-/* Define to 1 if you have the `loadquery' function. */
-#undef HAVE_LOADQUERY
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_LOCALE_H
-
-/* Define to 1 if you have the `log2' function. */
-#undef HAVE_LOG2
-
-/* Define to 1 if you have the `lstat' function. */
-#undef HAVE_LSTAT
-
-/* Define to 1 if you have the `memcpy' function. */
-#undef HAVE_MEMCPY
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mkfifo' function. */
-#undef HAVE_MKFIFO
-
-/* Define to 1 if there is a prototype defined for mknod() on your system. */
-#undef HAVE_MKNOD_PROTO
-
-/* Define to 1 if you have the `mkstemp' function. */
-#undef HAVE_MKSTEMP
-
-/* Define to 1 if you have the `mktime' function. */
-#undef HAVE_MKTIME
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* Define to 1 if you have the `msync' function. */
-#undef HAVE_MSYNC
-
-/* Define to 1 if you have the `munmap' function. */
-#undef HAVE_MUNMAP
-
-/* Define to 1 if you have the `nanosleep' function. */
-#undef HAVE_NANOSLEEP
-
-/* Define to 1 if you have the header file. */
-#undef HAVE_NCURSESW_NCURSES_H
-
-/* Define to 1 if you have the