From dbf02a8469e53b57115e67649660232ffdccd018 Mon Sep 17 00:00:00 2001 From: "William F. Jolitz" Date: Wed, 13 May 1992 13:03:42 -0800 Subject: [PATCH] 386BSD 0.1 development Work on file usr/othersrc/public/zsh-2.2/doc/intro.txt Work on file usr/othersrc/public/zsh-2.2/dots/zlogin Work on file usr/othersrc/public/zsh-2.2/dots/zshrc Work on file usr/othersrc/public/zsh-2.2/dots/zshenv Work on file usr/othersrc/public/zsh-2.2/func/acx Work on file usr/othersrc/public/zsh-2.2/func/cx Work on file usr/othersrc/public/zsh-2.2/func/harden Work on file usr/othersrc/public/zsh-2.2/func/mere Work on file usr/othersrc/public/zsh-2.2/func/namedir Work on file usr/othersrc/public/zsh-2.2/func/proto Work on file usr/othersrc/public/zsh-2.2/func/randline Work on file usr/othersrc/public/zsh-2.2/func/yp Work on file usr/othersrc/public/zsh-2.2/func/yu Work on file usr/othersrc/public/zsh-2.2/man/man1/zsh.1 Work on file usr/othersrc/public/zsh-2.2/scripts/aproto Work on file usr/othersrc/public/zsh-2.2/scripts/fproto Work on file usr/othersrc/public/zsh-2.2/scripts/ctoz Work on file usr/othersrc/public/zsh-2.2/scripts/fooz Work on file usr/othersrc/public/zsh-2.2/scripts/c2z Work on file usr/othersrc/public/zsh-2.2/scripts/c2z.orig Work on file usr/othersrc/public/zsh-2.2/src/builtin.c Work on file usr/othersrc/public/zsh-2.2/src/cond.c Work on file usr/othersrc/public/zsh-2.2/src/exec.c Work on file usr/othersrc/public/zsh-2.2/src/funcs.h Work on file usr/othersrc/public/zsh-2.2/src/glob.c Work on file usr/othersrc/public/zsh-2.2/src/hist.c Work on file usr/othersrc/public/zsh-2.2/src/init.c Work on file usr/othersrc/public/zsh-2.2/src/jobs.c Work on file usr/othersrc/public/zsh-2.2/src/lex.c Work on file usr/othersrc/public/zsh-2.2/src/loop.c Work on file usr/othersrc/public/zsh-2.2/src/math.c Work on file usr/othersrc/public/zsh-2.2/src/params.c Work on file usr/othersrc/public/zsh-2.2/src/subst.c Work on file usr/othersrc/public/zsh-2.2/src/table.c Work on file usr/othersrc/public/zsh-2.2/src/text.c Work on file usr/othersrc/public/zsh-2.2/src/watch.c Work on file usr/othersrc/public/zsh-2.2/src/zle.h Work on file usr/othersrc/public/zsh-2.2/src/zle_bindings.c Work on file usr/othersrc/public/zsh-2.2/src/zle_main.c Work on file usr/othersrc/public/zsh-2.2/src/zle_refresh.c Work on file usr/othersrc/public/zsh-2.2/src/zle_utils.c Work on file usr/othersrc/public/zsh-2.2/src/zsh.h Work on file usr/othersrc/public/zsh-2.2/src/zle_vi.c Work on file usr/othersrc/public/zsh-2.2/src/ztype.h Work on file usr/othersrc/public/zsh-2.2/src/zle_tricky.c Work on file usr/othersrc/public/zsh-2.2/src/builtin.pro Work on file usr/othersrc/public/zsh-2.2/src/cond.pro Work on file usr/othersrc/public/zsh-2.2/src/exec.pro Work on file usr/othersrc/public/zsh-2.2/src/glob.pro Work on file usr/othersrc/public/zsh-2.2/src/hist.pro Work on file usr/othersrc/public/zsh-2.2/src/init.pro Work on file usr/othersrc/public/zsh-2.2/src/jobs.pro Work on file usr/othersrc/public/zsh-2.2/src/lex.pro Work on file usr/othersrc/public/zsh-2.2/src/loop.pro Work on file usr/othersrc/public/zsh-2.2/src/math.pro Work on file usr/othersrc/public/zsh-2.2/src/mem.pro Work on file usr/othersrc/public/zsh-2.2/src/params.pro Work on file usr/othersrc/public/zsh-2.2/src/subst.pro Work on file usr/othersrc/public/zsh-2.2/src/table.pro Work on file usr/othersrc/public/zsh-2.2/src/text.pro Work on file usr/othersrc/public/zsh-2.2/src/utils.pro Work on file usr/othersrc/public/zsh-2.2/src/watch.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_main.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_refresh.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_vi.pro Work on file usr/othersrc/public/zsh-2.2/src/parse.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_tricky.pro Work on file usr/othersrc/public/zsh-2.2/src/parse.c Work on file usr/othersrc/public/zsh-2.2/src/zle_utils.pro Work on file usr/othersrc/public/zsh-2.2/src/signals.h.sample Work on file usr/othersrc/public/zsh-2.2/src/zle_move.c Work on file usr/othersrc/public/zsh-2.2/src/zle_misc.c Work on file usr/othersrc/public/zsh-2.2/src/zle_word.c Work on file usr/othersrc/public/zsh-2.2/src/zle_hist.c Work on file usr/othersrc/public/zsh-2.2/src/zle_hist.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_misc.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_move.pro Work on file usr/othersrc/public/zsh-2.2/src/zle_word.pro Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.1 --- usr/othersrc/public/zsh-2.2/doc/intro.txt | 2772 +++++++++++ usr/othersrc/public/zsh-2.2/dots/zlogin | 16 + usr/othersrc/public/zsh-2.2/dots/zshenv | 3 + usr/othersrc/public/zsh-2.2/dots/zshrc | 88 + usr/othersrc/public/zsh-2.2/func/acx | 6 + usr/othersrc/public/zsh-2.2/func/cx | 6 + usr/othersrc/public/zsh-2.2/func/harden | 6 + usr/othersrc/public/zsh-2.2/func/mere | 3 + usr/othersrc/public/zsh-2.2/func/namedir | 15 + usr/othersrc/public/zsh-2.2/func/proto | 8 + usr/othersrc/public/zsh-2.2/func/randline | 3 + usr/othersrc/public/zsh-2.2/func/yp | 2 + usr/othersrc/public/zsh-2.2/func/yu | 2 + usr/othersrc/public/zsh-2.2/man/man1/zsh.1 | 4089 +++++++++++++++++ usr/othersrc/public/zsh-2.2/scripts/aproto | 28 + usr/othersrc/public/zsh-2.2/scripts/c2z | 120 + usr/othersrc/public/zsh-2.2/scripts/c2z.orig | 102 + usr/othersrc/public/zsh-2.2/scripts/ctoz | 32 + usr/othersrc/public/zsh-2.2/scripts/fooz | 78 + usr/othersrc/public/zsh-2.2/scripts/fproto | 4 + usr/othersrc/public/zsh-2.2/src/builtin.c | 2969 ++++++++++++ usr/othersrc/public/zsh-2.2/src/builtin.pro | 73 + usr/othersrc/public/zsh-2.2/src/cond.c | 156 + usr/othersrc/public/zsh-2.2/src/cond.pro | 6 + usr/othersrc/public/zsh-2.2/src/exec.c | 1829 ++++++++ usr/othersrc/public/zsh-2.2/src/exec.pro | 53 + usr/othersrc/public/zsh-2.2/src/funcs.h | 47 + usr/othersrc/public/zsh-2.2/src/glob.c | 1273 +++++ usr/othersrc/public/zsh-2.2/src/glob.pro | 34 + usr/othersrc/public/zsh-2.2/src/hist.c | 1343 ++++++ usr/othersrc/public/zsh-2.2/src/hist.pro | 51 + usr/othersrc/public/zsh-2.2/src/init.c | 533 +++ usr/othersrc/public/zsh-2.2/src/init.pro | 11 + usr/othersrc/public/zsh-2.2/src/jobs.c | 764 +++ usr/othersrc/public/zsh-2.2/src/jobs.pro | 23 + usr/othersrc/public/zsh-2.2/src/lex.c | 828 ++++ usr/othersrc/public/zsh-2.2/src/lex.pro | 10 + usr/othersrc/public/zsh-2.2/src/loop.c | 294 ++ usr/othersrc/public/zsh-2.2/src/loop.pro | 6 + usr/othersrc/public/zsh-2.2/src/math.c | 455 ++ usr/othersrc/public/zsh-2.2/src/math.pro | 8 + usr/othersrc/public/zsh-2.2/src/mem.pro | 15 + usr/othersrc/public/zsh-2.2/src/params.c | 1315 ++++++ usr/othersrc/public/zsh-2.2/src/params.pro | 80 + usr/othersrc/public/zsh-2.2/src/parse.c | 960 ++++ usr/othersrc/public/zsh-2.2/src/parse.pro | 29 + .../public/zsh-2.2/src/signals.h.sample | 105 + usr/othersrc/public/zsh-2.2/src/subst.c | 764 +++ usr/othersrc/public/zsh-2.2/src/subst.pro | 13 + usr/othersrc/public/zsh-2.2/src/table.c | 349 ++ usr/othersrc/public/zsh-2.2/src/table.pro | 20 + usr/othersrc/public/zsh-2.2/src/text.c | 465 ++ usr/othersrc/public/zsh-2.2/src/text.pro | 10 + usr/othersrc/public/zsh-2.2/src/utils.pro | 83 + usr/othersrc/public/zsh-2.2/src/watch.c | 363 ++ usr/othersrc/public/zsh-2.2/src/watch.pro | 7 + usr/othersrc/public/zsh-2.2/src/zle.h | 343 ++ .../public/zsh-2.2/src/zle_bindings.c | 600 +++ usr/othersrc/public/zsh-2.2/src/zle_hist.c | 620 +++ usr/othersrc/public/zsh-2.2/src/zle_hist.pro | 27 + usr/othersrc/public/zsh-2.2/src/zle_main.c | 724 +++ usr/othersrc/public/zsh-2.2/src/zle_main.pro | 16 + usr/othersrc/public/zsh-2.2/src/zle_misc.c | 829 ++++ usr/othersrc/public/zsh-2.2/src/zle_misc.pro | 41 + usr/othersrc/public/zsh-2.2/src/zle_move.c | 328 ++ usr/othersrc/public/zsh-2.2/src/zle_move.pro | 24 + usr/othersrc/public/zsh-2.2/src/zle_refresh.c | 641 +++ .../public/zsh-2.2/src/zle_refresh.pro | 16 + usr/othersrc/public/zsh-2.2/src/zle_tricky.c | 1282 ++++++ .../public/zsh-2.2/src/zle_tricky.pro | 45 + usr/othersrc/public/zsh-2.2/src/zle_utils.c | 249 + usr/othersrc/public/zsh-2.2/src/zle_utils.pro | 18 + usr/othersrc/public/zsh-2.2/src/zle_vi.c | 310 ++ usr/othersrc/public/zsh-2.2/src/zle_vi.pro | 22 + usr/othersrc/public/zsh-2.2/src/zle_word.c | 272 ++ usr/othersrc/public/zsh-2.2/src/zle_word.pro | 19 + usr/othersrc/public/zsh-2.2/src/zsh.h | 1544 +++++++ usr/othersrc/public/zsh-2.2/src/ztype.h | 48 + 78 files changed, 30745 insertions(+) create mode 100644 usr/othersrc/public/zsh-2.2/doc/intro.txt create mode 100644 usr/othersrc/public/zsh-2.2/dots/zlogin create mode 100644 usr/othersrc/public/zsh-2.2/dots/zshenv create mode 100644 usr/othersrc/public/zsh-2.2/dots/zshrc create mode 100755 usr/othersrc/public/zsh-2.2/func/acx create mode 100755 usr/othersrc/public/zsh-2.2/func/cx create mode 100755 usr/othersrc/public/zsh-2.2/func/harden create mode 100755 usr/othersrc/public/zsh-2.2/func/mere create mode 100755 usr/othersrc/public/zsh-2.2/func/namedir create mode 100755 usr/othersrc/public/zsh-2.2/func/proto create mode 100755 usr/othersrc/public/zsh-2.2/func/randline create mode 100755 usr/othersrc/public/zsh-2.2/func/yp create mode 100755 usr/othersrc/public/zsh-2.2/func/yu create mode 100644 usr/othersrc/public/zsh-2.2/man/man1/zsh.1 create mode 100755 usr/othersrc/public/zsh-2.2/scripts/aproto create mode 100755 usr/othersrc/public/zsh-2.2/scripts/c2z create mode 100755 usr/othersrc/public/zsh-2.2/scripts/c2z.orig create mode 100644 usr/othersrc/public/zsh-2.2/scripts/ctoz create mode 100644 usr/othersrc/public/zsh-2.2/scripts/fooz create mode 100755 usr/othersrc/public/zsh-2.2/scripts/fproto create mode 100644 usr/othersrc/public/zsh-2.2/src/builtin.c create mode 100644 usr/othersrc/public/zsh-2.2/src/builtin.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/cond.c create mode 100644 usr/othersrc/public/zsh-2.2/src/cond.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/exec.c create mode 100644 usr/othersrc/public/zsh-2.2/src/exec.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/funcs.h create mode 100644 usr/othersrc/public/zsh-2.2/src/glob.c create mode 100644 usr/othersrc/public/zsh-2.2/src/glob.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/hist.c create mode 100644 usr/othersrc/public/zsh-2.2/src/hist.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/init.c create mode 100644 usr/othersrc/public/zsh-2.2/src/init.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/jobs.c create mode 100644 usr/othersrc/public/zsh-2.2/src/jobs.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/lex.c create mode 100644 usr/othersrc/public/zsh-2.2/src/lex.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/loop.c create mode 100644 usr/othersrc/public/zsh-2.2/src/loop.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/math.c create mode 100644 usr/othersrc/public/zsh-2.2/src/math.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/mem.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/params.c create mode 100644 usr/othersrc/public/zsh-2.2/src/params.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/parse.c create mode 100644 usr/othersrc/public/zsh-2.2/src/parse.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/signals.h.sample create mode 100644 usr/othersrc/public/zsh-2.2/src/subst.c create mode 100644 usr/othersrc/public/zsh-2.2/src/subst.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/table.c create mode 100644 usr/othersrc/public/zsh-2.2/src/table.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/text.c create mode 100644 usr/othersrc/public/zsh-2.2/src/text.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/utils.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/watch.c create mode 100644 usr/othersrc/public/zsh-2.2/src/watch.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle.h create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_bindings.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_hist.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_hist.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_main.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_main.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_misc.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_misc.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_move.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_move.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_refresh.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_refresh.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_tricky.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_tricky.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_utils.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_utils.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_vi.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_vi.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_word.c create mode 100644 usr/othersrc/public/zsh-2.2/src/zle_word.pro create mode 100644 usr/othersrc/public/zsh-2.2/src/zsh.h create mode 100644 usr/othersrc/public/zsh-2.2/src/ztype.h diff --git a/usr/othersrc/public/zsh-2.2/doc/intro.txt b/usr/othersrc/public/zsh-2.2/doc/intro.txt new file mode 100644 index 0000000000..a6616d327f --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/doc/intro.txt @@ -0,0 +1,2772 @@ + + + + + + + An Introduction to the Z Shell + + + Paul Falstad + pfalstad@phoenix.princeton.edu + + + + + + +zsh is a shell designed for interactive use, although it is +also a powerful scripting language. Many of the useful +features of bash, ksh, and tcsh were incorporated into zsh; +many original features were added. This document details +some of the unique features of zsh. It assumes basic +knowledge of the standard UNIX shells; the intent is to show +a reader already familiar with one of the other major shells +what makes zsh more useful or more powerful. This document +is not at all comprehensive; read the manual entry for a +description of the shell that is complete and concise, +although somewhat overwhelming and devoid of examples. + +Filename Generation + +Otherwise known as globbing, filename generation is quite +extensive in zsh. Of course, it has all the basics: + +% ls +Makefile file.pro foo.o main.o q.c run234 stuff +bar.o foo link morestuff run123 run240 sub +file.h foo.c main.h pipe run2 run303 +% ls *.c +foo.c q.c +% ls *.[co] +bar.o foo.c foo.o main.o q.c +% ls foo.? +foo.c foo.o +% ls *.[^c] +bar.o file.h foo.o main.h main.o +% ls *.[^oh] +foo.c q.c + + +Also, if the EXTENDEDGLOB option is set, some new features +are activated. For example, the ^ character negates the +pattern following it: + + + + + + + + + + + + + + + + - 2 - + +% setopt extendedglob +% ls -d ^*.c +Makefile file.pro link morestuff run2 run303 +bar.o foo main.h pipe run234 stuff +file.h foo.o main.o run123 run240 sub +% ls -d ^*.* +Makefile link pipe run2 run240 stuff +foo morestuff run123 run234 run303 sub +% ls -d ^Makefile +bar.o foo link morestuff run123 run240 sub +file.h foo.c main.h pipe run2 run303 +file.pro foo.o main.o q.c run234 stuff +% ls -d *.^c +.rhosts bar.o file.h file.pro foo.o main.h main.o + + +An expression of the form matches a range of integers: + +% ls run<200-300> +run234 run240 +% ls run<300-400> +run303 +% ls run<-200> +run123 run2 +% ls run<300-> +run303 +% ls run<> +run123 run2 run234 run240 run303 + + +Grouping is possible: + +% ls (foo|bar).* +bar.o foo.c foo.o +% ls *.(c|o|pro) +bar.o file.pro foo.c foo.o main.o q.c + + +Also, the string ****/ forces a recursive search of sub- +directories: + + + + + + + + + + + + + + + + + + + + + + + + + - 3 - + +% ls -R +Makefile file.pro foo.o main.o q.c run234 stuff +bar.o foo link morestuff run123 run240 sub +file.h foo.c main.h pipe run2 run303 + +morestuff: + +stuff: +file xxx yyy + +stuff/xxx: +foobar + +stuff/yyy: +frobar +% ls ****/*bar +stuff/xxx/foobar stuff/yyy/frobar +% ls ****/f* +file.h foo foo.o stuff/xxx/foobar +file.pro foo.c stuff/file stuff/yyy/frobar +% ls *bar* +bar.o +% ls ****/*bar* +bar.o stuff/xxx/foobar stuff/yyy/frobar +% ls stuff/****/*bar* +stuff/xxx/foobar stuff/yyy/frobar + + + +It is possible to exclude certain files from the patterns +using the ~ character. A pattern of the form *.c~bar.c +lists all files matching *.c, except for the file bar.c. + +% ls *.c +foo.c foob.c bar.c +% ls *.c~bar.c +foo.c foob.c +% ls *.c~f* +bar.c + + + +One can add a number of qualifiers to the end of any of +these patterns, to restrict matches to certain file types. +A qualified pattern is of the form + + pattern(...) + + +with single-letter qualifiers inside the parentheses. + + + + + + + + + + + + + + + - 4 - + +% alias l='ls -dF' +% l * +Makefile foo* main.h q.c run240 +bar.o foo.c main.o run123 run303 +file.h foo.o morestuff/ run2 stuff/ +file.pro link@ pipe run234 sub +% l *(/) +morestuff/ stuff/ +% l *(@) +link@ +% l *(*) +foo* link@ morestuff/ stuff/ +% l *(x) +foo* link@ morestuff/ stuff/ +% l *(X) +foo* link@ morestuff/ stuff/ +% l *(R) +bar.o foo* link@ morestuff/ run123 run240 +file.h foo.c main.h pipe run2 run303 +file.pro foo.o main.o q.c run234 stuff/ + + +Note that *(x) and *(*) both match executables. *(X) +matches files executable by others, as opposed to *(x), +which matches files executable by the owner. *(R) and *(r) +match readable files; *(W) and *(w), which checks for writ- +able files. *(W) is especially important, since it checks +for world-writable files: + +% l *(w) +bar.o foo* link@ morestuff/ run123 run240 +file.h foo.c main.h pipe run2 run303 +file.pro foo.o main.o q.c run234 stuff/ +% l *(W) +link@ run240 +% l -l link run240 +lrwxrwxrwx 1 pfalstad 10 May 23 18:12 link -> /bin/false* +-rw-rw-rw- 1 pfalstad 0 May 23 18:12 run240 + + +You can filter out the symbolic links with the ^ character: + +% l *(W^@) +run240 +% l *(x) +foo* link@ morestuff/ stuff/ +% l *(x^@/) +foo* + + +To find all plain files, you can use .: + + + + + + + + + + + + + + - 5 - + +% l *(.) +Makefile file.h foo* foo.o main.o run123 run234 run303 +bar.o file.pro foo.c main.h q.c run2 run240 sub +% l *(^.) +link@ morestuff/ pipe stuff/ +% l s*(.) +stuff/ sub +% l *(p) +pipe +% l -l *(p) +prw-r--r-- 1 pfalstad 0 May 23 18:12 pipe + + +*(U) matches all files owned by you. To search for all +files not owned by you, use *(^U): + +% l -l *(^U) +-rw------- 1 subbarao 29 May 23 18:13 sub + + +This searches for setuid files: + +% l -l *(s) +-rwsr-xr-x 1 pfalstad 16 May 23 18:12 foo* + + +This checks for a certain user's files: + +% ypmatch subbarao passwd +subbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh +% l -l *(u3338) +-rw------- 1 subbarao 29 May 23 18:13 sub + + + +Startup Files + +There are five startup files that zsh will read commands +from: + +$ZDOTDIR/.zshenv +$ZDOTDIR/.zprofile +$ZDOTDIR/.zshrc +$ZDOTDIR/.zlogin +$ZDOTDIR/.zlogout + + +If ZDOTDIR is not set, then the value of HOME is used; this +is the usual case. + +.zshenv is sourced on all invocations of the shell, unless +the -f option is set. It should contain commands to set the +command search path, plus other important environment vari- +ables. .zshenv should not contain commands that produce +output or assume the shell is attached to a tty. + +.zshrc is sourced in interactive shells. It should contain +commands to set up aliases, functions, options, key bind- +ings, etc. + + + + + + - 6 - +.zlogin is sourced in login shells. It should contain com- +mands that should be executed only in login shells. .zlo- +gout is sourced when login shells exit. .zprofile is simi- +lar to .zlogin, except that it is sourced before .zshrc. +.zprofile is meant as an alternative to .zlogin for ksh +fans; the two are not intended to be used together, although +this could certainly be done if desired. .zlogin is not the +place for alias definitions, options, environment variable +settings, etc.; as a general rule, it should not change the +shell environment at all. Rather, it should be used to set +the terminal type and run a series of external commands +(fortune, msgs, etc). + +Shell Functions + +zsh also allows you to create your own commands by defining +shell functions. For example: + +% yp () { +> ypmatch $1 passwd.byname +> } +% yp pfalstad +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh + + +This function looks up a user in the NIS password map. The +$1 expands to the first argument to yp. The function could +have been equivalently defined in one of the following ways: + +% function yp { +> ypmatch $1 passwd.byname +> } +% function yp () { +> ypmatch $1 passwd.byname +> } +% function yp () ypmatch $1 passwd.byname + + +Note that aliases are expanded when the function definition +is parsed, not when the function is executed. For example: + +% alias ypmatch=echo +% yp pfalstad +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh + + +Since the alias was defined after the function was parsed, +it has no effect on the function's execution. However, if +we define the function again with the alias in place: + +% function yp () { ypmatch $1 passwd.byname } +% yp pfalstad +pfalstad passwd.byname + + +it is parsed with the new alias definition in place. There- +fore, in general you must define aliases before functions. + +We can make the function take multiple arguments: + + + + + + + - 7 - + +% unalias ypmatch +% yp () { +> for i +> do ypmatch $i passwd.byname +> done +> } +% yp pfalstad subbarao sukthnkr +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh +subbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh +sukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh + + +The for i loops through each of the function's arguments, +setting i equal to each of them in turn. We can also make +the function do something sensible if no arguments are +given: + +% yp () { +> if (( $# == 0 )) +> then echo usage: yp name ...; fi +> for i; do ypmatch $i passwd.byname; done +> } +% yp +usage: yp name ... +% yp pfalstad sukthnkr +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh +sukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh + + +$# is the number of arguments supplied to the function. If +it is equal to zero, we print a usage message; otherwise, we +loop through the arguments, and ypmatch all of them. + +Here's a function that selects a random line from a file: + +% randline () { +> integer z=$(wc -l <$1) +> sed -n $[RANDOM % z + 1]p $1 +> } +% randline /etc/motd +PHOENIX WILL BE DOWN briefly Friday morning, 5/24/91 from 8 AM to +% randline /etc/motd +SunOS Release 4.1.1 (PHOENIX) #19: Tue May 14 19:03:15 EDT 1991 +% randline /etc/motd +| Please use the "msgs" command to read announcements. Refer to the | +% echo $z + +% + + +randline has a local variable, z, that holds the number of +lines in the file. $[RANDOM % z + 1] expands to a random +number between 1 and z. An expression of the form $[...] +expands to the value of the arithmetic expression within the +brackets, and the RANDOM variable returns a random number +each time it is referenced. % is the modulus operator, as +in C. Therefore, sed -n $[RANDOM%z+1]p picks a random line +from its input, from 1 to z. + + + + + + + - 8 - +Function definitions can be viewed with the functions buil- +tin: + +% functions randline +randline () { + integer z=$(wc -l <$1) + sed -n $[RANDOM % z + 1]p $1 + +} +% functions +yp () { + if let $# == 0 + + then + echo usage: yp name ... + + fi + for i + do + ypmatch $i passwd.byname + + done + +} +randline () { + integer z=$(wc -l <$1) + sed -n $[RANDOM % z + 1]p $1 + +} + + +Here's another one: + +% cx () { chmod +x $* } +% ls -l foo bar +-rw-r--r-- 1 pfalstad 29 May 24 04:38 bar +-rw-r--r-- 1 pfalstad 29 May 24 04:38 foo +% cx foo bar +% ls -l foo bar +-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar +-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo + + +Note that this could also have been implemented as an alias: + +% chmod 644 foo bar +% alias cx='chmod +x' +% cx foo bar +% ls -l foo bar +-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar +-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo + + + +Instead of defining a lot of functions in your .zshrc, all +of which you may not use, it is often better to use the +autoload builtin. The idea is, you create a directory where +function definitions are stored, declare the names in your +.zshrc, and tell the shell where to look for them. Whenever +you reference a function, the shell will automatically load + + + + + + - 9 - +it into memory. + +% mkdir /tmp/funs +% cat >/tmp/funs/yp +ypmatch $1 passwd.byname +^D +% cat >/tmp/funs/cx +chmod +x $* +^D +% FPATH=/tmp/funs +% autoload cx yp +% functions cx yp +undefined cx () +undefined yp () +% chmod 755 /tmp/funs/{cx,yp} +% yp egsirer +egsirer:*:3214:35:Emin Gun Sirer:/u/egsirer:/bin/sh +% functions yp +yp () { + ypmatch $1 passwd.byname +} + + +This idea has other benefits. By adding a #! header to the +files, you can make them double as shell scripts. (Although +it is faster to use them as functions, since a separate pro- +cess is not created.) + +% ed /tmp/funs/yp +25 +i +#! /usr/local/bin/zsh +w +42 +q +% cd src +~/src> + + +the shell will print the current directory in the prompt, +using the ~ character. However, zsh is smarter than most +other shells in this respect: + + + + + + + - 10 - + +~/src> cd ~subbarao +~subbarao> cd ~maruchck +~maruchck> cd lib +~maruchck/lib> cd fun +~maruchck/lib/fun> foo=/usr/princeton/common/src +~maruchck/lib/fun> cd ~foo +~foo> cd .. +/usr/princeton/common> cd src +~foo> cd news/nntp +~foo/news/nntp> cd inews +~foo/news/nntp/inews> + + +Note that zsh prints other users' directories in the form +~user. Also note that you can set a parameter and use it as +a directory name; zsh will act as if foo is a user with the +login directory /usr/princeton/common/src. This is con- +venient, especially if you're sick of seeing prompts like +this: + +phoenix:/usr/princeton/common/src/X.V11R4/contrib/clients/xv/docs> + + +If you get stuck in this position, you can give the current +directory a short name, like this: + +/usr/princeton/common/src/news/nntp/inews> inews=$PWD +/usr/princeton/common/src/news/nntp/inews> echo ~inews +/usr/princeton/common/src/news/nntp/inews +~inews> + + +When you reference a directory in the form ~inews, the shell +assumes that you want the directory displayed in this form; +thus simply typing echo ~inews or cd ~inews causes the +prompt to be shortened. You can define a shell function for +this purpose: + +~inews> namedir () { $1=$PWD ; : ~$1 } +~inews> cd /usr/princeton/bin +/usr/princeton/bin> namedir pbin +~pbin> cd /var/spool/mail +/var/spool/mail> namedir spool +~spool> cd .msgs +~spool/.msgs> + + +You may want to add this one-line function to your .zshrc. + +zsh can also put the current directory in your title bar, if +you are using a windowing system. One way to do this is +with the chpwd function, which is automatically executed by +the shell whenever you change directory. If you are using +xterm, this will work: + +chpwd () { print -Pn '^[]2;%~^G' } + + +The -P option tells print to treat its arguments like a + + + + + + - 11 - +prompt string; otherwise the %~ would not be expanded. The +-n option suppresses the terminating newline, as with echo. + +If you are using an IRIS wsh, do this: + +chpwd () { print -Pn '^[P1.y%~^[' } + + +The print -D command has other uses. For example, to print +the current directory to standard output in short form, you +can do this: + +% print -D $PWD +~subbarao/src + + +and to print each component of the path in short form: + +% print -D $path +/bin /usr/bin ~locbin ~locbin/X11 ~/bin + + + +Directory Stacks + +If you use csh, you may know about directory stacks. The +pushd command puts the current directory on the stack, and +changes to a new directory; the popd command pops a direc- +tory off the stack and changes to it. + +phoenix% cd +phoenix% PROMPT='Z %~> ' +Z ~> pushd /tmp +/tmp ~ +Z /tmp> pushd /usr/etc +/usr/etc /tmp ~ +Z /usr/etc> pushd /usr/bin +/usr/bin /usr/etc /tmp ~ +Z /usr/bin> popd +/usr/etc /tmp ~ +Z /usr/etc> popd +/tmp ~ +Z /tmp> pushd /etc +/etc /tmp ~ +Z /etc> popd +/tmp ~ + + +zsh's directory stack commands work similarly. One differ- +ence is the way pushd is handled if no arguments are given. +As in csh, this exchanges the top two elements of the direc- +tory stack: + +Z /tmp> dirs +/tmp ~ +Z /tmp> pushd +~ /tmp + + +unless the stack only has one entry: + + + + + + - 12 - + +Z ~> popd +/tmp +Z /tmp> dirs +/tmp +Z /tmp> pushd +~ /tmp + + +or unless the PUSHDTOHOME option is set: + +Z ~> setopt pushdtohome +Z ~> pushd +~ ~ /tmp + + + +As an alternative to using directory stacks in this manner, +we can get something like a directory history by setting a +few more options and parameters: + +~> DIRSTACKSIZE=8 +~> setopt autopushd pushdminus pushdsilent pushdtohome +~> alias dh='dirs -v' +~> cd /tmp +/tmp> cd /usr +/usr> cd bin +/usr/bin> cd ../pub +/usr/pub> dh +0 /usr/pub +1 /usr/bin +2 /usr +3 /tmp +4 ~ +/usr/pub> cd -3 +/tmp> dh +0 /tmp +1 /usr/pub +2 /usr/bin +3 /usr +4 ~ +/tmp> ls =2/df +/usr/bin/df +/tmp> cd -4 +~> + + +Note that =2 expanded to the second directory in the history +list, and that cd -3 recalled the third directory in the +list. + +You may be wondering what all those options do. AUTOPUSHD +made cd act like pushd. (alias cd=pushd is not sufficient, +for various reasons.) PUSHDMINUS swapped the meaning of cd ++1 and cd -1; we want them to mean the opposite of what they +mean in csh, because it makes more sense in this scheme, and +it's easier to type: + + + + + + + + + - 13 - + +~> dh +0 ~ +1 /tmp +2 /usr/pub +3 /usr/bin +4 /usr +~> unsetopt pushdminus +~> cd +1 +/tmp> dh +0 /tmp +1 ~ +2 /usr/pub +3 /usr/bin +4 /usr +/tmp> cd +2 +/usr/pub> + + +PUSHDSILENT keeps the shell from printing the directory +stack each time we do a cd, and PUSHDTOHOME we mentioned +earlier: + +/usr/pub> unsetopt pushdsilent +/usr/pub> cd /etc +/etc /usr/pub /tmp ~ /usr/bin /usr +/etc> cd +~ /etc /usr/pub /tmp ~ /usr/bin /usr +~> unsetopt pushdtohome +~> cd +/etc ~ /usr/pub /tmp ~ /usr/bin /usr +/etc> + + +DIRSTACKSIZE keeps the directory stack from getting too +large, much like HISTSIZE: + +/etc> setopt pushdsilent +/etc> cd / +/> cd / +/> cd / +/> cd / +/> cd / +/> cd / +/> cd / +/> cd / +/> dh +0 / +1 / +2 / +3 / +4 / +5 / +6 / +7 / + + + + + + + + + + + - 14 - +Command/Process Substitution + +Command substitution in zsh can take two forms. In the +traditional form, a command enclosed in backquotes (`...`) +is replaced on the command line with its output. This is +the form used by the older shells. Newer shells (like zsh) +also provide another form, $(...). This form is much easier +to nest. + +% ls -l `echo /vmunix` +-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix +% ls -l $(echo /vmunix) +-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix +% who | grep mad +subbarao ttyt7 May 23 15:02 (mad55sx15.Prince) +pfalstad ttyu1 May 23 16:25 (mad55sx14.Prince) +subbarao ttyu6 May 23 15:04 (mad55sx15.Prince) +pfalstad ttyv3 May 23 16:25 (mad55sx14.Prince) +% who | grep mad | awk '{print $2}' +ttyt7 +ttyu1 +ttyu6 +ttyv3 +% cd /dev; ls -l $(who | +> grep $(echo mad) | +> awk '{ print $2 }') +crwx-w---- 1 subbarao 20, 71 May 23 18:35 ttyt7 +crw--w---- 1 pfalstad 20, 81 May 23 18:42 ttyu1 +crwx-w---- 1 subbarao 20, 86 May 23 18:38 ttyu6 +crw--w---- 1 pfalstad 20, 99 May 23 18:41 ttyv3 + + +Many common uses of command substitution, however, are +superseded by other mechanisms of zsh: + +% ls -l `tty` +crw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc +% ls -l $TTY +crw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc +% ls -l `which rn` +-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn +% ls -l =rn +-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn + + +A command name with a = prepended is replaced with its full +pathname. This can be very convenient. If it's not con- +venient for you, you can turn it off: + +% ls +=foo =bar +% ls =foo =bar +zsh: foo not found +% setopt noequals +% ls =foo =bar +=foo =bar + + + +Another nice feature is process substitution: + + + + + + - 15 - + +% who | fgrep -f =(print -l root lemke shgchan subbarao) +root console May 19 10:41 +lemke ttyq0 May 22 10:05 (narnia:0.0) +lemke ttyr7 May 22 10:05 (narnia:0.0) +lemke ttyrd May 22 10:05 (narnia:0.0) +shgchan ttys1 May 23 16:52 (gaudi.Princeton.) +subbarao ttyt7 May 23 15:02 (mad55sx15.Prince) +subbarao ttyu6 May 23 15:04 (mad55sx15.Prince) +shgchan ttyvb May 23 16:51 (gaudi.Princeton.) + + +A command of the form =(...) is replaced with the name of a +file containing its output. (A command substitution, on the +other hand, is replaced with the output itself.) print -l is +like echo, excepts that it prints its arguments one per +line, the way fgrep expects them: + +% print -l foo bar +foo +bar + + +We could also have written: + +% who | fgrep -f =(echo 'root +> lemke +> shgchan +> subbarao') + + +Using process substitution, you can edit the output of a +command: + +% ed =(who | fgrep -f ~/.friends) +355 +g/lemke/d +w /tmp/filbar +226 +q +% cat /tmp/filbar +root console May 19 10:41 +shgchan ttys1 May 23 16:52 (gaudi.Princeton.) +subbarao ttyt7 May 23 15:02 (mad55sx15.Prince) +subbarao ttyu6 May 23 15:04 (mad55sx15.Prince) +shgchan ttyvb May 23 16:51 (gaudi.Princeton.) + + +or easily read archived mail: + + + + + + + + + + + + + + + + + - 16 - + +% mail -f =(zcat ~/mail/oldzshmail.Z) +"/tmp/zsha06024": 84 messages, 0 new, 43 unread +> 1 U TO: pfalstad, zsh (10) + 2 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3 + 3 U JAM%TPN@utrcgw.utc.com, zsh fix (15) + 4 U djm@eng.umd.edu, way to find out if running zsh? (25) + 5 U djm@eng.umd.edu, Re: way to find out if running zsh? (17) + 6 r djm@eng.umd.edu, Meta . (18) + 7 U jack@cs.glasgow.ac.uk, Re: problem building zsh (147) + 8 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3 + 9 ursa!jmd, Another fix... (61) + 10 U pplacewa@bbn.com, Re: v18i084: Zsh 2.00 - A small complaint (36) + 11 U lubkin@cs.rochester.edu, POSIX job control (34) + 12 U yale!bronson!tan@uunet.UU.NET + 13 U brett@rpi.edu, zsh (36) + 14 S subbarao, zsh sucks!!!! (286) + 15 U snibru!d241s008!d241s013!ala@relay.EU.net, zsh (165) + 16 U nytim!tim@uunet.UU.NET, Re: Zsh on Sparc1 /SunOS 4.0.3 + 17 U subbarao, zsh is a junk shell (43) + 18 U amaranth@vela.acs.oakland.edu, zsh (33) +43u/84 1: x +% ls -l /tmp/zsha06024 +/tmp/zsha06024 not found + + +Note that the shell creates a temporary file, and deletes it +when the command is finished. + +% diff =(ls) =(ls -F) +3c3 +< fortune +--- +> fortune* +10c10 +< strfile +--- +> strfile* + + +If you read zsh's man page, you may notice that <(...) is +another form of process substitution which is similar to +=(...). There is an important difference between the two. +In the <(...) case, the shell creates a named pipe (FIFO) +instead of a file. This is better, since it does not fill +up the file system; but it does not work in all cases. In +fact, if we had replaced =(...) with <(...) in the examples +above, all of them would have stopped working except for +fgrep -f <(...). You can not edit a pipe, or open it as a +mail folder; fgrep, however, has no problem with reading a +list of words from a pipe. You may wonder why diff <(foo) +bar doesn't work, since foo | diff - bar works; this is +because diff creates a temporary file if it notices that one +of its arguments is -, and then copies its standard input to +the temporary file. + +Aliasing + +Often-used commands can be abbreviated with an alias: + + + + + + + - 17 - + +% alias uc=uncompress +% ls +hanoi.Z +% uc hanoi +% ls +hanoi + + +or commands with certain desired options: + +% alias fm='finger -m' +% fm root +Login name: root In real life: Operator +Directory: / Shell: /bin/csh +On since May 19 10:41:15 on console 3 days 5 hours Idle Time +No unread mail +No Plan. + +% alias lock='lock -p -60000' +% lock +lock: /dev/ttyr4 on phoenix. timeout in 60000 minutes +time now is Fri May 24 04:23:18 EDT 1991 +Key: + +% alias l='ls -AF' +% l / +.bash_history kadb* +.bashrc lib@ +.cshrc licensed/ +.exrc lost+found/ +.login macsyma + + +Aliases can also be used to replace old commands: + +% alias grep=egrep ps=sps make=gmake +% alias whoami='echo root' +% whoami +root + + +or to define new ones: + + + + + + + + + + + + + + + + + + + + + + + - 18 - + +% cd / +% alias sz='ls -l | sort -n +3 | tail -10' +% sz +drwxr-sr-x 7 bin 3072 May 23 11:59 etc +drwxrwxrwx 26 root 5120 May 24 04:20 tmp +drwxr-xr-x 2 root 8192 Dec 26 19:34 lost+found +drwxr-sr-x 2 bin 14848 May 23 18:48 dev +-r--r--r-- 1 root 140520 Dec 26 20:08 boot +-rwxr-xr-x 1 root 311172 Dec 26 20:08 kadb +-rwxr-xr-x 1 root 1209695 Apr 16 15:33 vmunix.old +-rwxr-xr-x 1 root 1209702 May 14 19:04 vmunix +-rwxr-xr-x 1 root 1209758 May 21 12:23 vmunix.new.kernelmap.old +-rwxr-xr-x 1 root 1711848 Dec 26 20:08 vmunix.org +% cd +% alias rable='ls -AFtrd *(R)' nrable='ls -AFtrd *(^R)' +% rable +README func/ bin/ pub/ News/ src/ +nicecolors etc/ scr/ tmp/ iris/ zsh* +% nrable +Mailboxes/ mail/ notes + + +(The pattern *(R) matches all readable files in the current +directory, and *(^R) matches all unreadable files.) + +Most other shells have aliases of this kind (command +aliases). However, zsh also has global aliases, which are +substituted anywhere on a line. Global aliases can be used +to abbreviate frequently-typed usernames, hostnames, etc. + +% alias -g me=pfalstad gun=egsirer mjm=maruchck +% who | grep me +pfalstad ttyp0 May 24 03:39 (mickey.Princeton) +pfalstad ttyp5 May 24 03:42 (mickey.Princeton) +% fm gun +Login name: egsirer In real life: Emin Gun Sirer +Directory: /u/egsirer Shell: /bin/sh +Last login Thu May 23 19:05 on ttyq3 from bow.Princeton.ED +New mail received Fri May 24 02:30:28 1991; + unread since Fri May 24 02:30:27 1991 +% alias -g phx=phoenix.princeton.edu warc=wuarchive.wustl.edu +% ftp warc +Connected to wuarchive.wustl.edu. + + +Here are some more interesting uses. + +% alias -g M='| more' GF='| fgrep -f ~/.friends' +% who M # pipes the output of who through more +% who GF # see if your friends are on +% w GF # see what your friends are doing + + +Another example makes use of zsh's process substitution. If +you run NIS, and you miss being able to do this: + +% grep pfalstad /etc/passwd + + + + + + + + - 19 - +you can define an alias that will seem more natural than +ypmatch pfalstad passwd: + +% alias -g PASS='<(ypcat passwd)' +% grep pfalstad PASS +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh + + +If you're really crazy, you can even call it /etc/passwd: + +% alias -g /etc/passwd='<(ypcat passwd)' +% grep pfalstad /etc/passwd +pfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh + + +The last example shows one of the perils of global aliases; +they have a lot of potential to cause confusion. For exam- +ple, if you defined a global alias called | (which is possi- +ble), zsh would begin to act very strangely; every pipe sym- +bol would be replaced with the text of your alias. To some +extent, global aliases are like macros in C; discretion is +advised in using them and in choosing names for them. Using +names in all caps is not a bad idea, especially for aliases +which introduce shell metasyntax (like M and GF above). + +Note that zsh aliases are not like csh aliases. The syntax +for defining them is different, and they do not have argu- +ments. All your favorite csh aliases will probably not work +under zsh. For example, if you try: + +alias rm mv '\!* /tmp/wastebasket' + + +no aliases will be defined, but zsh will not report an +error. In csh, this line defines an alias that makes rm +safe---files that are rm'd will be moved to a temporary +directory instead of instantly destroyed. In zsh's syntax, +however, this line asks the shell to print any existing +alias definitions for rm, mv, or !* /tmp/wastebasket. Since +there are none, most likely, the shell will not print any- +thing, although alias will return a nonzero exit code. The +proper syntax is this: + +alias rm='mv \!* /tmp/wastebasket' + + +However, this won't work either: + +% rm foo.dvi +zsh: no matches found: !* + + +While this makes rm safe, it is certainly not what the user +intended. In zsh, you must use a shell function for this: + +% unalias rm +% rm () { mv $* /tmp/wastebasket } +% rm foo.dvi +% ls /tmp/wastebasket +foo.dvi + + + + + + - 20 - +While this is much cleaner and easier to read (I hope you +will agree), it is not csh-compatible. Therefore, a script +to convert csh aliases and variables has been provided. You +should only need to use it once, to convert all your csh +aliases and parameters to zsh format: + +% csh +csh> alias +l ls -AF +more less +on last -2 !:1 ; who | grep !:1 +csh> exit +% c2z >neat_zsh_aliases +% cat neat_zsh_aliases +alias l='ls -AF' +alias more='less' +on () { last -2 $1 ; who | grep $1 } +... + + +The first two aliases were converted to regular zsh aliases, +while the third, since it needed to handle arguments, was +converted to a function. c2z can convert most aliases to +zsh format without any problems. However, if you're using +some really arcane csh tricks, or if you have an alias with +a name like do (which is reserved in zsh), you may have to +fix some of the aliases by hand. + +The c2z script checks your csh setup, and produces a list of +zsh commands which replicate your aliases and parameter set- +tings as closely as possible. You could include its output +in your startup file, .zshrc. + +History + +There are several ways to manipulate history in zsh. One +way is to use csh-style ! history: + +% /usr/local/bin/!:0 !-2*:s/foo/bar/ >>!$ + + +If you don't want to use this, you can turn it off by typing +setopt nobanghist. + +Another way is to use the fc command. For example, if you +type an erroneous command: + +% for i in `cat /etc/clients` + do + rpu $i + done +zsh: command not found: rpu +zsh: command not found: rpu +zsh: command not found: rpu + + +typing fc will execute an editor on this command, allowing +you to fix it. (The default editor is vi, by the way, not +ed). + + + + + + + - 21 - + +% fc +49 +/rpu/s//rup/p + rup $i +w +49 +q +for i in `cat /etc/clients` + do + rup $i + done + beam up 2 days, 10:17, load average: 0.86, 0.80, 0.50 + bow up 4 days, 8:41, load average: 0.91, 0.80, 0.50 + burn up 17:18, load average: 0.91, 0.80, 0.50 + burst up 9 days, 1:49, load average: 0.95, 0.80, 0.50 + tan up 11:14, load average: 0.91, 0.80, 0.50 + bathe up 3 days, 17:49, load average: 1.84, 1.79, 1.50 + bird up 1 day, 9:13, load average: 1.95, 1.82, 1.51 + bonnet up 2 days, 21:18, load average: 0.93, 0.80, 0.50 + + +A variant of the fc command is r, which redoes the last com- +mand, with optional changes: + +% echo foo +foo +% r +echo foo +foo + +% echo foo +foo +% r foo=bar +echo bar +bar + + + +Command Line Editing + +zsh's command line editor, ZLE, is quite powerful. It is +designed to emulate either emacs or vi; the default is +emacs. To set the bindings for vi mode, type bindkey -v. + +In addition to basic editing, the shell allows you to recall +previous lines in the history. In emacs mode, this is done +with ^P (control-P): + +% ls ~ +- README file mail pub tmp +Mailboxes bin func nicecolors scr zsh +News etc iris notes src +% echo foobar +foobar +% ^P +% echo foobar^P +% ls ~_ + + + + + + + + - 22 - +Pressing ^P once brings up the previous line (echo foobar); +pressing it again brings up the line before that (ls ~). +The cursor is left at the end of the line, allowing you to +edit the line if desired before executing it. In many +cases, ZLE eliminates the need for the fc command, since it +is powerful enough to handle even multiline commands: + +% for i in a b c d e +> do +> echo $i +> done +a +b +c +d +e +% ^P +% for i in a b c d e + do + echo $i + done_ + + +Now you can just move up to the part you want to change... + +% for i in _ b c d e + do + echo $i + done + + +change it, and execute the new command. + +% for i in f g h i j + do + echo $i + done +f +g +h +i +j + + +Also, you can search the history for a certain command using +ESC-P: + +% set ESC-P +% setopt autolist ESC-P +% setopt nocorrect_ + + +Another way is to do an incremental search, emacs-style: + + + + + + + + + + + + + - 23 - + +% ^R +% _ +i-search: + +% l_ /usr/bin +i-search: l + +% date > foofile_c +i-search: le + + +Another useful feature of the editor is command and filename +completion. + +% compTAB +% compress _ + +% ls /nicTAB +% ls /nicecolors _ + +% ls /usr/prTAB +% ls /usr/princeton/_ + +% ls -l =comTAB +% ls -l =compress _ + + +If the completion is ambiguous, the editor will beep. You +can list possible completions by pressing ^D: + +% ls /vmuTAB -beep- +% ls /vmunix_ +% ls /vmunix^D +vmunix vmunix.old +vmunix.new.kernelmap.old vmunix.org + + +Or, you could just set the AUTOLIST option: + +% setopt autolist +% ls /vmuTAB -beep- +vmunix vmunix.old +vmunix.new.kernelmap.old vmunix.org +% ls /vmunix_ + + +Another option you could set is RECEXACT, which causes exact +matches to be accepted, even if there are other possible +completions: + +% setopt recexact +% ls /vmuTAB -beep- +vmunix vmunix.old +vmunix.new.kernelmap.old vmunix.org +% ls /vmunix_TAB +% ls /vmunix _ + + +The fignore variable lists suffixes of files to ignore + + + + + + - 24 - +during completion. + +% ls fooTAB -beep- +foofile.c foofile.o +% fignore=( .o \~ .bak .junk ) +% ls fooTAB +% ls foofile.c _ + + +Since foofile.o has a suffix that is in the fignore list, it +was not considered a possible completion of foo. + +Username completion is also supported: + +% ls ~pfalTAB +% ls ~pfalstad/_ + + +and parameter name completion: + +% echo $ORGTAB +% echo $ORGANIZATION _ + + +and hostname completion, if you give the shell a list of +hosts to complete: + +% hosts=( phoenix.princeton.edu uunet.uu.net nic.ddn.mil +> diskfarm.princeton.edu gnu.ai.mit.edu +> eniac.seas.upenn.edu ) +% telnet diskTAB +% telnet diskfarm.princeton.edu _ + +% ftp uuTAB +% ftp uunet.uu.net _ + +% mail subbarao@phTAB +% mail subbarao@phoenix.princeton.edu _ + + +and option completion: + +% setopt noclTAB +% setopt noclobber _ + + +and binding completion: + +% bindkey '^X^X' puTAB +% bindkey '^X^X' push-line _ + + + +The compctl command is used to control how completion works. +For example, to specify that certain commands show take com- +mands as arguments, you use compctl -c: + +% compctl -c man nohup +% man uptTAB +% man uptime _ + + + + + + - 25 - +To specify that a command should complete filenames, you +should use compctl -f. This is the default. It can be com- +bined with -c, as well. + +% compctl -cf echo +% echo uptTAB +% echo uptime _ + +% echo foTAB +% echo foo.c + + +Similarly, use -h to specify hostnames, -o to specify +options, -v to specify variables, and -b to specify bind- +ings. + +% compctl -h rlogin +% compctl -hfc rsh +% compctl -b bindkey + + +You can also use -k to specify a custom list of keywords to +use in completion. + +% ftphosts=(ftp.uu.net wuarchive.wustl.edu) +% compctl -k ftphosts ftp +% ftp wuTAB +% ftp wuarchive.wustl.edu _ + +% friends=(cpirazzi subbarao sukthnkr) +% compctl -k friends mail finger su +% finger cpTAB +% finger cpirazzi _ + + + +In addition to completion, TAB performs expansion if possi- +ble. + +% ls *.cTAB +% ls foofile.c fortune.c rnd.c strfile.c unstr.c_ + + +For example, suppose you have a bunch of weird files in an +important directory: + +% ls + * * * ; & % $??foo dspfok foo.c + !"foo"! ` \ ` foo rrr + + +You want to remove them, but you don't want to damage foo.c. +Here is one way to do this: + +% rm *TAB +% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' +'foo \`\ \\\ \` dspfok foo foo.c rrr_ + + +When you expand *, zsh inserts the names of all the files + + + + + + - 26 - +into the editing buffer, with proper shell quoting. Now, +just move back and remove foo.c from the buffer: + +% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' +'foo \`\ \\\ \` dspfok foo _rr + + +and press return. Everything except foo.c will be deleted +from the directory. + +Here's another trick; let's say you have typed this command +in: + +% gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs_ + + +and you forget which library you want. You need to escape +out for a minute and check by typing ls /usr/lib, or some +other such command; but you don't want to retype the whole +command again, and you can't press return now because the +current command is incomplete. In zsh, you can put the line +on the buffer stack, using ESC-Q, and type some other com- +mands. The next time a prompt is printed, the gcc line will +be popped off the stack and put in the editing buffer +automatically; you can then enter the proper library name +and press return (or, ESC-Q again and look for some other +libraries whose names you forgot). + +A similar situation: what if you forget the option to gcc +that finds bugs using AI techniques? You could either use +ESC-Q again, and type man gcc, or you could press ESC-H, +which essentially does the same thing; it puts the current +line on the buffer stack, and executes the command run-help +gcc, where run-help is an alias for man. + +Another interesting command is ESC-A. This executes the +current line, but retains it in the buffer, so that it +appears again when the next prompt is printed. Also, the +cursor stays in the same place. This is useful for execut- +ing a series of similar commands: + +% cc grok.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out +% cc fubar.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out +% cc fooble.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out + + + +The ESC-' command is useful for managing the shell's quoting +conventions. Let's say you want to print this string: + +don't do that; type 'rm -rf \*', with a \ before the *. + + +All that is necessary is to type it into the editing buffer: + +% don't do that; type 'rm -rf \*', with a \ before the *. + + +press ESC-' (escape-quote): + + + + + + + - 27 - + +% 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.' + + +then move to the beginning and add the echo command. + +% echo 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.' +don't do that; type 'rm -rf \*', with a \ before the *. + + +Let's say you want to create an alias to do this echo com- +mand. This can be done by recalling the line with ^P and +pressing ESC-' again: + +% 'echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm -rf +\*'\''\'\'''\'', with a \ before the *.'\''' + + +and then move to the beginning and add the command to create +an alias. + +% alias zoof='echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm +-rf \*'\''\'\'''\'', with a \ before the *.'\''' +% zoof +don't do that; type 'rm -rf \*', with a \ before the *. + + + +Another interesting option is MENUCOMPLETE. This affects +the way TAB works. Let's look at the /vmunix example again: + +% setopt menucomplete +% ls /vmuTAB +% ls /vmunixTAB +% ls /vmunix.new.kernelmap.oldTAB +% ls /vmunix.old_ + + +Each time you press TAB, it displays the next possible com- +pletion. In this way, you can cycle through the possible +completions until you find the one you want. + +The AUTOMENU option makes a nice compromise between this +method of completion and the regular method. If you set +this option, pressing the TAB key repeatedly after an ambi- +guous completion will cycle through the possible comple- +tions. + +Bindings + +Each of the above editor commands was actually a function +bound by default to a certain key. The real names of the +commands are: + +expand-or-complete TAB +push-line ESC-Q +run-help ESC-H +accept-and-hold ESC-A +quote-line ESC-' + + + + + + + - 28 - +These bindings are arbitrary; you could change them if you +want. For example, to bind accept-line to ^Z: + +% bindkey '^Z' accept-line + + +Another idea would be to bind the delete key to delete-char; +this might be convenient if you use ^H for backspace. + +% bindkey '^?' delete-char + + +Or, you could bind ^X^H to run-help: + +% bindkey '^X^H' run-help + + +Other examples: + +% bindkey '^X^Z' universal-argument +% bindkey ' ' magic-space +% bindkey -s '^T' 'uptime +> ' + + +universal-argument multiplies the next command by 4. Thus +^X^Z^W might delete the last four words on the line. If you +bind space to magic-space, then csh-style history expansion +is done on the line whenever you press the space bar. + +The -s flag to bindkey specifies that you are binding the +key to a string, not a command. Thus bindkey -s '^T' +'uptime\n' lets you VMS lovers get the load average whenever +you press ^T. + +If you have a NeXT keyboard, the one with the | and \ keys +very inconveniently placed, the following bindings may come +in handy: + +% bindkey -s '\e/' '\\' +% bindkey -s '\e=' '|' + + +Now you can type ALT-/ to get a backslash, and ALT-= to get +a vertical bar. This only works inside zsh, of course; +bindkey has no effect on the key mappings inside talk or +mail, etc. + +Another use of the editor is to edit the value of variables. +For example, an easy way to change your path is to use the +vared command: + +% vared PATH +> /u/pfalstad/scr:/u/pfalstad/bin/sun4:/u/maruchck/scr:/u/subbarao/bin:/u/maruc +hck/bin:/u/subbarao/scripts:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/usr/host +s:/usr/princeton/bin/X11:/./usr/lang:/./usr/etc:/./etc + + +You can now edit the path. When you press return, the con- +tents of the edit buffer will be assigned to PATH. + + + + + + - 29 - +Parameter Substitution + +In zsh, parameters are set like this: + +% foo=bar +% echo $foo +bar + + +Spaces before or after the = are frowned upon: + +% foo = bar +zsh: command not found: foo + + +Also, set doesn't work for setting parameters: + +% set foo=bar +% set foo = bar +% echo $foo + +% + + +Note that no error message was printed. This is because +both of these commands were perfectly valid; the set builtin +assigns its arguments to the positional parameters ($1, $2, +etc.). + +% set foo=bar +% echo $1 +foo=bar +% set foo = bar +% echo $3 $2 +bar = + + +If you're really intent on using the csh syntax, define a +function like this: + +% set () { +> eval "$1$2$3" +> } +% set foo = bar +% set fuu=brrr +% echo $foo $fuu +bar brrr + + +But then, of course you can't use the form of set with +options, like set -F (which turns off filename generation). +Also, the set command by itself won't list all the parame- +ters like it should. To get around that you need a case +statement: + + + + + + + + + + + + - 30 - + +% set () { +> case $1 in +> -*|+*|'') builtin set $* ;; +> *) eval "$1$2$3" ;; +> esac +> } + + +For the most part, this should make csh users happy. + +The following sh-style operators are supported in zsh: + +% unset null +% echo ${foo-xxx} +bar +% echo ${null-xxx} +xxx +% unset null +% echo ${null=xxx} +xxx +% echo $null +xxx +% echo ${foo=xxx} +bar +% echo $foo +bar +% unset null +% echo ${null+set} + +% echo ${foo+set} +set + + +Also, csh-style : modifiers may be appended to a parameter +substitution. + +% echo $PWD +/home/learning/pf/zsh/zsh2.00/src +% echo $PWD:h +/home/learning/pf/zsh/zsh2.00 +% echo $PWD:h:h +/home/learning/pf/zsh +% echo $PWD:t +src +% name=foo.c +% echo $name +foo.c +% echo $name:r +foo +% echo $name:e +c + + +The equivalent constructs in ksh (which are also supported +in zsh) are a bit more general and easier to remember. When +the shell expands ${foo#pat}, it checks to see if pat +matches a substring at the beginning of the value of foo. +If so, it removes that portion of foo, using the shortest +possible match. With ${foo##pat}, the longest possible + + + + + + - 31 - +match is removed. ${foo%pat} and ${foo%%pat} remove the +match from the end. Here are the ksh equivalents of the : +modifiers: + +% echo ${PWD%/*} +/home/learning/pf/zsh/zsh2.00 +% echo ${PWD%/*/*} +/home/learning/pf/zsh +% echo ${PWD##*/} +src +% echo ${name%.*} +foo +% echo ${name#*.} +c + + +zsh also has upper/lowercase modifiers: + +% xx=Test +% echo $xx:u +TEST +% echo $xx:l +test + + +and a substitution modifier: + +% echo $name:s/foo/bar/ +bar.c +% ls +foo.c foo.h foo.o foo.pro +% for i in foo.*; mv $i $i:s/foo/bar/ +% ls +bar.c bar.h bar.o bar.pro + + +One possible source of confusion is the fact that in zsh, +the result of parameter substitution is not split into +words. Thus, this will not work: + +% srcs='glob.c exec.c init.c' +% ls $srcs +glob.c exec.c init.c not found + + +This is considered a feature, not a bug. If splitting were +done by default, as it is in most other shells, functions +like this would not work properly: + +$ ll () { ls -F $* } +$ ll 'fuu bar' +fuu not found +bar not found + +% ll 'fuu bar' +fuu bar not found + + +Of course, a hackish workaround is available in sh (and +zsh): + + + + + + - 32 - + +% setopt shwordsplit +% ll () { ls -F "$@" } +% ll 'fuu bar' +fuu bar not found + + +If you like the sh behaviour, zsh can accomodate you: + +% ls ${=srcs} +exec.c glob.c init.c +% setopt shwordsplit +% ls $srcs +exec.c glob.c init.c + + +Another way to get the $srcs trick to work is to use an +array: + +% unset srcs +% srcs=( glob.c exec.c init.c ) +% ls $srcs +exec.c glob.c init.c + + +or an alias: + +% alias -g SRCS='exec.c glob.c init.c' +% ls SRCS +exec.c glob.c init.c + + +Another option that modifies parameter expansion is RCEX- +PANDPARAM: + +% echo foo/$srcs +foo/glob.c exec.c init.c +% setopt rcexpandparam +% echo foo/$srcs +foo/glob.c foo/exec.c foo/init.c +% echo foo/${^srcs} +foo/glob.c foo/exec.c foo/init.c +% echo foo/$^srcs +foo/glob.c foo/exec.c foo/init.c + + + +Shell Parameters + +The shell has many predefined parameters that may be +accessed. Here are some examples: + + + + + + + + + + + + + + + - 33 - + +% sleep 10 & +[1] 3820 +% echo $! +3820 +% set a b c +% echo $# +3 +% echo $ARGC +3 +% ( exit 20 ) ; echo $? +20 +% false; echo $status +1 + + +($? and $status are equivalent.) + +% echo $HOST $HOSTTYPE +dendrite sun4 +% echo $UID $GID +701 60 +% cd /tmp +% cd /home +% echo $PWD $OLDPWD +/home /tmp +% ls $OLDPWD/.getwd +/tmp/.getwd + + +~+ and ~- are short for $PWD and $OLDPWD, respectively. + +% ls ~-/.getwd +/tmp/.getwd +% ls -d ~+/learning +/home/learning +% echo $RANDOM +4880 +% echo $RANDOM +11785 +% echo $RANDOM +2062 +% echo $TTY +/dev/ttyp4 +% echo $VERSION +zsh v2.00.03 +% echo $USERNAME +pf + + + +The cdpath variable sets the search path for the cd command. +If you do not specify . somewhere in the path, it is assumed +to be the first component. + + + + + + + + + + + + - 34 - + +% cdpath=( /usr ~ ~/zsh ) +% ls /usr +5bin dict lang net sccs sys +5include etc lector nserve services tmp +5lib export lib oed share ucb +adm games local old skel ucbinclude +bin geac lost+found openwin spool ucblib +boot hosts macsyma_417 pat src xpg2bin +demo include man princeton stand xpg2include +diag kvm mdec pub swap xpg2lib +% cd spool +/usr/spool +% cd bin +/usr/bin +% cd func +~/func +% cd +% cd pub +% pwd +/u/pfalstad/pub +% ls -d /usr/pub +/usr/pub + + +PATH and path both set the search path for commands. These +two variables are equivalent, except that one is a string +and one is an array. If the user modifies PATH, the shell +changes path as well, and vice versa. + +% PATH=/bin:/usr/bin:/tmp:. +% echo $path +/bin /usr/bin /tmp . +% path=( /usr/bin . /usr/local/bin /usr/ucb ) +% echo $PATH +/usr/bin:.:/usr/local/bin:/usr/ucb + + +The same is true of CDPATH and cdpath: + +% echo $CDPATH +/usr:/u/pfalstad:/u/pfalstad/zsh +% CDPATH=/u/subbarao:/usr/src:/tmp +% echo $cdpath +/u/subbarao /usr/src /tmp + + +In general, parameters with names in all lowercase are +arrays; assignments to them take the form: + +name=( elem ... ) + + +Parameters with names in all uppercase are strings. If +there is both an array and a string version of the same +parameter, the string version is a colon-separated list, +like PATH. + +HISTFILE is the name of the history file, where the history +is saved when a shell exits. + + + + + + - 35 - + +% zsh +phoenix% HISTFILE=/tmp/history +phoenix% SAVEHIST=20 +phoenix% echo foo +foo +phoenix% date +Fri May 24 05:39:35 EDT 1991 +phoenix% uptime + 5:39am up 4 days, 20:02, 40 users, load average: 2.30, 2.20, 2.00 +phoenix% exit +% cat /tmp/history +HISTFILE=/tmp/history +SAVEHIST=20 +echo foo +date +uptime +exit +% HISTSIZE=3 +% history + 28 rm /tmp/history + 29 HISTSIZE=3 + 30 history + + + +In zsh, if you say + +% >file + + +the command cat is normally assumed: + +% >file +foo! +^D +% cat file +foo! + + +Thus, you can view a file simply by typing: + +% file +% ls -l file +-rw-r--r-- 1 pfalstad 0 May 24 05:41 file + + +If NULLCMD is unset, the shell reports an error if no com- +mand is specified (like csh). + + + + + + + + - 36 - + +% unset NULLCMD +% >file +zsh: redirection with no command + + +Actually, READNULLCMD is used whenever you have a null com- +mand reading input from a single file. Thus, you can set +READNULLCMD to more or less rather than cat. Also, if you +set NULLCMD to : for sh compatibility, you can still read +files with < file if you leave READNULLCMD set to more. + +Prompting + +The default prompt for zsh is: + +phoenix% echo $PROMPT +%m%# + + +The %m stands for the short form of the current hostname, +and the %# stands for a % or a #, depending on whether the +shell is running as root or not. zsh supports many other +control sequences in the PROMPT variable. + +% PROMPT='%/> ' +/u/pfalstad/etc/TeX/zsh> + +% PROMPT='%~> ' +~/etc/TeX/zsh> + +% PROMPT='%h %~> ' +6 ~/etc/TeX/zsh> + + +%h represents the number of current history event. + +% PROMPT='%h %~ %M> ' +10 ~/etc/TeX/zsh apple-gunkies.gnu.ai.mit.edu> + +% PROMPT='%h %~ %m> ' +11 ~/etc/TeX/zsh apple-gunkies> + +% PROMPT='%h %t> ' +12 6:11am> + +% PROMPT='%n %w tty%l>' +pfalstad Fri 24 ttyp0> + + +Also available is the RPROMPT parameter. If this is set, +the shell puts a prompt on the right side of the screen. + + + + + + + + + + + + + + - 37 - + +% RPROMPT='%t' +% 6:14am + +% RPROMPT='%~' +% ~/etc/TeX/zsh + +% PROMPT='%l %T %m[%h] ' RPROMPT=' %~' +p0 6:15 phoenix[5] ~/etc/TeX/zsh + + +These special escape sequences can also be used with the -P +option to print: + +% print -P %h tty%l +15 ttyp1 + + + +The POSTEDIT parameter is printed whenever the editor exits. +This can be useful for termcap tricks. To highlight the +prompt and command line while leaving command output +unhighlighted, try this: + +% POSTEDIT=`echotc se` +% PROMPT='%S%% ' + + + +Login/logout watching + +You can specify login or logout events to monitor by setting +the watch variable. Normally, this is done by specifying a +list of usernames. + +% watch=( pfalstad subbarao sukthnkr egsirer ) + + +The log command reports all people logged in that you are +watching for. + +% log +pfalstad has logged on p0 from mickey. +pfalstad has logged on p5 from mickey. +% ... +subbarao has logged on p8 from phoenix. +% ... +subbarao has logged off p8 from phoenix. +% ... +sukthnkr has logged on p8 from dew. +% ... +sukthnkr has logged off p8 from dew. + + +If you specify hostnames with an @ prepended, the shell will +watch for all users logging in from the specified host. + + + + + + + + + + - 38 - + +% watch=( @mickey @phoenix ) +% log +djthongs has logged on q2 from phoenix. +pfalstad has logged on p0 from mickey. +pfalstad has logged on p5 from mickey. + + +If you give a tty name with a % prepended, the shell will +watch for all users logging in on that tty. + +% watch=( %ttyp0 %console ) +% log +root has logged on console from . +pfalstad has logged on p0 from mickey. + + +The format of the reports may also be changed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 39 - + +% watch=( pfalstad gettes eps djthongs jcorr bdavis ) +% log +jcorr has logged on tf from 128.112.176.3:0. +jcorr has logged on r0 from 128.112.176.3:0. +gettes has logged on p4 from yo:0.0. +djthongs has logged on pe from grumpy:0.0. +djthongs has logged on q2 from phoenix. +bdavis has logged on qd from BRUNO. +eps has logged on p3 from csx30:0.0. +pfalstad has logged on p0 from mickey. +pfalstad has logged on p5 from mickey. +% WATCHFMT='%n on tty%l from %M' +% log +jcorr on ttytf from 128.112.176.3:0. +jcorr on ttyr0 from 128.112.176.3:0. +gettes on ttyp4 from yo:0.0 +djthongs on ttype from grumpy:0.0 +djthongs on ttyq2 from phoenix.Princeto +bdavis on ttyqd from BRUNO.pppl.gov +eps on ttyp3 from csx30:0.0 +pfalstad on ttyp0 from mickey.Princeton +pfalstad on ttyp5 from mickey.Princeton +% WATCHFMT='%n fm %m' +% log +jcorr fm 128.112.176.3:0 +jcorr fm 128.112.176.3:0 +gettes fm yo:0.0 +djthongs fm grumpy:0.0 +djthongs fm phoenix +bdavis fm BRUNO +eps fm csx30:0.0 +pfalstad fm mickey +pfalstad fm mickey +% WATCHFMT='%n %a at %t %w.' +% log +jcorr logged on at 3:15pm Mon 20. +jcorr logged on at 3:16pm Wed 22. +gettes logged on at 6:54pm Wed 22. +djthongs logged on at 7:19am Thu 23. +djthongs logged on at 7:20am Thu 23. +bdavis logged on at 12:40pm Thu 23. +eps logged on at 4:19pm Thu 23. +pfalstad logged on at 3:39am Fri 24. +pfalstad logged on at 3:42am Fri 24. + + +If you have a .friends file in your home directory, a con- +venient way to make zsh watch for all your friends is to do +this: + +% watch=( $(< ~/.friends) ) +% echo $watch +subbarao maruchck root sukthnkr ... + + +If watch is set to all, then all users logging in or out +will be reported. + + + + + + + + - 40 - +Options + +Some options have already been mentioned; here are a few +more: + +% cd / +% setopt autocd +% bin +% pwd +/bin +% ../etc +% pwd +/etc + + +Using the AUTOCD option, you can simply type the name of a +directory, and it will become the current directory. + +% setopt cdablevars +% foo=/tmp +% cd foo +/tmp + + +With CDABLEVARS, if the argument to cd is the name of a +parameter whose value is a valid directory, it will become +the current directory. + +CORRECT turns on spelling correction for commands, and the +CORRECTALL option turns on spelling correction for all argu- +ments. + +% setopt correct +% sl +zsh: correct `sl' to `ls' [nyae]? y +% setopt correctall +% ls x.v11r4 +zsh: correct `x.v11r4' to `X.V11R4' [nyae]? n +/usr/princton/src/x.v11r4 not found +% ls /etc/paswd +zsh: correct to `/etc/paswd' to `/etc/passwd' [nyae]? y +/etc/passwd + + +If you press y when the shell asks you if you want to +correct a word, it will be corrected. If you press n, it +will be left alone. Pressing a aborts the command, and +pressing e brings the line up for editing again, in case you +agree the word is spelled wrong but you don't like the +correction. + +Normally, a quoted expression may contain a newline: + +% echo ' +> foo +> ' + +foo + +% + + + + + + - 41 - +With CSHJUNKIEQUOTES set, this is illegal, as it is in csh. + +% setopt cshjunkiequotes +% ls 'foo +zsh: unmatched ' + + +GLOBDOTS lets files beginning with a . be matched without +explicitly specifying the dot. + +% ls -d *x* +Mailboxes +% setopt globdots +% ls -d *x* +.exrc .pnewsexpert .xserverrc +.mushexpert .xinitrc Mailboxes + + +HISTIGNOREDUPS prevents the current line from being saved in +the history if it is the same as the previous one; HISTIG- +NORESPACE prevents the current line from being saved if it +begins with a space. + +% PROMPT='%h> ' +39> setopt histignoredups +40> echo foo +foo +41> echo foo +foo +41> echo foo +foo +41> echo bar +bar +42> setopt histignorespace +43> echo foo +foo +43> echo fubar +fubar +43> echo fubar +fubar + + +IGNOREBRACES turns off csh-style brace expansion. + +% echo x{y{z,a},{b,c}d}e +xyze xyae xbde xcde +% setopt ignorebraces +% echo x{y{z,a},{b,c}d}e +x{y{z,a},{b,c}d}e + + +IGNOREEOF forces the user to type exit or logout, instead of +just pressing ^D. + +% setopt ignoreeof +% ^D +zsh: use 'exit' to exit. + + +INTERACTIVECOMMENTS turns on interactive comments; comments + + + + + + - 42 - +begin with a #. + +% setopt interactivecomments +% date # this is a comment +Fri May 24 06:54:14 EDT 1991 + + +NOCLOBBER prevents you from accidentally overwriting an +existing file. + +% setopt noclobber +% cat /dev/null >~/.zshrc +zsh: file exists: /u/pfalstad/.zshrc + + +If you really do want to clobber a file, you can use the >! +operator. To make things easier in this case, the > is +stored in the history list as a >!: + +% cat /dev/null >! ~/.zshrc +% cat /etc/motd > ~/.zshrc +zsh: file exists: /u/pfalstad/.zshrc +% !! +cat /etc/motd >! ~/.zshrc +% ... + + +RCQUOTES lets you use a more elegant method for including +single quotes in a singly quoted string: + +% echo '"don'\''t do that."' +"don't do that." +% echo '"don''t do that."' +"dont do that." +% setopt rcquotes +% echo '"don''t do that."' +"don't do that." + + +Finally, SUNKEYBOARDHACK wins the award for the strangest +option. If a line ends with `, and there are an odd number +of them on the line, the shell will ignore the trailing `. +This is provided for keyboards whose RETURN key is too +small, and too close to the ` key. + +% setopt sunkeyboardhack +% date` +Fri May 24 06:55:38 EDT 1991 + + + +Closing Comments + +I would be happy to receive mail if anyone has any tricks or +ideas to add to this document, or if there are some points +that could be made clearer or covered more thoroughly. +Please notify me of any errors in this document. + + + + + + diff --git a/usr/othersrc/public/zsh-2.2/dots/zlogin b/usr/othersrc/public/zsh-2.2/dots/zlogin new file mode 100644 index 0000000000..de27dc3856 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/dots/zlogin @@ -0,0 +1,16 @@ +clear +cd +stty dec new cr0 -tabs +ttyctl -f # freeze the terminal modes... can't change without a ttyctl -u +umask 022 +export MAIL=/usr/spool/mail/$USER +MAILCHECK=60 +mesg y +uptime +fortune +log +from 2>/dev/null +cat notes +unlimit +limit core 0 +msgs -fp diff --git a/usr/othersrc/public/zsh-2.2/dots/zshenv b/usr/othersrc/public/zsh-2.2/dots/zshenv new file mode 100644 index 0000000000..ab37dcba3b --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/dots/zshenv @@ -0,0 +1,3 @@ +path=(~/scr ~/bin/$HOSTTYPE + /usr/princeton/bin /usr/ucb /usr/bin /bin + /usr/hosts /usr/princeton/bin/X11 /usr/etc /etc .) diff --git a/usr/othersrc/public/zsh-2.2/dots/zshrc b/usr/othersrc/public/zsh-2.2/dots/zshrc new file mode 100644 index 0000000000..544f394787 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/dots/zshrc @@ -0,0 +1,88 @@ +# +# my rc file for zsh 2.2 +# all this runs in interactive shells only +# + +# search path for the cd command +cdpath=(. ~ ~/src/cs320 ~/src) + +# where to look for function definitions +# fpath=(~/func) + +# useful directory +csrc=/usr/princeton/common/src + +# use hard limits, except for a smaller stack and no core dumps +unlimit +limit stack 8192 +limit core 0 +limit -s + +umask 022 + +# define some aliases +alias a=alias +a a.out=./a.out sendmail=/usr/lib/sendmail c=cp 0=vi 09='vi -t' 00=r +a d=dirs en='enscript -2rGh' fm='finger -m' grep=egrep h=history +a hinfo='host -t hinfo' j=jobs l='ls -AF' lock='lock -p -60000' +a lsd='ls -d */' m=make mm=less +a nrable='ls -AFltrd *(^R)' sz='ls -l | sort -n +3 | tail -20' +a sn='sed -n' nw='l -ltr | tail' pd=pushd pop=popd mroe=more +a rable='ls -AFltrd *(R)' strings='strings -' t=cat +a v=mv where='hostname; echo >/dev/null' k9='kill -9' whoami='echo root' +a find='noglob find' bindkey='noglob bindkey' dh='dirs -v' +a mv='nocorrect mv' z=suspend + +# global aliases +a -g 'GF'='| fgrep -f ~/.friends' G='| grep' M='| less' cex='/u/pup/centrex' + +# setenv for csh junkies (including tset) +setenv() { export $1=$2 } + +manpath=(/usr/man /usr/princeton/man /u/cad/man /usr/lang/man) +export MANPATH + +# filename completion suffixes to ignore +fignore=(.o .pro .old) + +# hosts to use for completion +hosts=(uunet.uu.net `hostname` wuarchive.wustl.edu quiche.cs.mcgill.ca) + +PROMPT='%l %T %m[%h] ' + +# prompt on the right side of the screen +RPROMPT=' %~' + +# some environment variables +export MAILCALL='NEW MAIL! ' +export YOUSAID='In %C you wrote:' +export ATTRIBUTION='%f wrote:' + +# functions to autoload +# autoload cx acx mere yu yp randline proto namedir ilogin + +MAILCHECK=30 +HISTSIZE=600 +DIRSTACKSIZE=50 + +# lots of options +setopt notify globdots correct pushdtohome cdablevars autolist \ + sunkeyboardhack correctall autocd recexact longlistjobs mailwarning \ + autoresume histignoredups pushdsilent noclobber \ + autopushd pushdminus extendedglob rcquotes +unsetopt bgnice + +# watch for my friends +watch=($(cat ~/.friends)) +WATCHFMT='%n %a %l from %m at %t.' +LOGCHECK=0 + +export LESS=-ainx3 +unhash p + +# some nice bindings +bindkey '^X^Z' universal-argument ' ' magic-space +bindkey '^X^A' vi-find-prev-char-skip +bindkey '^Z' accept-and-hold +bindkey -s '\M-/' \\\\ +bindkey -s '\M-=' \| diff --git a/usr/othersrc/public/zsh-2.2/func/acx b/usr/othersrc/public/zsh-2.2/func/acx new file mode 100755 index 0000000000..f7c680bb0e --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/acx @@ -0,0 +1,6 @@ +#! /bin/sh +# +# zsh shell function to make its arguments 755 +# also works as an sh script +# +chmod 755 $* diff --git a/usr/othersrc/public/zsh-2.2/func/cx b/usr/othersrc/public/zsh-2.2/func/cx new file mode 100755 index 0000000000..a0b34a4f05 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/cx @@ -0,0 +1,6 @@ +#! /bin/sh +# +# zsh shell function to make its arguments executable +# also works as a sh script +# +chmod +x $* diff --git a/usr/othersrc/public/zsh-2.2/func/harden b/usr/othersrc/public/zsh-2.2/func/harden new file mode 100755 index 0000000000..c02689362e --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/harden @@ -0,0 +1,6 @@ +#! /bin/sh +# harden a link (convert it to a singly linked file) +cp $1 $1.foo +rm $1 +mv $1.foo $1 + diff --git a/usr/othersrc/public/zsh-2.2/func/mere b/usr/othersrc/public/zsh-2.2/func/mere new file mode 100755 index 0000000000..cf8d8ad14a --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/mere @@ -0,0 +1,3 @@ +#! /bin/sh +# read a man page in the current directory +nroff -man -Tman $1 | less -s diff --git a/usr/othersrc/public/zsh-2.2/func/namedir b/usr/othersrc/public/zsh-2.2/func/namedir new file mode 100755 index 0000000000..5f802f623a --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/namedir @@ -0,0 +1,15 @@ +# give a name to a directory + +$1=~+ +: ~$1 + +# for example, if we say: namedir foo +# where the current directory is /usr/princeton/common/src/news/nntp/inews +# this will do: +# +# foo=/usr/princeton/common/src/news/nntp/inews +# : ~foo +# +# The : ~foo just evaluates ~foo, which declares foo as a named directory. +# The first time a parameter is used with tilde expansion, it is declared +# as the name of a named dir. diff --git a/usr/othersrc/public/zsh-2.2/func/proto b/usr/othersrc/public/zsh-2.2/func/proto new file mode 100755 index 0000000000..df18265066 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/proto @@ -0,0 +1,8 @@ +#! /bin/sh +# generate prototypes, if your style is the same as mine +for i +do + rm $i:r.pro 2>/dev/null + grep -v '[{};:#]' $i | grep '^[A-Za-z]' | + grep -v static | sed 's/$/;/' >! $i:r.pro +done diff --git a/usr/othersrc/public/zsh-2.2/func/randline b/usr/othersrc/public/zsh-2.2/func/randline new file mode 100755 index 0000000000..9af714fa24 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/randline @@ -0,0 +1,3 @@ +# get a random line from a file +integer z=$(wc -l <$1) +sed -n $[RANDOM%z+1]p $1 diff --git a/usr/othersrc/public/zsh-2.2/func/yp b/usr/othersrc/public/zsh-2.2/func/yp new file mode 100755 index 0000000000..7e09613efb --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/yp @@ -0,0 +1,2 @@ +#! /bin/sh +ypmatch $1 passwd diff --git a/usr/othersrc/public/zsh-2.2/func/yu b/usr/othersrc/public/zsh-2.2/func/yu new file mode 100755 index 0000000000..3c5f170cfc --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/func/yu @@ -0,0 +1,2 @@ +#! /bin/sh +ypmatch $1 passwd.byuid diff --git a/usr/othersrc/public/zsh-2.2/man/man1/zsh.1 b/usr/othersrc/public/zsh-2.2/man/man1/zsh.1 new file mode 100644 index 0000000000..6c21a7b307 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/man/man1/zsh.1 @@ -0,0 +1,4089 @@ +.\" +.TH ZSH 1 "1992 May 2" +.SH NAME +zsh \- the Z shell +.SH SYNOPSIS +\fBzsh\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption\fP ] ... [ \-\fBc\fP \fIstring\fP ] [ \fIarg\fP ... ] +.SH "SHELL GRAMMAR" +A \fIsimple command\fP is a sequence of optional parameter +assignments followed by blank-separated words, +with optional redirections interspersed. +The first word is the command to be executed, and the remaining +words, if any, are arguments to the command. +If a command name is given, the parameter assignments modify +the environment of the command when it is executed. +The value of a simple command is its exit status, +or 128 plus the signal number if terminated by a signal. +.PP +If a simple command is preceded by the word \fBexec\fP, +it is executed in the parent shell without forking. +If preceded by \fBcommand\fP, the command word is taken +to be the name of an external command, rather than a +shell function or builtin. +If preceded by \fBnoglob\fP, filename generation is not performed +on any of the words. If preceded by a \-, the command +is executed with a \- prepended to its \fBargv[0]\fP string. +If preceded by \fBnocorrect\fP, spelling correction is not +done on any of the words. +.PP +A \fIpipeline\fP is a sequence of one or more commands +separated by \fB|\fP or \fB|&\fP. \fB|&\fP is shorthand +for \fB2>&1 |\fP. The standard output of each command is +connected to the standard input of the next command in the +pipeline. +.PP +The value of a pipeline is the value of the last command. +If a pipeline is preceded by a \fB!\fP, the value +of that pipeline is the logical NOT of the value of the last +command. +.PP +If a pipeline is preceded by \fBcoproc\fP, it is +executed as a coprocess; a two-way pipe is established +between it and the parent shell. The shell can read from or write to +the coprocess by means of the \fB>&p\fP and \fB<&p\fP +redirection operators. +.PP +A \fIsublist\fP is a sequence of one or more pipelines +separated by \fB&&\fP or \fB|\||\fP. If two pipelines +are separated by \fB&&\fP, the second pipeline is executed +only if the first is successful (returns a zero value). +If two pipelines are separated by \fB|\||\fP, the second is executed +only if the first is unsuccessful (returns a nonzero value). +.PP +A \fIlist\fP is a sequence of one or more sublists +separated by, and optionally terminated by, \fB;\fP, \fB&\fP, +or a newline. +Normally the shell waits for each list to finish before executing +the next one. +If a list is terminated by a \fB&\fP, the shell executes +it in the background, and does not wait for it to finish. +.PP +A \fIcomplex command\fP is one of the following: +.PP +.RS +.PD 0 +.TP +\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... ] +.TP +\fBdo\fP \fIlist\fP +.TP +\fBdone\fP +.PD +Expand the list of \fIword\fPs, and set the parameter +\fIname\fP to each of them in turn, executing +\fIlist\fP each time. If the \fBin\fP \fIword\fP is omitted, +use the positional parameters instead of the \fIword\fPs. +.TP +\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... ] ; \fIsublist\fP +This is a shorthand for \fBfor\fP. +Though it may cause confusion, it is included for convenience; +its use in scripts is discouraged, +unless \fIsublist\fP is a command of the form { \fIlist\fP }. +.PP +.PD 0 +.TP +\fBforeach\fP \fIname\fP \fB(\fP \fIword\fP ... \fB)\fP +.TP +\fIlist\fP +.TP +\fBend\fP +.PD +Another form of \fBfor\fP. +.PP +.PD 0 +.TP +\fBfor\fP \fIname\fP \fBin\fP \fIword\fP ... +.TP +\fB{\fP +.TP +\fIlist\fP +.TP +\fB}\fP +.PD +Another form of \fBfor\fP. +.PP +.PD 0 +.TP +\fBfor\fP \fIname\fP \fB(\fP \fIword\fP ... \fB) {\fP +.TP +\fIlist\fP +.TP +\fB}\fP +.PD +Another form of \fBfor\fP. +.PP +.PD 0 +.TP +\fBfor\fP \fIname\fP \fB(\fP \fIword\fP ... \fB) \fIsublist\fP +.PD +Another form of \fBfor\fP. +.PP +.PD 0 +.TP +\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ... ] +.TP +\fBdo\fP \fIlist\fP +.TP +\fBdone\fP +.PD +Print the set of \fIword\fPs, each preceded by a number. +If the \fBin\fP \fIword\fP is omitted, use the positional parameters. +The \fBPROMPT3\fP prompt is printed and a line is read from standard +input. If this line consists of the number of one of the listed +\fIword\fPs, then the parameter \fIname\fP +is set to the \fIword\fP corresponding to this number. +If this line is empty, the selection list is printed again. +Otherwise, the value of the parameter \fIname\fP is set to null. +The contents of the line read from standard input is saved +in the parameter \fBREPLY\fP. \fIlist\fP is executed +for each selection until a break or end-of-file is encountered. +.TP +\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fIsublist\fP +A short form of \fBselect\fP. +.TP +\fBcase\fP \fIword\fP \fBin\fP [ \fIpattern\fP ) \fIlist\fP ;; ] ... \fBesac\fP +Execute the \fIlist\fP associated with the first \fIpattern\fP +that matches \fIword\fP, if any. The form of the patterns +is the same as that used for filename generation. See +\fIFilename Generation\fP below. +.TP +\fBcase\fP \fIword\fP \fB{\fP [ \fIpattern\fP ) \fIlist\fP ;; ] ... \fB}\fP +Another form of \fBcase\fP. +.TP +.PD 0 +\fBif\fP \fIlist\fP +.TP +\fBthen\fP \fIlist\fP +.TP +[ \fBelif\fP \fIlist\fP ; \fBthen\fP \fIlist\fP ] ... +.TP +[ \fBelse\fP \fIlist\fP ] +.TP +\fBfi\fP +.PD +The \fBif\fP \fIlist\fP is executed, and, +if it returns a zero exit status, +the \fBthen\fP \fIlist\fP is executed. +Otherwise, the \fBelif\fP \fIlist\fP is +executed and, if its value is zero, +the \fBthen\fP \fIlist\fP is executed. +If each \fBelif\fP \fIlist\fP returns +nonzero, the \fBelse\fP \fIlist\fP is executed. +.TP +\fBif (\fP \fIlist\fP \fB)\fP \fIsublist\fP +A short form of \fBif\fP. +.PP +.PD 0 +.TP +\fBif\fP \fB(\fP \fIlist\fP \fB) {\fP +.TP +\fIlist\fP +.TP +\fB} elif (\fP \fIlist\fP \fB) {\fP +.TP +\fIlist\fP +.TP +\fB} ... else {\fP +.TP +\fIlist\fP +.TP +\fB}\fP +.PD +An alternate form of \fBif\fP. +.TP +.PD 0 +\fBwhile\fP \fIlist\fP +.TP +\fBdo\fP \fIlist\fP +.TP +\fBdone\fP +.PD +Execute the \fBdo\fP \fIlist\fP as long as the \fBwhile\fP \fIlist\fP +returns a zero exit status. +.PP +.PD 0 +.TP +\fBwhile (\fP \fIlist\fP \fB) {\fP +.TP +\fIlist\fP +.TP +\fB}\fP +.PD +An alternate form of \fBwhile\fP. +.TP +.PD 0 +\fBuntil\fP \fIlist\fP +.TP +\fBdo\fP \fIlist\fP +.TP +\fBdone\fP +.PD +Execute the \fBdo\fP \fIlist\fP as long as \fBuntil\fP \fIlist\fP +returns a nonzero exit status. +.TP +.PD 0 +\fBrepeat\fP \fIword\fP +.TP +\fBdo\fP \fIlist\fP +.TP +\fBdone\fP +.PD +\fIword\fP is expanded and treated as an arithmetic expression, +which must evaluate to a number \fIn\fP. +\fIlist\fP is then executed \fBn\fP times. +.TP +\fBrepeat\fP \fIword\fP \fIsublist\fP +This is a short form of \fBrepeat\fP. +.TP +( \fIlist\fP ) +Execute \fIlist\fP in a subshell. +.TP +{ \fIlist\fP } +Execute \fIlist\fP. +.TP +.PD 0 +\fBfunction\fP \fIword\fP [ (\|) ] ... { \fIlist\fP } +.TP +\fIword\fP ... (\|) { \fIlist\fP } +.TP +\fIword\fP ... (\|) \fIsublist\fP +.PD +Define a function which is referenced by any one of \fIword\fP. +Normally, only one \fIword\fP is provided; multiple \fIword\fPs +are usually only useful for setting traps. +The body of the function is the \fIlist\fP between +the { and }. +See \fBFUNCTIONS\fP below. +.TP +\fBtime\fP [ \fIpipeline\fP ] +The \fIpipeline\fP is executed, and timing statistics are +reported on the standard error in the form specified +by the \fBTIMEFMT\fP parameter. +If \fIpipeline\fP is omitted, print statistics about the +shell process and its children. +.TP +[[ \fIexp\fP ]] +Evaluates the conditional expression \fIexp\fP +and return a zero exit status if it is true. +See \fBConditional Expressions\fP below for a description +of \fIexp\fP. +.SH "RESERVED WORDS" +The following words are recognized as reserved words when used +as the first word of a command +unless quoted or removed using the \fBunalias\fP builtin: +.RS +.PP +\fBdo done esac then elif else fi for case +if while function repeat time until exec command +select coproc noglob \- nocorrect foreach end\fP +.RE +.SH COMMENTS +In noninteractive shells, or in interactive shells with the +\fBINTERACTIVE_COMMENTS\fP option set, a word beginning +with the third character of the \fBHISTCHARS\fP parameter +(`#' by default) causes that word and all the following +characters up to a newline to be ignored. +.SH ALIASING +Every token in the shell input is checked to see if there +is an alias defined for it. +If so, it is replaced by the text of the alias if it is in command +position (if it could be the first word of a simple command), +or if the alias is global. +If the text ends with a space, the next word in the shell input +is treated as though it were in command position for purposes of alias +expansion. +An alias is defined using the \fBalias\fP builtin; global aliases +may be defined using the \-\fBg\fP option to that bulitin. +.PP +Alias substitution is done on the shell input before any +other substitution except history substitution. Therefore, +if an alias is defined for the word \fBfoo\fP, alias substitution +may be avoided by quoting part of the word, e.g. \fB\efoo\fP. +But there is nothing to prevent an alias being defined +for \fB\efoo\fP as well. +.SH QUOTING +A character may be \fIquoted\fP (that is, made +to stand for itself) by preceding it with a \e\|. +\e followed by a newline is ignored. +All characters enclosed between a pair of single quotes ('') +are quoted. +A single quote cannot appear within single quotes. +Inside double quotes (""), parameter and command substitution +occurs, and \e quotes the characters \e\|, `, ", and $. +.SH EXPANSION +Expansion is performed on the command line after it has been +parsed. The types of expansions performed are +\fIfilename expansion\fP, +\fIprocess substitution\fP, +\fIparameter expansion\fP, +\fIcommand substitution\fP, +\fIarithmetic expansion\fP, +\fIbrace expansion\fP, +and \fIfilename generation\fP. +.SS Filename Expansion +Each word is checked to see if it begins with an unquoted ~. +If it does, then the word up to a / is checked to see if it matches +the name of a named directory. If so, then the ~ and the matched portion +are replaced with the value of the named directory. +A ~ by itself or followed by a / is replaced by the value of the +\fBHOME\fP parameter. +A ~ followed by a + or a \- is replaced by the value of +\fBPWD\fP or \fBOLDPWD\fP, respectively. +.PP +Named directories are typically login directories for users on the system. +They may also be defined if the text after the ~ is the name +of a shell parameter whose value begins with a /. +In certain circumstances (in prompts, for instance), when the shell +prints a path, the path is checked to see if it has a named +directory as its prefix. If so, then the prefix portion +is replaced with a ~ followed by the name of the directory. +The longest match is preferred. +.PP +If a word begins with an unquoted \fB=\fP and the +\fBNO_EQUALS\fP option is not set, +the remainder of the word is taken as the +name of a command or alias. If a command +exists by that name, the word is replaced +by the full pathname of the command. +If an alias exists by that name, the word +is replaced with the text of the alias. +Otherwise the word is checked up to a / +to see if it is a number or a \-. If so, +the matched portion is replaced with +the \fIn\fPth directory in the directory stack, +where \fIn\fP is the number matched, or +the last directory in the directory stack +if a \- is matched. +.SS Process Substitution +Each command argument of the form +\fB<(\fIlist\^\fB)\fR +or +\fB>(\fIlist\^\fB)\fR +or +\fB=(\fIlist\^\fB)\fR +is subject to process substitution. +In the case of the +.B < +or +.B > +forms, the shell will run process +.I list +asynchronously connected to a named pipe (FIFO). +The name of this pipe will become the argument to the command. +If the form with +.B > +is selected then writing on this file will provide input for +.IR list . +If +.B < +is used, +then the file passed as an argument will +be a named pipe connected to the output of the +.I list +process. +For example, +.RS +.PP +\fBpaste <(cut \-f1\fP \fIfile1\fB) <(cut \-f3\fP \fIfile2\fB) | tee >(\fIprocess1\fB) >(\fIprocess2\fB)\fR >/dev/null +.RE +.PP +.BR cut s +fields 1 and 3 from +the files +.I file1 +and +.I file2 +respectively, +.BR paste s +the results together, and sends it to the processes +.I process1 +and +.IR process2 . +Note that the file, which is passed as an argument to the command, +is a system +pipe +so programs that expect to +.BR lseek (2) +on the file will not work. +Also note that the previous example can be more compactly and +efficiently written as: +.RS +.PP +\fBpaste <(cut \-f1\fP \fIfile1\fB) <(cut \-f3\fP \fIfile2\fB) > >(\fIprocess1\fB) > >(\fIprocess2\fB)\fR +.RE +.PP +the shell uses pipes instead of a FIFOs to implement the latter +two process substitutions in the above example. +.PP +If +.B = +is used, +then the file passed as an argument will be the name +of a temporary file containing +the output of the +.I list +process. This may be used instead of the +.B < +form for a program that expects to \fBlseek\fP(2) on the input file. +.SS Parameter Expansion +The character \fB$\fP is used to introduce parameter expansions. +See \fBPARAMETERS\fP below for a description of parameters. +.PD +.RS +.TP +\fB${\fIname\fB}\fR +The value, if any, of the parameter \fIname\fP is substituted. +The braces are required with \fIname\fP is followed by +a letter, digit, or underscore that is not to be interpreted +as part of its name. +If \fIname\fP is an array parameter, then the values of each +element of \fIname\fP is substituted, one element per word. +Otherwise, the expansion results in one word only; no +word splitting is done on the result. +.TP +\fB${\fIname\fB:\-\fIword\fB}\fR +If \fIname\fP is set and is non-null then substitute its +value; otherwise substitute \fIword\fP. +.TP +\fB${\fIname\fB:=\fIword\fB}\fR +If \fIname\fP is unset and is null then +set it to \fIword\fP; the value of the parameter is then +substituted. +.TP +\fB${\fIname\fB:?\fIword\fB}\fR +If \fIname\fP is set and is non-null, then substitute +its value; otherwise, print \fIword\fP and exit from the shell. +If \fIword\fP is omitted, then a standard message is printed. +.TP +\fB${\fIname\fB:+\fIword\fB}\fR +If \fIname\fP is set and is non-null then substitute +\fIword\fP; otherwise substitute nothing. +.PD 0 +.TP +\fB${\fIname\fB#\fIpattern\fB}\fR +.TP +\fB${\fIname\fB##\fIpattern\fB}\fR +.PD +If the \fIpattern\fP matches the beginning of the value of +\fIname\fP, then substitute the value of \fIname\fP with +the matched portion deleted; otherwise, just +substitute the value of \fIname\fP. In the first +form, the smallest matching pattern is preferred; +in the second form, the largest matching pattern is preferred. +.PD 0 +.TP +${\fIname\fB%\fIpattern\fR} +.TP +${\fIname\fB%%\fIpattern\fR} +.PD +If the \fIpattern\fP matches the end of the value of +\fIname\fP, then substitute the value of \fIname\fP with +the matched portion deleted; otherwise, just +substitute the value of \fIname\fP. In the first +form, the smallest matching pattern is preferred; +in the second form, the largest matching pattern is preferred. +.TP +${\fB#\fIspec\fR} +If \fIspec\fP is one of the above substitutions, substitute +the length in characters of the result instead of +the result itself. If \fIspec\fP is an array expression, +substitute the number of elements of the result. +.TP +${\fB^\fIspec\fR} +Toggle the value of the \fBRC_EXPAND_PARAM\fP option for the +evaluation of \fIspec\fP. +When this option is set, array expansions of the form +\fIfoo\fB${\fIxx\fB}\fIbar\fR, where the parameter +\fIxx\fP is set to (\fIa b c\fP), are substituted with +\fIfooabar foobbar foocbar\fP instead of the default +\fIfooa b cbar\fP. +.TP +${\fB=\fIspec\fR} +Toggle the value of the \fBSH_WORD_SPLIT\fP option for the +evaluation of \fIspec\fP. +When this option is set, parameter values are split into +separate words using \fBIFS\fP as a delimiter +before substitution. +This is done by default in most other shells. +.PD +.RE +.PP +If the colon is omitted from one of the above expressions +containing a colon, then the shell only checks whether +\fIname\fP is set or not, not whether it is null. +.SS Command Substitution +A command enclosed in parentheses +preceded by a dollar sign, like so: $(...) or quoted with grave +accents: `...` is replaced with its standard output. +If the substitution is not enclosed in double quotes, the +output is broken into words using the \fBIFS\fP parameter. +The substitution \fB$(cat foo)\fP may be replaced +by the equivalent but faster \fB$(\fP +matches any number in the range x to y, inclusive. +If x is omitted, the number must be less than or equal to y. +If y is omitted, the number must be greater than or equal to x. +A pattern of the form \fB<\->\fP or +simply \fB<>\fP matches any number. +.TP +\fB^x\fP +matches anything except the pattern x. +.TP +\fBx|y\fP +matches either x or y. +.TP +\fBx#\fP +matches zero or more occurrences of the pattern x. +.TP +\fBx##\fP +matches one or more occurrences of the pattern x. +.RE +.PD +.PP +Parentheses may be used for grouping. Note that the \fB|\fP character +must be within parentheses, so that the lexical analyzer does +not think it is a pipe character. Also note that "/" has a +higher precedence than "^"; that is: +.RS +.PP +ls +.BI ^ foo / bar +.RE +.PP +will search directories in "." except "./foo" for a file named bar. +.PP +A pathname component of the form +.BI ( foo /)# +matches a path consisting of zero or more directories +matching the pattern foo. +As a shorthand, +.B **/ +is equivalent to +.BR (*/)# . +Thus: +.RS +.PP +ls +.BI (*/)# bar +.RE +.PP +or +.RS +.PP +ls +.BI **/ bar +.RE +.PP +does a recursive directory search for files named bar. +.PP +If used for filename generation, a pattern may contain an exclusion +specifier. Such patterns are of the form \fIpat1\fB~\fIpat2\fR. +This pattern will generate all files matching \fIpat1\fP, but which +do not match \fIpat2\fP. For example, \fB*.c~lex.c\fP will match +all files ending in .c, except the file \fBlex.c\fP. +.PP +Patterns used for filename generation may also end in a +list of qualifiers enclosed in parentheses. +The qualifiers +specify which filenames that otherwise match the given pattern +will be inserted in the argument list. +A qualifier may be any one of the following: +.PD 0 +.RS +.TP +.B / +directories +.TP +.B . +plain files +.TP +.B @ +symbolic links +.TP +.B = +sockets +.TP +.B p +named pipes (FIFOs) +.TP +.B * +executable plain files (0100) +.TP +.B % +device files (character or block special) +.TP +.B r +readable files (0400) +.TP +.B w +writable files (0200) +.TP +.B x +executable files (0100) +.TP +.B R +world-readable files (0004) +.TP +.B W +world-writable files (0002) +.TP +.B X +world-executable files (0001) +.TP +.B s +setuid files (04000) +.TP +.B S +setgid files (02000) +.TP +\fBd\fIdev\fR +files on the device \fIdev\fP +.TP +\fBl\fIct\fR +files having a link count of \fIct\fP +.TP +\fBU\fP +files owned by the effective user id +.TP +\fBG\fP +files owned by the effective group id +.TP +\fBu\fInum\fR +files owned by user id \fInum\fP +.TP +\fBg\fInum\fR +files owned by group id \fInum\fP +.TP +\fB^\fP +negates all qualifiers following it +.TP +\fBM\fP +sets the \fBMARKDIRS\fP option for the current pattern +.TP +\fBN\fP +sets the \fBNULLGLOB\fP option for the current pattern +.TP +\fBD\fP +sets the \fBGLOBDOTS\fP option for the current pattern +.PD +.RE +.PP +Thus: +.RS +.PP +ls +.B +*(%W) +.RE +.PP +lists all world-writable device files in the current directory, +and +.RS +.PP +ls +.B /tmp/foo*(u0^@) +.RE +.PP +lists all root-owned files beginning with the string +"foo" in /tmp, ignoring symlinks, and +.RS +.PP +ls +.B *.*~(lex|parse).[ch](^D^l1) +.RE +.PP +lists all files having a link count of one whose names contain a dot +(but not those starting with a dot, since \fBGLOBDOTS\fP is explicitly +switched off) except for lex.c, lex.h, parse.c, and parse.h. +A "/" at the end of a pattern +is equivalent to "(\|/\|)". +.SH REDIRECTION +Before a command is executed, its input and output +may be redirected. +The following may appear anywhere in a simple-command +or may precede or follow a complex command. +Substitution occurs before +.I word +is used except as noted below. +If the result of substitution on +.I word +produces more than one filename, +redirection occurs for each +separate filename in turn. +.TP +.BI < word +Open file +.I word +as standard input. +.TP +.BI > word +Open file +.I word +as standard output. +If the file does not exist then it is created. +If the file exists, and the +.B NOCLOBBER +option is set, +this causes an error; +otherwise, it is truncated to zero length. +.TP +.BI >! " word" +Same as +.BR > , +except that the file is truncated to zero length +if it exists, even if +.B NOCLOBBER +is set. +.TP +.BI >> word +Open file +.I word +as standard output. +If the file exists then output is appended to it. +If the file does not exist, and the +.B NOCLOBBER +option is set, +this causes an error; +otherwise, the file is created. +.TP +.BI >>! " word" +Same as +.BR >> , +except that the file is created if it does not +exist, even if +.B NOCLOBBER +is set. +.TP +\fB<<\fP[\-] \fIword\fP +The shell input is read up to a line that is the same as +.IR word , +or to an end-of-file. +No parameter substitution, command substitution or +filename generation is performed on +.IR word . +The resulting document, +called a +.IR here-document , +becomes +the standard input. +If any character of \fIword\fP is quoted with +single or double quotes (a \e alone is \fInot\fP sufficient), +no interpretation +is placed upon the characters of the document. +Otherwise, parameter and command substitution +occurs, \e followed by a newline is removed, +and \e must be used to quote the characters +\e, $, `, and the first character of \fIword\fP. +If <<\- is used, then all leading +tabs are stripped from \fIword\fP and from the document. +.TP +.BI <<< word +Open a file containing \fIword\fP, after expansion, +as standard input. +.TP +.BI <& digit +The standard input +is duplicated from file descriptor +.I digit +(see +.IR dup (2)). +Similarly for standard output using +\fB>&\fIdigit\fP. +.TP +.BI >& word +Same as +.BI > word +\fB2>&\fP1. +.TP +.BI >>& word +Same as +.BI >> word +\fB2>&\fP1. +.TP +.BI <&\- +Close the standard input. +.TP +.BI >&\- +Close the standard output. +.TP +.BI <&p +The input from the coprocess is moved to the standard input. +.TP +.BI >&p +The output to the coprocess is moved to the standard output. +.PP +If one of the above is preceded by a digit, then the file +descriptor referred to is that specified by the digit +(instead of the default 0 or 1). +The order in which redirections are specified is significant. +the shell evaluates each redirection in terms of the +.RI ( "file descriptor" ", " file ) +association at the time of evaluation. +For example: +.RS +.PP +\&.\|.\|. \|1>\fIfname\^\fP 2>&1 +.RE +.PP +first associates file descriptor 1 with file +.IR fname . +It then associates file descriptor 2 with the file associated with file +descriptor 1 (that is, +.IR fname ). +If the order of redirections were reversed, file descriptor 2 would be associated +with the terminal (assuming file descriptor 1 had been) and then file descriptor +1 would be associated with file +.IR fname . +.PP +If the user tries to open a file descriptor for writing more than once, +the shell opens the file descriptor as a pipe to a process that copies +its input to all the specified outputs, similar to tee(1). Thus: +.RS +.PP +.B date >foo >bar +.RE +.PP +writes the date to two files, named "foo" and "bar". +Note that a pipe is an implicit indirection; thus +.RS +.PP +.B date >foo | cat +.RE +.PP +writes the date to the file "foo", and also pipes it to cat. +.PP +If the user tries to open a file descriptor for reading more than once, +the shell opens the file descriptor as a pipe to a process that copies +all the specified inputs to its output in the order +specified, similar to cat(1). Thus +.RS +.PP +.B sort > +logical shift left, shift right +.TP +.B < > <= >= +comparison +.TP +.B == != +equality and inequality +.TP +.B && +boolean AND +.TP +.B |\|| ^^ +boolean OR, XOR +.TP +.B ? : +ternary operator +.TP +.B += += \-= *= /= %= &= ^= |= <<= >>= &&= |\||= ^^= +assignment +.TP +.B , +comma operator +.PD +.RE +.PP +The operators &&, |\||, &&=, and |\||= are short-circuiting, +and only one of the latter two expressions in a ternary operator +is evaluated. Note the precedence of the logical AND, OR, +and XOR operators. +.PP +Named parameters can be referenced by name within an arithmetic expression +without using the parameter substitution syntax. +.PP +An internal integer representation of a named parameter +can be specified with the +.B integer +builtin. +Arithmetic evaluation is performed on the value of each +assignment to a named parameter declared integer +in this manner. +.PP +Since many of the arithmetic operators require +quoting, an alternative form of the +.B let +command is provided. +For any command which begins with a +.BR (( , +all the characters until a matching +.B )) +are treated as a quoted expression. +More precisely, +.BR (( ... )) +is equivalent to +.B let +\fB"\fP...\fB"\fP. +.SH "CONDITIONAL EXPRESSIONS" +A \fIconditional expression\fP is used with the +.B [[ +compound command to test attributes of files and to compare strings. +Each expression can be constructed from one or more +of the following unary or binary expressions: +.PD 0 +.TP +\fB\-a\fP \fIfile\fP +true if +.I file +exists. +.TP +\fB\-b\fP \fIfile\fP +true if +.I file +exists and is a block special file. +.TP +\fB\-c\fP \fIfile\fP +true if +.I file +exists and is a character special file. +.TP +\fB\-d\fP \fIfile\fP +true if +.I file +exists and is a directory. +.TP +\fB\-e\fP \fIfile\fP +true if +.I file +exists. +.TP +\fB\-f\fP \fIfile\fP +true if +.I file +exists and is an ordinary file. +.TP +\fB\-g\fP \fIfile\fP +true if +.I file +exists and is has its setgid bit set. +.TP +\fB\-h\fP \fIfile\fP +true if +.I file +exists and is a symbolic link. +.TP +\fB\-k\fP \fIfile\fP +true if +.I file +exists and is has its sticky bit set. +.TP +\fB\-n\fP \fIstring\fP +true if length of +.I string +is non-zero. +.TP +\fB\-o\fP \fIoption\fP +true if option named +.I option +is on. +.TP +\fB\-p\fP \fIfile\fP +true if +.I file +exists and is a fifo special file or a pipe. +.TP +\fB\-r\fP \fIfile\fP +true if +.I file +exists and is readable by current process. +.TP +\fB\-s\fP \fIfile\fP +true if +.I file +exists and has size greater than zero. +.TP +\fB\-t\fP \fIfd\fP +true if file descriptor number +.I fd +is open and associated with a terminal device. +(note: \fIfd\fP is not optional) +.TP +\fB\-u\fP \fIfile\fP +true if +.I file +exists and is has its setuid bit set. +.TP +\fB\-w\fP \fIfile\fP +true if +.I file +exists and is writable by current process. +.TP +\fB\-x\fP \fIfile\fP +true if +.I file +exists and is executable by current process. +If +.I file +exists and is a directory, then the current process +has permission to search in the directory. +.TP +\fB\-z\fP \fIstring\fP +true if length of +.I string +is zero. +.TP +\fB\-L\fP \fIfile\fP +true if +.I file +exists and is a symbolic link. +.TP +\fB\-O\fP \fIfile\fP +true if +.I file +exists and is owned by the effective user id of this process. +.TP +\fB\-G\fP \fIfile\fP +true if +.I file +exists and its group matches the effective group id of this process. +.TP +\fB\-S\fP \fIfile\fP +true if +.I file +exists and is a socket. +.TP +\fIfile1\fP \fB\-nt\fP \fIfile2\fP +true if +.I file1 +exists and is newer than +.IR file2 . +.TP +\fIfile1\fP \fB\-ot\fP \fIfile2\fP +true if +.I file1 +exists and is older than +.IR file2 . +.TP +\fIfile1\fP \fB\-ef\fP \fIfile2\fP +true if +.I file1 +and +.I file2 +exist and refer to the same file. +.TP +\fIstring\fP \fB=\fP \fIpattern\fP +true if +.I string +matches +.IR pattern . +.TP +\fIstring\fP \fB!=\fP \fIpattern\fP +true if +.I string +does not match +.IR pattern . +.TP +\fIstring1\fP \fB<\fP \fIstring2\fP +true if +.I string1 +comes before +.I string2 +based on ASCII value of their characters. +.TP +\fIstring1\fP \fB>\fP \fIstring2\fP +true if +.I string1 +comes after +.I string2 +based on ASCII value of their characters. +.TP +\fIexp1\fP \fB\-eq\fP \fIexp2\fP +true if +.I exp1 +is equal to +.IR exp2. +.TP +\fIexp1\fP \fB\-ne\fP \fIexp2\fP +true if +.I exp1 +is not equal to +.IR exp2. +.TP +\fIexp1\fP \fB\-lt\fP \fIexp2\fP +true if +.I exp1 +is less than +.IR exp2. +.TP +\fIexp1\fP \fB\-gt\fP \fIexp2\fP +true if +.I exp1 +is greater than +.IR exp2. +.TP +\fIexp1\fP \fB\-le\fP \fIexp2\fP +true if +.I exp1 +is less than or equal to +.IR exp2. +.TP +\fIexp1\fP \fB\-ge\fP \fIexp2\fP +true if +.I exp1 +is greater than or equal to +.IR exp2. +.TP +\fB(\fP \fIexp\fP \fB)\fP +true if \fIexp\fP is true. +.TP +\fB!\fP \fIexp\fP +true if \fIexp\fP is false. +.TP +\fIexp1\fP \fB&&\fP \fIexp2\fP +true if \fIexp1\fP and \fIexp2\fP are both true. +.TP +\fIexp1\fP \fB|\||\fP \fIexp2\fP +true if either \fIexp1\fP or \fIexp2\fP is true. +.PD +.PP +In each of the above expressions, if +.I file +is of the form +\fB/dev/fd/\fP\fIn\fR, +where +.I n +is an integer, +then the test applied to the open file whose +descriptor number is +.IR n , +even if the underlying system does not support +the \fB/dev/fd\fP directory. +.PD +.SH "ZSH LINE EDITOR" +If the \fBZLE\fP option is set (it is by default) +and the shell input is attached to the terminal, the user +is allowed to edit command lines. +.PP +There are two display modes. The first, multiline mode, is the default. +It only works if the \fBTERM\fP parameter is set to a valid +terminal type that can move the cursor up. The second, +single line mode, is used if \fBTERM\fP is invalid or incapable +of moving the cursor up, or if the \fBSINGLE_LINE_ZLE\fP +option is set. This mode is similar to ksh, and uses no +termcap sequences. +.SS Bindings +Command bindings may be set using the \fBbindkey\fP builtin. +There are two keymaps\-the main keymap and the alternate keymap. +The alternate keymap is bound to vi command mode. +The main keymap is bound to emacs mode by default. +To bind the main keymap to vi insert mode, use +\fBbindkey \-v\fP, or set one of the \fBVISUAL\fP or \fBEDITOR\fP +environment variables to a string containing \fBvi\fP. +.PP +The following is a list of all the key commands +and their default bindings in emacs and vi command mode. +.SS Movement +.TP +\fBvi-backward-blank-word\fP (unbound) (B) +Move backward one word, where a word is defined as a series of +non-blank characters. +.TP +\fBbackward-char\fP (^B ESC-[D) (\|) +Move backward one character. +.TP +\fBvi-backward-char\fP (\|) (h) +Move backward one character, without changing lines. +.TP +\fBbackward-word\fP (ESC-B ESC-b) (unbound) +Move to the beginning of the previous word. +.TP +\fBemacs-backward-word\fP +Move to the beginning of the previous word. +.TP +\fBvi-backward-word\fP (unbound) (b) +Move to the beginning of the previous word, vi-style. +.TP +\fBbeginning-of-line\fP (^A) (0) +Move to the beginning of the line. If already at the beginning +of the line, move to the beginning of the previous line, if any. +.TP +\fBvi-beginning-of-line\fP +Move to the beginning of the line, without changing lines. +.TP +\fBend-of-line\fP (^E) +Move to the end of the line. If already at the end +of the line, move to the end of the next line, if any. +.TP +\fBvi-end-of-line\fP (unbound) ($) +Move to the end of the line. +.TP +\fBvi-forward-blank-word\fP (unbound) (W) +Move forward one word, where a word is defined as a series of +non-blank characters. +.TP +\fBvi-forward-blank-word-end\fP (unbound) (E) +Move to the end of the current word, +or, if at the end of the current word, +to the end of the next word, +where a word is defined as a series of +non-blank characters. +.TP +\fBforward-char\fP (^F ESC-[C) +Move forward one character. +.TP +\fBvi-forward-char\fP (unbound) (space l) +Move forward one character. +.TP +\fBvi-find-next-char\fP (^X^F) (f) +Read a character from the keyboard, and move to +the next occurrence of it in the line. +.TP +\fBvi-find-next-char-skip\fP (unbound) (t) +Read a character from the keyboard, and move to +the position just before the next occurrence of it in the line. +.TP +\fBvi-find-prev-char\fP (unbound) (F) +Read a character from the keyboard, and move to +the previous occurrence of it in the line. +.TP +\fBvi-find-prev-char-skip\fP (unbound) (T) +Read a character from the keyboard, and move to +the position just after the previous occurrence of it in the line. +.TP +\fBvi-first-non-blank\fP (unbound) (^) +Move to the first non-blank character in the line. +.TP +\fBvi-forward-word\fP (unbound) (w) +Move forward one word, vi-style. +.TP +\fBforward-word\fP (ESC-F ESC-f) (unbound) +Move to the beginning of the next word. +The editor's idea of a word is specified with the \fBWORDCHARS\fP +parameter. +.TP +\fBemacs-forward-word\fP +Move to the end of the next word. +.TP +\fBvi-forward-word-end\fP (unbound) (e) +Move to the end of the next word. +.TP +\fBvi-goto-column\fP (ESC-|) (|) +Move to the column specified by the numeric argument. +.TP +\fBvi-goto-mark\fP (unbound) (`) +Move to the specified mark. +.TP +\fBvi-goto-mark-line\fP (unbound) (') +Move to beginning of the line containing the specified mark. +.TP +\fBvi-repeat-find\fP (unbound) (;) +Repeat the last \fBvi-find\fP command. +.TP +\fBvi-rev-repeat-find\fP (unbound) (,) +Repeat the last \fBvi-find\fP command in the opposite direction. +.SS History +.TP +\fBbeginning-of-buffer-or-history\fP (ESC-<) +Move to the beginning of the buffer, or if already there, +move to the first event in the history list. +.TP +\fBbeginning-of-line-hist\fP +Move to the beginning of the line. If already at the +beginning of the buffer, move to the previous history line. +.TP +\fBbeginning-of-history\fP +Move to the first event in the history list. +.TP +\fBdown-line-or-history\fP (^N ESC-[B) (+ j) +Move down a line in the buffer, or if already at the bottom line, +move to the next event in the history list. +.TP +\fBdown-history\fP (unbound) (^N) +Move to the next event in the history list. +.TP +\fBend-of-buffer-or-history\fP (ESC->) +Move to the end of the buffer, or if already there, +move to the last event in the history list. +.TP +\fBend-of-line-hist\fP +Move to the end of the line. If already at the end of +the buffer, move to the next history line. +.TP +\fBend-of-history\fP +Move to the last event in the history list. +.TP +\fBvi-fetch-history\fP (unbound) (G) +Fetch the history line specified by the numeric argument. +.TP +\fBhistory-incremental-search-backward\fP (^R ^Xr) +Search backward incrementally for a specified string. +The string may begin with `^' to anchor the search to the +beginning of the line. +.TP +\fBhistory-incremental-search-forward\fP (^Xs) +Search forward incrementally for a specified string. +The string may begin with `^' to anchor the search to the +beginning of the line. +.TP +\fBhistory-search-backward\fP (ESC-P ESC-p) (K) +Search backward in the history for a line beginning with the first +word in the buffer. +.TP +\fBvi-history-search-backward\fP (unbound) (/) +Search backward in the history for a specified string. +The string may begin with `^' to anchor the search to the +beginning of the line. +.TP +\fBhistory-search-forward\fP (ESC-N ESC-n) (J) +Search forward in the history for a line beginning with the first +word in the buffer. +.TP +\fBvi-history-search-forward\fP (unbound) (?) +Search forward in the history for a specified string. +The string may begin with `^' to anchor the search to the +beginning of the line. +.TP +\fBinfer-next-history\fP (^X^N) +Search in the history list for a line matching the current one and +fetch the event following it. +.TP +\fBinsert-last-word\fP (ESC-_ ESC-.) +Insert the last word from the previous history event at the +cursor position. +.TP +\fBvi-repeat-search\fP (unbound) (n) +Repeat the last vi history search. +.TP +\fBvi-rev-repeat-search\fP (unbound) (N) +Repeat the last vi history search, but in reverse. +.TP +\fBtoggle-literal-history\fP (ESC-R ESC-r) +Toggle between literal and lexical history. The default is +lexical history unless the \fBHISTLIT\fP option is set. +.TP +\fBup-line-or-history\fP (^P ESC-[A) (- k) +Move up a line in the buffer, or if already at the top line, +move to the previous event in the history list. +.TP +\fBup-history\fP (unbound) (^P) +Move to the previous event in the history list. +.SS Modifying Text +.TP +\fBvi-add-eol\fP (unbound) (A) +Move to the end of the line and enter insert mode. +.TP +\fBvi-add-next\fP (unbound) (a) +Move forward one character and enter insert mode. +.TP +\fBbackward-delete-char\fP (^H ^?) (^?) +Delete the character behind the cursor. +.TP +\fBvi-backward-delete-char\fP (unbound) (X) +Delete the character behind the cursor, without changing lines. +.TP +\fBbackward-delete-word\fP +Delete the word behind the cursor. +.TP +\fBbackward-kill-line\fP +Kill from the beginning of the line to the cursor position. +.TP +\fBbackward-kill-word\fP (^W ESC-^H ESC-^?) +Kill the word behind the cursor. +.TP +\fBvi-backward-kill-word\fP (unbound) (^W) +Kill the word behind the cursor. +.TP +\fBcapitalize-word\fP (ESC-C ESC-c) +Capitalize the current word and move past it. +.TP +\fBvi-change\fP (unbound) (c) +Read a movement command from the keyboard, and kill +from the cursor position to the endpoint of the movement. +Then enter insert mode. +If the command is \fBvi-change\fP, kill the current line. +.TP +\fBvi-change-eol\fP (unbound) (C) +Kill to the end of the line and enter insert mode. +.TP +\fBvi-change-whole-line\fP (unbound) (S s) +Kill the current line and enter insert mode. +.TP +\fBcopy-region-as-kill\fP (ESC-W ESC-w) +Copy the area from the cursor to the mark to the kill buffer. +.TP +\fBcopy-prev-word\fP (ESC-^_) +Duplicate the word behind the cursor. +.TP +\fBvi-delete\fP (unbound) (d) +Read a movement command from the keyboard, and kill +from the cursor position to the endpoint of the movement. +If the command is \fBvi-delete\fP, kill the current line. +.TP +\fBdelete-char\fP (unbound) (x) +Delete the character under the cursor. +.TP +\fBvi-delete-char\fP (unbound) (x) +Delete the character under the cursor. +.TP +\fBdelete-word\fP (ESC-D ESC-d) +Delete the current word. +.TP +\fBdown-case-word\fP (ESC-L ESC-l) +Convert the current word to all lowercase and move past it. +.TP +\fBkill-word\fP +Kill the current word. +.TP +\fBgosmacs-transpose-chars\fP +Exchange the two characters behind the cursor. +.TP +\fBvi-indent\fP (unbound) (>) +Indent a number of lines. +.TP +\fBvi-insert\fP (unbound) (i) +Enter insert mode. +.TP +\fBvi-insert-bol\fP (unbound) (I) +Move to the beginning of the line and enter insert mode.\fP +.TP +\fBvi-join\fP (^X^J) +Join the current line with the next one. +.TP +\fBkill-line\fP (^K) (D) +Kill from the cursor to the end of the line. +.TP +\fBkill-region\fP +Kill from the cursor to the mark. +.TP +\fBkill-buffer\fP (^X^U) (^U) +Kill the entire buffer. +.TP +\fBkill-whole-line\fP (^U) (unbound) +Kill the current line. +.TP +\fBvi-match-bracket\fP (^X^B) (%) +Move to the bracket character (one of {\|}, (\|), or [\|]) that +matches the one under the cursor. +.TP +\fBvi-open-line-above\fP (unbound) (O) +Open a line above the cursor and enter insert mode. +.TP +\fBvi-open-line-below\fP (unbound) (o) +Open a line below the cursor and enter insert mode. +.TP +\fBvi-oper-swap-case\fP +Read a movement command from the keyboard, and swap +the case of all characters +from the cursor position to the endpoint of the movement. +If the movement command is \fBvi-oper-swap-case\fP, +swap the case of all characters on the current line. +.TP +\fBoverwrite-mode\fP (^X^O) +Toggle between overwrite mode and insert mode. +.TP +\fBvi-put-after\fP (unbound) (p) +Insert the contents of the kill buffer after the cursor. +.TP +\fBquoted-insert\fP (^V) +Insert the next character typed into the buffer literally. +.TP +\fBquote-line\fP (ESC-') +Quote the current line; that is, put a ' character at the +beginning and the end, and convert all ' characters +to '\e''. +.TP +\fBquote-region\fP (ESC-") +Quote the region from the cursor to the mark. +.TP +\fBvi-replace\fP (unbound) (R) +Enter overwrite mode. +.TP +\fBvi-repeat-change\fP (unbound) (.) +Repeat the last vi mode text modification. +.TP +\fBvi-replace-chars\fP (unbound) (r) +Replace the character under the cursor with a character +read from the keyboard. +.TP +\fBself-insert\fP (printable characters) +Put a character in the buffer at the cursor position. +.TP +\fBself-insert-unmeta\fP (ESC-^I ESC-^J ESC-^M) +Put a character in the buffer after stripping the meta bit +and converting \fB^M\fP to \fB^J\fP. +.TP +\fBvi-substitute\fP (unbound) (s) +Substitute the next character(s). +.TP +\fBvi-swap-case\fP (unbound) (~) +Swap the case of the character under the cursor and move past it. +.TP +\fBtranspose-chars\fP (^T) +Exchange the two characters to the left of the +cursor if at end of line, else exchange the +character under the cursor with the character +to the left. +.TP +\fBtranspose-words\fP (ESC-T ESC-t) +Exchange the current word with the one before it. +.TP +\fBvi-unindent\fP (unbound) (<) +Unindent a number of lines. +.TP +\fBup-case-word\fP (ESC-U ESC-u) +Convert the current word to all caps and move past it. +.TP +\fByank\fP (^Y) (P) +Insert the contents of the kill buffer at the cursor position. +.TP +\fByank-pop\fP (ESC-y) (unbound) +Remove the text just yanked, rotate the kill\-ring, +and yank the new top. Only works following +\fByank\fP or \fByank-pop\fP. +.TP +\fBvi-yank\fP (unbound) (y) +Read a movement command from the keyboard, and copy the region +from the cursor position to the endpoint of the movement +into the kill buffer. +If the command is \fBvi-yank\fP, copy the current line. +.TP +\fBvi-yank-eol\fP (unbound) (Y) +Copy the region from the cursor position to the end of the line +into the kill buffer. +.SS Arguments +.TP +\fBdigit-argument\fP (ESC-0..ESC-9) (0-9) +Start a new numeric argument, or add to the current one. +.TP +\fBuniversal-argument\fP +Multiply the argument of the next command by 4. +.SS Completion +.TP +\fBaccept-and-menu-complete\fP +In a menu completion, insert the current completion into the buffer, +and advance to the next possible completion. +.TP +\fBcomplete-word\fP (unbound) (\|\e\|) +Attempt completion on the current word. +.TP +\fBdelete-char-or-list\fP (^D) +Delete the character under the cursor. If the cursor +is at the end of the line, list possible completions for the +current word. +.TP +\fBexecute-named-cmd\fP (ESC-x) +Read the name of a editor command and execute it. +.TP +\fBexecute-last-named-cmd\fP (ESC-z) +Redo the last function executed with \fBexecute-named-cmd\fP. +.TP +\fBexpand-cmd-path\fP +Expand the current command to its full pathname. +.TP +\fBexpand-or-complete\fP (TAB) (TAB ^X) +Attempt shell expansion on the current word. +If that fails, +attempt completion. +.TP +\fBexpand-history\fP (ESC-space ESC-!) +Perform history expansion on the edit buffer. +.TP +\fBexpand-word\fP (^X*) +Attempt shell expansion on the current word. +.TP +\fBlist-choices\fP (ESC-^D) (^D =) +List possible completions for the current word. +.TP +\fBlist-expand\fP (^Xg ^XG) (^G) +List the expansion of the current word. +.TP +\fBmagic-space\fP +Perform history expansion and insert a space into the +buffer. This is intended to be bound to space. +.TP +\fBmenu-complete\fP +Like \fBcomplete-word\fP, except that menu completion is used. +See the \fBMENU_COMPLETE\fP option below. +.TP +\fBmenu-expand-or-complete\fP +Like \fBexpand-or-complete\fP, except that menu completion is used. +.TP +\fBreverse-menu-complete\fP +See the \fBMENU_COMPLETE\fP option below. +.SS Miscellaneous +.TP +\fBaccept-and-hold\fP (ESC-A ESC-a) +Push the contents of the buffer on the buffer stack +and execute it. +.TP +\fBaccept-and-infer-next-history\fP +Execute the contents of the buffer. +Then search the history list for a line matching the current one +and push the event following onto the buffer stack. +.TP +\fBaccept-line\fP (^J ^M) +Execute the contents of the buffer. +.TP +\fBaccept-line-and-down-history\fP (^O) +Execute the current line, and push the next history +event on the the buffer stack. +.TP +\fBvi-cmd-mode\fP (^X^V) (^[) +Enter command mode; that is, use the alternate keymap. +Yes, this is bound by default in emacs mode. +.TP +\fBvi-caps-lock-panic\fP (unbound) (H K) +Hang until any lowercase key is pressed. +This is for vi users without the mental capacity to keep +track of their caps lock key (like the author). +.TP +\fBclear-screen\fP (^L ESC-^L) +Clear the screen and redraw the prompt. +.TP +\fBexchange-point-and-mark\fP (^X^X) +Exchange the cursor position with the position of the mark. +.TP +\fBget-line\fP (ESC-G ESC-g) +Pop the top line off the buffer stack and insert it at the +cursor position. +.TP +\fBpound-insert\fP (unbound) (#) +If there is no # character at the beginning of the current line, +add one. If there is one, remove it. In either case, accept the +current line. The \fBINTERACTIVE_COMMENTS\fP option must be set +for this to have any usefulness. +.TP +\fBpush-line\fP (^Q ESC-Q ESC-q) +Push the current buffer onto the buffer stack and clear +the buffer. +Next time the editor starts up, the buffer will be popped +off the top of the buffer stack and loaded into the editing +buffer. +.TP +\fBredisplay\fP (unbound) (^R) +Redisplays the edit buffer. +.TP +\fBrun-help\fP (ESC-H ESC-h) +Push the buffer onto the buffer stack, and execute the +command "\fBrun-help\fP \fIcmd\fP", where \fIcmd\fP is the current +command. \fBrun-help\fP is normally aliased to \fBman\fP. +.TP +\fBsend-break\fP (^C) +Abort the parsing of the current line. +.TP +\fBvi-set-buffer\fP (unbound) (") +Specify a buffer to be used in the following command. +.TP +\fBvi-set-mark\fP (unbound) (m) +Set the specified mark at the cursor position. +.TP +\fBset-mark-command\fP (^@) +Set the mark at the cursor position. +.TP +\fBspell-word\fP (ESC-$ ESC-S ESC-s) +Attempt spelling correction on the current word. +.TP +\fBundefined-key\fP +Beep. +.TP +\fBundo\fP (^_ ^X^U) (u) +Incrementally undo the last text modification. +.TP +\fBwhich-command\fP (ESC-?) +Push the buffer onto the buffer stack, and execute the +command "\fBwhich-command\fP \fIcmd\fP", where \fIcmd\fP is the current +command. \fBwhich-command\fP is normally aliased to \fBwhence\fP. +.SH PARAMETERS +A parameter has a name, a value, and a number of attributes. +A name may be any sequence of alphanumeric +characters and _'s, or the single characters +*, @, #, ?, \-, $, or !. +The value may be either a \fIscalar\fP (a string), +an integer, or an array. +To assign a scalar or integer value to a parameter, +use the \fBtypeset\fP builtin. +To assign an array value, use \fBset \-A\fP \fIname\fP \fIvalue\fP .... +The value of a parameter may also be assigned by writing: +.RS +.PP +\fIname\fP=\fIvalue\fP ... +.RE +.PP +If the integer attribute, \-\fBi\fP, is set for \fIname\fP, +the \fIvalue\fP is subject to arithmetic evaluation. +.PP +The value of an array parameter may be assigned by writing: +.RS +.PP +\fIname\fP=(\fIvalue\fP ...) ... +.RE +Individual elements of an array may be selected using a +subscript. A subscript of the form \fB[\fIexp\fB]\fR +selects the single element \fIexp\fP, where \fIexp\fP is +an arithmetic expression. The elements are numbered +beginning with 1. +A subscript of the form \fB[*]\fP or \fB[@]\fP evaluates to all +elements of an array; there is no difference between the two +except when they appear within double quotes. +"$foo[*]" evaluates to "$foo[1] $foo[2] ...", while +"$foo[@]" evaluates to "$foo[1]" "$foo[2]", etc. +A subscript of the form \fB[\fIexp1\fP,\fIexp2\fB]\fR +selects all elements in the range \fIexp1\fP to \fIexp2\fP, +inclusive. +If one of the subscripts evaluates to a negative number, +say \-\fIn\fP, then the \fIn\fPth element from the end +of the array is used. Thus "$foo[-3]" is the third element +from the end of the array \fIfoo\fP, and +"$foo[1,-1]" is the same as "$foo[*]". +.PP +Subscripting may also be performed on non-array values, in which +case the subscripts specify a substring to be extracted. +For example, if \fBFOO\fP is set to \fBfoobar\fP, then +\fBecho $FOO[2,5]\fP prints \fBooba\fP. +.SS Positional Parameters +Positional parameters are set by the shell on invocation, +by the \fBset\fP builtin, or by direct assignment. +The parameter \fIn\fP, where \fIn\fP is a number, +is the \fIn\fPth positional parameter. +The parameters \fB*\fP, \fB@\fP, and \fBargv\fP are +arrays containing all the positional parameters; +thus \fBargv\fP[\fIn\fP], etc. is equivalent to simply \fIn\fP. +.SS Special Parameters +The following parameters are automatically set by the shell: +.PP +.RS +.PD 0 +.TP +.B ! +The process id of the last background command invoked. +.TP +.B # +The number of positional parameters in decimal. +.TP +.B ARGC +Same as \fB#\fP. +.TP +.B $ +The process id of this shell. +.TP +.B \- +Flags supplied to the shell on invocation or by the \fBset\fP +or \fBsetopt\fP commands. +.TP +.B * +An array containing the positional parameters. +.TP +.B argv +Same as \fB*\fP. +.TP +.B @ +Same as \fBargv[@]\fP. +.TP +.B ? +The exit value returned by the last command. +.TP +.B status +Same as \fB?\fP. +.TP +.B _ +The last argument of the previous command. +Also, this parameter is set in the environment of every command +executed to the full pathname of the command. +.TP +.B ERRNO +The value of errno as set by the most recently failed system call. +This value is system dependent and is intended for debugging +purposes. +.TP +.B GID +The group id of the shell process. +.TP +.B HOST +The current hostname. +.TP +.B HOSTTYPE +A string corresponding to the type of the host the shell +is running on. +.TP +.B LINENO +The line number of the current line within the current script +being executed. +.TP +.B OLDPWD +The previous working directory. +.TP +.B OPTARG +The value of the last option argument processed by the \fBgetopts\fP +command. +.TP +.B OPTIND +The index of the last option argument processed by the \fBgetopts\fP +command. +.TP +.B PPID +The process id of the parent of the shell. +.TP +.B PWD +The present working directory. +.TP +.B RANDOM +A random integer from 0 to 32767, newly generated each time +this parameter is referenced. The random number generator +can be seeded by assigning a numeric value to \fBRANDOM\fP. +.TP +.B SECONDS +The number of seconds since shell invocation. If this parameter +is assigned a value, then the value returned upon reference +will be the value that was assigned plus the number of seconds +since the assignment. +.TP +.B SHLVL +Incremented by one each time a new shell is started. +.TP +.B signals +An array containing the names of the signals. +.TP +.B TTY +The name of the tty associated with the shell, if any. +.TP +.B UID +The user id of the shell process. +.TP +.B USERNAME +.TP +.B LOGNAME +The username corresponding to the user id of the shell process. +.TP +.B VERSION +The version number of this \fBzsh\fP. +.PD +.RE +.PP +The following parameters are used by the shell: +.PP +.RS +.PD 0 +.TP +.B BAUD +The baud rate of the current connection. Used by the line editor +update mechanism to compensate for a slow terminal by delaying +updates until necessary. This may be profitably set to a lower value +in some circumstances, e.g. +for slow modems dialing into a communications server which is connected +to a host via a fast link; in this case, this variable +would be set by default to the speed of the fast link, and not +the modem. +This parameter should be set to the baud +rate of the slowest part of the link for best performance. +.TP +.B bindcmds +An write-only array +of command names which take line editor function names +as arguments, and which therefore should allow binding +completion. +.TP +.B cdpath (CDPATH) +An array (colon-separated list) +of directories specifying the search path for the \fBcd\fP command. +.TP +.B COLUMNS +The number of columns for this terminal session. +Used for printing select lists and for the line editor. +.TP +.B DIRSTACKSIZE +The maximum size of the directory stack. If the +stack gets larger than this, it will be truncated automatically. +This is useful with the \fBAUTO_PUSHD\fP option. +.TP +.B FCEDIT +The default editor for the \fBfc\fP builtin. +.TP +.B fignore (FIGNORE) +An array (colon separated list) +containing the suffixes of files to be ignored +during filename completion. +.TP +.B fpath (FPATH) +An array (colon separated list) +of directories specifying the search path for +function definitions. This path is searched when a function +with the \-\fBu\fP attribute is referenced. If an executable +file is found, then it is read and executed in the current environment. +.TP +.B HISTCHARS +Three characters used by the shell's history and lexical analysis +mechanism. The first character signals the start of a history +substitution (default `!'). The second character signals the +start of a quick history substitution (default `^'). The third +character is the comment character (default `#'). +.TP +.B HISTFILE +The file to save the history in when an interactive shell exits. +If unset, the history is not saved. +.TP +.B HISTSIZE +The maximum size of the history list. +.TP +.B HOME +The default argument for the \fBcd\fP command. +.TP +.B hostcmds +An write-only array of command names which +take hostnames as arguments, and which should therefore +allow hostname completion. This sort of completion is also +used in words containing a \fB@\fP character. +.TP +.B hosts (HOSTS) +An array (colon separated list) of hostnames to use +for hostname completion. +.TP +.B IFS +Internal field separators, normally space, tab, and newline, that +are used to separate words which result from +command or parameter substitution and words read by +the \fBread\fP builtin. +.TP +.B LINES +The number of lines for this terminal session. +Used for printing select lists and for the line editor. +.TP +.B LISTMAX +In the line editor, +the number of filenames to list without asking first. +.TP +.B LITHISTSIZE +The maximum size of the literal history list (before history expansion). +.TP +.B LOGCHECK +The interval in seconds between checks for login/logout activity +using the \fBwatch\fP parameter. +.TP +.B MAIL +If this parameter is set and \fBmailpath\fP is not set, +the shell looks for mail in the specified file. +.TP +.B MAILCHECK +The interval in seconds between checks for new mail. +.TP +.B mailpath (MAILPATH) +An array (colon-separated list) +of filenames to check for new mail. Each filename can +be followed by a ? and a message that will be printed. +The sequence $_ in the message will be replaced by the name +of the mail file. +The default message is "You have new mail." +.TP +.B manpath (MANPATH) +An array (colon-separated list) +whose value is not used by the shell. The \fBmanpath\fP +array can be useful, however, since setting it also sets +\fBMANPATH\fP, and vice versa. +.TP +.B NULLCMD +The command name to assume if a redirection is specified +with no command. Defaults to \fBcat\fP. For sh/ksh-like +behavior, change this to \fB:\fP. For csh-like +behavior, unset this parameter; the shell will print an +error message if null commands are entered. +.TP +.B optcmds +An write-only array of +commands which take options as arguments, and which +therefore should allow option completion. +.TP +.B path (PATH) +An array (colon-separated list) +of directories to search for commands. +When this parameter is set, each directory is scanned +and all files found are put in a hash table. +.TP +.B POSTEDIT +This string is output whenever the line editor exits. +It usually contains termcap strings to reset the terminal. +.TP +.B PROMPT +The primary prompt string, printed before a command is read; +the default is "%m%# ". +The following escape sequences are recognized: +.PD +.PP +.PD 0 +.RS +.TP +.B %d +.TP +.B %/ +Present working directory ($PWD). +.TP +.B %~ +$PWD. +If it has a named directory as its prefix, that part is replaced +by a ~ followed by the name of the directory. +If it starts with $HOME, that part is +replaced by a ~. +.TP +.B %c +.TP +.B %. +.TP +.B %C +Trailing component of $PWD. +May be followed by a digit to get more than one component. +Unless \fB%C\fP is used, tilde expansion is performed first. +.TP +.B ! +.TP +.B %h +.TP +.B %! +Current history event number +.TP +.B %M +The full machine hostname. +.TP +.B %m +The hostname up to the first '.'. +May be followed by a digit to specify +how many components of the hostname are desired. +.TP +.B %S (%s) +Start (stop) standout mode. +.TP +.B %U (%u) +Start (stop) underline mode. +.TP +.B %B (%b) +Start (stop) boldface mode. +.TP +.B %t +.TP +.B %@ +Current time of day, in 12-hour, am/pm format. +.TP +.B %T +Current time of day, in 24-hour format. +.TP +.B %* +Current time of day in 24-hour format, with seconds. +.TP +.B %n +\fB$USERNAME\fP. +.TP +.B %w +The date in day\-dd format. +.TP +.B %W +The date in mm/dd/yy format. +.TP +.B %D +The date in yy\-mm\-dd format. +.TP +.B %D{\fIstring\fP} +\fIstring\fP is formatted using the \fBstrftime\fP function. +See \fBstrftime(3)\fP for more details, if your system has it. +.TP +.B %l +The line (tty) the user is logged in on. +.TP +.B %? +The return code of the last command executed just before the prompt. +.TP +.B %# +A '#' if the shell is running as root, a '%' if not. +.TP +\fB%{\fP...\fB%}\fP +Include a string as a literal escape sequence. +The string within the braces should not change the cursor +position. +.RE +.PD +.PP +.PD 0 +.TP +.B PROMPT2 +The secondary prompt, printed when the shell needs more information +to complete a command. +Recognizes the same escape sequences as \fB$PROMPT\fP. +The default is "> ". +.TP +.B PROMPT3 +Selection prompt used within a \fBselect\fP loop. +Recognizes the same escape sequences as \fB$PROMPT\fP. +The default is "?# ". +.TP +.B PROMPT4 +The execution trace prompt. Default is "+ ". +.TP +.B PS1 +.TP +.B PS2 +.TP +.B PS3 +.TP +.B PS4 +Same as \fBPROMPT\fP, \fBPROMPT2\fP, \fBPROMPT3\fP, and \fBPROMPT4\fP, +respectively. +.TP +.B prompt +Same as \fBPROMPT\fP. +.TP +.B READNULLCMD +The command name to assume if a single input redirection +is specified with no command. Defaults to \fBmore\fP. +.TP +.B REPORTTIME +If nonzero, commands whose combined user and system execution times +(measured in seconds) are greater than this value have timing +statistics printed for them. +.TP +.B RPROMPT +.TP +.B RPS1 +This prompt is displayed on the right-hand side of the screen +when the primary prompt is being displayed on the left. +This does not work if the \fBSINGLELINEZLE\fP option is set. +Recognizes the same escape sequences as \fBPROMPT\fP, +except that termcap sequences like \fB%s\fP, etc. will not work. +.TP +.B SAVEHIST +The maximum number of history events to save in the history file. +.TP +.B SPROMPT +The prompt used for spelling correction. The sequence +\fB%R\fP expands to the string which presumably needs spelling +correction, and \fB%r\fP expands to the proposed correction. +All other \fBPROMPT\fP escapes are also allowed. +.TP +.B STTY +If this parameter is set in a command's environment, the shell +runs the \fBstty\fP command with the value of this parameter as arguments +in order to set up the terminal before executing the command. +.TP +.B TIMEFMT +The format of process time reports with the \fBtime\fP keyword. +The default is "%E real %U user %S system %P". +Recognizes the following escape sequences: +.PD +.PP +.PD 0 +.RS +.TP +.B %U +CPU seconds spent in user mode. +.TP +.B %S +CPU seconds spent in kernel mode. +.TP +.B %E +Elapsed time in seconds. +.TP +.B %P +The CPU percentage, computed as (%U+%S)/%E. +.TP +.B %W +Number of times the process was swapped. +.TP +.B %X +The average amount in (shared) text space used in Kbytes. +.TP +.B %D +The average amount in (unshared) data/stack space used in Kbytes. +.TP +.B %K +The total space used (%X+%D) in Kbytes. +.TP +.B %M +The maximum memory the process had in use at any time in Kbytes. +.TP +.B %F +The number of major page faults (page needed to be brought from disk). +.TP +.B %R +The number of minor page faults. +.TP +.B %I +The number of input operations. +.TP +.B %O +The number of output operations. +.TP +.B %r +The number of socket messages received. +.TP +.B %s +The number of socket messages sent. +.TP +.B %k +The number of signals received. +.TP +.B %w +Number of voluntary context switches (waits). +.TP +.B %c +Number of involuntary context switches. +.TP +.B %J +The name of this job. +.RE +.PD +.PP +.PD 0 +.TP +.B TMOUT +If this parameter is nonzero, the shell will terminate if a command is not +entered within the specified number of seconds after issuing +a prompt. +.TP +.B TMPPREFIX +A pathname prefix which the shell will use for all temporary files. +.TP +.B varcmds +An write-only array +of command names which take parameter names +as arguments, and which therefore should allow parameter +completion. +.TP +.B watch (WATCH) +An array (colon-separated list) of login/logout events to report. +If it contains the single word "all", then all login/logout events +are reported. +An entry in this list may consist of a username, +an `@' followed by a remote hostname, +and a `%' followed by a line (tty). +Any or all of these components may be present in an entry; +if a login/logout event matches all of them, +it is reported. +.TP +.B WATCHFMT +The format of login/logout reports if the \fBwatch\fP parameter is set. +Default is "%n has %a %l from %m." +Recognizes the following escape sequences: +.PD +.PP +.PD 0 +.RS +.TP +.B %n +The name of the user that logged in/out. +.TP +.B %a +The observed action, i.e. "logged on" or "logged off". +.TP +.B %l +The line (tty) the user is logged in on. +.TP +.B %M +The full hostname of the remote host. +.TP +.B %m +The hostname up to the first ".". If only the +ip address is available or the utmp field contains +the name of an X-windows display, the whole name is printed. +.TP +.B %S (%s) +Start (stop) standout mode. +.TP +.B %U (%u) +Start (stop) underline mode. +.TP +.B %B (%b) +Start (stop) boldface mode. +.TP +.B %t +.TP +.B %@ +The time, in 12-hour, am/pm format. +.TP +.B %T +The time, in 24-hour format. +.TP +.B %w +The date in day\-dd format. +.TP +.B %W +The date in mm/dd/yy format. +.TP +.B %D +The date in yy\-mm\-dd format. +.RE +.PD +.PP +.PD 0 +.TP +.B WORDCHARS +A list of nonalphanumeric characters considered part of a word +by the line editor. +.TP +.B ZDOTDIR +The directory to search for shell startup files (.zshrc, etc), +if not \fB$HOME\fP. +.PD +.RE +.PP +.SH OPTIONS +The following options may be set upon invocation of the shell, +or with the \fBset\fP or \fBsetopt\fP builtins: +.RS +.PD 0 +.TP +\fBALLEXPORT\fP (\-\fBa\fP) +All parameters subsequently defined are automatically exported. +.TP +\fBAUTO_CD\fP (\-\fBJ\fP) +If a command is not in the hash table, and there exists an +executable directory by that name, perform the \fBcd\fP +command to that directory. +.TP +\fBAUTOLIST\fP (\-\fB9\fP) +Automatically list choices on an ambiguous completion. +.TP +\fBAUTOMENU\fP +Automatically use menu completion if the \fPTAB\fP +key is pressed repeatedly. +.TP +\fBAUTO_PUSHD\fP (\-\fBN\fP) +Make \fBcd\fP act like \fBpushd\fP. +.TP +\fBAUTO_RESUME\fP (\-\fBW\fP) +Treat single word simple commands without redirection +as candidates for resumption of an existing job. +.TP +\fBBGNICE\fP (\-\fB6\fP) +Run all background jobs at a lower priority. This option +is set by default. +.TP +\fBBRACECCL\fP +Allow brace expansions of the form \fB{a-zA-Z}\fP, etc. +.TP +\fBCDABLEVARS\fP (\-\fBT\fP) +If the argument to a \fBcd\fP command is not a directory, +but a parameter exists by the same name whose value +begins with a /, try to change to the directory +specified by the parameter's value. +.TP +\fBCHASELINKS\fP (\-\fBw\fP) +Resolve symbolic links to their true values. +.TP +\fBCORRECT\fP (\-\fB0\fP) +Try to correct the spelling of commands. +.TP +\fBCORRECT_ALL\fP (\-\fBO\fP) +Try to correct the spelling of all arguments in a line. +.TP +\fBCSH_JUNKIE_LOOPS\fP +Allow loop bodies to take the form +"\fIlist\fP; \fBend\fP" instead of +"\fBdo\fP \fIlist\fP; \fBdone\fP". +.TP +\fBCSH_JUNKIE_QUOTES\fP +Complain if a quoted expression runs off the end of a line; +prevent quoted expressions from containing unescaped newlines. +.TP +\fBCSH_NULL_GLOB\fP +If a pattern for filename generation has no matches, +delete the pattern from the argument list; +do not report an error unless all the patterns +in a command have no matches. +Overrides \fBNULLGLOB\fP. +.TP +\fBERREXIT\fP (\-\fBe\fP) +If a command has a non-zero exit status, execute the \fBERR\fP +trap, if set, and exit. +.TP +\fBEXTENDED_GLOB\fP +Treat the # and ^ characters as part of patterns for filename +generation, etc. +.TP +\fBGLOB_COMPLETE\fP +Like \fBMENU_COMPLETE\fP, except that the current word +is expanded using normal shell expansion instead of completion. +If no matches are found, a * is added to the end of the word, and expansion +is attempted again. +.TP +\fBGLOB_DOTS\fP (\-\fB4\fP) +Do not require a leading . in a filename to be matched explicitly. +.TP +\fBHASH_CMDS\fP +Place the location of each command in the hash table the first +time it is executed. If this option is unset, no path hashing +will be done at all. +.TP +\fBHASH_DIRS\fP +Whenever a command is executed, hash the directory containing it, +as well as all directories that occur earlier in the path. +Has no effect if \fBHASH_CMDS\fP is unset. +.TP +\fBHASH_LIST_ALL\fP +Whenever a command completion is attempted, make sure the entire +command path is hashed first. This makes the first completion slower. +.TP +\fBHIST_IGNORE_DUPS\fP (\-\fBh\fP) +Do not enter command lines into the history list +if they are duplicates of the previous event. +.TP +\fBHIST_IGNORE_SPACE\fP (\-\fBg\fP) +Do not enter command lines into the history list +if they begin with a blank. +.TP +\fBHISTLIT\fP (\-\fBj\fP) +Use literal (unparsed) versions of the history lines +in the editor. +.TP +\fBHIST_NO_STORE\fP +Remove the \fBhistory\fP (\fBfc\fP \-\fBl\fP) command from +the history when invoked. +.TP +\fBHIST_VERIFY\fP +Whenever the user enters a line with history substitution, +don't execute the line directly; instead, perform +history substitution and reload the line into the editing buffer. +.TP +\fBIGNORE_BRACES\fP (\-\fBI\fP) +Do not perform brace expansion. +.TP +\fBIGNOREEOF\fP (\-\fB7\fP) +Do not exit on end-of-file. Require the use +of \fBexit\fP or \fBlogout\fP instead. +.TP +\fBINTERACTIVE\fP (\-\fBi\fP) +This is an interactive shell. +.TP +\fBINTERACTIVE_COMMENTS\fP (\-\fBk\fP) +Allow comments even in interactive shells. +.TP +\fBKSH_OPTION_PRINT\fP +Alters the way options settings are printed. +.TP +\fBLIST_TYPES\fP (\-\fBX\fP) +When listing files that are possible completions, show the +type of each file with a trailing identifying mark. +.TP +\fBLOGIN\fP (\-\fBl\fP) +This is a login shell. +.TP +\fBLONG_LIST_JOBS\fP (\-\fBR\fP) +List jobs in the long format by default. +.TP +\fBMAIL_WARNING\fP (\-\fBU\fP) +Print a warning message if a mail file has been +accessed since the shell last checked. +.TP +\fBMARKDIRS\fP (\-\fB8\fP) +Append a trailing / to all directory +names resulting from filename generation (globbing). +.TP +\fBMENU_COMPLETE\fP (\-\fBY\fP) +On an ambiguous completion, instead of listing possibilities, +insert the first match. Then when completion is requested +again, remove the first match and insert the second match, etc. +When there are no more matches, go back to the first one again. +\fBreverse-menu-complete\fP may be used to loop through the list +in the other direction. +.TP +\fBMENU_COMPLETE_BEEP\fP +Beep on an ambiguous menu completion. +.TP +\fBMONITOR\fP (\-\fBm\fP) +Allow job control. Set by default in interactive shells. +.TP +\fBNO_BAD_PATTERN\fP (\-\fB2\fP) +If a pattern for filename generation is badly formed, +leave it unchanged in the argument list instead of +printing an error. +.TP +\fBNO_BANG_HIST\fP (\-\fBK\fP) +Do not perform textual history substitution. Do not +treat the ! character specially. +.TP +\fBNOBEEP\fP (\-\fBB\fP) +Do not beep. +.TP +\fBNO_CLOBBER\fP (\-\fB1\fP) +Prevents \fB>\fP redirection from truncating existing files. +\fB>!\fP may be used to truncate a file instead. +Also prevents \fB>>\fP from creating files. +\fB>>!\fP may be used instead. +.TP +\fBNO_EQUALS\fP +Don't perform \fB=\fP filename substitution. +.TP +\fBNOEXEC\fP (\-\fBn\fP) +Read commands and check them for syntax errors, but do not execute them. +.TP +\fBNOGLOB\fP (\-\fBF\fP) +Disable filename generation. +.TP +\fBNO_HIST_BEEP\fP +Don't beep when an attempt is made to access a history entry which +isn't there. +.TP +\fBNOHUP\fP +Don't send the \fBHUP\fP signal to running jobs when the +shell exits. +.TP +\fBNO_LIST_BEEP\fP +Don't beep on an ambiguous completion. +.TP +\fBNO_NOMATCH\fP (\-\fB3\fP) +If a pattern for filename generation has no matches, +leave it unchanged in the argument list instead of +printing an error. +.TP +\fBNO_PROMPT_CR\fP (\-\fBV\fP) +Don't print a carriage return just before printing +a prompt in the line editor. +.TP +\fBNO_RCS\fP (\-\fBf\fP) +Do not source the .zshenv, .zshrc, .zlogin, .zlogout, or .zprofile files. +.TP +\fBNO_SHORT_LOOPS\fP +Disallow the short forms of \fBfor\fP, \fBselect\fP, +\fBif\fP, and \fBfunction\fP constructs. +.TP +\fBNOTIFY\fP (\-\fB5\fP) +Report the status of background jobs immediately, rather than +waiting until just before printing a prompt. +.TP +\fBNOUNSET\fP (\-\fBu\fP) +Treat unset parameters as an error when substituting. +.TP +\fBNULLGLOB\fP (\-\fBG\fP) +If a pattern for filename generation has no matches, +delete the pattern from the argument list instead +of reporting an error. Overrides \fBNO_NOMATCH\fP. +.TP +\fBNUMERICGLOBSORT\fP +If numeric filenames are matched by a filename generation pattern, +sort the filenames numerically rather than lexicographically. +.TP +\fBOVERSTRIKE\fP +Start up the line editor in overstrike mode. +.TP +\fBPATH_DIRS\fP (\-\fBQ\fP) +Perform a path search even on command names with slashes in them. +Thus if "/usr/local/bin" is in the user's path, and he types +"X11/xinit", the command "/usr/local/bin/X11/xinit" will be executed +(assuming it exists). +.TP +\fBPRINT_EXIT_VALUE\fP (\-\fBC\fP) +Print the exit value of programs with non-zero exit status. +.TP +\fBPUSHD_IGNORE_DUPS\fP +Don't push multiple copies of the same directory onto the directory stack. +.TP +\fBPUSHD_MINUS\fP +See \fBpopd\fP below. +.TP +\fBPUSHD_SILENT\fP (\-\fBE\fP) +Do not print the directory stack after \fBpushd\fP +or \fBpopd\fP. +.TP +\fBPUSHD_TO_HOME\fP (\-\fBD\fP) +Have \fBpushd\fP with no arguments act like +\fBpushd\fP $HOME. +.TP +\fBRC_EXPAND_PARAM\fP (\-\fBP\fP) +See \fIParameter Expansion\fP. +.TP +\fBRC_QUOTES\fP +Allow the character sequence \fB''\fP to signify a single quote +within singly quoted strings. +.TP +\fBRECEXACT\fP (\-\fBS\fP) +In completion, recognize exact matches even +if they are ambiguous. +.TP +\fBRMSTARSILENT\fP (\-\fBH\fP) +Do not query the user before executing "rm *" or "rm path/*". +.TP +\fBSHINSTDIN\fP (\-\fBs\fP) +Read commands from the standard input. +.TP +\fBSH_WORD_SPLIT\fP (\-\fBy\fP) +See \fIParameter Expansion\fP. +.TP +\fBSINGLE_LINE_ZLE\fP (\-\fBM\fP) +Use single-line command line editing instead of multi-line. +.TP +\fBSUN_KEYBOARD_HACK\fP (\-\fBL\fP) +If a line ends with a backquote, and there are an odd number +of backquotes on the line, ignore the trailing backquote. +This is useful on some keyboards where the return key is +too small, and the backquote key lies annoyingly close to it. +.TP +\fBVERBOSE\fP (\-\fBv\fP) +Print shell input lines as they are read. +.TP +\fBXTRACE\fP (\-\fBx\fP) +Print commands and their arguments as they are executed. +.TP +\fBZLE\fP (\-\fBZ\fP) +Use the zsh line editor. +.RE +.PD +.SH "SHELL BUILTIN COMMANDS" +.TP +\fB\&.\fP \fIfile\fP [ \fIarg\fP ... ] +Read and execute commands from \fIfile\fP in the current shell +environment. +If \fIfile\fP does not contain a slash, the shell +looks in the components of \fBpath\fP to find the directory +containing \fIfile\fP. +If any arguments \fIarg\fP are given, +they become the positional parameters; the old positional +parameters are restored when the \fIfile\fP is done executing. +The exit status is the exit status of the last command executed. +.TP +\fB:\fP [ \fIarg\fP ... ] +This command only expands parameters. A zero exit code is returned. +.TP +\fBalias\fP [ \-\fBg\fP ] [ \fIname\fP[=\fIvalue\fP] ] ... +With no arguments, print the list of aliases in the form +\fIname\fP=\fBvalue\fP on the standard output. +For each \fIname\fP with a corresponding \fIvalue\fP, define an alias +with that value. +A trailing space in \fIvalue\fP causes the next +word to be checked for alias substitution. +If the \-\fBg\fP flag is present, define a global alias; global aliases +are expanded even if they do not occur in command position. +For each \fIname\fP with no \fIvalue\fP, print the value of \fIname\fP, +if any. +The exit status is nonzero if a \fIname\fP (with no \fIvalue\fP) +given for which no alias has been defined. +.TP +\fBautoload\fP [ \fIname\fP ... ] +For each of the \fIname\fPs (which are names of functions), +create a function marked undefined. +The \fBfpath\fP variable will be searched to find the +actual function definition when the function is first referenced. +.TP +.PD 0 +\fBbg\fP [ \fIjob\fP ... ] +.TP +\fIjob\fP ... \fB&\fP +.PD +Put each specified \fIjob\fP in the background, +or the current job if none is specified. +.TP +.PD 0 +\fBbindkey\fP \-\fBmevd +.TP +\fBbindkey\fP \-\fBr\fP \fIin-string\fP ... +.TP +\fBbindkey\fP [ \-\fBa\fP ] \fIin-string\fP [ \fIcommand\fP ] ... +.TP +\fBbindkey\fP \-\fBs\fP [ \-\fBa\fP ] \fIin-string\fP \fIout-string\fP ... +.PD +If one of the \-\fBe\fP, \-\fBv\fP, or \-\fBd\fP options is given, +reset the keymaps for emacs mode, vi mode, or the default mode, +respectively; if the \-\fBm\fP option is also given, +allow the use of a meta key. +If the \-\fBr\fP option is given, remove any binding for each \fIin-string\fP. +If the \-\fBs\fP option is not specified, bind each \fIin-string\fP +to a specified \fIcommand\fP. If no \fIcommand\fP is specified, +print the binding of \fIin-string\fP if it is bound, or return +a nonzero exit code if it is not bound. +If the \-\fBs\fP option is specified, bind each \fIin-string\fP +to each specified \fIout-string\fP. When \fIin-string\fP is typed, +\fIout-string\fP will be pushed back and treated as input to the +line editor. +If the \-\fBa\fP option is specified, bind the \fIin-string\fPs in the +alternative keymap instead of the standard one. The alternative +keymap is used in vi command mode. +.RS +.PP +For either \fIin-string\fP or \fIout-string\fP, control characters +may be specified in the form \fB^X\fP, and the backslash may +be used to introduce one of the following escape sequences: +.RS +.PD 0 +.TP +.B \ea +bell character +.TP +.B \en +linefeed (newline) +.TP +.B \eb +backspace +.TP +.B \et +horizontal tab +.TP +.B \ev +vertical tab +.TP +.B \ef +form feed +.TP +.B \er +carriage return +.TP +.B \ee +escape +.TP +.B \ennn +character code in octal +.TP +.B \eM\-xxx +character or escape sequence with meta bit set +.PD +.PP +.RE +In all other cases, \e escapes the following character. Delete is +written as `\fB^?\fP'. +.RE +.TP +\fBbreak\fP [ \fIn\fP ] +Exit from an enclosing \fBfor\fP, \fBwhile\fP, +\fBuntil\fP, \fBselect\fP, or \fBrepeat\fP loop. If \fIn\fP +is specified, then break \fIn\fP levels instead of just one. +.TP +\fBbuiltin\fP \fIname\fP [ \fIargs\fP ] ... +Executes the builtin \fIname\fP, with the given \fIargs\fP. +.TP +\fBbye\fP +Same as \fBexit\fP. +.TP +.PD 0 +\fBcd\fP [ \fIarg\fP ] +.TP +\fBcd\fP \fIold\fP \fInew\fP +.TP +\fBcd\fP \(+-\fBn\fP +.PD +Change the current directory. In the first form, change the +current directory to \fIarg\fP, or to the value of \fBHOME\fP if +\fIarg\fP is not specified. If \fIarg\fP is \-, change to the +value of \fBOLDPWD\fP, the previous directory. +If a directory named \fIarg\fP is not found in the current directory +and \fIarg\fP does not begin with a slash, +search each component of the shell parameter \fBcdpath\fP. +If the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP +exists whose value begins with a slash, treat its value as +the directory. +.RS +.PP +The second form of \fBcd\fP substitutes the string \fInew\fP +for the string \fIold\fP in the name of the current directory, +and tries to change to this new directory. +.PP +The third form of \fBcd\fP is equivalent to \fBpopd\fP. +.RE +.TP +\fBchdir\fP +Same as \fBcd\fP. +.TP +\fBcompctl\fP [ \-\fBcfhovbCD\fP ] [ \-\fBk\fP \fIname\fP ] [ \fIarg\fP ... ] +Control the editor's completion behavior when one of \fIarg\fP is the current +command. With the \-\fBD\fP flag, control default completion behavior +for commands not assigned any special behavior; with \-\fBC\fP, control +completion when there is no current command. The remaining options +specify the type of command arguments to look for during completion. +For example, \fBcompctl\fP \-\fBhf\fP \fBrlogin\fP is equivalent +to \fBhostcmds=(rlogin)\fP. +.RS +.PD 0 +.TP +\-\fBc\fP +Expect command names. +.TP +\-\fBf\fP +Expect filenames and filesystem paths. +.TP +\-\fBh\fP +Expect hostnames taken from the \fB$hosts\fP variable. +.TP +\-\fBo\fP +Expect option names. +.TP +\-\fBv\fP +Expect variable names. +.TP +\-\fBb\fP +Expect key binding names. +.TP +\-\fBk\fP \fIname\fP +Expect names taken from the elements of \fB$name\fP. +.PD +.RE +.TP +\fBcontinue\fP [ \fInum\fP ] +Resume the next iteration of the enclosing +\fBfor\fP, \fBwhile\fP, \fBuntil\fP, \fBselect\fP, or +\fBrepeat\fP loop. If \fIn\fP is specified, break out of +\fIn\fP \- 1 loops and resume at the \fIn\fPth enclosing loop. +.TP +\fBdeclare\fP [ \fIarg\fP ... ] +Same as \fBtypeset\fP. +.TP +\fBdirs\fP [ \-\fBv\fP ] [ \fIarg\fP ... ] +With no arguments, print the contents of the directory stack. +If the \-\fBv\fP option is given, number the directories +in the stack when printing. +Directories are added to this stack with the \fBpushd\fP command, +and removed with the \fBcd\fP or \fBpopd\fP commands. +If arguments are specified, load them onto the directory stack, +replacing anything that was there, and push the current directory +onto the stack. +.TP +\fBdisable\fP \fIarg\fP ... +Disable the builtin \fIarg\fP temporarily. This allows you to use +an external command with the same name as a shell builtin. +Actually the same as \fBunhash\fP. +Builtins can be enabled with the \fBenable\fP command. +.TP +\fBdisown\fP \fIjob\fP ... +Remove the specified jobs from the job table; the shell will +no longer report their status, and will not complain if you +try to exit an interactive shell with them running or stopped. +.TP +\fBecho\fP [ \-\fBn\fP ] [ \fIarg\fP ... ] +Write each \fIarg\fP on the standard output, with a space separating +each one. +If the \-\fBn\fP flag is not present, print a newline at the end. +\fBecho\fP recognizes the following escape sequences: +.RS +.PD 0 +.TP +.B \eb +backspace +.TP +.B \ec +don't print an ending newline +.TP +.B \ee +escape +.TP +.B \ef +form feed +.TP +.B \en +newline +.TP +.B \er +carriage return +.TP +.B \et +horizontal tab +.TP +.B \ev +vertical tab +.TP +.B \e\e +backslash +.TP +.B \exxx +character code in octal +.PD +.RE +.TP +\fBechotc\fP \fIcap\fP [ \fIarg\fP ... ] +Output the termcap string corresponding to the capability +\fIcap\fP, with optional arguments. +.TP +\fBenable\fP \fIarg\fP ... +Enable the specified builtin commands, presumably disabled earlier +with \fBdisable\fP. +.TP +\fBeval\fP [ \fIarg\fP ... ] +Read the arguments as input to the shell and execute the resulting +command(s) in the current shell process. +.TP +\fBexit\fP [ \fIn\fP ] +Exit the shell with the exit code specified by \fIn\fP; if none +is specified, use the exit code from the last command executed. +An EOF condition will also cause the shell to exit, unless +the \fBIGNOREEOF\fP option is set. +.TP +\fBexport\fP [ \fIname\fP[=\fIvalue\fP] ... ] +The specified \fIname\fPs are marked for automatic export +to the environment of subsequently executed commands. +.TP +\fBfalse\fP +Do nothing and return an exit code of 1. +.TP +.PD 0 +\fBfc\fP [ \-\fBe\fP \fIename\fP ] [ \-\fBnlrdD\fP ] [ \fIold\fP=\fInew\fP ... ] [ \fIfirst\fP [ \fIlast\fP ] ] +.TP +\fBfc\fP \-\fBARW\fP [ \fIfilename\fP ] +.PD +Select a range of commands from \fIfirst\fP to \fIlast\fP from the +history list. +The arguments \fIfirst\fP and \fIlast\fP may be specified as a +number or as a string. A negative number is used as an offset +to the current history event number. +A string specifies the most recent event +beginning with the given string. +All substitutions \fIold\fP=\fInew\fP, if any, are then performed +on the commands. +If the \-\fBl\fP flag is given, the resulting commands are listed on +standard output. +Otherwise the editor program \fIename\fP is invoked on a file containing +these history events. If \fIename\fP is not given, the value +of the parameter \fBFCEDIT\fP is used. If \fIename\fP is "\-", +no editor is invoked. When editing is complete, the edited +command(s) is executed. +If \fIfirst\fP is not specified, it will be set to \-1 (the most recent +event), or to -16 if the \-\fBl\fP flag is given. +If \fIlast\fP is not specified, it will be set to \fIfirst\fP, +or to \-1 if the \-\fBl\fP flag is given. +The flag \-\fBr\fP reverses the order of the commands and the +flag \-\fBn\fP suppresses command numbers when listing. +Also when listing, \-\fBd\fP prints datestamps for each command, +and \-\fBD\fP prints real execution times. +.RS +.PP +\fBfc\fP \-\fBR\fP reads the history from the given file, +\fBfc\fP \-\fBW\fP writes the history out to the given file, +and \fBfc\fP \-\fBA\fP appends the history out to the given file. +.RE +.TP +.PD 0 +\fBfg\fP [ \fIjob\fP ... ] +.TP +\fIjob\fP ... +.PD +Bring the specified \fIjob\fPs to the foreground. +If no \fIjob\fP is specified, use the current job. +.TP +\fBfunctions\fP [ \(+-\fBtu\fP ] [ \fIname\fP ... ] +Equivalent to \fBtypeset\fP \-\fBf\fP. +.TP +\fBgetln\fP \fIname\fP ... +Read the top value from the buffer stack and put it in +the shell parameter \fIname\fP. Equivalent to +\fBread\fP \-\fBzr\fP. +.TP +\fBgetopts\fP \fIoptstring\fP \fIname\fP [ \fIarg\fP ... ] +Checks \fBarg\fP for legal options. If \fIarg\fP is omitted, +use the positional parameters. A valid option argument +begins with a + or a \-. An argument not beginning with +a + or a \-, or the argument \-\-, ends the options. +\fIoptstring\fP contains the letters that \fBgetopts\fP +recognizes. If a letter is followed by a `:', that option +is expected to have an argument. The options can be +separated from the argument by blanks. +.RS +.PP +Each time it is invoked, \fBgetopts\fP places the option letter it finds +in the shell parameter \fIname\fP, prepended with a + when +\fIarg\fP begins with a +. The index of the next \fIarg\fP +is stored in \fBOPTIND\fP. The option argument, if any, +is stored in \fBOPTARG\fP. +.PP +A leading : in \fIoptstring\fP causes \fBgetopts\fP to store the +letter of the invalid option in \fBOPTARG\fP, and to set \fIname\fP +to `?' for an unknown option and to `:' when a required option +is missing. Otherwise, \fBgetopts\fP prints an error +message. The exit status is nonzero when there are no more options. +.RE +.TP +\fBhash\fP \fIname\fP \fIpath\fP +Puts \fIname\fP in the command hash table, associating it with +the pathname \fIpath\fP. Whenever \fIname\fP is used as a command +argument, the shell will try to execute the file given by \fIpath\fP. +.TP +\fBhistory\fP [ \-\fBnr\fP ] [ \fIfirst\fP [ \fIlast\fP ] ] +Same as \fBfc\fP \-\fBl\fP. +.TP +\fBinteger\fP +Same as \fBtypeset\fP \-\fBi\fP. +.TP +\fBjobs\fP [ \-\fBlp\fP ] [ \fIjob\fP ... ] +Lists information about each given job, or all jobs +if \fIjob\fP is omitted. The \-\fBl\fP flag lists process +ids, and the \-\fBp\fP flag lists process groups. +.TP +.PD 0 +\fBkill\fP [ \-\fIsig\fP ] \fIjob\fP ... +.TP +\fBkill\fP \-\fBl\fP +.PD +Sends either SIGTERM or the specified signal to the given +jobs or processes. +Signals are given by number or by names +(with the prefix "SIG" removed). +If the signal being sent is not KILL or CONT, then the job +will be sent a CONT signal if it is stopped. +The argument \fIjob\fP can be the process id of a job +not in the job list. +In the second form, \fBkill\fP \-\fBl\fP, the signal names +are listed. +.TP +\fBlet\fP \fIarg\fP ... +Evaluate each \fIarg\fP as an arithmetic expression. +See \fBARITHMETIC EVALUATION\fP above for a description +of arithmetic expressions. The exit status is 0 if the +value of the last expression is nonzero, and 1 otherwise. +.TP +.PD 0 +\fBlimit\fP [ \-\fBh\fP ] [ \fIresource\fP [ \fIlimit\fP ] ] ... +.TP +\fBlimit\fP \-\fBs\fP +.PD +Limit the resource consumption of children of the current shell. +If \fIlimit\fP is not specified, print the current limit placed +on \fIresource\fP; otherwise +set the limit to the specified value. If the \-\fBh\fP flag +is given, use hard limits instead of soft limits. +If no \fIresource\fP is given, print all limits. +.RS +.PP +\fIresource\fP is one of: +.PP +.PD 0 +.TP +.B cputime +Maximum CPU seconds per process. +.TP +.B filesize +Largest single file allowed. +.TP +.B datasize +Maximum data size (including stack) for each process. +.TP +.B stacksize +Maximum stack size for each process. +.TP +.B coredumpsize +Maximum size of a core dump. +.TP +.B resident +Maximum resident set size. +.TP +.B descriptors +Maximum value for a file descriptor. +.PD +.PP +\fIlimit\fP is a number, with an optional scaling factor, as follows: +.PP +.PD 0 +.TP +\fIn\fPh +hours. +.TP +\fIn\fPk +kilobytes. +This is the default for all but cputime. +.TP +\fIn\fPm +megabytes or minutes. +.TP +\fImm\fP:\fBss\fP +minutes and seconds. +.PD +.RE +.TP +\fBlocal\fP +Same as \fBtypeset\fP. +.TP +\fBlog\fP +List all users currently logged in who are affected by +the current setting of the \fBwatch\fP parameter. +.TP +\fBlogout\fP +Exit the shell, if this is a login shell. +.TP +\fBpopd\fP [ \(+-\fIn\fP ] +Removes entries from the directory stack. With no arguments, +removes the top directory from the stack, and performs a \fBcd\fP +to the new top directory. With an argument of the form +\fIn\fP, +remove the \fIn\fPth entry counting from the left of the list +shown by the \fBdirs\fP command, starting with zero, and change +to that directory. With an argument of the form \-\fIn\fP, +remove the \fIn\fPth entry counting from the right. +If the \fBPUSHD_MINUS\fP option is set, the meanings of + +and \- in this context are swapped. +.TP +\fBprint\fP [ \-\fBRnrslzpNDP\fP ] [ \-\fBu\fP\fIn\fP ] [ \fIarg\fP ... ] +With no flags or with flag \-, the arguments are printed on +the standard output as described by \fBecho\fP. +.RS +.PD 0 +.TP +\-\fBR\fP, \-\fBr\fP +ignore the escape conventions of \fBecho\fP. +The \-\fBR\fP option will print all subsequent +arguments and options. +.TP +\-\fBs\fP +place the results in the history list instead of on the standard output. +.TP +\-\fBn\fP +do not add a newline to the output. +.TP +\-\fBl\fP +print the arguments separated by newlines instead of spaces. +.TP +\-\fBN\fP +print the arguments separated and terminated by nulls. +.TP +\-\fBu\fP\fIn\fP +print the arguments to file descriptor \fIn\fP. +.TP +\-\fBp\fP +print the arguments to the input of the coprocess. +.TP +\-\fBz\fP +push the arguments onto the editing buffer stack, separated by spaces; +no escape sequences are recognized. +.TP +\-\fBD\fP +treat the arguments as directory names, replacing prefixes with ~ +expressions, as appropriate. +.TP +\-\fBP\fP +recognize the same escape sequences as in the \fBPROMPT\fP parameter. +.PD +.RE +.TP +.PD 0 +\fBpushd\fP [ \fIarg\fP ] +.TP +\fBpushd\fP \fIold\fP \fInew\fP +.TP +\fBpushd\fP \(+-\fBn\fP +.PD +Change the current directory, and push the old current directory +onto the directory stack. In the first form, change the +current directory to \fIarg\fP. +If \fIarg\fP is not specified, change to the second directory +on the stack (that is, exchange the top two entries), or +change to the value of \fBHOME\fP if the \fBPUSHD_TO_HOME\fP +option is set or if there is only one entry on the stack. +If \fIarg\fP is \-, change to the +value of \fBOLDPWD\fP, the previous directory. +If a directory named \fIarg\fP is not found in the current directory +and \fIarg\fP does not contain a slash, +search each component of the shell parameter \fBcdpath\fP. +If the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP +exists whose value begins with a slash, treat its value as +the directory. +If the option \fBPUSHD_SILENT\fP is not set, the directory +stack will be printed after a \fBpushd\fP is performed. +.RS +.PP +The second form of \fBpushd\fP substitutes the string \fInew\fP +for the string \fIold\fP in the name of the current directory, +and tries to change to this new directory. +.PP +The third form of \fBpushd\fP is equivalent to \fBpopd\fP. +.RE +.TP +\fBpwd\fP +Equivalent to \fBprint \-R $PWD\fP. +.TP +\fBr\fP +Equivalent to \fBfc \-e \-\fP. +.TP +\fBread\fP [ \-\fBrzp\fP ] [ \-\fBu\fIn\fR ] [ \fIname\fP?\fIprompt\fP ] [ \fIname\fP ... ] +Read one line and break it into fields using the characters +in \fBIFS\fP as separators. In raw mode, \-\fBr\fP, a \e +at the end of a line does not signify line continuation. +If the \-\fBz\fP flag is set, read from the editor buffer stack. +The first field is assigned to the first \fIname\fP, the second field +to the second \fIname\fP, etc., with leftover +fields assigned to the last \fIname\fP. +If \fIname\fP is omitted then \fBREPLY\fP is used. +If \-\fBu\fIn\fR is specified, then input is read from file +descriptor \fIn\fP; if \-\fBp\fP is specified, then input is +read from the coprocess. +The exit status is 0 unless end-of-file is encountered. +If the first argument contains a \fB?\fP, the remainder of this +word is used as a \fIprompt\fP on standard error when the shell +is interactive. The exit status is 0 unless an end-of-file +is encountered. +.TP +\fBreadonly\fP [ \fIname\fP[=\fIvalue\fP] ] ... +The given \fInames\fP are marked readonly; these names +cannot be changed by subsequent assignment. +.TP +\fBrehash\fP [ \-\fBf\fP ] +Throw out the command hash table and start over. +If the \-\fBf\fP option is set, rescan the command path +immediately, instead of rebuilding the hash table incrementally. +.TP +\fBreturn\fP [ \fIn\fP ] +Causes a shell function or \fB\&.\fP script to return to +the invoking script +with the return status specified by \fIn\fP. If \fIn\fP +is omitted then the return status is that of the last command +executed. +.TP +.PD 0 +\fBsched\fP [+]\fIhh\fP:\fImm\fP \fIcommand\fP ... +.TP +\fBsched\fP [ \-\fIitem\fP ] +.PD +Make an entry in the scheduled list of commands to execute. +The time may be specified in either absolute or relative time. +With no arguments, prints the list of scheduled commands. +With the argument \-\fIitem\fP, removes the given item +from the list. +.TP +\fBset\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption name\fP ] ... [ \-\fBA\fP \fIname\fP ] [ \fIarg\fP ] ... +Set the options for the shell and/or set the positional parameters, or +declare an array. For the meaning of the flags, see +\fBOPTIONS\fP above. +Flags may be specified by name using the \-\fBo\fP option. +If the \-\fBA\fP flag is specified, \fIname\fP is set to an +array containing the given \fIarg\fPs. +Otherwise the positional parameters are set. +If no arguments are given, then the names and values +of all parameters are printed on the standard output. +If the only argument is +, the names of all parameters are printed. +.TP +\fBsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ] +Set the options for the shell. All options specified either +with flags or by name are set. If no arguments are supplied, +the names of all options currently set are printed. +In option names, case is insignificant, and all underscore +characters are ignored. +.TP +\fBshift\fP [ \fIn\fP ] +The positional parameters from $\fIn\fP+\fB1\fP ... are renamed +$\fB1\fP, where \fIn\fP is an arithmetic expression that +defaults to 1. +.TP +\fBsource\fP +Same as \fB.\fP. +.TP +\fBsuspend\fP [ \-\fBf\fP ] +Suspend the execution of the shell (send it a \fBSIGTSTP\fP) +until it receives a \fBSIGCONT\fP. +If the \-\fBf\fP option is not given, complain if this is a login shell. +.TP +.PD 0 +\fBtest\fP \fIarg\fP ... +.TP +\fB[\fP \fIarg\fP ... \fB]\fP +.PD +Like the system version of \fBtest\fP. Added for compatibility; +use conditional expressions instead. +.TP +\fBtimes\fP +Print the accumulated user and system times for the shell +and for processes run from the shell. +.TP +\fBtrap\fP [ \fIarg\fP ] [ \fIsig\fP ] ... +\fIarg\fP is a command to be read and executed when the shell +receives \fIsig\fP. Each \fIsig\fP can be given as a number +or as the name of a signal. +If \fIarg\fP is \-, then all traps \fIsig\fP are reset to their +default values. If \fIarg\fP is the null string, then this signal +is ignored by the shell and by the commands it invokes. +If \fIsig\fP is \fBERR\fP then \fIarg\fP will be executed +after each command. +If \fIsig\fP is \fB0\fP or \fBEXIT\fP +and the \fBtrap\fP statement is executed inside the body of a function, +then the command \fIarg\fP is executed after the function completes. +If \fIsig\fP is \fB0\fP or \fBEXIT\fP +and the \fBtrap\fP statement is not executed inside the body of a function, +then the command \fIarg\fP is executed when the shell terminates. +The \fBtrap\fP command with no arguments prints a list of commands +associated with each signal. +.TP +\fBtrue\fP +Do nothing and return an exit code of 0. +.TP +\fBttyctl\fP \-\fBfu\fP +The \-\fBf\fP option freezes the tty, and \-\fBu\fP unfreezes it. +When the tty is frozen, no changes made to the tty settings by +external programs will be honored by the shell; the shell will +simply reset the settings to their previous values as soon as each +command exits. Thus, \fBstty\fP and similar programs have no +effect when the tty is frozen. +.TP +\fBtype\fP +Same as \fBwhence\fP \-\fBv\fP. +.TP +\fBtypeset\fP [ \(+-\fBLRZfilrtux [\fIn\fP]] [ \fIname\fP[=\fIvalue\fP] ] ... +Set attributes and values for shell parameters. +When invoked inside a function, if \fIname\fP is not already +defined, a new parameter is created which will be unset when the +function completes. +The following attributes are valid: +.RS +.PD 0 +.TP +\-\fBL\fP +Left justify and remove leading blanks from \fIvalue\fP. +If \fIn\fP is nonzero, it defines the width of the field; +otherwise it is determined by the width of the value of the first +assignment. +When the parameter is printed, it is filled on the right with +blanks or truncated if necessary to fit the field. +Leading zeros are removed if the \-\fBZ\fP flag is also set. +.TP +\-\fBR\fP +Right justify and fill with leading blanks. If \fIn\fP is nonzero +if defines the width of the field; +otherwise it is determined by the width of the value of the first +assignment. +When the parameter is printed, the field is left filled with +blanks or truncated from the end. +.TP +\-\fBZ\fP +Right justify and fill with leading zeros if the first non-blank +character is a digit and the \-\fBL\fP flag has not been set. +If \fIn\fP is nonzero it defines the width of the field; +otherwise it is determined by the width of the value of the +first assignment. +.TP +\-\fBf\fP +The names refer to functions rather than parameters. No assignments +can be made, and the only other valid flags are \-\fBt\fP +and \-\fBu\fP. The flag \-\fBt\fP turns on execution tracing for this +function. The flag \-\fBu\fP causes this function to be marked +for autoloading. The \fBfpath\fP parameter will be searched to find the +function definition when the function is first referenced. +.TP +\-\fBi\fP +Use an internal integer representation. If \fBi\fP is nonzero +it defines the output arithmetic base, otherwise it is determined by the first +assignment. +.TP +\-\fBl\fP +Convert to lower case. +.TP +\-\fBr\fP +The given \fIname\fPs are marked readonly. +.TP +\-\fBt\fP +Tags the named parameters. Tags have no special meaning to the shell. +.TP +\-\fBu\fP +Convert to upper case. +.TP +\-\fBx\fP +Mark for automatic export to the environment of subsequently +executed commands. +.RE +.PD +.PP +Using + rather than \- causes these flags to be turned off. +If no arguments are given but flags are specified, +a list of named parameters which have these flags set is printed. +Using + instead of \- keeps their values from being printed. +If no arguments or options are given, the names and attributes +of all parameters are printed. +.TP +\fBulimit\fP [ \-\fBHSacdfmnt\fP ] [ \fIlimit\fP ] +Set or display a resource limit. The value of limit can be a number +in the unit specified below or the value \fBunlimited\fP. +The \fBH\fP and \fBS\fP flags specify whether the hard limit +or the soft limit for the given resource is set. +.RS +.PD 0 +.TP +\-\fBa\fP +Lists all of the current resource limits. +.TP +\-\fBc\fP +The number of 512-byte blocks on the size of core dumps. +.TP +\-\fBd\fP +The number of K-bytes on the size of the data segment. +.TP +\-\fBf\fP +The number of 512-byte blocks on the size of files written. +.TP +\-\fBm\fP +The number of K-bytes on the size of physical memory. +.TP +\-\fBn\fP +The number of file descriptors. +.TP +\-\fBs\fP +The number of K-bytes on the size of the stack. +.TP +\-\fBt\fP +The number of CPU seconds to be used. +.RE +.PD +.TP +\fBumask\fP [ \fImask\fP ] +The umask is set to \fImask\fP. \fImask\fP can be either +an octal number or a symbolic value as described in \fBchmod\fP(1). +If \fImask\fP is omitted, the current value is printed. +.TP +\fBunalias\fP \fIname\fP ... +The alias definition, if any, for each \fIname\fP is removed. +.TP +\fBunfunction\fP \fIname\fP ... +The function definition, if any, for each \fIname\fP is removed. +.TP +\fBunhash\fP \fIname\fP ... +The entry in the command hash table, if any, for each \fIname\fP +is removed. +.TP +\fBunlimit\fP [ \-\fBh\fP ] \fIresource\fP ... +The resource limit for each \fIresource\fP is set to the hard limit. +If the \-\fBh\fP flag is given and the shell is running as root, +the hard resource limit for each \fIresource\fP is removed. +.TP +\fBunset\fP \fIname\fP ... +Each named parameter is unset. +.TP +\fBunsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ] +Unset the options for the shell. All options specified either +with flags or by name are unset. +.TP +\fBvared\fP \fIname\fP +The value of the parameter \fIname\fP is loaded into the edit +buffer, and the line editor is invoked. When the editor exits, +\fIname\fP is set to the string value returned by the editor. +.TP +\fBwait\fP [ \fIjob\fP ... ] +Wait for the specified jobs or processes. If \fIjob\fP is not given +then all currently active child processes are waited for. +Each \fIjob\fP can be either a job specification or the process-id +of a job in the job table. +The exit status from this command is that of the job waited for. +.TP +\fBwhence\fP [ \-\fBacpv\fP ] \fIname\fP ... +For each name, indicate how it would be interpreted if used +as a command name. The \-\fBv\fP flag produces a more verbose +report. The \-\fBp\fP flag does a path search for \fIname\fP +even if it is a shell function, alias, or reserved word. +The \-\fBc\fP flag prints the results in a csh-like format. +The \-\fBa\fP flag does a search for all occurences of \fIname\fP +throughout the command path. +.TP +\fBwhich\fP +Same as \fBwhence \-c\fP. +.RE +.SH INVOCATION +Commands are first read from /etc/zshenv. +Then, if the \fBNO_RCS\fP option is unset, commands are read +from $ZDOTDIR/.zshenv. +(If \fBZDOTDIR\fP is unset, \fBHOME\fP is used instead). +Then, if the shell is interactive and +the \fBNO_RCS\fP option is unset, commands are read +from /etc/zshrc and $ZDOTDIR/.zshrc, in that order, if either file +exists. +If the first character of argument zero passed to the shell +is \-, then the shell is assumed to be a login shell, and commands +are read from /etc/zprofile and $ZDOTDIR/.zprofile before .zshrc is read, +then /etc/zlogin and $ZDOTDIR/.zlogin after .zshrc is read. +If the \fBNO_RCS\fP option is set, only /etc/zshrc +/etc/zlogin, and /etc/zprofile may be read. +If the \-\fBs\fP flag is not present and an argument is given, +the first argument is taken to be the pathname of a script to +execute. The remaining arguments are assigned to the positional +parameters. The following flags are interpreted by the shell +when invoked: +.TP +.PD 0 +\-\fBc\fP \fIstring\fP +Read commands from \fIstring\fP. +.TP +\-\fBs\fP +Read command from the standard input. +.TP +\-\fBi\fP +If this flag is present or the shell input and output +are attached to a terminal, this shell is interactive. +.PD +.SH "SEE ALSO" +sh(1), +csh(1), +tcsh(1), +itcsh(1), +rc(1), +bash(1), +ash(1), +ksh(1), +clam(1), +strftime(3). +.SH FILES +$ZDOTDIR/.zshenv +.br +$ZDOTDIR/.zshrc +.br +$ZDOTDIR/.zlogin +.br +$ZDOTDIR/.zlogout +.br +$ZDOTDIR/.zprofile +.br +/tmp/zsh* +.br +/etc/zshenv +.br +/etc/zprofile +.br +/etc/zshrc +.br +/etc/zlogin +.SH AUTHOR +Paul Falstad (pfalstad@phoenix.princeton.edu) +.SH "UNDOCUMENTED FEATURES" +None known, but many suspected. +Please mail the author if you find any. diff --git a/usr/othersrc/public/zsh-2.2/scripts/aproto b/usr/othersrc/public/zsh-2.2/scripts/aproto new file mode 100755 index 0000000000..bfdde4c780 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/aproto @@ -0,0 +1,28 @@ +#! /bin/sh +fproto builtin.c >builtin.pro +fproto cond.c >cond.pro +fproto exec.c >exec.pro +fproto glob.c >glob.pro +fproto hist.c >hist.pro +fproto init.c >init.pro +fproto jobs.c >jobs.pro +fproto lex.c >lex.pro +fproto loop.c >loop.pro +fproto math.c >math.pro +fproto mem.c >mem.pro +fproto params.c >params.pro +fproto subst.c >subst.pro +fproto table.c >table.pro +fproto text.c >text.pro +fproto utils.c >utils.pro +fproto watch.c >watch.pro +fproto parse.c >parse.pro +fproto zle_hist.c >zle_hist.pro +fproto zle_main.c >zle_main.pro +fproto zle_misc.c >zle_misc.pro +fproto zle_move.c >zle_move.pro +fproto zle_refresh.c >zle_refresh.pro +fproto zle_tricky.c >zle_tricky.pro +fproto zle_utils.c >zle_utils.pro +fproto zle_vi.c >zle_vi.pro +fproto zle_word.c >zle_word.pro diff --git a/usr/othersrc/public/zsh-2.2/scripts/c2z b/usr/othersrc/public/zsh-2.2/scripts/c2z new file mode 100755 index 0000000000..a7e70c6e5f --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/c2z @@ -0,0 +1,120 @@ +#! /bin/sh +# +# c2z - environment conversion tool +# Contributed by Bart Schaefer +# (Tweaked a bit by Paul Falstad) +# +# This is a quick script to convert csh aliases to zsh aliases/functions. +# It also converts the csh environment and local variables to zsh. c2z +# uses the csh to parse its own dot-files, then processes csh output to +# convert the csh settings to zsh. +# +# When run as a zsh fuction, c2z runs csh as if it were an interactive +# shell whenever the parent zsh is interactive. When run as a shell +# script, the -i switch can be used to force this behavior. +# +# The -l (login) switch causes csh to run as if it were a login shell. +# This is done "properly" if c2z is used as a zsh function, otherwise +# it's faked by explicitly sourcing .login. Use with caution if your +# .login initializes an X server or does other one-time-only startup +# procedures. +# +# usage: +# c2z [-i] [-l] +# +# You can use this script in your .zshrc or .zlogin files to load your +# regular csh environment into zsh; for example, in .zlogin: +# +# . =(c2z -l) +# +# This is not perfect, but it gets most common aliases and variables. +# It's also rather time-consuming to do this every time you log in. +# However, if you're moving from csh to zsh for the first time, this +# can get you started with a familiar environment right away. +# +# In case your mailer eats tabs, $T is set to expand to a tab. +# +T="`echo x | tr x '\011'`" + +# If we're zsh, we can run "- csh" to get the complete environment. +# +MINUS="" +LOGIN="" +INTERACT="" +case "$VERSION" in +zsh*) + case $1 in + -l*) MINUS="-" ;; + -i*) INTERACT="-i" ;; + esac + if [[ -o INTERACTIVE ]]; then INTERACT="-i"; fi + setopt nobanghist + ;; +*) + case $1 in + -l*) LOGIN="source ~/.login" ;; + -i*) INTERACT="-i" ;; + esac + ;; +esac + +( eval $MINUS csh $INTERACT ) <&1 >/dev/null +$LOGIN +alias >! /tmp/cz$$.a +setenv >! /tmp/cz$$.e +set >! /tmp/cz$$.v +EOF + +# save stdin +exec 9<&0 + +# First convert aliases +exec < /tmp/cz$$.a + +# Taken straight from ctoz except for $T and "alias --" +sed -e 's/'"$T"'(\(.*\))/'"$T"'\1/' >/tmp/cz$$.1 +grep ! /tmp/cz$$.1 >/tmp/cz$$.2 +grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3 +sed -e "s/'/'"\\\\"''"/g \ + -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/alias -- \1='"'\2'/" \ + /tmp/cz$$.3 +sed -e 's/![:#]*/$/g' \ + -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/\1 () { \2 }/' \ + /tmp/cz$$.2 + +# Next, convert environment variables +exec < /tmp/cz$$.e + +# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ... +sed -e '/^SHLVL/d' \ + -e "s/'/'"\\\\"''"/g \ + -e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \ + -e "s/$/'/" + +# Finally, convert local variables +exec < /tmp/cz$$.v + +sed -e 's/'"$T"'/=/' \ + -e "s/'/'"\\\\"''"/g \ + -e '/^[A-Za-z0-9_]*=[^(]/{ + s/=/='"'/"' + s/$/'"'/"' + }' | +sed -e '/^argv=/d' -e '/^cwd=/d' -e '/^filec=/d' -e '/^status=/d' \ + -e '/^histchars=/s//HISTCHARS=/' \ + -e '/^history=/s//HISTSIZE=/' \ + -e '/^home=/s//HOME=/' \ + -e '/^ignoreeof=/s/.*/setopt ignoreeof/' \ + -e '/^noclobber=/s/.*/setopt noclobber/' \ + -e '/^notify=/d' \ + -e '/^showdots=/s/.*/setopt globdots/' \ + -e '/^savehist=/s//HISTFILE=\~\/.zhistory SAVEHIST=/' \ + -e '/^autolist=/s/.*/setopt autolist/' \ + -e '/^correct=[cmd]*/s//setopt autocorrect/' \ + -e '/^who=/s//WATCHFMT=/' + + +exec 0<&9 + +rm /tmp/cz$$.? +exit diff --git a/usr/othersrc/public/zsh-2.2/scripts/c2z.orig b/usr/othersrc/public/zsh-2.2/scripts/c2z.orig new file mode 100755 index 0000000000..4752d9131d --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/c2z.orig @@ -0,0 +1,102 @@ +#! /bin/sh +# +# c2z - environment conversion tool +# Contributed by Bart Schaefer +# +# This is a quick script to convert csh aliases to zsh aliases/functions. +# It also converts the csh environment and local variables to zsh. c2z +# uses the csh to parse its own dot-files, then processes csh output to +# convert the csh settings to zsh. +# +# When run as a zsh fuction, c2z runs csh as if it were an interactive +# shell whenever the parent zsh is interactive. When run as a shell +# script, the -i switch can be used to force this behavior. +# +# The -l (login) switch causes csh to run as if it were a login shell. +# This is done "properly" if c2z is used as a zsh function, otherwise +# it's faked by explicitly sourcing .login. Use with caution if your +# .login initializes an X server or does other one-time-only startup +# procedures. +# +# usage: +# c2z [-i] [-l] +# +# You can use this script in your .zshrc or .zlogin files to load your +# regular csh environment into zsh; for example, in .zlogin: +# +# . =(c2z -l) +# +# This is not perfect, but it gets most common aliases and variables. +# It's also rather time-consuming to do this every time you log in. +# However, if you're moving from csh to zsh for the first time, this +# can get you started with a familiar environment right away. +# +# In case your mailer eats tabs, $T is set to expand to a tab. +# +T="`echo x | tr x '\011'`" + +# If we're zsh, we can run "- csh" to get the complete environment. +# +MINUS="" +LOGIN="" +INTERACT="" +case "$VERSION" in +zsh*) + case $1 in + -l*) MINUS="-" ;; + -i*) INTERACT="-i" ;; + esac + if [[ -o INTERACTIVE ]]; then INTERACT="-i"; fi + setopt nobanghist + ;; +*) + case $1 in + -l*) LOGIN="source ~/.login" ;; + -i*) INTERACT="-i" ;; + esac + ;; +esac + +( eval $MINUS csh $INTERACT ) <&1 >/dev/null +$LOGIN +alias >! /tmp/cz$$.a +setenv >! /tmp/cz$$.e +set >! /tmp/cz$$.v +EOF + +# First convert aliases +exec < /tmp/cz$$.a + +# Taken straight from ctoz except for $T and "alias --" +sed -e 's/'"$T"'(\(.*\))/'"$T"'\1/' >/tmp/cz$$.1 +grep ! /tmp/cz$$.1 >/tmp/cz$$.2 +grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3 +sed -e "s/'/'"\\\\"''"/g \ + -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/alias -- \1='"'\2'/" \ + /tmp/cz$$.3 +sed -e 's/![:#]*/$/g' \ + -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/\1 () { \2 }/' \ + /tmp/cz$$.2 + +# Next, convert environment variables +exec < /tmp/cz$$.e + +# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ... +sed -e '/^SHLVL/d' \ + -e "s/'/'"\\\\"''"/g \ + -e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \ + -e "s/$/'/" + +# Finally, convert local variables +sed -e ' +exec < /tmp/cz$$.v + +sed -e 's/'"$T"'/=/' \ + -e "s/'/'"\\\\"''"/g \ + -e '/^[A-Za-z0-9_]*=[^(]/{ + s/=/='"'/"' + s/$/'"'/"' + }' + +rm /tmp/cz$$.? +exit diff --git a/usr/othersrc/public/zsh-2.2/scripts/ctoz b/usr/othersrc/public/zsh-2.2/scripts/ctoz new file mode 100644 index 0000000000..4f18c84583 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/ctoz @@ -0,0 +1,32 @@ +#! /bin/sh +# +# ctoz - alias conversion tool +# This file is part of zsh, the Z shell. +# (c) 1991 Paul Falstad +# +# This is a quick script to convert csh aliases to zsh aliases/functions. +# Pipe the output of csh's alias command through this; it will generate +# a series of alias/function definitions on stdout, suitable for +# processing by zsh (probably also ksh or bash). +# +# This is not perfect, but it gets most common aliases; it should manage to +# cut down a lot of the busy work. +# +sed -e 's/ (\(.*\))/ \1/' >/tmp/cz$$.1 +grep ! /tmp/cz$$.1 >/tmp/cz$$.2 +grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3 +sed -e "s/'/'"\\\\"''"/g -e 's/^\([^ ]*\) \(.*\)$/alias \1='"'\2'/" \ + /tmp/cz$$.3 +sed -e 's/![:#]*/$/g' -e 's/^\([^ ]*\) \(.*\)$/\1 () { \2 }/' /tmp/cz$$.2 +rm /tmp/cz$$.? +# +# in case your mailer eats tabs, here it is again, with the tabs +# marked with a T: +# +#sed -e 's/T(\(.*\))/T\1/' >/tmp/cz$$.1 +#grep ! /tmp/cz$$.1 >/tmp/cz$$.2 +#grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3 +#sed -e "s/'/'"\\\\"''"/g -e 's/^\([^T]*\)T\(.*\)$/alias \1='"'\2'/" \ +# /tmp/cz$$.3 +#sed -e 's/![:#]*/$/g' -e 's/^\([^T]*\)T\(.*\)$/\1 () { \2 }/' /tmp/cz$$.2 +#rm /tmp/cz$$.? diff --git a/usr/othersrc/public/zsh-2.2/scripts/fooz b/usr/othersrc/public/zsh-2.2/scripts/fooz new file mode 100644 index 0000000000..f69f41071f --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/fooz @@ -0,0 +1,78 @@ +alias -- 0='vi' +alias -- a='alias' +alias -- a.out='./a.out' +alias -- c='cp' +alias -- gnu='telnet gnu.ai.mit.edu' +alias -- grep='egrep' +alias -- gz='gdb zsh' +alias -- j='jobs -l' +alias -- k='kill' +alias -- l='ls -AF' +alias -- lock='lock -p -600' +alias -- lsd='ls -d */' +alias -- m='make' +alias -- main='./main' +alias -- man='woman' +alias -- mm='less' +alias -- more='less' +alias -- nw='l -ltr | tail' +alias -- pd='pushd' +alias -- pop='popd' +alias -- ps='sps' +alias -- pwrite='talk' +alias -- rn='h /usr/princeton/bin/rn.4.1' +alias -- rtfm='man' +alias -- strings='strings -' +alias -- t='cat' +alias -- talk='h talk' +alias -- v='mv' +alias -- where='hostname; echo >/dev/null' +alias -- whm='who | mm' +alias -- wm='w | mm' +320 () { $* | fgrep -f /u/pfalstad/src/cs320/cs320list } +acx () { chmod 755 $* } +cx () { chmod +x $* } +f () { $* | fgrep -f /u/pfalstad/.friends } +k9 () { kill -9 $* } +mere () { nroff <$1 -man -Tman | less -s } +nrable () { ls -AFltr $* | grep -v r..r.. } +rable () { ls -AFltr $* | grep r..r.. } +export ATTRIBUTION='%f wrote:' +export CAD_HOME='/u/cad/magic' +export COSMOS='/u/cad/cosmos' +export HOME='/u/pfalstad' +export LESS='-ainx3' +export LM_LICENSE_FILE='/u/cs475/Mentor/etc/license_file' +export LOGNAME='pfalstad' +export MAIL='/usr/spool/mail/pfalstad' +export MAILCALL='NEW MAIL! ' +export MANPATH='/usr/man:/usr/princeton/man:/u/cad/man' +export NAME='Paul Falstad' +export OCTTOOLS='/u/cad/octtools' +export ORGANIZATION='The E. Henry Thripshaw Fan Club' +export PATH='/u/pfalstad/scr:/u/pfalstad/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/u/maruchck/scr:/u/cs320/bin:/u/subbarao/bin:/u/maruchck/bin:/usr/hosts:/usr/princeton/bin/X11:/usr/etc:/etc' +export PRINTER='dod' +export PWD='/n/homeserver/c/pfalstad/zsh2.1/scripts' +export RNINIT='/u/pfalstad/.rninit' +export SCS='/u/cs475/Mentor' +export SCS_LICENSE_CLASS='2' +export SHELL='/u/pfalstad/bin/sun4/zsh' +export TERM='vt100' +export TERMCAP='d0|vt100|vt100-am|vt100am|dec-vt100:do=^J:co#80:li#24:cl=50\E[;H\E[2J:sf=5\ED:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E>\E[?1l\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rf=/usr/share/lib/tabset/vt100:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:xn:sc=\E7:rc=\E8:cs=\E[%i%d;%dr:' +export USER='pfalstad' +export YOUSAID='In %C you wrote:' +export _='/u/pfalstad/zsh2.1/scripts/c2z' +DISPLAY='phoenix:0.0' +HOSTTYPE='sun4' +cdpath=(/u/pfalstad /u/pfalstad/src/cs320 /u/pfalstad/src) +edit= +HISTSIZE='200' +HOME='/u/pfalstad' +mail=(30 /usr/spool/mail/pfalstad) +path=(/u/pfalstad/scr /u/pfalstad/bin/sun4 /usr/princeton/bin /usr/ucb /usr/bin /bin /u/maruchck/scr /u/cs320/bin /u/subbarao/bin /u/maruchck/bin /usr/hosts /usr/princeton/bin/X11 /usr/etc /etc) +prompt='c phoenix% ' +shell='/bin/csh' +setopt globdots +term='vt100' +user='pfalstad' +vi= diff --git a/usr/othersrc/public/zsh-2.2/scripts/fproto b/usr/othersrc/public/zsh-2.2/scripts/fproto new file mode 100755 index 0000000000..46b0988ef9 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/scripts/fproto @@ -0,0 +1,4 @@ +#! /bin/sh +# prototype generator +sed -n '/\/\*\*\/$/{N;s/^\([^(]*\).*\/\*\*\/.\(.*\)/\1 DCLPROTO((\2))/p;}' $1 | sed -e 's/;/,/g' -e 's/,))$/));/' -e 's/(({))$/((void));/' + diff --git a/usr/othersrc/public/zsh-2.2/src/builtin.c b/usr/othersrc/public/zsh-2.2/src/builtin.c new file mode 100644 index 0000000000..8791b7af65 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/builtin.c @@ -0,0 +1,2969 @@ +/* + * + * builtin.c - builtin commands + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include + +#define makecond() allocnode(N_COND) + +/* builtin flags */ + +#define BINF_PLUSOPTS 1 /* +xyz legal */ +#define BINF_R 2 /* this is r (fc -e -) */ +#define BINF_PRINTOPTS 4 +#define BINF_SETOPTS 8 +#define BINF_FCOPTS 16 +#define BINF_TYPEOPT 32 +#define BINF_TYPEOPTS (BINF_TYPEOPT|BINF_PLUSOPTS) +#define BINF_ECHOPTS 64 + +/* builtin funcs */ + +#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_SHIFT 10 +#define BIN_CD 11 +#define BIN_POPD 12 +#define BIN_PUSHD 13 +#define BIN_PRINT 14 +#define BIN_EVAL 15 +#define BIN_SCHED 16 +#define BIN_FC 17 +#define BIN_PUSHLINE 18 +#define BIN_LOGOUT 19 +#define BIN_BUILTIN 20 +#define BIN_TEST 21 +#define BIN_BRACKET 22 + +struct bincmd { + char *name; + int (*handlerfunc) DCLPROTO((char *,char **,char *,int)); + int minargs; /* min # of args */ + int maxargs; /* max # of args, or -1 for no limit */ + int flags; /* BINF_flags (see above) */ + int funcid; /* xbins (see above) for overloaded handlerfuncs */ + char *optstr; /* string of legal options */ + char *defopts; /* options set by default for overloaded handlerfuncs */ + }; + +/* structure for foo=bar assignments */ + +struct asgment { + struct asgment *next; + char *name,*value; + }; + +static char *auxdata; +static int auxlen; +static int showflag = 0,showflag2 = 0; + +struct bincmd builtins[] = { + "[",bin_test,0,-1,0,BIN_BRACKET,NULL,NULL, + ".",bin_dot,1,-1,0,0,NULL,NULL, + ":",bin_colon,0,-1,0,0,NULL,NULL, + "alias",bin_alias,0,-1,0,0,"ga",NULL, + "autoload",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tx","fu", + "bg",bin_fg,0,-1,0,BIN_BG,NULL,NULL, + "bindkey",bin_bindkey,0,-1,0,0,"asvemdrl",NULL, + "break",bin_break,0,1,0,BIN_BREAK,NULL,NULL, + "builtin",NULL,0,0,0,BIN_BUILTIN,NULL,NULL, + "bye",bin_break,0,1,0,BIN_EXIT,NULL,NULL, + "cd",bin_cd,0,2,0,BIN_CD,NULL,NULL, + "chdir",bin_cd,0,2,0,BIN_CD,NULL,NULL, + "compctl",bin_compctl,0,-1,0,0,NULL,NULL, + "continue",bin_break,0,1,0,BIN_CONTINUE,NULL,NULL, + "declare",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL, + "dirs",bin_dirs,0,-1,0,0,"v",NULL, + "disable",bin_disable,1,-1,0,0,NULL,NULL, + "disown",bin_fg,1,-1,0,BIN_DISOWN,NULL,NULL, + "echo",bin_print,0,-1,BINF_PRINTOPTS|BINF_ECHOPTS,BIN_PRINT,"n","-", + "echotc",bin_echotc,1,-1,0,0,NULL,NULL, + "enable",bin_enable,1,-1,0,0,NULL,NULL, + "eval",bin_eval,0,-1,0,BIN_EVAL,NULL,NULL, + "exit",bin_break,0,1,0,BIN_EXIT,NULL,NULL, + "export",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtu","x", + "false",bin_let,0,0,0,0,NULL,NULL, + "fc",bin_fc,0,-1,BINF_FCOPTS,BIN_FC,"nlreRWAdD",NULL, + "fg",bin_fg,0,-1,0,BIN_FG,NULL,NULL, + "functions",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tu","f", + "getln",bin_read,0,-1,0,0,NULL,"zr", + "getopts",bin_getopts,2,-1,0,0,NULL,NULL, + "hash",bin_hash,2,2,0,0,"r",NULL, + "history",bin_fc,0,-1,0,BIN_FC,"nrdD","l", + "integer",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZlrtux","i", + "jobs",bin_fg,0,-1,0,BIN_JOBS,"lpZ",NULL, + "kill",bin_kill,0,-1,0,0,NULL,NULL, + "let",bin_let,1,-1,0,0,NULL,NULL, + "limit",bin_limit,0,-1,0,0,"sh",NULL, + "local",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL, + "log",bin_log,0,0,0,0,NULL,NULL, + "logout",bin_break,0,1,0,BIN_LOGOUT,NULL,NULL, + "popd",bin_cd,0,2,0,BIN_POPD,NULL,NULL, + "print",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,"RDPnrslzNu0123456789p-",NULL, + "pushd",bin_cd,0,2,0,BIN_PUSHD,NULL,NULL, + "pushln",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,NULL,"-nz", + "pwd",bin_pwd,0,0,0,0,NULL,NULL, + "r",bin_fc,0,-1,BINF_R,BIN_FC,"nrl",NULL, + "read",bin_read,0,-1,0,0,"rzu0123456789p",NULL, + "readonly",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfiltux","r", + "rehash",bin_rehash,0,0,0,0,"f",NULL, + "return",bin_break,0,1,0,BIN_RETURN,NULL,NULL, + "sched",bin_sched,0,-1,0,0,NULL,NULL, + "set",bin_set,0,-1,BINF_SETOPTS|BINF_PLUSOPTS,0,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZaefghijklnosuvwxy",NULL, + "setopt",bin_setopt,0,-1,BINF_PLUSOPTS,0,"0123456789BCDEFGHIJKLMNOPQRSTUVWXYZaefghijklmnosuvwxy",NULL, + "shift",bin_break,0,1,0,BIN_SHIFT,NULL,NULL, + "source",bin_dot,1,-1,0,0,NULL,NULL, + "suspend",bin_suspend,0,0,0,0,"f",NULL, + "test",bin_test,0,-1,0,BIN_TEST,NULL,NULL, + "ttyctl",bin_ttyctl,0,0,0,0,"fu",NULL, + "times",bin_times,0,0,0,0,NULL,NULL, + "trap",bin_trap,0,-1,0,0,NULL,NULL, + "true",bin_colon,0,0,0,0,NULL,NULL, + "type",bin_whence,0,-1,0,0,"pfa","v", + "typeset",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL, + "ulimit",bin_ulimit,0,1,0,0,"HSacdfmnt",NULL, + "umask",bin_umask,0,1,0,0,NULL,NULL, + "unalias",bin_unalias,1,-1,0,0,NULL,NULL, + "unfunction",bin_unhash,1,-1,0,0,NULL,NULL, + "unhash",bin_unhash,1,-1,0,0,NULL,NULL, + "unlimit",bin_unlimit,0,-1,0,0,"h",NULL, + "unset",bin_unset,1,-1,0,0,NULL,NULL, + "unsetopt",bin_setopt,0,-1,BINF_PLUSOPTS,1,"0123456789BCDEFGHIJKLMNOPQRSTUWXYZabefghijklmnosuvwxy",NULL, + "vared",bin_vared,1,1,0,0,NULL,NULL, + "wait",bin_fg,0,-1,0,BIN_WAIT,NULL,NULL, + "whence",bin_whence,0,-1,0,0,"pvcfa",NULL, + "which",bin_whence,0,-1,0,0,"pa","c", + NULL,NULL,0,0,0,0,NULL,NULL + }; + +/* print options */ + +static void prtopt() +{ +struct option *opp; + + if (isset(KSHOPTIONPRINT)) { + printf("Current option settings\n"); + for (opp = optns; opp->name; opp++) + printf("%-20s%s\n", opp->name, + (opts[opp->id] == OPT_SET) ? "on" : "off"); + } else + for (opp = optns; opp->name; opp++) + if (opts[opp->id] == OPT_SET) + puts(opp->name); +} + +/* add builtins to the command hash table */ + +void addbuiltins() /**/ +{ +struct cmdnam *c; +struct bincmd *b; +int t0; + + for (t0 = 0, b = builtins; b->name; b++,t0++) + { + c = (Cmdnam) zcalloc(sizeof *c); + c->type = BUILTIN; + c->u.binnum = t0; + addhperm(b->name,c,cmdnamtab,freecmdnam); + } +} + +/* enable */ + +int bin_enable(name,argv,ops,whocares) /**/ +char *name;char **argv;char *ops;int whocares; +{ +struct cmdnam *c; +struct bincmd *b; +int t0,ret = 0; + + for (; *argv; argv++) + { + for (t0 = 0, b = builtins; b->name; b++,t0++) + if (!strcmp(*argv,b->name)) + break; + if (!b->name) + { + zerrnam(name,"no such builtin: %s",*argv,0); + ret = 1; + } + else + { + c = (Cmdnam) zcalloc(sizeof *c); + c->type = BUILTIN; + c->u.binnum = t0; + addhperm(b->name,c,cmdnamtab,freecmdnam); + } + } + return ret; +} + +/* :, true */ + +int bin_colon(name,argv,ops,whocares) /**/ +char *name;char **argv;char *ops;int whocares; +{ + return 0; +} + +/* break, bye, continue, exit, logout, return, shift */ + +int bin_break(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int num = -1; + + if (*argv) + num = matheval(*argv); + if ((func == BIN_BREAK || func == BIN_CONTINUE) && !loops) + { + if (func == BIN_CONTINUE) + zerrnam(name,"not in loop",NULL,0); + return 1; + } + switch (func) + { + case BIN_CONTINUE: + contflag = 1; + case BIN_BREAK: + breaks = (num == -1) ? 1 : num; + if (breaks > loops) breaks = loops; + break; + case BIN_LOGOUT: + if (!islogin) + { + zerrnam(name,"not login shell",NULL,0); + return 1; + } + case BIN_EXIT: + zexit((num == -1) ? lastval : num); + break; + case BIN_RETURN: + retflag = 1; + return lastval = (num == -1) ? lastval : num; + case BIN_SHIFT: + { + char **s; + + if (num == -1) + num = 1; + if (num > arrlen(pparams)) + num = arrlen(pparams); + permalloc(); + s = arrdup(pparams+num); + heapalloc(); + freearray(pparams); + pparams = s; + break; + } + } + return 0; +} + +/* bg, disown, fg, jobs, wait */ + +int bin_fg(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int job,lng,firstjob = -1,retval = 0; + + if (ops['Z']) { if (*argv) strcpy(hackzero,*argv); return 0; } + lng = (ops['l']) ? 1 : (ops['p']) ? 2 : 0; + if ((func == BIN_FG || func == BIN_BG) && !jobbing) + { + zerrnam(name,"no job control in this shell.",NULL,0); + return 1; + } + if (unset(NOTIFY)) scanjobs(); + if (!(jobtab[curjob].stat & STAT_INUSE)) + { + curjob = prevjob; setprevjob(); + if (!(jobtab[curjob].stat & STAT_INUSE)) + curjob = prevjob; setprevjob(); + } + if (func == BIN_JOBS) + stopmsg = 2; + if (!*argv) + if (func == BIN_FG || func == BIN_BG) + { + if (curjob == -1 || curjob == thisjob) + { + zerrnam(name,"no current job",NULL,0); + return 1; + } + firstjob = curjob; + } + else if (func == BIN_JOBS) + { + for (job = 0; job != MAXJOB; job++) + if (job != thisjob && jobtab[job].stat) + printjob(job+jobtab,lng); + return 0; + } + else + { + for (job = 0; job != MAXJOB; job++) + if (job != thisjob && jobtab[job].stat) + waitjob(job); + return lastval; + } + for (; (firstjob != -1) || *argv; ( void ) (*argv && argv++)) + { + int stopped,ocj = thisjob; + + if (func == BIN_WAIT && isanum(*argv)) { + waitforpid((long) atoi(*argv)); + retval = lastval; + thisjob = ocj; + continue; + } + job = (*argv) ? getjob(*argv,name) : firstjob; + firstjob = -1; + if (job == -1) + break; + if (!(jobtab[job].stat & STAT_INUSE)) + { + zerrnam(name,"no such job: %d",0,job); + return 1; + } + switch (func) + { + case BIN_FG: + case BIN_BG: + if (stopped = (jobtab[job].stat & STAT_STOPPED)) + makerunning(jobtab+job); + else if (func == BIN_BG) + { + zerrnam(name,"job already in background",NULL,0); + thisjob = ocj; + return 1; + } + if (curjob == job) + { + curjob = prevjob; + prevjob = (func == BIN_BG) ? -1 : job; + } + if (prevjob == job) + prevjob = -1; + if (prevjob == -1) + setprevjob(); + if (curjob == -1) + { + curjob = prevjob; + setprevjob(); + } + printjob(jobtab+job,(stopped) ? -1 : 0); + if (func == BIN_FG) + { + thisjob = job; + if (strcmp(jobtab[job].pwd,pwd)) + { + printf("(pwd : "); + printdir(jobtab[job].pwd); + printf(")\n"); + } + fflush(stdout); + attachtty(jobtab[job].gleader); + } + if (stopped) + killpg(jobtab[job].gleader,SIGCONT); + if (func == BIN_FG) + waitjobs(); + break; + case BIN_JOBS: + printjob(job+jobtab,lng); + break; + case BIN_WAIT: + waitjob(job); + retval = lastval; + break; + case BIN_DISOWN: + { + static struct job zero; + jobtab[job] = zero; + break; + } + } + thisjob = ocj; + } + return retval; +} + +/* false, let */ + +int bin_let(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +long val = 0; + + while (*argv) + val = matheval(*argv++); + return !val; +} + +/* print the directory stack */ + +static void pdstack() +{ +Lknode node; + + printdir(pwd); + for (node = firstnode(dirstack); node; incnode(node)) + { + putchar(' '); + printdir(getdata(node)); + } + putchar('\n'); +} + +/* exit the shell */ + +int zexit(val) /**/ +int val; +{ + if (isset(MONITOR)) + if (!stopmsg) { + checkjobs(); + if (stopmsg) { + stopmsg = 2; + return 1; + } + } else killrunjobs(); + savehistfile(getsparam("HISTFILE"),0,0); + if (islogin && unset(NORCS)) + sourcehome(".zlogout"); + if (sigtrapped[SIGEXIT]) + dotrap(SIGEXIT); + exit(val); return 0; +} + +/* identify an option name */ + +int optlookup(s) /**/ +char *s; +{ +char *t; +struct option *o; + + t = s = strdup(s); + while (*t) + if (*t == '_') + chuck(t); + else { + *t = tulower(*t); + t++; + } + for (o = optns; o->name; o++) + if (!strcmp(o->name,s)) + return o->id; + return -1; +} + +/* setopt, unsetopt */ + +int bin_setopt(nam,args,ops,isun) /**/ +char *nam;char **args;char *ops;int isun; +{ +struct option *opp; +int c; + + if (!ops['@'] && !*args) { + if (!isun) + prtopt(); + return 0; + } + for (opp = optns; opp->name; opp++) + if (ops[opp->id] == 1+isun) + opts[opp->id] = OPT_SET; + else if (ops[opp->id] == 2-isun) + opts[opp->id] = OPT_UNSET; + while (*args) { + c = optlookup(*args++); + if (c != -1) { + if (c == INTERACTIVE || c == MONITOR) + zerrnam(nam,"can't change that option",NULL,0); + else + opts[c] = (isun) ? OPT_UNSET : OPT_SET; + } else { + zerrnam(nam,"no such option: %s",args[-1],0); + return 1; + } + } + return 0; +} + +/* execute func on each member of the hash table ht */ + +void listhtable(ht,func) /**/ +Hashtab ht;HFunc func; +{ +int t0; +struct hashnode *hn; + + for (t0 = ht->hsize-1; t0 >= 0; t0--) + for (hn = ht->nodes[t0]; hn; hn = hn->next) + func(hn->nam,(char *) hn); +} + +/* print a shell function (used with listhtable) */ + +void pshfunc(s,cc) /**/ +char *s;Cmdnam cc; +{ +char *t; + + if (cc->type != SHFUNC) + return; + if (showflag && (cc->flags & showflag2) != showflag2) + return; + if (cc->flags & PMFLAG_u) + printf("undefined "); + if (cc->flags & PMFLAG_t) + printf("traced "); + if (!cc->u.list || !showflag) { + printf("%s ()\n",s); + return; + } + t = getpermtext((vptr) (cc->u.list)); + printf("%s () {\n\t%s\n}\n",s,t); + free(t); +} + +void niceprint(s) /**/ +char *s; +{ + niceprintf(s,stdout); +} + +void niceprintf(s,f) /**/ +char *s;FILE *f; +{ + for (; *s; s++) + { + if (isprint(*s)) + fputc(*s,f); + else if (*s == '\n') + { + putc('\\',f); + putc('n',f); + } + else + { + putc('^',f); + fputc(*s | 0x40,f); + } + } +} + +int bin_umask(nam,args,ops,func) /**/ +char *nam;char **args;char *ops;int func; +{ +int um; +char *s = *args; + + um = umask(0); + umask(um); + if (!s) + { + printf("%03o\n",um); + return 0; + } + if (idigit(*s)) + { + um = zstrtol(s,&s,8); + if (*s) + { + zerrnam(nam,"bad umask",NULL,0); + return 1; + } + } + else + { + int whomask,op,mask; + + for (;;) + { + if (*s == 'u') + s++, whomask = 0100; + else if (*s == 'g') + s++, whomask = 0010; + else if (*s == 'o') + s++, whomask = 0001; + else + whomask = 0111; + op = *s++; + if (!(op == '+' || op == '-' || op == '=')) + { + zerrnam(nam,"bad symbolic mode operator: %c",NULL,op); + return 1; + } + mask = whomask; + if (*s == 'r') + mask *= 04; + else if (*s == 'w') + mask *= 02; + else if (*s != 'x') + { + zerrnam(nam,"bad symbolic mode permission: %c",NULL,*s); + return 1; + } + if (op == '+') + um |= mask; + else if (op == '-') + um &= ~mask; + else /* op == '=' */ + um = (um & ~(whomask*07)) | mask; + if (*++s == ',') + s++; + else + break; + } + if (*s) + { + zerrnam(nam,"bad character in symbolic mode: %c",NULL,*s); + return 1; + } + } + umask(um); + return 0; +} + +/* type, whence, which */ + +int bin_whence(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +struct cmdnam *chn; +struct alias *a; +int retval = 0; +int csh = ops['c'],all = ops['a']; +int v = ops['v'] || csh; +char *cnam; + + for (; *argv; argv++) { + if (!ops['p'] && (a = (Alias) gethnode(*argv,aliastab))) { + if (a->cmd < 0) + printf((csh) ? "%s: shell reserved word\n" : + (v) ? "%s is a reserved word\n" : "%s\n",*argv); + else if (!v) + puts(a->text); + else if (a->cmd) + printf((csh) ? "%s: aliased to %s\n" : + "%s is an alias for %s\n",*argv,a->text); + else + printf((csh) ? "%s: globally aliased to %s\n" : + "%s is a global alias for %s\n",*argv,a->text); + retval = 0; + if (!all) continue; + } + if (!ops['p'] && (chn = (Cmdnam) gethnode(*argv,cmdnamtab)) && + (chn->type == SHFUNC || chn->type == BUILTIN)) { + if (chn->type == SHFUNC) { + if (csh || ops['f']) { + showflag = 1; showflag2 = 0; + pshfunc(*argv,chn); + } else { + printf((v) ? "%s is a function\n" : "%s\n",*argv); + } + } else + printf((csh) ? "%s: shell built-in command\n" : + (v) ? "%s is a shell builtin\n" : "%s\n",*argv); + retval = 0; + if (!all) continue; + } + if (all) { + char **pp,buf[MAXPATHLEN],*z; + for (pp = path; *pp; pp++) { + z = buf; + strucpy(&z,*pp); + *z++ = '/'; + strcpy(z,*argv); + if (iscom(buf)) { + if (v && !csh) printf("%s is %s\n",*argv,buf); + else puts(buf); + retval = 0; + } + } + } else if (!(cnam = findcmd(*argv))) { + if (v) printf("%s not found\n",*argv); + retval = 1; + break; + } else { + if (v && !csh) printf("%s is %s\n",*argv,cnam); + else puts(cnam); + retval = 0; + } + } + return retval; +} + +/* cd, chdir, pushd, popd */ + +int bin_cd(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +char *dest; + + if (func == BIN_CD && isset(AUTOPUSHD)) + func = BIN_PUSHD; + dest = cd_get_dest(nam,argv,ops,func); + if (!dest) return 1; + dest = cd_do_chdir(nam,dest); + if (!dest) return 1; + cd_new_pwd(func,dest); + return 0; +} + +char *cd_get_dest(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +char *dest; + + if (!argv[0]) + if (func == BIN_CD || (func == BIN_PUSHD && isset(PUSHDTOHOME) + || !full(dirstack))) + dest = home; + else + dest = getnode(dirstack); + else if (!argv[1]) { + Lknode n; + int dd; + + if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '-' : '+')) { + dd = atoi(argv[0]+1)-1; + if (dd < 0) { + zerrnam(nam,"bad directory specification",NULL,0); + return NULL; + } + for (n = firstnode(dirstack); n && dd; dd--, incnode(n)); + if (!n) { + zerrnam(nam,"no such entry in dir stack",NULL,0); + return NULL; + } + dest = remnode(dirstack,n); + } else if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '+' : '-')) { + dd = atoi(argv[0]+1); + for (n = lastnode(dirstack); n != (Lknode) dirstack && dd; + dd--, n = prevnode(n)); + if (n == (Lknode) dirstack) { + zerrnam(nam,"no such entry in dir stack",NULL,0); + return NULL; + } + dest = remnode(dirstack,n); + } else { + if (!strcmp(argv[0],"-")) printdircr(dest = oldpwd); + else dest = argv[0]; + } + } else { + char *u; + int len1,len2,len3; + + if (!(u = ztrstr(pwd,argv[0]))) { + zerrnam(nam,"string not in pwd: %s",argv[0],0); + return NULL; + } + len1 = strlen(argv[0]); + len2 = strlen(argv[1]); + len3 = u-pwd; + dest = alloc(len3+len2+strlen(u+len1)+1); + strncpy(dest,pwd,len3); + strcpy(dest+len3,argv[1]); + strcat(dest,u+len1); + printdircr(dest); + } + return dest; +} + +char *cd_do_chdir(cnam,dest) /**/ +char *cnam; char *dest; +{ +int hasdot = 0, eno = ENOENT; +char **pp,*ret; + + if (*dest == '/') { + if (ret = cd_try_chdir(NULL,dest)) return ret; + zerrnam(cnam,"%e: %s",dest,errno); + return NULL; + } + for (pp = cdpath; *pp; pp++) + if ((*pp)[0] == '.' && (*pp)[1] == '\0') hasdot = 1; + if (!hasdot) { + if (ret = cd_try_chdir(NULL,dest)) return ret; + if (errno != ENOENT) eno = errno; + } + for (pp = cdpath; *pp; pp++) { + if (ret = cd_try_chdir(*pp,dest)) { + if (strcmp(*pp,".")) { + printdircr(ret); + } + return ret; + } + if (errno != ENOENT) eno = errno; + } + if (isset(CDABLEVARS)) { + char *s = getsparam(dest); + if (s && *s == '/' && chdir(s) != -1) { + printdircr(s); + return s; + } + if (errno != ENOENT) eno = errno; + } + zerrnam(cnam,"%e: %s",dest,eno); + return NULL; +} + +char *cd_try_chdir(pfix,dest) /**/ +char *pfix; char *dest; +{ +static char buf[MAXPATHLEN], buf2[MAXPATHLEN]; +char *s; +int dotsct; + + if (pfix) sprintf(buf,"%s/%s",(!strcmp("/",pfix)) ? "" : pfix,dest); + else strcpy(buf,dest); + dotsct = fixdir(buf2,buf); + if (buf2[0] == '/') return (chdir(buf2) == -1) ? NULL : buf2; + if (!dotsct) { + if (chdir((*buf2) ? buf2 : ".") == -1) return NULL; + if (*buf2) sprintf(buf,"%s/%s",(!strcmp("/",pwd)) ? "" : pwd,buf2); + else strcpy(buf,pwd); + return buf; + } + strcpy(buf,pwd); + s = buf+strlen(buf)-1; + while (dotsct--) while (s != buf) if (*--s == '/') break; + if (s == buf || *buf2) s++; + strcpy(s,buf2); + if (chdir(buf) != -1 || chdir(dest) != -1) return buf; + return NULL; +} + +int fixdir(d,s) /**/ +char *d; char *s; +{ +int ct = 0; +char *d0 = d; + +#ifdef HAS_RFS + if (*s == '/' && s[1] == '.' && s[2] == '.') { + *d++ = '/'; *d++ = '.'; *d++ = '.'; + s += 3; + } +#endif + for (;;) { + if (*s == '/') { + *d++ = *s++; + while (*s == '/') s++; + } + if (!*s) { + while (d > d0+1 && d[-1] == '/') d--; + *d = '\0'; + return ct; + } + if (s[0] == '.' && s[1] == '.' && (s[2] == '\0' || s[2] == '/')) { + if (d > d0+1) { + for (d--; d > d0+1 && d[-1] != '/'; d--); + } else ct++; + s += 2; if (*s) s++; + } else if (s[0] == '.' && (s[1] == '/' || s[1] == '\0')) { + s++; if (*s) s++; + } else { + while (*s != '/' && *s != '\0') *d++ = *s++; + } + } +} + +void cd_new_pwd(func,s) /**/ +int func; char *s; +{ +Param pm; +List l; + + oldpwd = pwd; + if (isset(CHASELINKS)) + pwd = findpwd(s); + else + pwd = ztrdup(s); + if ((pm = gethnode("PWD", paramtab)) && + (pm->flags & PMFLAG_x) && pm->env) + pm->env = replenv(pm->env,pwd); + if ((pm = gethnode("OLDPWD", paramtab)) && + (pm->flags & PMFLAG_x) && pm->env) + pm->env = replenv(pm->env,oldpwd); + if (func == BIN_PUSHD) { + permalloc(); + if (isset(PUSHDIGNOREDUPS)) { + Lknode n; + for (n = firstnode(dirstack); n; incnode(n)) + if (!strcmp(oldpwd,getdata(n))) { + free(remnode(dirstack,n)); break; + } + } + pushnode(dirstack,oldpwd); + heapalloc(); + } + if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE)) + pdstack(); + if (l = getshfunc("chpwd")) { + fflush(stdout); fflush(stderr); + doshfuncnoval(dupstruct(l),NULL,0); + } + if (dirstacksize != -1 && countnodes(dirstack) >= dirstacksize) { + if (dirstacksize < 2) + dirstacksize = 2; + else + free(remnode(dirstack,lastnode(dirstack))); + } +} + +void convertwd(s,t,off) /**/ +char *s; char *t; int off; +{ +char *u,*start; + + *t++ = '/'; + start = t; + while (off--) *t++ = *s++; + for (;;) { + while (*s == '/') s++; + for (u = s; *u && *u != '/'; u++); + if (!strncmp(s,".",u-s)) { + ; + } else if (!strncmp(s,"..",u-s)) { + while (t != start && *--t != '/'); + } else { + if (t != start) *t++ = '/'; + struncpy(&t,s,u-s); + } + if (!*u) break; + s = u; + } + *t = '\0'; +} + +int bin_rehash(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ + newcmdnamtab(); + if (ops['f']) fullhash(); + return 0; +} + +int bin_hash(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +struct cmdnam *chn; + + chn = (Cmdnam) zcalloc(sizeof *chn); + chn->type = EXCMD; + chn->pcomp = NULL; /* this is probably a bug ! */ + chn->u.nam = ztrdup(argv[1]); + addhnode(ztrdup(argv[0]),chn,cmdnamtab,freecmdnam); + return 0; +} + +/* != 0 if s is a prefix of t */ + +int prefix(s,t) /**/ +char *s;char *t; +{ + while (*s && *t && *s == *t) s++,t++; + return (!*s); +} + +/* convert %%, %1, %foo, %?bar? to a job number */ + +int getjob(s,prog) /**/ +char *s;char *prog; +{ +int t0,retval; + + if (*s != '%') + goto jump; + s++; + if (*s == '%' || *s == '+' || !*s) + { + if (curjob == -1) + { + zerrnam(prog,"no current job",NULL,0); + retval = -1; goto done; + } + retval = curjob; goto done; + } + if (*s == '-') + { + if (prevjob == -1) + { + zerrnam(prog,"no previous job",NULL,0); + retval = -1; goto done; + } + retval = prevjob; goto done; + } + if (idigit(*s)) + { + t0 = atoi(s); + if (t0 && t0 < MAXJOB && jobtab[t0].stat && t0 != thisjob) + { retval = t0; goto done; } + zerrnam(prog,"no such job",NULL,0); + retval = -1; goto done; + } + if (*s == '?') + { + struct process *pn; + + for (t0 = MAXJOB-1; t0 >= 0; t0--) + if (jobtab[t0].stat && t0 != thisjob) + for (pn = jobtab[t0].procs; pn; pn = pn->next) + if (ztrstr(pn->text,s+1)) + { retval = t0; goto done; } + zerrnam(prog,"job not found: %s",s,0); + retval = -1; goto done; + } +jump: + if ((t0 = findjobnam(s)) != -1) + { retval = t0; goto done; } + zerrnam(prog,"job not found: %s",s,0); + retval = -1; +done: + return retval; +} + +/* find a job named s */ + +int findjobnam(s) /**/ +char *s; +{ +int t0; + + for (t0 = MAXJOB-1; t0 >= 0; t0--) + if (jobtab[t0].stat && jobtab[t0].procs && t0 != thisjob && + jobtab[t0].procs->text && prefix(s,jobtab[t0].procs->text)) + return t0; + return -1; +} + +int isanum(s) /**/ +char *s; +{ + while (*s == '-' || idigit(*s)) s++; + return *s == '\0'; +} + +int bin_kill(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +int sig = SIGTERM; +int retval = 0; + + if (*argv && **argv == '-') { + if (idigit((*argv)[1])) + sig = atoi(*argv+1); + else { + if ((*argv)[1] == 'l' && (*argv)[2] == '\0') { + printf("%s",sigs[1]); + for (sig = 2; sig != SIGCOUNT; sig++) + printf(" %s",sigs[sig]); + putchar('\n'); + return 0; + } + for (sig = 0; sig != SIGCOUNT; sig++) + if (!strcmp(sigs[sig],*argv+1)) break; + if (sig == SIGCOUNT) { + zerrnam(nam,"unknown signal: SIG%s",*argv+1,0); + zerrnam(nam,"type kill -l for a List of signals",NULL,0); + return 1; + } + } + argv++; + } + for (; *argv; argv++) { + if (**argv == '%') { + int p = getjob(*argv,"kill"); + + if (p == -1) { + retval = 1; + continue; + } + if (killjb(jobtab+p,sig) == -1) { + zerrnam("kill","kill failed: %e",NULL,errno); + retval = 1; + continue; + } + if (jobtab[p].stat & STAT_STOPPED) { + if (sig == SIGCONT) + jobtab[p].stat &= ~STAT_STOPPED; + if (sig != SIGKILL && sig != SIGCONT && sig != SIGTSTP + && sig != SIGTTOU && sig != SIGTTIN && sig != SIGSTOP) + killjb(jobtab+p,SIGCONT); + } + } else if (!isanum(*argv)) { + zerrnam("kill","illegal pid: %s",*argv,0); + } else if (kill(atoi(*argv),sig) == -1) { + zerrnam("kill","kill failed: %e",NULL,errno); + retval = 1; + } + } + return 0; +} + +static char *recs[] = { + "cputime","filesize","datasize","stacksize","coredumpsize", + "resident","descriptors" + }; + +int bin_limit(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +#ifndef RLIM_INFINITY + zerrnam(nam,"not available on this system",NULL,0); + return 1; +#else +char *s; +int hard = ops['h'],t0,lim; +long val; + + if (ops['s']) + { + if (*argv) + zerrnam(nam,"arguments after -s ignored",NULL,0); + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + if (setrlimit(t0,limits+t0) < 0) + zerrnam(nam,"setrlimit failed: %e",NULL,errno); + return 0; + } + if (!*argv) + { + showlimits(hard,-1); + return 0; + } + while (s = *argv++) + { + for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++) + if (!strncmp(recs[t0],s,strlen(s))) + { + if (lim != -1) + lim = -2; + else + lim = t0; + } + if (lim < 0) + { + zerrnam("limit", + (lim == -2) ? "ambiguous resource specification: %s" + : "no such resource: %s",s,0); + return 1; + } + if (!(s = *argv++)) + { + showlimits(hard,lim); + return 0; + } + if (!lim) + { + val = zstrtol(s,&s,10); + if (*s) + if ((*s == 'h' || *s == 'H') && !s[1]) + val *= 3600L; + else if ((*s == 'm' || *s == 'M') && !s[1]) + val *= 60L; + else if (*s == ':') + val = val*60+zstrtol(s+1,&s,10); + else + { + zerrnam("limit","unknown scaling factor: %s",s,0); + return 1; + } + } +#ifdef RLIMIT_NOFILE + else if (lim == RLIMIT_NOFILE) + val = zstrtol(s,&s,10); +#endif + else + { + val = zstrtol(s,&s,10); + if (!*s || ((*s == 'k' || *s == 'K') && !s[1])) + val *= 1024L; + else if ((*s == 'M' || *s == 'm') && !s[1]) + val *= 1024L*1024; + else + { + zerrnam("limit","unknown scaling factor: %s",s,0); + return 1; + } + } + if (hard) + if (val > limits[lim].rlim_max && geteuid()) + { + zerrnam("limit","can't raise hard limits",NULL,0); + return 1; + } + else + { + limits[lim].rlim_max = val; + if (limits[lim].rlim_max < limits[lim].rlim_cur) + limits[lim].rlim_cur = limits[lim].rlim_max; + } + else + if (val > limits[lim].rlim_max) + { + zerrnam("limit","limit exceeds hard limit",NULL,0); + return 1; + } + else + limits[lim].rlim_cur = val; + } + return 0; +#endif +} + +int bin_unlimit(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +#ifndef RLIM_INFINITY + zerrnam(nam,"not available on this system",NULL,0); + return 1; +#else +int hard = ops['h'],t0,lim; + + if (hard && geteuid()) + { + zerrnam(nam,"can't remove hard limits",NULL,0); + return 1; + } + if (!*argv) + { + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + { + if (hard) + limits[t0].rlim_max = RLIM_INFINITY; + else + limits[t0].rlim_cur = limits[t0].rlim_max; + } + return 0; + } + for (; *argv; argv++) + { + for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++) + if (!strncmp(recs[t0],*argv,strlen(*argv))) + { + if (lim != -1) + lim = -2; + else + lim = t0; + } + if (lim < 0) + { + zerrnam(nam, + (lim == -2) ? "ambiguous resource specification: %s" + : "no such resource: %s",*argv,0); + return 1; + } + if (hard) + limits[lim].rlim_max = RLIM_INFINITY; + else + limits[lim].rlim_cur = limits[lim].rlim_max; + } + return 0; +#endif +} + +void showlimits(hard,lim) /**/ +int hard;int lim; +{ +int t0; +long val; + +#ifdef RLIM_INFINITY + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + if (t0 == lim || lim == -1) + { + printf("%-16s",recs[t0]); + val = (hard) ? limits[t0].rlim_max : limits[t0].rlim_cur; + if (val == RLIM_INFINITY) + printf("unlimited\n"); + else if (!t0) + printf("%d:%02d:%02d\n",(int) (val/3600), + (int) (val/60) % 60,(int) (val % 60)); +#ifdef RLIMIT_NOFILE + else if (t0 == RLIMIT_NOFILE) + printf("%d\n",(int) val); +#endif + else if (val >= 1024L*1024L) + printf("%ldMb\n",val/(1024L*1024L)); + else + printf("%ldKb\n",val/1024L); + } +#endif +} + +int bin_sched(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +char *s = *argv++; +time_t t; +long h,m; +struct tm *tm; +struct schedcmd *sch,*sch2,*schl; +int t0; + + if (s && *s == '-') + { + t0 = atoi(s+1); + + if (!t0) + { + zerrnam("sched","usage for delete: sched -.",NULL,0); + return 1; + } + for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds, t0--; + sch && t0; sch = (schl = sch)->next, t0--); + if (!sch) + { + zerrnam("sched","not that many entries",NULL,0); + return 1; + } + schl->next = sch->next; + free(sch->cmd); + free(sch); + return 0; + } + if (!s) + { + char tbuf[40]; + + for (t0 = 1, sch = schedcmds; sch; sch = sch->next,t0++) + { + t = sch->time; + tm = localtime(&t); + ztrftime(tbuf,20,"%a %b %e %k:%M:%S",tm); + printf("%3d %s %s\n",t0,tbuf,sch->cmd); + } + return 0; + } + else if (!*argv) + { + zerrnam("sched","not enough arguments",NULL,0); + return 1; + } + if (*s == '+') + { + h = zstrtol(s+1,&s,10); + if (*s != ':') + { + zerrnam("sched","bad time specifier",NULL,0); + return 1; + } + m = zstrtol(s+1,&s,10); + if (*s) + { + zerrnam("sched","bad time specifier",NULL,0); + return 1; + } + t = time(NULL)+h*3600+m*60; + } + else + { + h = zstrtol(s,&s,10); + if (*s != ':') + { + zerrnam("sched","bad time specifier",NULL,0); + return 1; + } + m = zstrtol(s+1,&s,10); + if (*s && *s != 'a' && *s != 'p') + { + zerrnam("sched","bad time specifier",NULL,0); + return 1; + } + t = time(NULL); + tm = localtime(&t); + t -= tm->tm_sec+tm->tm_min*60+tm->tm_hour*3600; + if (*s == 'p') + h += 12; + t += h*3600+m*60; + if (t < time(NULL)) + t += 3600*24; + } + sch = zcalloc(sizeof *sch); + sch->time = t; + sch->cmd = ztrdup(spacejoin(argv)); + sch->next = NULL; + for (sch2 = (struct schedcmd *) &schedcmds; sch2->next; sch2 = sch2->next); + sch2->next = sch; + return 0; +} + +int bin_eval(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +char *s = ztrdup(spacejoin(argv)); +List list; + + hungets(s); + free(s); + strinbeg(); + if (!(list = parse_list())) + { + hflush(); + strinend(); + return 1; + } + strinend(); + runlist(list); + return lastval; +} + +/* get the history event associated with s */ + +int fcgetcomm(s) /**/ +char *s; +{ +int cmd; + + if (cmd = atoi(s)) + { + if (cmd < 0) + cmd = curhist+cmd+1; + return cmd; + } + cmd = hcomsearch(s); + if (cmd == -1) + zerrnam("fc","event not found: %s",s,0); + return cmd; +} + +/* perform old=new substituion */ + +int fcsubs(sp,sub) /**/ +char **sp;struct asgment *sub; +{ +char *s1,*s2,*s3,*s4,*s = *sp,*s5; +int subbed = 0; + + while (sub) + { + s1 = sub->name; + s2 = sub->value; + sub = sub->next; + s5 = s; + while (s3 = (char *) ztrstr(s5,s1)) + { + s4 = alloc(1+(s3-s)+strlen(s2)+strlen(s3+strlen(s1))); + ztrncpy(s4,s,s3-s); + strcat(s4,s2); + s5 = s4+strlen(s4); + strcat(s4,s3+strlen(s1)); + s = s4; + subbed = 1; + } + } + *sp = s; + return subbed; +} + +/* print a series of history events to a file */ + +int fclist(f,n,r,D,d,first,last,subs) /**/ +FILE *f;int n;int r;int D;int d;int first;int last;struct asgment *subs; +{ +int done = 0; +char *s,*hs; +Histent ent; + + if (!subs) done = 1; + for (;;) { + hs = quietgetevent(first); + if (!hs) { + zerrnam("fc","no such event: %d",NULL,first); + return 1; + } + s = makehstr(hs); + done |= fcsubs(&s,subs); + if (n) fprintf(f,"%5d ",first); + ent = NULL; + if (d) { + struct tm *ltm; + + if (!ent) ent = gethistent(first); + ltm = localtime(&ent->stim); + fprintf(f,"%2d:%02d ",ltm->tm_hour,ltm->tm_min); + } + if (D) { + long diff; + + if (!ent) ent = gethistent(first); + diff = (ent->ftim) ? ent->ftim-ent->stim : 0; + fprintf(f,"%d:%02d ",diff/60,diff%60); + } + if (f == stdout) { + niceprintf(s,f); + putc('\n',f); + } else fprintf(f,"%s\n",s); + if (first == last) break; + (r) ? first-- : first++; + } + if (f != stdout) fclose(f); + if (!done) { + zerrnam("fc","no substitutions performed",NULL,0); + return 1; + } + return 0; +} + +int fcedit(ename,fn) /**/ +char *ename;char *fn; +{ + if (!strcmp(ename,"-")) + return 1; + return !zyztem(ename,fn); +} + +/* fc, history, r */ + +int bin_fc(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ +int first = -1,last = -1,retval,minflag = 0; +char *s; +struct asgment *asgf = NULL,*asgl = NULL; + + if (!interact) { + zerrnam(nam,"not interactive shell",NULL,0); + return 1; + } + if (!(ops['l'] && unset(HISTNOSTORE))) remhist(); + if (ops['R']) { + readhistfile(*argv ? *argv : getsparam("HISTFILE"),1); + return 0; + } + if (ops['W']) { + savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,0); + return 0; + } + if (ops['A']) { + savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,1); + return 0; + } + while (*argv && equalsplit(*argv,&s)) { + struct asgment *a = (struct asgment *) alloc(sizeof *a); + + if (!asgf) asgf = asgl = a; + else { + asgl->next = a; + asgl = a; + } + a->name = *argv; + a->value = s; + argv++; + } + if (*argv) { + minflag = **argv == '-'; + first = fcgetcomm(*argv); + if (first == -1) return 1; + argv++; + } + if (*argv) { + last = fcgetcomm(*argv); + if (last == -1) return 1; + argv++; + } + if (*argv) { + zerrnam("fc","too many arguments",NULL,0); + return 1; + } + if (first == -1) first = (ops['l']) ? curhist-16 : curhist; + if (last == -1) last = (ops['l']) ? curhist : first; + if (first < firsthist()) first = firsthist(); + if (last == -1) last = (minflag) ? curhist : first; + if (ops['l']) + retval = fclist(stdout,!ops['n'],ops['r'],ops['D'],ops['d'], + first,last,asgf); + else { + FILE *out; + char *fil = gettemp(); + + out = fopen(fil,"w"); + if (!out) + zerrnam("fc","can't open temp file: %e",NULL,errno); + else { + retval = 1; + if (!fclist(out,0,ops['r'],0,0,first,last,asgf)) + if (fcedit(auxdata ? auxdata : fceditparam,fil)) + if (stuff(fil)) + zerrnam("fc","%e: %s",s,errno); + else + retval = 0; + } + unlink(fil); + } + return retval; +} + +int bin_suspend(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ + if (islogin && !ops['f']) { + zerrnam(name,"can't suspend login shell",NULL,0); + return 1; + } + if (jobbing) { + signal(SIGPIPE,SIG_DFL); + signal(SIGTTIN,SIG_DFL); + signal(SIGTSTP,SIG_DFL); + signal(SIGTTOU,SIG_DFL); + } + kill(0,SIGTSTP); + if (jobbing) { + while (gettygrp() != mypgrp) { + sleep(1); + if (gettygrp() != mypgrp) kill(0,SIGTTIN); + } + signal(SIGTTOU,SIG_IGN); + signal(SIGTSTP,SIG_IGN); + signal(SIGTTIN,SIG_IGN); + signal(SIGPIPE,SIG_IGN); + } + return 0; +} + +int bin_alias(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +struct alias *an; +struct asgment *asg; +int incm = !(ops['a'] || ops['g']),ret = 0; + + showflag = !incm; + if (!*argv) + listhtable(aliastab,(HFunc) printalias); + else while (asg = getasg(*argv++)) + { + if (asg->value) + addhnode(ztrdup(asg->name),mkanode(ztrdup(asg->value),incm), + aliastab,freeanode); + else if (an = (Alias) gethnode(asg->name,aliastab)) + printalias(asg->name,an); + else + ret = 1; + } + return ret; +} + +/* print an alias; used with listhtable */ + +void printalias(s,a) /**/ +char *s;struct alias *a; +{ + if (a->cmd >= 0 && !(showflag && a->cmd)) + printf("%s=%s\n",s,a->text); +} + +/* print a param; used with listhtable */ + +void printparam(s,p) /**/ +char *s;Param p; +{ + if (showflag > 0 && !(p->flags & showflag)) + return; + if (!showflag) + { + int fgs = p->flags; + + if (fgs & PMFLAG_i) printf("integer "); + if (fgs & PMFLAG_A) printf("array "); + if (fgs & PMFLAG_L) printf("left justified %d ",p->ct); + if (fgs & PMFLAG_R) printf("right justified %d ",p->ct); + if (fgs & PMFLAG_Z) printf("zero filled %d ",p->ct); + if (fgs & PMFLAG_l) printf("lowercase "); + if (fgs & PMFLAG_u) printf("uppercase "); + if (fgs & PMFLAG_r) printf("readonly "); + if (fgs & PMFLAG_t) printf("tagged "); + if (fgs & PMFLAG_x) printf("exported "); + } + if (showflag2) + printf("%s\n",s); + else + { + char *t,**u; + + printf("%s=",s); + switch (p->flags & PMTYPE) + { + case PMFLAG_s: + if (p->gets.cfn && (t = p->gets.cfn(p))) + puts(t); + else + putchar('\n'); + break; + case PMFLAG_i: printf("%ld\n",p->gets.ifn(p)); break; + case PMFLAG_A: + putchar('('); + u = p->gets.afn(p); + if (!*u) + printf(")\n"); + else + { + while (u[1]) + printf("%s ",*u++); + printf("%s)\n",*u); + } + break; + } + } +} + +/* autoload, declare, export, functions, integer, local, readonly, typeset */ + +int bin_typeset(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int on = 0,off = 0,roff,bit = 1,retcode = 0; +char *optstr = "LRZilurtx"; +struct param *pm; +struct asgment *asg; + + for (; *optstr; optstr++,bit <<= 1) + if (ops[*optstr] == 1) + on |= bit; + else if (ops[*optstr] == 2) + off |= bit; + roff = off; + if (ops['f']) { + on &= PMFLAG_t|PMFLAG_u; + off &= PMFLAG_t|PMFLAG_u; + showflag = (ops['f'] == 1); + if (ops['@'] && ((off & ~PMFLAG_t) || (on & ~(PMFLAG_u|PMFLAG_t)))) { + zerrnam(name,"invalid option(s)",NULL,0); + return 1; + } + showflag2 = 0; + if (!*argv) { + showflag2 = off|on; + listhtable(cmdnamtab,(HFunc) pshfunc); + } else for (; *argv; argv++) { + Cmdnam cc; + + if ((cc = (Cmdnam) gethnode(*argv,cmdnamtab)) && cc->type == SHFUNC) + if (on|off) cc->flags = (cc->flags | on) & (~off); + else pshfunc(*argv,cc); + else if (on & PMFLAG_u) { + cc = (Cmdnam) zcalloc(sizeof *cc); + cc->type = SHFUNC; + cc->flags = on; + addhnode(ztrdup(*argv),cc,cmdnamtab,freecmdnam); + } else + retcode = 1; + } + return retcode; + } + if (on & PMFLAG_L) + off |= PMFLAG_R; + if (on & PMFLAG_R) + off |= PMFLAG_L; + if (on & PMFLAG_u) + off |= PMFLAG_l; + if (on & PMFLAG_l) + off |= PMFLAG_u; + on &= ~off; + showflag = showflag2 = 0; + if (!*argv) { + showflag = on|off; + showflag2 = roff; + listhtable(paramtab,(HFunc) printparam); + } else while (asg = getasg(*argv++)) { + if (asg->value && *asg->value == '~') { + *asg->value = Tilde; + singsub(&asg->value); + } + pm = (Param) gethnode(asg->name,paramtab); + if (pm) { + if (!on && !roff && !asg->value) { + printparam(asg->name,pm); + continue; + } + pm->flags = (pm->flags | on) & ~off; + if ((on & (PMFLAG_L | PMFLAG_R | PMFLAG_Z | PMFLAG_i)) + && (pmtype(pm) != PMFLAG_A)) + pm->ct = auxlen; + if (pmtype(pm) != PMFLAG_A) { + if (pm->flags & PMFLAG_x) { + if (!pm->env) + pm->env = addenv(asg->name, + (asg->value) ? asg->value : getsparam(asg->name)); + } else if (pm->env) { + delenv(pm->env); + free(pm->env); + pm->env = NULL; + } + if (asg->value) + setsparam(asg->name,ztrdup(asg->value)); + } + } else { + if (locallist && !(on & PMFLAG_x)) { + permalloc(); + addnode(locallist,ztrdup(asg->name)); + heapalloc(); + } + createparam(ztrdup(asg->name), + ztrdup((asg->value) ? asg->value : ""),on); + pm = (Param) gethnode(asg->name,paramtab); + pm->ct = auxlen; + } + } + return 0; +} + +/* convert s with escape sequences */ + +char *escsubst(s,nnl) /**/ +char *s; int *nnl; +{ +char *t = alloc(strlen(s)+1),*ret = t; + + for (; *s; s++) + if (*s == '\\' && s[1]) + switch (*++s) { + case 'b': *t++ = '\b'; break; + case 'c': *nnl |= 1; break; + case 'e': *t++ = '\033'; break; + case 'f': *t++ = '\f'; break; + case 'n': *t++ = '\n'; break; + case 'r': *t++ = '\r'; break; + case 't': *t++ = '\t'; break; + case 'v': *t++ = '\v'; break; + case '\\': *t++ = '\\'; break; + case '0': *t++ = zstrtol(s,&s,8); s--; break; + default: *t++ = '\\'; *t++ = *s; break; + } + else *t++ = *s; + *t = '\0'; + return ret; +} + +/* echo, print, pushln */ + +int bin_print(name,args,ops,func) /**/ +char *name;char **args;char *ops;int func; +{ +int nnl = 0, fd; +Histent ent; +FILE *fout = stdout; + + if (ops['z']) { + permalloc(); + pushnode(bufstack,ztrdup(spacejoin(args))); + heapalloc(); + return 0; + } + if (ops['s']) { + permalloc(); + ent = gethistent(++curhist); + ent->lex = ztrdup(join(args,HISTSPACE)); + ent->lit = ztrdup(join(args,' ')); + ent->stim = ent->ftim = time(NULL); + heapalloc(); + return 0; + } + if (ops['R']) + ops['r'] = 1; + if (ops['u'] || ops['p']) { + if (ops['u']) { + for (fd = 0; fd < 10; fd++) if (ops[fd+'0']) break; + if (fd == 10) fd = 0; + } else fd = coprocout; + if ((fd = dup(fd)) < 0) { + zerrnam(name,"bad file number",NULL,0); + return 1; + } + if ((fout = fdopen(fd,"w")) == 0) { + zerrnam(name,"bad mode on fd",NULL,0); + return 1; + } + } + for (; *args; args++) { + if (!ops['r']) *args = escsubst(*args,&nnl); + if (ops['D']) fprintdir(*args,fout); + else if (ops['P']) { + int junk; + fputs(putprompt(*args,&junk),fout); + } else fputs(*args,fout); + if (args[1]) fputc(ops['l'] ? '\n' : ops['0'] ? '\0' : ' ',fout); + } + if (!(ops['n'] || nnl)) fputc(ops['N'] ? '\0' : '\n',fout); + if (fout != stdout) fclose(fout); + return 0; +} + +int bin_dirs(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +Lklist l; + + if (ops['v']) + { + Lknode node; + int t0 = 1; + + printf("0\t"); + printdir(pwd); + for (node = firstnode(dirstack); node; incnode(node)) + { + printf("\n%d\t",t0++); + printdir(getdata(node)); + } + putchar('\n'); + return 0; + } + if (!*argv) + { + pdstack(); + return 0; + } + permalloc(); + l = newlist(); + if (!*argv) + { + heapalloc(); + return 0; + } + while (*argv) + addnode(l,ztrdup(*argv++)); + freetable(dirstack,freestr); + dirstack = l; + heapalloc(); + return 0; +} + +int bin_unalias(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int ret = 0; +vptr dat; + + while (*argv) + { + if (dat = remhnode(*argv++,aliastab)) + freeanode(dat); + else + ret = 1; + } + return ret; +} + +int bin_disable(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +Cmdnam chn; + + while (*argv) { + if (!strncmp(*argv,"TRAP",4)) + unsettrap(getsignum(*argv+4)); + chn = zalloc(sizeof *chn); + chn->type = DISABLED; + addhnode(ztrdup(*argv++),chn,cmdnamtab,freecmdnam); + } + return 0; +} + +int bin_unhash(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +vptr dat; + + while (*argv) { + if (!strncmp(*argv,"TRAP",4)) unsettrap(getsignum(*argv+4)); + if (dat = remhnode(*argv++,cmdnamtab)) freecmdnam(dat); + } + return 0; +} + +int bin_unset(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int retval = 0; +char *s; + + while (s = *argv++) + if (gethnode(s,paramtab)) + unsetparam(s); + else + retval = 1; + return retval; +} + +static char *zbuf; +static int readfd; + +int zread() /**/ +{ +char cc; + + if (zbuf) + return (*zbuf) ? *zbuf++ : EOF; + if (read(readfd,&cc,1) != 1) + return EOF; + return cc; +} + +int bin_read(name,args,ops,func) /**/ +char *name;char **args;char *ops;int func; +{ +char *reply,*pmpt; +int bsiz,c,gotnl = 0; +char *buf,*bptr; + + reply = (*args) ? *args++ : "REPLY"; + if (ops['u'] && !ops['p']) { + for (readfd = 0; readfd < 10; ++readfd) if (ops[readfd+'0']) break; + if (readfd == 10) readfd = 0; + } else if (ops['p']) readfd = coprocin; + else { + attachtty((jobtab[thisjob].gleader) ? jobtab[thisjob].gleader : mypgrp); + readfd = 0; + if (isatty(0)) { + for (pmpt = reply; *pmpt && *pmpt != '?'; pmpt++); + if (*pmpt++) { + write(2,pmpt,strlen(pmpt)); + pmpt[-1] = '\0'; + } + } +#if 0 + else if (isset(SHINSTDIN) && unset(INTERACTIVE)) { + if (isatty(1)) readfd = 1; + else if (isatty(2)) readfd = 2; + } +#endif + } + zbuf = (!ops['z']) ? NULL : + (full(bufstack)) ? (char *) getnode(bufstack) : NULL; + while (*args) { + buf = bptr = zalloc(bsiz = 64); +redo: + for(;;) { + if (gotnl) break; + c = zread(); + if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') { + bptr--; + continue; + } + if (c == EOF || isep(c) || c == '\n') break; + *bptr++ = c; + if (bptr == buf+bsiz) { + buf = realloc(buf,bsiz *= 2); + bptr = buf+(bsiz/2); + } + } + if (c == EOF) { + if (readfd == coprocin) { + close(coprocin); + close(coprocout); + coprocin = coprocout = -1; + } + return 1; + } + if (c == '\n') gotnl = 1; + if (bptr == buf) goto redo; + *bptr = '\0'; + setsparam(reply,buf); + reply = *args++; + } + buf = bptr = zalloc(bsiz = 64); + if (!gotnl) + for (;;) { + c = zread(); + if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') { + bptr--; + continue; + } + if (c == EOF || (c == '\n' && !zbuf)) break; + *bptr++ = c; + if (bptr == buf+bsiz) { + buf = realloc(buf,bsiz *= 2); + bptr = buf+(bsiz/2); + } + } + *bptr = '\0'; + setsparam(reply,buf); + if (c == EOF) { + if (readfd == coprocin) { + close(coprocin); + close(coprocout); + coprocin = coprocout = -1; + } + return 1; + } + return 0; +} + +int bin_vared(name,args,ops,func) /**/ +char *name;char **args;char *ops;int func; +{ +char *s;char *t; +struct param *pm; + + if (!(s = getsparam(args[0]))) { + zerrnam(name,"no such variable: %s",args[0],0); + return 1; + } + permalloc(); + pushnode(bufstack,ztrdup(s)); + heapalloc(); + t = (char *) zleread((unsigned char *)"> ",NULL,2); + if (!t || errflag) + return 1; + if (t[strlen(t)-1] == '\n') + t[strlen(t)-1] = '\0'; + pm = gethnode(args[0],paramtab); + if (pmtype(pm) == PMFLAG_A) + setaparam(args[0],spacesplit(t)); + else + setsparam(args[0],t); + return 0; +} + +#define fset(X) (flags & X) + +/* execute a builtin handler function after parsing the arguments */ + +int execbin(args,cnode) /**/ +Lklist args;Cmdnam cnode; +{ +struct bincmd *b; +char ops[128],*arg,*pp,*name,**argv,**oargv,*optstr; +int t0,flags,sense,argc = 0,op; +Lknode n; + + auxdata = NULL; + auxlen = 0; + for (t0 = 0; t0 != 128; t0++) + ops[t0] = 0; + name = ugetnode(args); + b = builtins+cnode->u.binnum; + +/* the 'builtin' builtin is handled specially */ + + if (b->funcid == BIN_BUILTIN) + { + if (!(name = ugetnode(args))) + { + zerrnam("builtin","command name expected",NULL,0); + return 1; + } + for (t0 = 0, b = builtins; b->name; b++,t0++) + if (!strcmp(name,b->name)) + break; + if (!b->name) + { + zerrnam("builtin","no such builtin: %s",name,0); + return 1; + } + } + flags = b->flags; + arg = ugetnode(args); + optstr = b->optstr; + if (flags & BINF_ECHOPTS && arg && strcmp(arg,"-n")) + optstr = NULL; + if (optstr) + while (arg && + ((sense = *arg == '-') || fset(BINF_PLUSOPTS) && *arg == '+') && + (fset(BINF_PLUSOPTS) || !atoi(arg))) + { + pp = arg; + if (arg[1] == '-') + arg++; + if (!arg[1]) + { + ops['-'] = 1; + if (!sense) + ops['+'] = 1; + } + else + ops['@'] = 1; + op = -1; + while (*++arg) + if (strchr(b->optstr,op = *arg)) + ops[*arg] = (sense) ? 1 : 2; + else + break; + if (*arg) + { + zerr("bad option: %c",NULL,*arg); + return 1; + } + arg = ugetnode(args); + if (fset(BINF_SETOPTS) && op == 'o') + { + int c; + + if (!arg) + prtopt(); + else + { + c = optlookup(arg); + if (c == -1) + { + zerr("bad option: %s",arg,0); + return 1; + } + else + { + ops[c] = ops['o']; + arg = ugetnode(args); + } + } + } + if ((fset(BINF_PRINTOPTS) && ops['R']) || ops['-']) + break; + if (fset(BINF_SETOPTS) && ops['A']) + { + auxdata = arg; + arg = ugetnode(args); + break; + } + if (fset(BINF_FCOPTS) && op == 'e') + { + auxdata = arg; + arg = ugetnode(args); + } + if (fset(BINF_TYPEOPT) && (op == 'L' || op == 'R' || + op == 'Z' || op == 'i') && arg && idigit(*arg)) + { + auxlen = atoi(arg); + arg = ugetnode(args); + } + } + if (fset(BINF_R)) + auxdata = "-"; + if (pp = b->defopts) + while (*pp) + ops[*pp++] = 1; + if (arg) + { + argc = 1; + n = firstnode(args); + while (n) + argc++,incnode(n); + } + oargv = argv = (char **) ncalloc(sizeof(char **) * (argc+1)); + if (*argv++ = arg) + while (*argv++ = ugetnode(args)); + argv = oargv; + if (errflag) + return 1; + if (argc < b->minargs || (argc > b->maxargs && b->maxargs != -1)) { + zerrnam(name,(argc < b->minargs) + ? "not enough arguments" : "too many arguments",NULL,0); + return 1; + } + if (isset(XTRACE)) { + char **pp = argv; + fprintf(stderr,"%s%s",(prompt4) ? prompt4 : "",name); + while (*pp) fprintf(stderr," %s",*pp++); + fputc('\n',stderr); + fflush(stderr); + } + return (*(b->handlerfunc))(name,argv,ops,b->funcid); +} + +struct asgment *getasg(s) /**/ +char *s; +{ +static struct asgment asg; + + if (!s) + return NULL; + if (*s == '=') + { + zerr("bad assignment",NULL,0); + return NULL; + } + asg.name = s; + for (; *s && *s != '='; s++); + if (*s) + { + *s = '\0'; + asg.value = s+1; + } + else + asg.value = NULL; + return &asg; +} + +/* ., source */ + +int bin_dot(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +char **old,*old0; +int ret; +char buf[MAXPATHLEN]; +char *s,**t,*enam; + + if (!*argv) + return 0; + old = pparams; + old0 = argzero; + if (argv[1]) { + permalloc(); + pparams = arrdup(argv+1); + heapalloc(); + } + enam = argzero = ztrdup(*argv); + errno = ENOENT; + ret = 1; + for (s = argzero; *s; s++) + if (*s == '/') { + ret = source(argzero); + break; + } + if (!*s) { + for (t = path; *t; t++) + if ((*t)[0] == '.' && !(*t)[1]) { + ret = source(argzero); + break; + } else { + sprintf(buf,"%s/%s",*t,argzero); + if (access(buf,F_OK) == 0) { + ret = source(enam = buf); + break; + } + } + if (!*t && access(argzero,F_OK) == 0) + ret = source(enam = argzero); + } + if (argv[1]) { + freearray(pparams); + pparams = old; + } + if (ret) zerrnam(name,"%e: %s",enam,errno); + free(argzero); + argzero = old0; + return ret; +} + +int bin_set(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +struct option *opp; +char **x; + + if (((ops['+'] && ops['-']) || !ops['-']) && !ops['@'] && !*argv) + { + showflag = ~0; + showflag2 = ops['+']; + listhtable(paramtab,(HFunc) printparam); + } + for (opp = optns; opp->name; opp++) + if (ops[opp->id] == 1) + opts[opp->id] = OPT_SET; + else if (ops[opp->id] == 2) + opts[opp->id] = OPT_UNSET; + if (!*argv && !ops['-']) + return 0; + permalloc(); + x = arrdup(argv); + heapalloc(); + if (ops['A']) + setaparam(auxdata,x); + else { + freearray(pparams); + pparams = x; + } + return 0; +} + +#define pttime(X) printf("%dm%ds",(X)/3600,(X)/60%60) + +int bin_times(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +struct tms buf; + + if (times(&buf) == -1) + return 1; + pttime(buf.tms_utime); + putchar(' '); + pttime(buf.tms_stime); + putchar('\n'); + pttime(buf.tms_cutime); + putchar(' '); + pttime(buf.tms_cstime); + putchar('\n'); + return 0; +} + +int bin_getopts(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +char *optstr = *argv++,*var = *argv++; +char **args = (*argv) ? argv : pparams; +static int optcind = 1,quiet; +char *str,optbuf[3],*opch = optbuf+1; + + if (zoptind < 1) zoptind = 1; + optbuf[0] = '+'; optbuf[1] = optbuf[2] = '\0'; + if (optarg) free(optarg); + optarg = ztrdup(""); + setsparam(var,ztrdup("")); + if (*optstr == ':') { + quiet = 1; + optstr++; + } + if (zoptind > arrlen(args)) return 1; + str = args[zoptind-1]; + if (*str != '+' && *str != '-' || optcind >= strlen(str) || + !strcmp("--",str)) { + if (*str == '+' || *str == '-') + zoptind++; + optcind = 0; + return 1; + } + if (!optcind) + optcind = 1; + *opch = str[optcind++]; + if (!args[zoptind-1][optcind]) { + zoptind++; + optcind = 0; + } + for (; *optstr; optstr++) + if (*opch == *optstr) + break; + if (!*optstr) { + setsparam(var,ztrdup("?")); + if (quiet) { + free(optarg); optarg = ztrdup(opch); + return 0; + } + zerr("bad option: %c",NULL,*opch); errflag = 0; + return 0; + } + setsparam(var,ztrdup(opch-(*str == '+'))); + if (optstr[1] == ':') { + if (!args[zoptind-1]) { + if (quiet) { + free(optarg); optarg = ztrdup(opch); + setsparam(var,ztrdup(":")); + return 0; + } + setsparam(var,ztrdup("?")); + zerr("argument expected after %c option",NULL,*opch); errflag = 0; + return 0; + } + free(optarg); + optarg = ztrdup(args[zoptind-1]+optcind); + zoptind++; + optcind = 0; + } + return 0; +} + +/* get a signal number from a string */ + +int getsignum(s) /**/ +char *s; +{ +int x = atoi(s),t0; + + if (idigit(*s) && x >= 0 && x < VSIGCOUNT) + return x; + for (t0 = 0; t0 != VSIGCOUNT; t0++) + if (!strcmp(s,sigs[t0])) + return t0; + return -1; +} + +int bin_trap(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +List l; +char *arg; + + if (!*argv) { + int t0; + + for (t0 = 0; t0 != VSIGCOUNT; t0++) + if (sigtrapped[t0]) + if (!sigfuncs[t0]) + printf("TRAP%s () {}\n",sigs[t0]); + else { + char *s = getpermtext((vptr) sigfuncs[t0]); + printf("TRAP%s () {\n\t%s\n}\n",sigs[t0],s); + free(s); + } + return 0; + } + if (!strcmp(*argv,"-")) { + int t0; + + argv++; + if (!*argv) + for (t0 = 0; t0 != VSIGCOUNT; t0++) unsettrap(t0); + else + while (*argv) unsettrap(getsignum(*argv++)); + return 0; + } + arg = *argv++; + if (!*arg) l = NULL; + else if (!(l = parselstring(arg))) { + zerrnam(name,"couldn't parse trap command",NULL,0); + popheap(); + return 1; + } + for (; *argv; argv++) { + int sg = getsignum(*argv); + if (sg == -1) { + zerrnam(name,"undefined signal: %s",*argv,0); + break; + } + settrap(sg,l); + } + if (l) popheap(); + return errflag; +} + +void printulimit(lim,hard) /**/ +int lim;int hard; +{ +long t0; + +#ifdef RLIM_INFINITY + t0 = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur; + switch (lim) + { + case RLIMIT_CPU: printf("cpu time (seconds) "); break; + case RLIMIT_FSIZE: printf("file size (blocks) "); t0 /= 512; break; + case RLIMIT_DATA: printf("data seg size (kbytes) "); t0 /= 1024; break; + case RLIMIT_STACK: printf("stack size (kbytes) "); t0 /= 1024; break; + case RLIMIT_CORE: printf("core file size (blocks) "); t0 /= 512; break; +#ifdef RLIMIT_RSS + case RLIMIT_RSS: printf("resident set size (kbytes) "); t0 /= 1024; break; +#endif +#ifdef RLIMIT_NOFILE + case RLIMIT_NOFILE: printf("file descriptors "); break; +#endif + } + printf("%ld\n",t0); +#endif +} + +int bin_ulimit(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int res,hard; + +#ifndef RLIM_INFINITY + zerrnam(name,"not available on this system",NULL,0); + return 1; +#else + hard = ops['H']; + if (ops['a'] || !ops['@']) + res = -1; + else if (ops['t']) + res = RLIMIT_CPU; + else if (ops['f']) + res = RLIMIT_FSIZE; + else if (ops['d']) + res = RLIMIT_DATA; + else if (ops['s']) + res = RLIMIT_STACK; + else if (ops['c']) + res = RLIMIT_CORE; +#ifdef RLIMIT_RSS + else if (ops['m']) + res = RLIMIT_RSS; +#endif +#ifdef RLIMIT_NOFILE + else if (ops['n']) + res = RLIMIT_NOFILE; +#endif + else + { + zerrnam(name,"no such limit",NULL,0); + return 1; + } + if (res == -1) + if (*argv) + { + zerrnam(name,"no arguments required after -a",NULL,0); + return 1; + } + else + { + int t0; + + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + printulimit(t0,hard); + return 0; + } + if (!*argv) + printulimit(res,hard); + else if (strcmp(*argv,"unlimited")) + { + long t0; + + t0 = atol(*argv); + switch(res) + { + case RLIMIT_FSIZE: case RLIMIT_CORE: t0 *= 512; break; + case RLIMIT_DATA: case RLIMIT_STACK: +#ifdef RLIMIT_RSS + case RLIMIT_RSS: +#endif + t0 *= 1024; break; + } + if (hard) + { + if (t0 > limits[res].rlim_max && geteuid()) + { + zerrnam(name,"can't raise hard limits",NULL,0); + return 1; + } + limits[res].rlim_max = t0; + } + else + { + if (t0 > limits[res].rlim_max) + { + if (geteuid()) + { + zerrnam(name,"value exceeds hard limit",NULL,0); + return 1; + } + limits[res].rlim_max = limits[res].rlim_cur = t0; + } + else + limits[res].rlim_cur = t0; + } + } + else + { + if (hard) + { + if (geteuid()) + { + zerrnam(name,"can't remove hard limits",NULL,0); + return 1; + } + limits[res].rlim_max = RLIM_INFINITY; + } + else + limits[res].rlim_cur = limits[res].rlim_max; + } + return 0; +#endif +} + +int putraw(c) /**/ +int c; +{ + putchar(c); + return 0; +} + +int bin_echotc(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +char *s,buf[2048],*t,*u; +int num,argct,t0; + + s = *argv++; + if (!termok) + return 1; + if ((num = tgetnum(s)) != -1) + { + printf("%d\n",num); + return 0; + } + u = buf; + t = tgetstr(s,&u); + if (!t || !*t) + { + zerrnam(name,"no such capability: %s",s,0); + return 1; + } + for (argct = 0, u = t; *u; u++) + if (*u == '%') + { + if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' || + *u == '+')) + argct++; + } + if (arrlen(argv) != argct) + { + zerrnam(name,(arrlen(argv) < argct) ? "not enough arguments" : + "too many arguments",NULL,0); + return 1; + } + if (!argct) + tputs(t,1,putraw); + else + { + t0 = (argv[1]) ? atoi(argv[1]) : atoi(*argv); + tputs(tgoto(t,atoi(*argv),t0),t0,putraw); + } + return 0; +} + +int bin_pwd(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ + printf("%s\n",pwd); + return 0; +} + +#define TEST_END 0 +#define TEST_INPAR 1 +#define TEST_OUTPAR 2 +#define TEST_STR 3 +#define TEST_AND 4 +#define TEST_OR 5 +#define TEST_NOT 6 + +static char **tsp; +static int *tip; + +int bin_test(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +char **s; +int cnt,*arr,*ap; +Cond c; + + if (func == BIN_BRACKET) + { + for (s = argv; *s; s++); + if (s == argv || strcmp(s[-1],"]")) + { + zerrnam(name,"']' expected",NULL,0); + return 1; + } + s[-1] = NULL; + } + for (s = argv, cnt = 0; *s; s++,cnt++); + ap = arr = alloc((cnt+1)*sizeof *arr); + for (s = argv; *s; s++,ap++) + if (!strcmp(*s,"(")) + *ap = TEST_INPAR; + else if (!strcmp(*s,")")) + *ap = TEST_OUTPAR; + else if (!strcmp(*s,"-a")) + *ap = TEST_AND; + else if (!strcmp(*s,"-o")) + *ap = TEST_OR; + else if (!strcmp(*s,"!")) + *ap = TEST_NOT; + else + *ap = TEST_STR; + *ap = TEST_END; + tsp = argv; + tip = arr; + c = partest(0); + if (*tip != TEST_END || errflag) + { + zerrnam(name,"parse error",NULL,0); + return 1; + } + return (c) ? !evalcond(c) : 1; +} + +Cond partest(level) /**/ +int level; +{ +Cond a,b; + + switch (level) + { + case 0: + a = partest(1); + if (*tip == TEST_OR) + { + tip++,tsp++; + b = makecond(); + b->left = a; + b->right = partest(0); + b->type = COND_OR; + return b; + } + return a; + case 1: + a = partest(2); + if (*tip == TEST_AND) + { + tip++,tsp++; + b = makecond(); + b->left = a; + b->right = partest(1); + b->type = COND_AND; + return b; + } + return a; + case 2: + if (*tip == TEST_NOT) + { + tip++,tsp++; + b = makecond(); + b->left = partest(2); + b->type = COND_NOT; + return b; + } + case 3: + if (*tip == TEST_INPAR) + { + tip++,tsp++; + b = partest(0); + if (*tip != TEST_OUTPAR) + { + zerrnam("test","parse error",NULL,0); + return NULL; + } + tip++,tsp++; + return b; + } + if (tip[0] != TEST_STR) + { + zerrnam("test","parse error",NULL,0); + return NULL; + } + else if (tip[1] != TEST_STR) + { + b = makecond(); + if (!strcmp(*tsp,"-t")) + { + b->left = strdup("1"); + b->type = 't'; + } + else + { + b->left = tsp[0]; + b->type = 'n'; + } + tip++,tsp++; + return b; + } + else if (tip[2] != TEST_STR) + { + b = par_cond_double(tsp[0],tsp[1]); + tip += 2,tsp += 2; + return b; + } + else + { + b = par_cond_triple(tsp[0],tsp[1],tsp[2]); + tip += 3,tsp += 3; + return b; + } + } + return NULL; +} + +int bin_compctl(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ +int flags = 0; +Compctl cc = NULL; +char *usrkeys = NULL; + + for (; *argv && **argv == '-'; argv++) + while (*++(*argv)) switch(**argv) { + case 'c': flags |= CC_COMMPATH; break; + case 'f': flags |= CC_FILES; break; + case 'h': flags |= CC_HOSTS; break; + case 'o': flags |= CC_OPTIONS; break; + case 'v': flags |= CC_VARS; break; + case 'b': flags |= CC_BINDINGS; break; + case 'k': + flags |= CC_USRKEYS; + if ((*argv)[1]) { usrkeys = (*argv)+1; *argv = ""-1; } + else if (!argv[1]) { + zerrnam(name,"variable name expected after -k",NULL,0); + return 1; + } else { usrkeys = *++argv; *argv = ""-1; } + break; + case 'C': cc = &cc_compos; break; + case 'D': cc = &cc_default; break; + default: zerrnam(name,"bad option: %c",NULL,**argv); return 1; + } + if (cc) { + cc->mask = flags; + if (cc->keyvar) free(cc->keyvar); + cc->keyvar = ztrdup(usrkeys); + } + if (!*argv) { + if (!cc) { + showflag = flags; + listhtable(compctltab,(HFunc) printcompctl); + printcompctl("COMMAND",&cc_compos); + printcompctl("DEFAULT",&cc_default); + } + return 0; + } + compctl_process(argv,flags,usrkeys); + return 0; +} + +void printcompctl(s,cc) /**/ +char *s;Compctl cc; +{ +char *css = "fchovb"; + + if (cc->mask & showflag) { + puts(s); + } else if (!showflag) { + int flags = cc->mask; + printf("%s -",s); + while (*css) { + if (flags & 1) putchar(*css); + css++; flags >>= 1; + } + if (flags & 1) printf("k %s",cc->keyvar); + putchar('\n'); + } +} + +void compctl_process(s,mask,uk) /**/ +char **s;int mask;char *uk; +{ +Compctl cc; + + for (;*s;s++) { + cc = zalloc(sizeof *cc); + cc->mask = mask; cc->keyvar = ztrdup(uk); + addhnode(ztrdup(*s),cc,compctltab,freecompctl); + } +} + +int bin_ttyctl(name,argv,ops,func) /**/ +char *name;char **argv;char *ops;int func; +{ + if (ops['f'] || !ops['@']) ttyfrozen = 1; + else if (ops['u']) ttyfrozen = 0; + return 0; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/builtin.pro b/usr/othersrc/public/zsh-2.2/src/builtin.pro new file mode 100644 index 0000000000..cc10f71e90 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/builtin.pro @@ -0,0 +1,73 @@ +void addbuiltins DCLPROTO((void)); +int bin_enable DCLPROTO((char *name,char **argv,char *ops,int whocares)); +int bin_colon DCLPROTO((char *name,char **argv,char *ops,int whocares)); +int bin_break DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_fg DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_let DCLPROTO((char *name,char **argv,char *ops,int func)); +int zexit DCLPROTO((int val)); +int optlookup DCLPROTO((char *s)); +int bin_setopt DCLPROTO((char *nam,char **args,char *ops,int isun)); +void listhtable DCLPROTO((Hashtab ht,HFunc func)); +void pshfunc DCLPROTO((char *s,Cmdnam cc)); +void niceprint DCLPROTO((char *s)); +void niceprintf DCLPROTO((char *s,FILE *f)); +int bin_umask DCLPROTO((char *nam,char **args,char *ops,int func)); +int bin_whence DCLPROTO((char *nam,char **argv,char *ops,int func)); +int bin_cd DCLPROTO((char *nam,char **argv,char *ops,int func)); +char *cd_get_dest DCLPROTO((char *nam,char **argv,char *ops,int func)); +char *cd_do_chdir DCLPROTO((char *cnam, char *dest)); +char *cd_try_chdir DCLPROTO((char *pfix, char *dest)); +int fixdir DCLPROTO((char *d, char *s)); +void cd_new_pwd DCLPROTO((int func, char *s)); +void convertwd DCLPROTO((char *s, char *t, int off)); +int bin_rehash DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_hash DCLPROTO((char *name,char **argv,char *ops,int func)); +int prefix DCLPROTO((char *s,char *t)); +int getjob DCLPROTO((char *s,char *prog)); +int findjobnam DCLPROTO((char *s)); +int isanum DCLPROTO((char *s)); +int bin_kill DCLPROTO((char *nam,char **argv,char *ops,int func)); +int bin_limit DCLPROTO((char *nam,char **argv,char *ops,int func)); +int bin_unlimit DCLPROTO((char *nam,char **argv,char *ops,int func)); +void showlimits DCLPROTO((int hard,int lim)); +int bin_sched DCLPROTO((char *nam,char **argv,char *ops,int func)); +int bin_eval DCLPROTO((char *nam,char **argv,char *ops,int func)); +int fcgetcomm DCLPROTO((char *s)); +int fcsubs DCLPROTO((char **sp,struct asgment *sub)); +int fclist DCLPROTO((FILE *f,int n,int r,int D,int d,int first,int last,struct asgment *subs)); +int fcedit DCLPROTO((char *ename,char *fn)); +int bin_fc DCLPROTO((char *nam,char **argv,char *ops,int func)); +int bin_suspend DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_alias DCLPROTO((char *name,char **argv,char *ops,int func)); +void printalias DCLPROTO((char *s,struct alias *a)); +void printparam DCLPROTO((char *s,Param p)); +int bin_typeset DCLPROTO((char *name,char **argv,char *ops,int func)); +char *escsubst DCLPROTO((char *s, int *nnl)); +int bin_print DCLPROTO((char *name,char **args,char *ops,int func)); +int bin_dirs DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_unalias DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_disable DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_unhash DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_unset DCLPROTO((char *name,char **argv,char *ops,int func)); +int zread DCLPROTO((void)); +int bin_read DCLPROTO((char *name,char **args,char *ops,int func)); +int bin_vared DCLPROTO((char *name,char **args,char *ops,int func)); +int execbin DCLPROTO((Lklist args,Cmdnam cnode)); +struct asgment *getasg DCLPROTO((char *s)); +int bin_dot DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_set DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_times DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_getopts DCLPROTO((char *name,char **argv,char *ops,int func)); +int getsignum DCLPROTO((char *s)); +int bin_trap DCLPROTO((char *name,char **argv,char *ops,int func)); +void printulimit DCLPROTO((int lim,int hard)); +int bin_ulimit DCLPROTO((char *name,char **argv,char *ops,int func)); +int putraw DCLPROTO((int c)); +int bin_echotc DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_pwd DCLPROTO((char *name,char **argv,char *ops,int func)); +int bin_test DCLPROTO((char *name,char **argv,char *ops,int func)); +Cond partest DCLPROTO((int level)); +int bin_compctl DCLPROTO((char *name,char **argv,char *ops,int func)); +void printcompctl DCLPROTO((char *s,Compctl cc)); +void compctl_process DCLPROTO((char **s,int mask,char *uk)); +int bin_ttyctl DCLPROTO((char *name,char **argv,char *ops,int func)); diff --git a/usr/othersrc/public/zsh-2.2/src/cond.c b/usr/othersrc/public/zsh-2.2/src/cond.c new file mode 100644 index 0000000000..0e20f3bb89 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/cond.c @@ -0,0 +1,156 @@ +/* + * + * cond.c - evaluate conditional expressions + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +int evalcond(c) /**/ +Cond c; +{ +struct stat *st; + + switch (c->type) + { + case COND_NOT: return !evalcond(c->left); + case COND_AND: return evalcond(c->left) && evalcond(c->right); + case COND_OR: return evalcond(c->left) || evalcond(c->right); + } + singsub((char **) &c->left); + untokenize(c->left); + if (c->right) + { + singsub((char **) &c->right); + if (c->type != COND_STREQ && c->type != COND_STRNEQ) + untokenize(c->right); + } + switch (c->type) + { + case COND_STREQ: return matchpat(c->left,c->right); + case COND_STRNEQ: return !matchpat(c->left,c->right); + case COND_STRLT: return strcmp(c->left,c->right) < 0; + case COND_STRGTR: return strcmp(c->left,c->right) > 0; + case 'e': case 'a': return(doaccess(c->left,F_OK)); + case 'b': return(S_ISBLK(dostat(c->left))); + case 'c': return(S_ISCHR(dostat(c->left))); + case 'd': return(S_ISDIR(dostat(c->left))); + case 'f': return(S_ISREG(dostat(c->left))); + case 'g': return(!!(dostat(c->left) & S_ISGID)); + case 'k': return(!!(dostat(c->left) & S_ISVTX)); + case 'n': return(!!strlen(c->left)); + case 'o': return(optison(c->left)); + case 'p': return(S_ISFIFO(dostat(c->left))); + case 'r': return(doaccess(c->left,R_OK)); + case 's': return((st = getstat(c->left)) && !!(st->st_size)); + case 'S': return(S_ISSOCK(dostat(c->left))); + case 'u': return(!!(dostat(c->left) & S_ISUID)); + case 'w': return(doaccess(c->left,W_OK)); + case 'x': return(doaccess(c->left,X_OK)); + case 'z': return(!strlen(c->left)); + case 'h': case 'L': return(S_ISLNK(dolstat(c->left))); + case 'O': return((st = getstat(c->left)) && st->st_uid == geteuid()); + case 'G': return((st = getstat(c->left)) && st->st_gid == getegid()); + case 't': return isatty(matheval(c->left)); + case COND_EQ: return matheval(c->left) == matheval(c->right); + case COND_NE: return matheval(c->left) != matheval(c->right); + case COND_LT: return matheval(c->left) < matheval(c->right); + case COND_GT: return matheval(c->left) > matheval(c->right); + case COND_LE: return matheval(c->left) <= matheval(c->right); + case COND_GE: return matheval(c->left) >= matheval(c->right); + case COND_NT: case COND_OT: + { + time_t a; + if (!(st = getstat(c->left))) + return 0; + a = st->st_mtime; + if (!(st = getstat(c->right))) + return 0; + return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime; + } + case COND_EF: + { + dev_t d; + ino_t i; + + if (!(st = getstat(c->left))) + return 0; + d = st->st_dev; + i = st->st_ino; + if (!(st = getstat(c->right))) + return 0; + return d == st->st_dev && i == st->st_ino; + } + default: zerr("bad cond structure",NULL,0); + } + return 0; +} + +int doaccess(s,c) /**/ +char *s;int c; +{ + return !access(s,c); +} + +static struct stat st; + +struct stat *getstat(s) /**/ +char *s; +{ + if (!strncmp(s,"/dev/fd/",8)) + { + if (fstat(atoi(s+8),&st)) + return NULL; + } + else if (stat(s,&st)) + return NULL; + return &st; +} + +unsigned short dostat(s) /**/ +char *s; +{ +struct stat *st; + + if (!(st = getstat(s))) + return 0; + return st->st_mode; +} + +/* pem@aaii.oz; needed since dostat now uses "stat" */ + +unsigned short dolstat(s) /**/ +char *s; +{ + if (lstat(s, &st) < 0) + return 0; + return st.st_mode; +} + +int optison(s) /**/ +char *s; +{ +int i; + + if (strlen(s) == 1) + return opts[*s]; + if ((i = optlookup(s)) != -1) + return opts[i]; + zerr("no such option: %s",s,0); + return 0; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/cond.pro b/usr/othersrc/public/zsh-2.2/src/cond.pro new file mode 100644 index 0000000000..7c6629d967 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/cond.pro @@ -0,0 +1,6 @@ +int evalcond DCLPROTO((Cond c)); +int doaccess DCLPROTO((char *s,int c)); +struct stat *getstat DCLPROTO((char *s)); +unsigned short dostat DCLPROTO((char *s)); +unsigned short dolstat DCLPROTO((char *s)); +int optison DCLPROTO((char *s)); diff --git a/usr/othersrc/public/zsh-2.2/src/exec.c b/usr/othersrc/public/zsh-2.2/src/exec.c new file mode 100644 index 0000000000..0119e71390 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/exec.c @@ -0,0 +1,1829 @@ +/* + * + * exec.c - command execution + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include +#ifdef __hpux +#include +#else +#include +#endif + +#define execerr() { if (forked) exit(1); \ + closemnodes(mfds); errflag = 1; return; } + +static Lklist args; +static Cmdnam cn; + +/* parse list in a string */ + +List parselstring(s) /**/ +char *s; +{ +List l; + + hungets(s); + strinbeg(); + pushheap(); + if (!(l = parse_list())) { + strinend(); + hflush(); + popheap(); + return NULL; + } + strinend(); + return l; +} + +/* execute a string */ + +void execstring(s) /**/ +char *s; +{ +List l; + + if (l = parselstring(s)) { + execlist(l); + popheap(); + } +} + +/* fork and set limits */ + +int phork() /**/ +{ +int pid,t0; + + if (thisjob >= MAXJOB-1) { + zerr("job table full",NULL,0); + return -1; + } + pid = fork(); + if (pid == -1) { + zerr("fork failed: %e",NULL,errno); + return -1; + } +#ifdef RLIM_INFINITY + if (!pid) + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + setrlimit(t0,limits+t0); +#endif + return pid; +} + +/* execute a current shell command */ + +int execcursh(cmd) /**/ +Cmd cmd; +{ + runlist(cmd->u.list); + cmd->u.list = NULL; + return lastval; +} + +/* execve after handling $_ and #! */ + +#define POUNDBANGLIMIT 64 + +int zexecve(pth,argv) /**/ +char *pth;char **argv; +{ +int eno; +static char buf[MAXPATHLEN*2]; +char **eep; + + for (eep = environ; *eep; eep++) + if (**eep == '_' && (*eep)[1] == '=') break; + buf[0] = '_'; + buf[1] = '='; + if (*pth == '/') strcpy(buf+2,pth); + else sprintf(buf+2,"%s/%s",pwd,pth); + if (!*eep) eep[1] = NULL; + *eep = buf; + execve(pth,argv,environ); + if ((eno = errno) == ENOEXEC) { + char buf[POUNDBANGLIMIT+1],*ptr,*ptr2,*argv0; + int fd,ct,t0; + + if ((fd = open(pth,O_RDONLY)) >= 0) { + argv0 = *argv; + *argv = pth; + ct = read(fd,buf,POUNDBANGLIMIT); + close(fd); + if (ct > 0) { + if (buf[0] == '#') + if (buf[1] == '!') { + for (t0 = 0; t0 != ct; t0++) + if (buf[t0] == '\n') + buf[t0] = '\0'; + buf[POUNDBANGLIMIT] = '\0'; + for (ptr = buf+2; *ptr && *ptr == ' '; ptr++); + for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++); + if (*ptr) { + *ptr = '\0'; + argv[-2] = ptr2; + argv[-1] = ptr+1; + execve(ptr2,argv-2,environ); + } else { + argv[-1] = ptr2; + execve(ptr2,argv-1,environ); + } + } else { + argv[-1] = "sh"; + execve("/bin/sh",argv-1,environ); + } + else { + for (t0 = 0; t0 != ct; t0++) + if (!buf[t0]) break; + if (t0 == ct) { + argv[-1] = "sh"; + execve("/bin/sh",argv-1,environ); + } + } + } else eno = errno; + *argv = argv0; + } else eno = errno; + } + return eno; +} + +#define MAXCMDLEN (MAXPATHLEN*4) + +/* execute an external command */ + +void execute(dash) /**/ +int dash; +{ +char **argv,*arg0,**pp; +char *z,*s,buf[MAXCMDLEN],buf2[MAXCMDLEN]; +int ee = 0,eno = 0; + + if (!full(args)) { + zerr("no command",NULL,0); + _exit(1); + } + cn = (Cmdnam) gethnode(peekfirst(args),cmdnamtab); + if (cn && cn->type == DISABLED) + cn = NULL; + if (s = zgetenv("STTY")) + zyztem("stty",s); + arg0 = peekfirst(args); + if (z = zgetenv("ARGV0")) { + setdata(firstnode(args),ztrdup(z)); + delenv(z-6); + } else if (dash) { + sprintf(buf2,"-%s",arg0); + setdata(firstnode(args),ztrdup(buf2)); + } + argv = makecline(args); + fixsigs(); + if (strlen(arg0) > MAXPATHLEN) { + zerr("command too long: %s",arg0,0); + _exit(1); + } + for (s = arg0; *s; s++) + if (*s == '/') { + errno = zexecve(arg0,argv); + if (arg0 == s || unset(PATHDIRS)) { + zerr("%e: %s",arg0,errno); + _exit(1); + } + break; + } + if (cn && ISEXCMD(cn->type)) { + for (pp = path; pp < cn->pcomp; pp++) + if (**pp == '.' && (*pp)[1] == '\0') { + ee = zexecve(arg0,argv); + if (ee != ENOENT) eno = ee; + } else if (**pp != '/') { + z = buf; + strucpy(&z,*pp); + *z++ = '/'; + strcpy(z,arg0); + ee = zexecve(buf,argv); + if (ee != ENOENT) eno = ee; + } + ee = zexecve(cn->u.nam,argv); + if (ee != ENOENT) eno = ee; + } + for (pp = path; *pp; pp++) + if ((*pp)[0] == '.' && !(*pp)[1]) { + ee = zexecve(arg0,argv); + if (ee != ENOENT) eno = ee; + } else { + z = buf; + strucpy(&z,*pp); + *z++ = '/'; + strcpy(z,arg0); + ee = zexecve(buf,argv); + if (ee != ENOENT) eno = ee; + } + if (eno) zerr("%e: %s",arg0,eno); + else zerr("command not found: %s",arg0,0); + _exit(1); +} + +#define try(X) { if (iscom(X)) return ztrdup(X); } + +/* get the full pathname of an external command */ + +char *findcmd(arg0) /**/ +char *arg0; +{ +char **pp; +char *z,*s,buf[MAXCMDLEN]; + + cn = (Cmdnam) gethnode(arg0,cmdnamtab); + if (!cn && isset(HASHCMDS)) hashcmd(arg0,path); + if (cn && cn->type == DISABLED) cn = NULL; + if (strlen(arg0) > MAXPATHLEN) return NULL; + for (s = arg0; *s; s++) + if (*s == '/') { + try(arg0); + if (arg0 == s || unset(PATHDIRS)) { + return NULL; + } + break; + } + if (cn && ISEXCMD(cn->type)) { + for (pp = path; pp < cn->pcomp; pp++) + if (**pp != '/') { + z = buf; + strucpy(&z,*pp); + *z++ = '/'; + strcpy(z,arg0); + try(buf); + } + try(cn->u.nam); + } + for (pp = path; *pp; pp++) { + z = buf; + strucpy(&z,*pp); + *z++ = '/'; + strcpy(z,arg0); + try(buf); + } + return NULL; +} + +int iscom(s) /**/ +char *s; +{ +struct stat statbuf; + + return (access(s,X_OK) == 0 && stat(s,&statbuf) >= 0 && + S_ISREG(statbuf.st_mode)); +} + +int isrelative(s) /**/ +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; +} + +int hashcmd(arg0,pp) /**/ +char *arg0;char **pp; +{ +char *s,buf[MAXPATHLEN]; +char **pq; +DIR *dir; +struct direct *de; + + for (; *pp; pp++) + if (**pp == '/') { + s = buf; + strucpy(&s,*pp); + *s++ = '/'; + strcpy(s,arg0); + if (iscom(buf)) break; + } + if (!*pp || isrelative(*pp)) return 0; + cn = (Cmdnam) zcalloc(sizeof *cn); + cn->type = EXCMD; + cn->pcomp = pp; + cn->u.nam = ztrdup(buf); + addhnode(ztrdup(arg0),cn,cmdnamtab,freecmdnam); + if (unset(HASHDIRS)) return 1; + for (pq = pathchecked; pq <= pp; pq++) { + if (isrelative(*pq) || !(dir = opendir(*pq))) continue; + readdir(dir); readdir(dir); + while (de = readdir(dir)) addhcmdnode(de->d_name,pq); + closedir(dir); + } + pathchecked = pp+1; + return 1; +} + +void fullhash() /**/ +{ +char **pq; +DIR *dir; +struct direct *de; + + for (pq = pathchecked; *pq; pq++) { + if (isrelative(*pq) || !(dir = opendir(*pq))) continue; + readdir(dir); readdir(dir); + while (de = readdir(dir)) addhcmdnode(de->d_name,pq); + closedir(dir); + } + pathchecked = pq; +} + +void execlist(list) /**/ +List list; +{ + if (breaks) return; + if (!list) return; + simplifyright(list); + switch(list->type) { + case SYNC: + case ASYNC: + execlist2(list->left,list->type,!list->right); + if (sigtrapped[SIGDEBUG]) + dotrap(SIGDEBUG); + if (sigtrapped[SIGERR] && lastval) + dotrap(SIGERR); + if (list->right && !retflag) + execlist(list->right); + break; + } +} + +void execlist2(list,type,last1) /**/ +Sublist list;int type;int last1; +{ + if (!list) return; + switch(list->type) { + case END: + execpline(list,type,last1); + break; + case ORNEXT: + if (!execpline(list,SYNC,0)) execlist2(list->right,type,last1); + else while (list = list->right) + if (list->type == ANDNEXT) { + execlist2(list->right,type,last1); + return; + } + break; + case ANDNEXT: + if (execpline(list,SYNC,0)) execlist2(list->right,type,last1); + else while (list = list->right) + if (list->type == ORNEXT) { + execlist2(list->right,type,last1); + return; + } + break; + } +} + +int execpline(l,how,last1) /**/ +Sublist l;int how;int last1; +{ +int ipipe[2],opipe[2]; + + if (!l) return 0; + ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0; + blockchld(); + if ((thisjob = getfreejob()) == -1) + return 1; + initjob(); + if (how == TIMED) { + jobtab[thisjob].stat |= STAT_TIMED; + how = SYNC; + } + if (l->flags & PFLAG_COPROC) { + how = ASYNC; + if (coprocin >= 0) { + close(coprocin); + close(coprocout); + } + mpipe(ipipe); + mpipe(opipe); + coprocin = ipipe[0]; + coprocout = opipe[1]; + } + execpline2(l->left,how,opipe[0],ipipe[1],last1); + if (how == ASYNC) { + if (l->flags & PFLAG_COPROC) close(ipipe[1]); + spawnjob(); + unblockchld(); + return 1; + } else { + waitjobs(); + unblockchld(); + if (l->flags & PFLAG_NOT) lastval = !lastval; + return !lastval; + } +} + +void execpline2(pline,how,input,output,last1) /**/ +Pline pline;int how;int input;int output;int last1; +{ +int pid; +int pipes[2]; + + if (breaks) + return; + if (!pline) + return; + if (pline->type == END) { + execcmd(pline->left,input,output,how==ASYNC,last1); + pline->left = NULL; + } else { + mpipe(pipes); + if (pline->left->type >= CURSH && how == SYNC) { + + /* if we are doing "foo | bar" where foo is a current + shell command, do foo in a subshell and do + the rest of the pipeline in the current shell. */ + + if (!(pid = fork())) { + close(pipes[0]); + entersubsh(how==ASYNC); + exiting = 1; + execcmd(pline->left,input,pipes[1],how==ASYNC,0); + _exit(lastval); + } else if (pid == -1) + zerr("fork failed: %e",NULL,errno); + else { + char *text = getjobtext((vptr) pline->left); + addproc(pid,text); + } + } else { + /* otherwise just do the pipeline normally. */ + execcmd(pline->left,input,pipes[1],how==ASYNC,0); + } + pline->left = NULL; + close(pipes[1]); + if (pline->right) { + execpline2(pline->right,how,pipes[0],output,last1); + close(pipes[0]); + } + } +} + +/* make the argv array */ + +char **makecline(list) /**/ +struct lklist *list; +{ +int ct = 0; +Lknode node; +char **argv,**ptr; + + if (isset(XTRACE)) { + fprintf(stderr,"%s",(prompt4) ? prompt4 : ""); + for (node = firstnode(list); node; incnode(node),ct++); + ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *)); + for (node = firstnode(list); node; incnode(node)) + if (*(char *) getdata(node)) { + *ptr++ = getdata(node); + untokenize(getdata(node)); + fputs(getdata(node),stderr); + if (nextnode(node)) + fputc(' ',stderr); + } + *ptr = NULL; + fputc('\n',stderr); + fflush(stderr); + return(argv); + } else { + for (node = firstnode(list); node; incnode(node),ct++); + ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *)); + for (node = firstnode(list); node; incnode(node)) + if (*(char *) getdata(node)) { + *ptr++ = getdata(node); + untokenize(getdata(node)); + } + *ptr = NULL; + return(argv); + } +} + +/* untokenize the command line and remove null arguments */ + +void fixcline(l) /**/ +Lklist l; +{ +Lknode node,next; + + for (node = firstnode(l); node; node = next) { + next = nextnode(node); + if (!*(char *) getdata(node)) uremnode(l,node); + else untokenize(getdata(node)); + } +} + +void untokenize(s) /**/ +char *s; +{ + for (; *s; s++) + if (itok(*s)) + if (*s == Nularg) chuck(s--); + else *s = ztokens[*s-Pound]; +} + +/* nonzero if we shouldn't clobber a file */ + +int dontclob(f) /**/ +struct redir *f; +{ +struct stat buf; + + if (unset(NOCLOBBER) || f->type & 1) return 0; + if (stat(f->name,&buf) == -1) return 1; + return S_ISREG(buf.st_mode); +} + +/* close an multio (success) */ + +void closemn(mfds,fd) /**/ +struct multio **mfds;int fd; +{ + if (mfds[fd]) { + if (mfds[fd]->ct > 1) + if (mfds[fd]->rflag == 0) + catproc(mfds[fd]); + else + teeproc(mfds[fd]); + mfds[fd] = NULL; + } +} + +/* close all the mnodes (failure) */ + +void closemnodes(mfds) /**/ +struct multio **mfds; +{ +int t0,t1; + + for (t0 = 0; t0 != 10; t0++) + if (mfds[t0]) { + for (t1 = 0; t1 != mfds[t0]->ct; t1++) + close(mfds[t0]->fds[t1]); + mfds[t0] = NULL; + } +} + +/* add a fd to an multio */ +/* an 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",....). */ + +void addfd(forked,save,mfds,fd1,fd2,rflag) /**/ +int forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag; +{ +int pipes[2]; + + if (!mfds[fd1]) { /* starting a new multio */ + mfds[fd1] = (struct multio *) alloc(sizeof(struct multio)); + if (!forked && fd1 != fd2 && fd1 < 10) + save[fd1] = movefd(fd1); + 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",NULL,fd1); + return; + } + if (mfds[fd1]->ct == 1) { /* split the stream */ + mfds[fd1]->fds[0] = movefd(fd1); + mfds[fd1]->fds[1] = movefd(fd2); + mpipe(pipes); + mfds[fd1]->pipe = pipes[1-rflag]; + redup(pipes[rflag],fd1); + mfds[fd1]->ct = 2; + } else /* add another fd to an already split stream */ + mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2); + } +} + +void addvars(l,export) /**/ +Lklist l;int export; +{ +struct varasg *v; +Lklist vl; + + while (full(l)) { + char **arr,**ptr; + + v = (struct varasg *) ugetnode(l); + singsub(&v->name); + if (errflag) + return; + untokenize(v->name); + if (v->type == PMFLAG_s) { + vl = newlist(); + addnode(vl,v->str); + } else + vl = v->arr; + prefork(vl); + if (errflag) + return; + postfork(vl,1); + if (errflag) + return; + if (v->type == PMFLAG_s && (!full(vl) || !nextnode(firstnode(vl)))) { + Param pm; + char *val; + + if (!full(vl)) + pm = setsparam(v->name,val = ztrdup("")); + else { + untokenize(peekfirst(vl)); + pm = setsparam(v->name,val = ztrdup(ugetnode(vl))); + } + if (export && !(pm->flags & PMFLAG_x)) + addenv(v->name,val); + continue; + } + ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(vl)+1)); + while (full(vl)) { + char *pp; + pp = ugetnode(vl); + if (*pp) { + *ptr = ztrdup(pp); + untokenize(*ptr++); + } + } + *ptr = NULL; + setaparam(v->name,arr); + } +} + +void execcmd(cmd,input,output,bkg,last1) /**/ +Cmd cmd;int input;int output;int bkg;int last1; +{ +int type; +long pid = 0; +int save[10],t0; +struct redir *fn; +struct multio *mfds[10]; +int fil,forked = 0,iscursh = 0,nullexec = 0; +char *text; + + args = cmd->args; + cn = NULL; + for (t0 = 0; t0 != 10; t0++) { + save[t0] = 0; + mfds[t0] = NULL; + } + if ((type = cmd->type) == SIMPLE && !full(args)) + if (full(cmd->redir)) + if (cmd->flags & CFLAG_EXEC) { + nullexec = 1; + } else if (!*nullcmd) { + zerr("redirection with no command",NULL,0); + errflag = lastval = 1; + return; + } else if (*readnullcmd && + ((Redir)peekfirst(cmd->redir))->type == READ && + !nextnode(firstnode(cmd->redir))) { + addnode(args,strdup(readnullcmd)); + } else + addnode(args,strdup(nullcmd)); + else { + addvars(cmd->vars,0); + return; + } + if (full(args) && *(char *) peekfirst(args) == '%') { + insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg")); + bkg = 0; + } + if (isset(AUTORESUME) && !bkg && !full(cmd->redir) && full(args) && + !input && type == SIMPLE && !nextnode(firstnode(args))) { + if (unset(NOTIFY)) scanjobs(); + if (findjobnam(peekfirst(args)) != -1) + pushnode(args,strdup("fg")); + } + if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) && + type == SIMPLE && full(args) && nextnode(firstnode(args)) && + !strcmp(peekfirst(args),"rm")) { + char *s = getdata(nextnode(firstnode(args))); + int l = strlen(s); + + if (s[0] == Star && !s[1]) + checkrmall(pwd); + else if (l > 2 && s[l-2] == '/' && s[l-1] == Star) { + char t = s[l-2]; + s[l-2] = 0; + checkrmall(s); + s[l-2] = t; + } + } + if (jobbing) { /* get the text associated with this command */ + char *s; + s = text = getjobtext((vptr) cmd); + } else text = NULL; + prefork(args); /* do prefork substitutions */ + if (errflag) { + lastval = 1; + return; + } + if (full(args) && ((char*)peekfirst(args))[0] == Inbrack && + ((char*)peekfirst(args))[1] == '\0') + ((char*)peekfirst(args))[0] = '['; + if (type == SIMPLE && full(args) && !(cmd->flags & CFLAG_COMMAND)) { + char *s,*t; + cn = (Cmdnam) gethnode(t = s = peekfirst(args),cmdnamtab); + if (!cn && isset(HASHCMDS) && strcmp(t,"..")) { + while (*t && *t != '/') t++; + if (!*t) hashcmd(s,pathchecked); + } + } + if (type == SIMPLE && !cn && isset(AUTOCD) && isset(SHINSTDIN) && + full(args) && !full(cmd->redir) && + !nextnode(firstnode(args)) && cancd(peekfirst(args))) { + pushnode(args,strdup("cd")); + cn = (Cmdnam) gethnode("cd",cmdnamtab); + } + + /* this is nonzero if cmd is a current shell procedure */ + + iscursh = (type >= CURSH) || (type == SIMPLE && cn && + (cn->type == BUILTIN || cn->type == SHFUNC)); + + /* if this command is backgrounded or (this is an external + command and we are not exec'ing it) or this is a builtin + with output piped somewhere, then fork. If this is the + last stage in a subshell pipeline, don't fork, but make + the rest of the function think we forked. */ + + if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) || + (cn && (cn->type == BUILTIN || cn->type == SHFUNC) && output)) { + int synch[2]; + + pipe(synch); + pid = (last1 && execok()) ? 0 : phork(); + if (pid == -1) { + close(synch[0]); + close(synch[1]); + return; + } + if (pid) { + close(synch[1]); + read(synch[0],"foo",1); + close(synch[0]); + if (pid == -1) + zerr("%e",NULL,errno); + else { + if (bkg) lastpid = pid; + ( void ) addproc(pid,text); + } + return; + } + close(synch[0]); + entersubsh(bkg); + close(synch[1]); + forked = 1; + } + if (bkg && isset(BGNICE)) + nice(5); + + /* perform postfork substitutions */ + postfork(args,!(cmd->flags & CFLAG_NOGLOB)); + if (errflag) { + lastval = 1; + goto err; + } else { + char *s; + while (full(args) && (s = peekfirst(args)) && !*s) ugetnode(args); + } + + if (input) /* add pipeline input/output to mnodes */ + addfd(forked,save,mfds,0,input,0); + if (output) + addfd(forked,save,mfds,1,output,1); + spawnpipes(cmd->redir); /* do process substitutions */ + while (full(cmd->redir)) + if ((fn = (struct redir*) ugetnode(cmd->redir))->type == INPIPE) { + if (fn->fd2 == -1) + execerr(); + addfd(forked,save,mfds,fn->fd1,fn->fd2,0); + } else if (fn->type == OUTPIPE) { + if (fn->fd2 == -1) + execerr(); + addfd(forked,save,mfds,fn->fd1,fn->fd2,1); + } else { + if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type == + MERGE || fn->type == MERGEOUT)) + if (xpandredir(fn,cmd->redir)) + continue; + if (errflag) execerr(); + if (fn->type == HERESTR) { + fil = getherestr(fn); + if (fil == -1) { + if (errno != EINTR) + zerr("%e",NULL,errno); + execerr(); + } + addfd(forked,save,mfds,fn->fd1,fil,0); + } else if (fn->type == READ) { + fil = open(fn->name,O_RDONLY); + if (fil == -1) { + if (errno != EINTR) + zerr("%e: %s",fn->name,errno); + execerr(); + } + addfd(forked,save,mfds,fn->fd1,fil,0); + } else if (fn->type == CLOSE) { + if (!forked && fn->fd1 < 10) + save[fn->fd1] = movefd(fn->fd1); + closemn(mfds,fn->fd1); + close(fn->fd1); + } else if (fn->type == MERGE || fn->type == MERGEOUT) { + if (fn->fd2 == FD_COPROC) + fn->fd2 = (fn->type == MERGEOUT) ? coprocout : coprocin; + if (!forked && fn->fd1 < 10) + save[fn->fd1] = movefd(fn->fd1); + closemn(mfds,fn->fd1); + fil = dup(fn->fd2); + addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT); + } else { + if (fn->type >= APP) + fil = open(fn->name, + (isset(NOCLOBBER) && !(fn->type & 1)) ? + O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666); + else + fil = open(fn->name,dontclob(fn) ? + O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666); + if (fil == -1) { + if (errno != EINTR) + zerr("%e: %s",fn->name,errno); + execerr(); + } + addfd(forked,save,mfds,fn->fd1,fil,1); + } + } + + /* we are done with redirection. close the mnodes, spawning + tee/cat processes as necessary. */ + for (t0 = 0; t0 != 10; t0++) + closemn(mfds,t0); + + if (nullexec) + return; + if (unset(NOEXEC)) + if (type >= CURSH) + { + static int (*func[]) DCLPROTO((Cmd)) = { + execcursh,exectime,execfuncdef,execfor,execwhile, + execrepeat,execif,execcase,execselect,execcond }; + + fixcline(args); + lastval = (func[type-CURSH])(cmd); + } + else if (iscursh) /* builtin or shell function */ + { + if (cmd->vars) + addvars(cmd->vars,0); + fixcline(args); + if (cn && cn->type == SHFUNC) + execshfunc(cmd,cn); + else + { + if (forked) closem(); + lastval = execbin(args,cn); + if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) && + lastval && !subsh) { + fprintf(stderr,"zsh: exit %d\n",lastval); + } + fflush(stdout); + if (ferror(stdout)) + { + zerr("write error: %e",NULL,errno); + clearerr(stdout); + } + } + } + else + { + if (cmd->vars) + addvars(cmd->vars,1); + if (type == SIMPLE) + { + closem(); + execute(cmd->flags & CFLAG_DASH); + } + else /* ( ... ) */ + execlist(cmd->u.list); + } +err: + if (forked) + _exit(lastval); + fixfds(save); +} + +/* restore fds after redirecting a builtin */ + +void fixfds(save) /**/ +int *save; +{ +int t0; + + for (t0 = 0; t0 != 10; t0++) + if (save[t0]) + redup(save[t0],t0); +} + +void entersubsh(bkg) /**/ +int bkg; +{ + if (!jobbing) + { + if (bkg && isatty(0)) + { + close(0); + if (open("/dev/null",O_RDWR)) + { + zerr("can't open /dev/null: %e",NULL,errno); + _exit(1); + } + } + } + else if (!jobtab[thisjob].gleader) + { + jobtab[thisjob].gleader = getpid(); + setpgrp(0L,jobtab[thisjob].gleader); + if (!bkg) + attachtty(jobtab[thisjob].gleader); + } + else + setpgrp(0L,jobtab[thisjob].gleader); + subsh = 1; + if (SHTTY != -1) + { + close(SHTTY); + SHTTY = -1; + } + if (jobbing) + { + signal(SIGTTOU,SIG_DFL); + signal(SIGTTIN,SIG_DFL); + signal(SIGTSTP,SIG_DFL); + signal(SIGPIPE,SIG_DFL); + } + if (interact) + { + signal(SIGTERM,SIG_DFL); + if (sigtrapped[SIGINT]) + signal(SIGINT,SIG_IGN); + } + if (!sigtrapped[SIGQUIT]) + signal(SIGQUIT,SIG_DFL); + opts[MONITOR] = OPT_UNSET; + clearjobtab(); +} + +/* close all internal shell fds */ + +void closem() /**/ +{ +int t0; + + for (t0 = 10; t0 != NOFILE; t0++) + close(t0); +} + +/* convert here document into a here string */ + +char *gethere(str,typ) /**/ +char *str;int typ; +{ +char pbuf[256]; +int qt = 0,siz = 0,l,strip = 0; +char *s,*t,*bptr; + + for (s = str; *s; s++) + if (*s == Nularg) + qt = 1; + untokenize(str); + if (typ == HEREDOCDASH) + { + strip = 1; + while (*str == '\t') + str++; + } + t = ztrdup(""); + for(;;) + { + char *u,*v; + + if (!hgets(pbuf,256)) + break; + bptr = pbuf; + if (strip) + while (*bptr == '\t') + bptr++; + for (u = bptr, v = str; *u != '\n' && *v; u++,v++) + if (*u != *v) + break; + if (!(*u == '\n' && !*v)) + { + l = strlen(bptr); + if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\') + bptr[l -= 2] = '\0'; + t = realloc(t,siz+l+1); + strncpy(t+siz,bptr,l); + siz += l; + } + else + break; + } + t[siz] = '\0'; + if (siz && t[siz-1] == '\n') + t[siz-1] = '\0'; + if (!qt) + for (s = t; *s; s++) + if (*s == '$') { + *s = Qstring; + } else if (*s == '`') { + *s = Qtick; + } else if (*s == '(') { + *s = Inpar; + } else if (*s == ')') { + *s = Outpar; + } else if (*s == '\\' && + (s[1] == '$' || s[1] == '`')) chuck(s); + s = strdup(t); + free(t); + return s; +} + +/* open here string fd */ + +int getherestr(fn) /**/ +struct redir *fn; +{ +Lklist fake; +char *s = gettemp(),*t; +int fd; + + fake = newlist(); + addnode(fake,fn->name); + prefork(fake); + if (!errflag) + postfork(fake,1); + if (errflag) + return -1; + if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1) + return -1; + while (t = ugetnode(fake)) + { + untokenize(t); + write(fd,t,strlen(t)); + if (full(fake)) + write(fd," ",1); + } + write(fd,"\n",1); + close(fd); + fd = open(s,O_RDONLY); + unlink(s); + return fd; +} + +void catproc(mn) /**/ +struct multio *mn; +{ +int len,t0; +char *buf; + + if (phork()) + { + for (t0 = 0; t0 != mn->ct; t0++) + close(mn->fds[t0]); + close(mn->pipe); + return; + } + closeallelse(mn); + buf = zalloc(4096); + for (t0 = 0; t0 != mn->ct; t0++) + while (len = read(mn->fds[t0],buf,4096)) + write(mn->pipe,buf,len); + _exit(0); +} + +void teeproc(mn) /**/ +struct multio *mn; +{ +int len,t0; +char *buf; + + if (phork()) + { + for (t0 = 0; t0 != mn->ct; t0++) + close(mn->fds[t0]); + close(mn->pipe); + return; + } + buf = zalloc(4096); + closeallelse(mn); + while ((len = read(mn->pipe,buf,4096)) > 0) + for (t0 = 0; t0 != mn->ct; t0++) + write(mn->fds[t0],buf,len); + _exit(0); +} + +void closeallelse(mn) /**/ +struct multio *mn; +{ +int t0,t1; + + for (t0 = 0; t0 != NOFILE; t0++) + if (mn->pipe != t0) + { + for (t1 = 0; t1 != mn->ct; t1++) + if (mn->fds[t1] == t0) + break; + if (t1 == mn->ct) + close(t0); + } +} + +long int zstrtol(s,t,base) /**/ +char *s;char **t;int base; +{ +int ret = 0; + + if (base <= 10) + for (; *s >= '0' && *s < ('0'+base); s++) + ret = ret*base+*s-'0'; + else + for (; idigit(*s) || (*s >= 'a' && *s < ('a'+base-10)) + || (*s >= 'A' && *s < ('A'+base-10)); s++) + ret = ret*base+(idigit(*s) ? (*s-'0') : (*s & 0x1f)+9); + if (t) + *t = (char *) s; + return ret; +} + +/* $(...) */ + +Lklist getoutput(cmd,qt) /**/ +char *cmd;int qt; +{ +List list; +int pipes[2]; + + if (*cmd == '<') { + int stream; + char *fi,*s,x; + + for (cmd++; *cmd == ' '; cmd++); + for (s = cmd; *s && *s != ' '; s++) + if (*s == '\\') s++; + else if (*s == '$') *s = String; + x = *s; + *s = '\0'; + fi = strdup(cmd); + *s = x; + if (*fi == '~') + *fi = Tilde; + else if (*fi == '=') + *fi = Equals; + singsub(&fi); + if (errflag) + return NULL; + stream = open(fi,O_RDONLY); + if (stream == -1) { + zerr("%e: %s",fi,errno); + return NULL; + } + return readoutput(stream,qt); + } + if (!(list = parselstring(cmd))) + return NULL; + mpipe(pipes); + if (phork()) + { + popheap(); + close(pipes[1]); + /* chldsuspend(); */ + return readoutput(pipes[0],qt); + } + subsh = 1; + close(pipes[0]); + redup(pipes[1],1); + entersubsh(0); + signal(SIGTSTP,SIG_IGN); + exiting = 1; + execlist(list); + close(1); + exit(0); return NULL; +} + +/* read output of command substitution */ + +Lklist readoutput(in,qt) /**/ +int in;int qt; +{ +Lklist ret; +char *buf,*ptr; +int bsiz,c,cnt = 0; +FILE *fin; + + fin = fdopen(in,"r"); + ret = newlist(); + ptr = buf = ncalloc(bsiz = 64); + while ((c = fgetc(fin)) != EOF) + if (!qt && isep(c)) { + if (cnt) { + *ptr = '\0'; + addnode(ret,buf); + ptr = buf = ncalloc(bsiz = 64); + cnt = 0; + ptr = buf; + } + } else { + *ptr++ = c; + if (++cnt == bsiz) { + char *pp = ncalloc(bsiz *= 2); + + memcpy(pp,buf,cnt); + ptr = (buf = pp)+cnt; + } + } + if (ptr != buf && ptr[-1] == '\n') + ptr[-1] = '\0'; + else + *ptr = '\0'; + if (cnt) addnode(ret,buf); + fclose(fin); + return ret; +} + +/* =(...) */ + +char *getoutputfile(cmd) /**/ +char *cmd; +{ +#ifdef WAITPID +int pid; +#endif +char *nam = gettemp(),*str; +int tfil; +List list; + + if (thisjob == -1) + return NULL; + for (str = cmd; *str && *str != Outpar; str++); + if (!*str) + zerr("oops.",NULL,0); + *str = '\0'; + if (!(list = parselstring(cmd))) + return NULL; + permalloc(); + if (!jobtab[thisjob].filelist) + jobtab[thisjob].filelist = newlist(); + addnode(jobtab[thisjob].filelist,ztrdup(nam)); + heapalloc(); +#ifdef WAITPID + if (pid = phork()) + { + popheap(); + waitpid(pid,NULL,WUNTRACED); + return nam; + } +#else + if (waitfork()) { + popheap(); + return nam; + } +#endif + subsh = 1; + close(1); + entersubsh(0); + tfil = creat(nam,0666); + exiting = 1; + execlist(list); + close(1); + exit(0); return NULL; +} + +/* get a temporary named pipe */ + +char *namedpipe() /**/ +{ +#ifndef NO_FIFOS +char *tnam = gettemp(); + + if (mknod(tnam,0010666,0) < 0) return NULL; + return tnam; +#else + return NULL; +#endif +} + +/* <(...) */ + +char *getoutproc(cmd) /**/ +char *cmd; +{ +#ifdef NO_FIFOS + zerr("doesn't look like your system supports FIFOs.",NULL,0); + return NULL; +#else +List list; +int fd; +char *pnam,*str; + + if (thisjob == -1) + return NULL; + for (str = cmd; *str && *str != Outpar; str++); + if (!*str) + zerr("oops.",NULL,0); + *str = '\0'; + pnam = namedpipe(); + if (!pnam) return NULL; + permalloc(); + if (!jobtab[thisjob].filelist) + jobtab[thisjob].filelist = newlist(); + addnode(jobtab[thisjob].filelist,ztrdup(pnam)); + heapalloc(); + if (!(list = parselstring(cmd))) + return NULL; + if (phork()) + { + popheap(); + return pnam; + } + entersubsh(1); + closem(); + fd = open(pnam,O_WRONLY); + if (fd == -1) + { + zerr("can't open %s: %e",pnam,errno); + _exit(0); + } + redup(fd,1); + fd = open("/dev/null",O_RDONLY); + redup(fd,0); + exiting = 1; + execlist(list); + close(1); + _exit(0); return NULL; +#endif +} + +/* >(...) */ + +char *getinproc(cmd) /**/ +char *cmd; +{ +#ifdef NO_FIFOS + zerr("doesn't look like your system supports FIFOs.",NULL,0); + return NULL; +#else +List list; +int pid,fd; +char *pnam,*str; + + if (thisjob == -1) + return NULL; + for (str = cmd; *str && *str != Outpar; str++); + if (!*str) + zerr("oops.",NULL,0); + *str = '\0'; + pnam = namedpipe(); + if (!pnam) return NULL; + permalloc(); + if (!jobtab[thisjob].filelist) + jobtab[thisjob].filelist = newlist(); + addnode(jobtab[thisjob].filelist,ztrdup(pnam)); + heapalloc(); + if (!(list = parselstring(cmd))) + return NULL; + if (pid = phork()) + { + popheap(); + return pnam; + } + entersubsh(1); + closem(); + fd = open(pnam,O_RDONLY); + redup(fd,0); + exiting = 1; + execlist(list); + _exit(0); return NULL; +#endif +} + +/* > >(...) (does not use named pipes) */ + +int getinpipe(cmd) /**/ +char *cmd; +{ +List list; +int pipes[2]; +char *str = cmd; + + for (str = cmd; *str && *str != Outpar; str++); + if (!*str) + zerr("oops.",NULL,0); + *str = '\0'; + if (!(list = parselstring(cmd+2))) + return -1; + mpipe(pipes); + if (phork()) + { + popheap(); + close(pipes[1]); + return pipes[0]; + } + close(pipes[0]); + closem(); + entersubsh(1); + redup(pipes[1],1); + exiting = 1; + execlist(list); + _exit(0); return 0; +} + +/* < <(...) */ + +int getoutpipe(cmd) /**/ +char *cmd; +{ +List list; +int pipes[2]; +char *str; + + for (str = cmd; *str && *str != Outpar; str++); + if (!*str) + zerr("oops.",NULL,0); + *str = '\0'; + if (!(list = parselstring(cmd+2))) + return -1; + strinend(); + mpipe(pipes); + if (phork()) + { + popheap(); + close(pipes[0]); + return pipes[1]; + } + close(pipes[1]); + closem(); + entersubsh(1); + redup(pipes[0],0); + exiting = 1; + execlist(list); + _exit(0); return 0; +} + +/* run a list, saving the current job num */ + +void runlist(l) /**/ +List l; +{ +int cj = thisjob; + + execlist(l); + thisjob = cj; +} + +char *gettemp() /**/ +{ + return mktemp(dyncat(tmpprefix,"XXXXXX")); +} + +/* my getwd; all the other ones I tried confused the SIGCHLD handler */ + +char *zgetwd() /**/ +{ +static char buf0[MAXPATHLEN]; +char buf3[MAXPATHLEN],*buf2 = buf0+1; +struct stat sbuf; +struct direct *de; +DIR *dir; +ino_t ino = -1; +dev_t dev = -1; + + holdintr(); + buf2[0] = '\0'; + buf0[0] = '/'; + for(;;) + { + if (stat(".",&sbuf) < 0) + { + chdir(buf0); + noholdintr(); + return ztrdup("."); + } + ino = sbuf.st_ino; + dev = sbuf.st_dev; + if (stat("..",&sbuf) < 0) + { + chdir(buf0); + noholdintr(); + return ztrdup("."); + } + if (sbuf.st_ino == ino && sbuf.st_dev == dev) + { + chdir(buf0); + noholdintr(); + return ztrdup(buf0); + } + dir = opendir(".."); + if (!dir) + { + chdir(buf0); + noholdintr(); + return ztrdup("."); + } + chdir(".."); + readdir(dir); readdir(dir); + while (de = readdir(dir)) + if (de->d_ino == ino) + { + lstat(de->d_name,&sbuf); + if (sbuf.st_dev == dev) + goto match; + } + rewinddir(dir); + readdir(dir); readdir(dir); + while (de = readdir(dir)) + { + lstat(de->d_name,&sbuf); + if (sbuf.st_dev == dev) + goto match; + } + noholdintr(); + closedir(dir); + return ztrdup("."); +match: + strcpy(buf3,de->d_name); + if (*buf2) + strcat(buf3,"/"); + strcat(buf3,buf2); + strcpy(buf2,buf3); + closedir(dir); + } +} + +/* open pipes with fds >= 10 */ + +void mpipe(pp) /**/ +int *pp; +{ + pipe(pp); + pp[0] = movefd(pp[0]); + pp[1] = movefd(pp[1]); +} + +/* do process substitution with redirection */ + +void spawnpipes(l) /**/ +Lklist l; +{ +Lknode n = firstnode(l); +Redir f; + + for (; n; incnode(n)) + { + f = (Redir) getdata(n); + if (f->type == OUTPIPE) + { + char *str = f->name; + f->fd2 = getoutpipe(str); + } + if (f->type == INPIPE) + { + char *str = f->name; + f->fd2 = getinpipe(str); + } + } +} + +/* perform time ... command */ + +int exectime(cmd) /**/ +Cmd cmd; +{ +int jb = thisjob; + + if (!cmd->u.pline) { shelltime(); return 0; } + execpline(cmd->u.pline,TIMED,0); + thisjob = jb; + return lastval; +} + +/* define a function */ + +int execfuncdef(cmd) /**/ +Cmd cmd; +{ +Cmdnam cc; +char *s; + + permalloc(); + while (s = ugetnode(cmd->args)) + { + cc = (Cmdnam) zalloc(sizeof *cc); + cc->type = SHFUNC; + cc->flags = 0; + if (!cmd->u.list) + cc->u.list = NULL; + else + cc->u.list = (List) dupstruct(cmd->u.list); + addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam); + if (!strncmp(s,"TRAP",4)) + { + int t0 = getsignum(s+4); + + if (t0 != -1) + settrap(t0,cmd->u.list); + } + } + heapalloc(); + return 0; +} + +/* evaluate a [[ ... ]] */ + +int execcond(cmd) /**/ +Cmd cmd; +{ + return !evalcond(cmd->u.cond); +} + +void execshfunc(cmd,cn) /**/ +Cmd cmd;Cmdnam cn; +{ +List l; + + if (errflag) return; + l = cn->u.list; + if (!l) { + char *nam; + + if (!(cn->flags & PMFLAG_u)) return; + if (!(l = getfpfunc(nam = peekfirst(cmd->args)))) { + zerr("function not found: %s",nam,0); + lastval = 1; + return; + } + cn->flags &= ~PMFLAG_u; + permalloc(); + cn->u.list = (List) dupstruct(l); + heapalloc(); + } + doshfunc(l,cmd->args,cn->flags); +} + +void doshfuncnoval(list,args,flags) /**/ +List list; Lklist args; int flags; +{ +int val = lastval; + + doshfunc(list,args,flags); + lastval = val; +} + +void doshfunc(list,args,flags) /**/ +List list; Lklist args; int flags; +{ +char **tab,**x,*oargv0; +int oxtr = opts[XTRACE],opev = opts[PRINTEXITVALUE],xexittr; +Lklist olist; +char *s; +List xexitfn; + + xexittr = sigtrapped[SIGEXIT]; + xexitfn = sigfuncs[SIGEXIT]; + tab = pparams; + oargv0 = argzero; + zoptind = 1; + if (flags & PMFLAG_t) opts[XTRACE] = OPT_SET; + opts[PRINTEXITVALUE] = OPT_UNSET; + if (args) { + pparams = x = (char **) zcalloc(((sizeof *x)*(1+countnodes(args)))); + argzero = ztrdup(ugetnode(args)); + while (*x = ugetnode(args)) + *x = ztrdup(*x), x++; + } else { + pparams = zcalloc(sizeof *pparams); + argzero = ztrdup(argzero); + } + permalloc(); + olist = locallist; + locallist = newlist(); + heapalloc(); + runlist(dupstruct(list)); + while (s = getnode(locallist)) unsetparam(s); + free(locallist); + locallist = olist; + retflag = 0; + freearray(pparams); + free(argzero); + argzero = oargv0; + pparams = tab; + if (sigfuncs[SIGEXIT] && sigfuncs[SIGEXIT] != xexitfn) { + dotrap(SIGEXIT); + freestruct(sigfuncs[SIGEXIT]); + } + sigtrapped[SIGEXIT] = xexittr; + sigfuncs[SIGEXIT] = xexitfn; + opts[XTRACE] = oxtr; + opts[PRINTEXITVALUE] = opev; +} + +/* search fpath for an undefined function */ + +List getfpfunc(s) /**/ +char *s; +{ +char **pp = fpath,buf[MAXPATHLEN]; +int fd; + + for (; *pp; pp++) + { + sprintf(buf,"%s/%s",*pp,s); + if (!access(buf,R_OK) && (fd = open(buf,O_RDONLY)) != -1) + { + int len = lseek(fd,0,2); + + if (len == -1) + close(fd); + else + { + char *d; + + lseek(fd,0,0); + d = zcalloc(len+1); + if (read(fd,d,len) != len) + { + free(d); + close(fd); + } + else + { + close(fd); + return parselstring(d); + } + } + } + } + return NULL; +} + +/* check to see if AUTOCD applies here */ + +int cancd(s) +char *s; +{ +char *t; + + if ((t = getsparam(s)) && *t == '/') return 1; + if (*s != '/') + { + char sbuf[MAXPATHLEN],**cp; + + if (cancd2(s)) + return 1; + if (access(s,X_OK) == 0) + return 0; + for (cp = cdpath; *cp; cp++) + { + sprintf(sbuf,"%s/%s",*cp,s); + if (cancd2(sbuf)) + return 1; + } + return 0; + } + return cancd2(s); +} + +int cancd2(s) +char *s; +{ +struct stat buf; + + return !(access(s,X_OK) || stat(s,&buf) || !S_ISDIR(buf.st_mode)); +} + diff --git a/usr/othersrc/public/zsh-2.2/src/exec.pro b/usr/othersrc/public/zsh-2.2/src/exec.pro new file mode 100644 index 0000000000..b59cc180b6 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/exec.pro @@ -0,0 +1,53 @@ +List parselstring DCLPROTO((char *s)); +void execstring DCLPROTO((char *s)); +int phork DCLPROTO((void)); +int execcursh DCLPROTO((Cmd cmd)); +int zexecve DCLPROTO((char *pth,char **argv)); +void execute DCLPROTO((int dash)); +char *findcmd DCLPROTO((char *arg0)); +int iscom DCLPROTO((char *s)); +int isrelative DCLPROTO((char *s)); +int hashcmd DCLPROTO((char *arg0,char **pp)); +void fullhash DCLPROTO((void)); +void execlist DCLPROTO((List list)); +void execlist2 DCLPROTO((Sublist list,int type,int last1)); +int execpline DCLPROTO((Sublist l,int how,int last1)); +void execpline2 DCLPROTO((Pline pline,int how,int input,int output,int last1)); +char **makecline DCLPROTO((struct lklist *list)); +void fixcline DCLPROTO((Lklist l)); +void untokenize DCLPROTO((char *s)); +int dontclob DCLPROTO((struct redir *f)); +void closemn DCLPROTO((struct multio **mfds,int fd)); +void closemnodes DCLPROTO((struct multio **mfds)); +void addfd DCLPROTO((int forked,int *save,struct multio **mfds,int fd1,int fd2,int rflag)); +void addvars DCLPROTO((Lklist l,int export)); +void execcmd DCLPROTO((Cmd cmd,int input,int output,int bkg,int last1)); +void fixfds DCLPROTO((int *save)); +void entersubsh DCLPROTO((int bkg)); +void closem DCLPROTO((void)); +char *gethere DCLPROTO((char *str,int typ)); +int getherestr DCLPROTO((struct redir *fn)); +void catproc DCLPROTO((struct multio *mn)); +void teeproc DCLPROTO((struct multio *mn)); +void closeallelse DCLPROTO((struct multio *mn)); +long int zstrtol DCLPROTO((char *s,char **t,int base)); +Lklist getoutput DCLPROTO((char *cmd,int qt)); +Lklist readoutput DCLPROTO((int in,int qt)); +char *getoutputfile DCLPROTO((char *cmd)); +char *namedpipe DCLPROTO((void)); +char *getoutproc DCLPROTO((char *cmd)); +char *getinproc DCLPROTO((char *cmd)); +int getinpipe DCLPROTO((char *cmd)); +int getoutpipe DCLPROTO((char *cmd)); +void runlist DCLPROTO((List l)); +char *gettemp DCLPROTO((void)); +char *zgetwd DCLPROTO((void)); +void mpipe DCLPROTO((int *pp)); +void spawnpipes DCLPROTO((Lklist l)); +int exectime DCLPROTO((Cmd cmd)); +int execfuncdef DCLPROTO((Cmd cmd)); +int execcond DCLPROTO((Cmd cmd)); +void execshfunc DCLPROTO((Cmd cmd,Cmdnam cn)); +void doshfuncnoval DCLPROTO((List list, Lklist args, int flags)); +void doshfunc DCLPROTO((List list, Lklist args, int flags)); +List getfpfunc DCLPROTO((char *s)); diff --git a/usr/othersrc/public/zsh-2.2/src/funcs.h b/usr/othersrc/public/zsh-2.2/src/funcs.h new file mode 100644 index 0000000000..be6a3a1deb --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/funcs.h @@ -0,0 +1,47 @@ +struct asgment; +struct utmp; + +#include "builtin.pro" +#include "cond.pro" +#include "exec.pro" +#include "glob.pro" +#include "hist.pro" +#include "init.pro" +#include "jobs.pro" +#include "lex.pro" +#include "loop.pro" +#include "math.pro" +#include "mem.pro" +#include "params.pro" +#include "parse.pro" +#include "subst.pro" +#include "table.pro" +#include "text.pro" +#include "utils.pro" +#include "watch.pro" +#include "zle_hist.pro" +#include "zle_main.pro" +#include "zle_misc.pro" +#include "zle_move.pro" +#include "zle_refresh.pro" +#include "zle_tricky.pro" +#include "zle_utils.pro" +#include "zle_vi.pro" +#include "zle_word.pro" + +char *mktemp DCLPROTO((char *)); +#ifndef HAS_STDLIB +char *malloc DCLPROTO((int)); +char *realloc DCLPROTO((char *,int)); +char *calloc DCLPROTO((int,int)); +#endif +char *ttyname DCLPROTO((int)); + +extern char PC, *BC, *UP; +extern short ospeed; +extern int tgetent DCLPROTO((char *bp, char *name)); +extern int tgetnum DCLPROTO((char *id)); +extern int tgetflag DCLPROTO((char *id)); +extern char *tgetstr DCLPROTO((char *id, char **area)); +extern char *tgoto DCLPROTO((char *cm, int destcol, int destline)); +extern int tputs DCLPROTO((char *cp, int affcnt, int (*outc)())); diff --git a/usr/othersrc/public/zsh-2.2/src/glob.c b/usr/othersrc/public/zsh-2.2/src/glob.c new file mode 100644 index 0000000000..ec15a92181 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/glob.c @@ -0,0 +1,1273 @@ +/* + * + * glob.c - filename generation + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +#ifdef __hpux +#include +#else +#ifdef SYSV +#define direct dirent +#else +#include +#endif +#endif +#include + +#define exists(X) (access(X,0) == 0 || readlink(X,NULL,0) == 0) + +static int mode; /* != 0 if we are parsing glob patterns */ +static int pathpos; /* position in pathbuf */ +static int matchsz; /* size of matchbuf */ +static int matchct; /* number of matches found */ +static char pathbuf[MAXPATHLEN]; /* pathname buffer */ +static char **matchbuf; /* array of matches */ +static char **matchptr; /* &matchbuf[matchct] */ +static Comp exclude; /* pattern to exclude */ + +/* max # of qualifiers */ + +#define QUALCT 16 + +static int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long)); +static long qualdata[QUALCT]; +static int qualsense[QUALCT]; +static int qualct; +static int gf_nullglob,gf_markdirs,gf_noglobdots; + +/* pathname component in filename patterns */ + +struct complist { + Complist next; + Comp comp; + int closure; /* 1 if this is a (foo/)# */ + }; +struct comp { + Comp left,right,next; + char *str; + int closure,last; + }; + +void glob(list,np) /**/ +Lklist list;Lknode *np; +{ +Lknode node = prevnode(*np); +Lknode next = nextnode(*np); +int sl; /* length of the pattern */ +char *ostr; /* the pattern before the parser chops it up */ +Complist q; /* pattern after parsing */ +char *str = getdata(*np); /* the pattern */ + + sl = strlen(str); + ostr = strdup(str); + uremnode(list,*np); + qualct = 0; + gf_nullglob = isset(NULLGLOB); + gf_markdirs = isset(MARKDIRS); + gf_noglobdots = unset(GLOBDOTS); + if (str[sl-1] == Outpar) /* check for qualifiers */ + { + char *s; + int sense = 0; + long data; + int (*func) DCLPROTO((struct stat *,long)); + + for (s = str+sl-2; s != str; s--) + if (*s == Bar || *s == Outpar || *s == Inpar) + break; + if (*s == Inpar) + { + *s++ = '\0'; + func = NULL; + while (*s != Outpar) + { + func = NULL; + if (idigit(*s)) + { + func = qualflags; + data = 0; + while (idigit(*s)) + data = data*010+(*s++-'0'); + } + else switch ((int)(unsigned char)(*s++)) + { + case (int)(unsigned char)Hat: case '^': sense = 1-sense; break; +#ifdef S_IFLNK + case '@': func = qualmode; data = S_IFLNK; break; +#endif +#ifdef S_IFSOCK + case '=': func = qualmode; data = S_IFSOCK; break; +#endif +#ifdef S_IFIFO + case 'p': func = qualmode; data = S_IFIFO; break; +#endif + case '/': func = qualmode; data = S_IFDIR; break; + case '.': func = qualmode; data = S_IFREG; break; + case '%': func = qualisdev; break; + case (int)(unsigned char)Star: func = qualiscom; break; + case 'R': func = qualflags; data = 0004; break; + case 'W': func = qualflags; data = 0002; break; + case 'X': func = qualflags; data = 0001; break; + case 'r': func = qualflags; data = 0400; break; + case 'w': func = qualflags; data = 0200; break; + case 'x': func = qualflags; data = 0100; break; + case 's': func = qualflags; data = 04000; break; + case 'S': func = qualflags; data = 02000; break; + case 'd': func = qualdev; data = qgetnum(&s); break; + case 'l': func = qualnlink; data = qgetnum(&s); break; + case 'U': func = qualuid; data = geteuid(); break; + case 'G': func = qualgid; data = getegid(); break; + case 'u': func = qualuid; data = qgetnum(&s); break; + case 'g': func = qualgid; data = qgetnum(&s); break; + case 'M': gf_markdirs = !sense; break; + case 'N': gf_nullglob = !sense; break; + case 'D': gf_noglobdots = sense; break; + default: zerr("unknown file attribute",NULL,0); return; + } + if (func) + { + if (qualct == QUALCT-1) + { + zerr("too many qualifiers",NULL,0); + return; + } + qualfuncs[qualct] = func; + qualsense[qualct] = sense; + qualdata[qualct] = data; + qualct++; + } + if (errflag) + return; + } + } + } + else if ((str[sl-1] == '/') && !((str[sl-2] == Star)&& + (str[sl-3] == Star)&&(str[sl-4] == Star)&& + (str[sl-5]==Star))) /* foo/ == foo(/) */ + { + str[sl-1] = '\0'; + qualfuncs[0] = qualmode; + qualdata[0] = S_IFDIR; + qualsense[0] = 0; + qualct = 1; + } + qualfuncs[qualct] = NULL; + if (*str == '/') /* pattern has absolute path */ + { + str++; + pathbuf[0] = '/'; + pathbuf[pathpos = 1] = '\0'; + } + else /* pattern is relative to pwd */ + pathbuf[pathpos = 0] = '\0'; + q = parsepat(str); + if (!q || errflag) /* if parsing failed */ + { + if (isset(NOBADPATTERN)) + { + insnode(list,node,ostr); + return; + } + errflag = 0; + zerr("bad pattern: %s",ostr,0); + return; + } + matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *)); + matchct = 0; + scanner(q); /* do the globbing */ + if (matchct) + badcshglob |= 2; + else if (!gf_nullglob) + if (isset(CSHNULLGLOB)) { + badcshglob |= 1; + } else if (unset(NONOMATCH)) { + zerr("no matches found: %s",ostr,0); + free(matchbuf); + return; + } else { + *matchptr++ = strdup(ostr); + matchct = 1; + } + qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp); + matchptr = matchbuf; + while (matchct--) /* insert matches in the arg list */ + insnode(list,node,*matchptr++); + free(matchbuf); + *np = (next) ? prevnode(next) : lastnode(list); +} + +/* get number after qualifier */ + +long qgetnum(s) /**/ +char **s; +{ +long v = 0; + + if (!idigit(**s)) + { + zerr("number expected",NULL,0); + return 0; + } + while (idigit(**s)) + v = v*10+*(*s)++-'0'; + return v; +} + +int notstrcmp(a,b) /**/ +char **a;char **b; +{ +char *c = *b,*d = *a; +int x1,x2; + + for (; *c == *d && *c; c++,d++); + x1 = atoi(c); x2 = atoi(d); + if (x1==x2 || unset(NUMERICGLOBSORT)) + return ((int) (unsigned char) *c-(int) (unsigned char) *d); + return x1-x2; +} + +int forstrcmp(a,b) /**/ +char **a;char **b; +{ +char *c = *b,*d = *a; + + for (; *c == *d && *c; c++,d++); + return ((int) (unsigned char) *d-(int) (unsigned char) *c); +} + +/* add a match to the list */ + +void insert(s) /**/ +char *s; +{ +struct stat buf; +int statted = 0; + + if (exclude && domatch(s,exclude,gf_noglobdots)) return; + if (gf_markdirs && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) { + char *t; + int ll = strlen(s); + + t = ncalloc(ll+2); + strcpy(t,s); + t[ll] = '/'; + t[ll+1] = '\0'; + s = t; + statted = 1; + } + if (qualct) { /* do the (X) (^X) stuff */ + int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs; + int *sptr = qualsense; + long *lptr = qualdata; + struct stat buf; + + if (statted || lstat(s,&buf) >= 0) + while (*fptr) if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++)) return; + } + *matchptr++ = s; + if (++matchct == matchsz) { + matchbuf = (char **) realloc((char *) matchbuf, + sizeof(char **)*(matchsz *= 2)); + matchptr = matchbuf+matchct; + } +} + +/* check to see if str is eligible for filename generation */ + +int haswilds(str) /**/ +char *str; +{ + if ((*str == Inbrack || *str == Outbrack) && !str[1]) return 0; + if (str[0] == '%') return 0; + for (; *str; str++) + if (*str == Pound || *str == Hat || *str == Star || + *str == Bar || *str == Inbrack || *str == Inang || + *str == Quest) return 1; + return 0; +} + +/* check to see if str is eligible for brace expansion */ + +int hasbraces(str) /**/ +char *str; +{ +int mb,bc,cmct1,cmct2; +char *lbr = NULL; + + if (str[0] == Inbrace && str[1] == Outbrace) + return 0; + if (isset(BRACECCL)) { + for (mb = bc = 0; *str; ++str) + if (*str == Inbrace) { + if (++bc > mb) + mb = bc; + } + else if (*str == Outbrace) + if (--bc < 0) + return(0); + return(mb && bc == 0); + } + for (mb = bc = cmct1 = cmct2 = 0; *str; str++) + { + if (*str == Inbrace) + { + if (!bc) + lbr = str; + bc++; + if (str[4] == Outbrace && str[2] == '-') /* {a-z} */ + { + cmct1++; + if (bc == 1) + cmct2++; + } + } + else if (*str == Outbrace) + { + bc--; + if (!bc) + { + if (!cmct2) + { + *lbr = '{'; + *str = '}'; + } + cmct2 = 0; + } + } + else if (*str == Comma && bc) + { + cmct1++; + if (bc == 1) + cmct2++; + } + if (bc > mb) + mb = bc; + if (bc < 0) + return 0; + } + return (mb && bc == 0 && cmct1); +} + +/* expand stuff like >>*.c */ + +int xpandredir(fn,tab) /**/ +struct redir *fn;Lklist tab; +{ +Lklist fake; +char *nam; +struct redir *ff; +int ret = 0; + + fake = newlist(); + addnode(fake,fn->name); + prefork(fake); + if (!errflag) + postfork(fake,1); + if (errflag) return 0; + if (full(fake) && !nextnode(firstnode(fake))) { + fn->name = peekfirst(fake); + untokenize(fn->name); + } else + while (nam = ugetnode(fake)) { + ff = alloc(sizeof *ff); + *ff = *fn; + ff->name = nam; + addnode(tab,ff); + ret = 1; + } + return ret; +} + +/* concatenate s1 and s2 in dynamically allocated buffer */ + +char *dyncat(s1,s2) /**/ +char *s1;char *s2; +{ +char *ptr; + + ptr = ncalloc(strlen(s1)+strlen(s2)+1); + strcpy(ptr,s1); + strcat(ptr,s2); + return ptr; +} + +/* concatenate s1, s2, and s3 in dynamically allocated buffer */ + +char *tricat(s1,s2,s3) /**/ +char *s1;char *s2;char *s3; +{ +char *ptr; + + ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1); + strcpy(ptr,s1); + strcat(ptr,s2); + strcat(ptr,s3); + return ptr; +} + +/* brace expansion */ + +void xpandbraces(list,np) /**/ +Lklist list;Lknode *np; +{ +Lknode node = (*np),last = prevnode(node); +char *str = getdata(node),*str3 = str,*str2; +int prev, bc, comma; + + for (; *str != Inbrace; str++); + for (str2 = str, bc = comma = 0; *str2; ++str2) + if (*str2 == Inbrace) + ++bc; + else if (*str2 == Outbrace) { + if (--bc == 0) + break; + } + else if (bc == 1 && *str2 == Comma) + ++comma; + if (!comma && !bc && isset(BRACECCL)) { /* {a-mnop} */ + char ccl[256], *p; + unsigned char c1,c2,lastch; + + uremnode(list,node); + memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0])); + for (p = str + 1, lastch = 0; p < str2; ) { + if (itok(c1 = *p++)) + c1 = ztokens[c1 - (unsigned char)Pound]; + if (itok(c2 = *p)) + c2 = ztokens[c2 - (unsigned char)Pound]; + if (c1 == '-' && lastch && p < str2 && lastch <= c2) { + while (lastch < c2) + ccl[lastch++] = 1; + lastch = 0; + } + else + ccl[lastch = c1] = 1; + } + strcpy(str + 1, str2 + 1); + for (p = ccl+255; p-- > ccl; ) + if (*p) { + *str = p - ccl; + insnode(list, last, strdup(str3)); + } + *np = nextnode(last); + return; + } + if (str[2] == '-' && str[4] == Outbrace) /* {a-z} */ + { + char c1,c2; + + uremnode(list,node); + chuck(str); + c1 = *str; + chuck(str); + chuck(str); + c2 = *str; + chuck(str); + if (itok(c1)) + c1 = ztokens[c1-Pound]; + if (itok(c2)) + c2 = ztokens[c2-Pound]; + if (c1 < c2) + for (; c2 >= c1; c2--) /* {a-z} */ + { + *str = c2; + insnode(list,last,strdup(str3)); + } + else + for (; c2 <= c1; c2++) /* {z-a} */ + { + *str = c2; + insnode(list,last,strdup(str3)); + } + *np = nextnode(last); + return; + } + prev = str-str3; + str2 = getparen(str++); + if (!str2) + { + zerr("how did you get this error?",NULL,0); + return; + } + uremnode(list,node); + node = last; + 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--; + else if (!*str) + exit(10); + zz = zalloc(prev+(str-str4)+strlen(str2)+1); + ztrncpy(zz,str3,prev); + strncat(zz,str4,str-str4); + strcat(zz,str2); + insnode(list,node,zz); + incnode(node); + if (*str != Outbrace) + str++; + else + break; + } + *np = nextnode(last); +} + +/* get closing paren, given pointer to opening paren */ + +char *getparen(str) /**/ +char *str; +{ +int cnt = 1; +char typein = *str++,typeout = typein+1; + + for (; *str && cnt; str++) + if (*str == typein) + cnt++; + else if (*str == typeout) + cnt--; + if (!str && cnt) + return NULL; + return str; +} + +/* check to see if a matches b (b is not a filename pattern) */ + +int matchpat(a,b) /**/ +char *a;char *b; +{ +Comp c; +int val,len; +char *b2; + + remnulargs(b); + len = strlen(b); + b2 = alloc(len+3); + strcpy(b2+1,b); + b2[0] = Inpar; + b2[len+1] = Outpar; + b2[len+2] = '\0'; + c = parsereg(b2); + if (!c) + { + zerr("bad pattern: %s",b,0); + return 0; + } + val = domatch(a,c,0); + return val; +} + +/* do the ${foo%%bar}, ${foo#bar} stuff */ +/* please do not laugh at this code. */ + +void getmatch(sp,pat,dd) /**/ +char **sp;char *pat;int dd; +{ +Comp c; +char *t,*lng = NULL,cc,*s = *sp; + + remnulargs(pat); + c = parsereg(pat); + if (!c) + { + zerr("bad pattern: %s",pat,0); + return; + } + if (!(dd & 2)) + { + for (t = s; t==s || t[-1]; t++) + { + cc = *t; + *t = '\0'; + if (domatch(s,c,0)) + { + if (!(dd & 1)) + { + *t = cc; + t = strdup(t); + *sp = t; + return; + } + lng = t; + } + *t = cc; + } + if (lng) + { + t = strdup(lng); + *sp = t; + return; + } + } + else + { + for (t = s+strlen(s); t >= s; t--) + { + if (domatch(t,c,0)) + { + if (!(dd & 1)) + { + cc = *t; + *t = '\0'; + *sp = strdup(*sp); + *t = cc; + return; + } + lng = t; + } + } + if (lng) + { + cc = *lng; + *lng = '\0'; + *sp = strdup(*sp); + *lng = cc; + return; + } + } +} + +/* add a component to pathbuf */ + +static int addpath(s) +char *s; +{ + if (strlen(s)+pathpos >= MAXPATHLEN) return 0; + while (pathbuf[pathpos++] = *s++); + pathbuf[pathpos-1] = '/'; + pathbuf[pathpos] = '\0'; + return 1; +} + +char *getfullpath(s) /**/ +char *s; +{ +static char buf[MAXPATHLEN]; + + strcpy(buf,pathbuf); + strcat(buf,s); + return buf; +} + +/* do the globbing */ + +void scanner(q) /**/ +Complist q; +{ +Comp c; +int closure; + + if (closure = q->closure) /* (foo/)# */ + if (q->closure == 2) /* (foo/)## */ + q->closure = 1; + else + scanner(q->next); + if (c = q->comp) + { + if (!(c->next || c->left) && !haswilds(c->str)) + if (q->next) + { + int oppos = pathpos; + + if (errflag) + return; + if (q->closure && !strcmp(c->str,".")) return; + if (!addpath(c->str)) return; + if (!closure || exists(pathbuf)) + scanner((q->closure) ? q : q->next); + pathbuf[pathpos = oppos] = '\0'; + } + else + { + char *s; + + if (exists(s = getfullpath(c->str))) + insert(strdup(s)); + } + else + { + char *fn; + int dirs = !!q->next; + struct direct *de; + DIR *lock = opendir((*pathbuf) ? pathbuf : "."); + + if (lock == NULL) + return; + readdir(lock); readdir(lock); /* skip . and .. */ + while (de = readdir(lock)) + { + if (errflag) + break; + fn = &de->d_name[0]; + if (domatch(fn,c,gf_noglobdots)) + { + int oppos = pathpos; + + if (dirs) + { + if (closure) + { + int type3; + struct stat buf; + + if (lstat(getfullpath(fn),&buf) == -1) + { + if (errno != ENOENT && errno != EINTR && + errno != ENOTDIR) + { + zerr("%e: %s",fn,errno); + errflag = 0; + } + continue; + } + type3 = buf.st_mode & S_IFMT; + if (type3 != S_IFDIR) + continue; + } + if (addpath(fn)) + scanner((q->closure) ? q : q->next); /* scan next level */ + pathbuf[pathpos = oppos] = '\0'; + } + else insert(dyncat(pathbuf,fn)); + } + } + closedir(lock); + } + } + else + zerr("no idea how you got this error message.",NULL,0); +} + +/* do the [..(foo)..] business */ + +int minimatch(pat,str) /**/ +char **pat;char **str; +{ +char *pt = *pat+1,*s = *str; + + for (; *pt != Outpar; s++,pt++) + if ((*pt != Quest || !*s) && *pt != *s) + { + *pat = getparen(*pat)-1; + return 0; + } + *str = s-1; + return 1; +} + +static char *pptr; +static Comp tail = 0; +static int first; + +int domatch(str,c,fist) /**/ +char *str;Comp c;int fist; +{ + pptr = str; + first = fist; + return doesmatch(c); +} + +/* see if current pattern matches c */ + +int doesmatch(c) /**/ +Comp c; +{ +char *pat = c->str; + + if (c->closure == 1) { + char *saves = pptr; + + if (first && *pptr == '.') return 0; + if (doesmatch(c->next)) return 1; + pptr = saves; + first = 0; + } + for(;;) + { + if (!pat || !*pat) + { + char *saves; + int savei; + + if (errflag) + return 0; + saves = pptr; + savei = first; + if (c->left || c->right) + if (!doesmatch(c->left)) + if (c->right) + { + pptr = saves; + first = savei; + if (!doesmatch(c->right)) + return 0; + } + else + return 0; + if (c->closure) + return doesmatch(c); + if (!c->next) + return (!c->last || !*pptr); + return doesmatch(c->next); + } + if (first && *pptr == '.' && *pat != '.') + return 0; + if (*pat == Star) /* final * is not expanded to ?#; returns success */ + { + while (*pptr) pptr++; + return 1; + } + first = 0; + if (*pat == Quest && *pptr) + { + pptr++; + pat++; + continue; + } + if (*pat == Hat) + return 1-doesmatch(c->next); + if (*pat == Inbrack) { + if (!*pptr) break; + if (pat[1] == Hat || pat[1] == '^') { + pat[1] = Hat; + for (pat += 2; *pat != Outbrack && *pat; pat++) + if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) { + if (pat[-1] <= *pptr && pat[1] >= *pptr) + break; + } else if (*pptr == *pat) break; + if (!*pat) { + zerr("something is very wrong.",NULL,0); + return 0; + } + if (*pat != Outbrack) + break; + pat++; + pptr++; + continue; + } else { + for (pat++; *pat != Outbrack && *pat; pat++) + if (*pat == Inpar) { + if (minimatch(&pat,&pptr)) + break; + } else if (*pat == '-' && pat[-1] != Inbrack && + pat[1] != Outbrack) { + if (pat[-1] <= *pptr && pat[1] >= *pptr) + break; + } else if (*pptr == *pat) break; + if (!pat || !*pat) { + zerr("oh dear. that CAN'T be right.",NULL,0); + return 0; + } + if (*pat == Outbrack) + break; + for (pptr++; *pat != Outbrack; pat++); + pat++; + continue; + } + } + if (*pat == Inang) + { + int t1,t2,t3; + char *ptr; + + if (*++pat == Outang) /* handle <> case */ + { + ( void ) zstrtol(pptr,&ptr,10); + if (ptr == pptr) + break; + pptr = ptr; + pat++; + } + else + { + t1 = zstrtol(pptr,&ptr,10); + if (ptr == pptr) + break; + pptr = ptr; + t2 = zstrtol(pat,&ptr,10); + if (*ptr != '-') + exit(31); + t3 = zstrtol(ptr+1,&pat,10); + if (!t3) + t3 = -1; + if (*pat++ != Outang) + exit(21); + if (t1 < t2 || (t3 != -1 && t1 > t3)) + break; + } + continue; + } + if (*pptr == *pat) + { + pptr++; + pat++; + continue; + } + break; + } + return 0; +} + +Complist parsepat(str) /**/ +char *str; +{ +char *s; + + exclude = NULL; + if (isset(EXTENDEDGLOB)) { + s = str+strlen(str); + while (s-- > str) { + if (*s == Tilde && s[1]) { + *s++ = '\0'; + exclude = parsereg(s); + if (!exclude) return NULL; + break; + } + } + } + mode = 0; + pptr = str; + return parsecomplist(); +} + +Comp parsereg(str) /**/ +char *str; +{ + mode = 1; + pptr = str; + return parsecompsw(); +} + +Complist parsecomplist() /**/ +{ +Comp c1; +Complist p1; + + if (pptr[0] == Star && pptr[1] == Star && + (pptr[2] == '/' || + (pptr[2] == Star && pptr[3] == Star && pptr[4] == '/'))) { + pptr += 3; + if (pptr[-1] == Star) pptr += 2; + p1 = (Complist) alloc(sizeof *p1); + p1->next = parsecomplist(); + p1->comp = (Comp) alloc(sizeof *p1->comp); + p1->comp->last = 1; + p1->comp->str = strdup("*"); + *p1->comp->str = Star; + p1->closure = 1; + return p1; + } + if (*pptr == Inpar) + { + char *str; + int pars = 1; + + for (str = pptr+1; *str && pars; str++) + if (*str == Inpar) + pars++; + else if (*str == Outpar) + pars--; + if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/') + goto kludge; + pptr++; + if (!(c1 = parsecompsw())) + return NULL; + if (pptr[0] == '/' && pptr[1] == Outpar && pptr[2] == Pound) + { + int pdflag = 0; + + pptr += 3; + if (*pptr == Pound) + { + pdflag = 1; + pptr++; + } + p1 = (Complist) alloc(sizeof *p1); + p1->comp = c1; + p1->closure = 1+pdflag; + p1->next = parsecomplist(); + return (p1->comp) ? p1 : NULL; + } + } + else + { +kludge: + if (!(c1 = parsecompsw())) + return NULL; + if (*pptr == '/' || !*pptr) + { + int ef = *pptr == '/'; + + p1 = (Complist) alloc(sizeof *p1); + p1->comp = c1; + p1->closure = 0; + p1->next = (*pptr == '/') ? (pptr++,parsecomplist()) : NULL; + return (ef && !p1->next) ? NULL : p1; + } + } + errflag = 1; + return NULL; +} + +Comp parsecomp() /**/ +{ +Comp c = (Comp) alloc(sizeof *c),c1,c2; +char *s = c->str = alloc(MAXPATHLEN*2),*ls = NULL; + + c->next = tail; + + while (*pptr && (mode || *pptr != '/') && *pptr != Bar && + *pptr != Outpar) + { + if (*pptr == Hat) + { + *s++ = Hat; + *s++ = '\0'; + pptr++; + if (!(c->next = parsecomp())) + return NULL; + return c; + } + if (*pptr == Star && pptr[1] && (mode || pptr[1] != '/')) + { + *s++ = '\0'; + pptr++; + c1 = (Comp) alloc(sizeof *c1); + *(c1->str = strdup("?")) = Quest; + c1->closure = 1; + if (!(c2 = parsecomp())) return NULL; + c1->next = c2; + c->next = c1; + return c; + } + if (*pptr == Inpar) + { + int pars = 1; + char *startp = pptr, *endp; + Comp stail = tail; + int dpnd = 0; + + for (pptr = pptr+1; *pptr && pars; pptr++) + if (*pptr == Inpar) + pars++; + else if (*pptr == Outpar) + pars--; + if (pptr[-1] != Outpar) + { + errflag = 1; + return NULL; + } + if (*pptr == Pound) + { + dpnd = 1; + pptr++; + if (*pptr == Pound) + { + pptr++; + dpnd = 2; + } + } + if (!(c1 = parsecomp())) return NULL; + tail = c1; + endp = pptr; + pptr = startp; + pptr++; + *s++ = '\0'; + c->next = (Comp) alloc(sizeof *c); + c->next->left = parsecompsw(); + c->next->closure = dpnd; + c->next->next = (Comp) alloc(sizeof *c); + pptr = endp; + tail = stail; + return c; + } + if (*pptr == Pound) + { + *s = '\0'; + pptr++; + if (!ls) + return NULL; + if (*pptr == Pound) + { + pptr++; + c->next = c1 = (Comp) alloc(sizeof *c); + c1->str = strdup(ls); + } + else + c1 = c; + c1->next = c2 = (Comp) alloc(sizeof *c); + c2->str = strdup(ls); + c2->closure = 1; + c2->next = parsecomp(); + if (!c2->next) + return NULL; + *ls++ = '\0'; + return c; + } + ls = s; + if (*pptr == Inang) + { + int dshct; + + dshct = (pptr[1] == Outang); + *s++ = *pptr++; + while (*pptr && (*s++ = *pptr++) != Outang) + if (s[-1] == '-') + dshct++; + else if (!idigit(s[-1])) + break; + if (s[-1] != Outang || dshct != 1) + return NULL; + } + else if (*pptr == Inbrack) + { + while (*pptr && (*s++ = *pptr++) != Outbrack); + if (s[-1] != Outbrack) + return NULL; + } + else if (itok(*pptr) && *pptr != Star && *pptr != Quest) + *s++ = ztokens[*pptr++-Pound]; + else + *s++ = *pptr++; + } + if (*pptr == '/' || !*pptr) + c->last = 1; + *s++ = '\0'; + return c; +} + +Comp parsecompsw() /**/ +{ +Comp c1,c2,c3; + + c1 = parsecomp(); + if (!c1) + return NULL; + if (*pptr == Bar) + { + c2 = (Comp) alloc(sizeof *c2); + pptr++; + c3 = parsecompsw(); + if (!c3) + return NULL; + c2->str = strdup(""); + c2->left = c1; + c2->right = c3; + return c2; + } + return c1; +} + +/* tokenize and see if ss matches tt */ + +int patmatch(ss,tt) /**/ +char *ss;char *tt; +{ +char *s = ss,*t; + + for (; *s; s++) + if (*s == '\\') + chuck(s); + else + for (t = ztokens; *t; t++) + if (*t == *s) + { + *s = (t-ztokens)+Pound; + break; + } + return matchpat(ss,tt); +} + +/* remove unnecessary Nulargs */ + +void remnulargs(s) /**/ +char *s; +{ +int nl = *s; +char *t = s; + + while (*s) + if (*s == Nularg) + chuck(s); + else + s++; + if (!*t && nl) + { + t[0] = Nularg; + t[1] = '\0'; + } +} + +/* qualifier functions */ + +int qualdev(buf,dv) /**/ +struct stat *buf;long dv; +{ + return buf->st_dev == dv; +} + +int qualnlink(buf,ct) /**/ +struct stat *buf;long ct; +{ + return buf->st_nlink == ct; +} + +int qualuid(buf,uid) /**/ +struct stat *buf;long uid; +{ + return buf->st_uid == uid; +} + +int qualgid(buf,gid) /**/ +struct stat *buf;long gid; +{ + return buf->st_gid == gid; +} + +int qualisdev(buf,junk) /**/ +struct stat *buf;long junk; +{ + junk = buf->st_mode & S_IFMT; + return junk == S_IFBLK || junk == S_IFCHR; +} + +int qualmode(buf,mod) /**/ +struct stat *buf;long mod; +{ + return (buf->st_mode & S_IFMT) == mod; +} + +int qualflags(buf,mod) /**/ +struct stat *buf;long mod; +{ + return buf->st_mode & mod; +} + +int qualiscom(buf,mod) /**/ +struct stat *buf;long mod; +{ + return (buf->st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC); +} + diff --git a/usr/othersrc/public/zsh-2.2/src/glob.pro b/usr/othersrc/public/zsh-2.2/src/glob.pro new file mode 100644 index 0000000000..ac7ac00671 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/glob.pro @@ -0,0 +1,34 @@ +void glob DCLPROTO((Lklist list,Lknode *np)); +long qgetnum DCLPROTO((char **s)); +int notstrcmp DCLPROTO((char **a,char **b)); +int forstrcmp DCLPROTO((char **a,char **b)); +void insert DCLPROTO((char *s)); +int haswilds DCLPROTO((char *str)); +int hasbraces DCLPROTO((char *str)); +int xpandredir DCLPROTO((struct redir *fn,Lklist tab)); +char *dyncat DCLPROTO((char *s1,char *s2)); +char *tricat DCLPROTO((char *s1,char *s2,char *s3)); +void xpandbraces DCLPROTO((Lklist list,Lknode *np)); +char *getparen DCLPROTO((char *str)); +int matchpat DCLPROTO((char *a,char *b)); +void getmatch DCLPROTO((char **sp,char *pat,int dd)); +char *getfullpath DCLPROTO((char *s)); +void scanner DCLPROTO((Complist q)); +int minimatch DCLPROTO((char **pat,char **str)); +int domatch DCLPROTO((char *str,Comp c,int fist)); +int doesmatch DCLPROTO((Comp c)); +Complist parsepat DCLPROTO((char *str)); +Comp parsereg DCLPROTO((char *str)); +Complist parsecomplist DCLPROTO((void)); +Comp parsecomp DCLPROTO((void)); +Comp parsecompsw DCLPROTO((void)); +int patmatch DCLPROTO((char *ss,char *tt)); +void remnulargs DCLPROTO((char *s)); +int qualdev DCLPROTO((struct stat *buf,long dv)); +int qualnlink DCLPROTO((struct stat *buf,long ct)); +int qualuid DCLPROTO((struct stat *buf,long uid)); +int qualgid DCLPROTO((struct stat *buf,long gid)); +int qualisdev DCLPROTO((struct stat *buf,long junk)); +int qualmode DCLPROTO((struct stat *buf,long mod)); +int qualflags DCLPROTO((struct stat *buf,long mod)); +int qualiscom DCLPROTO((struct stat *buf,long mod)); diff --git a/usr/othersrc/public/zsh-2.2/src/hist.c b/usr/othersrc/public/zsh-2.2/src/hist.c new file mode 100644 index 0000000000..0bba35f05d --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/hist.c @@ -0,0 +1,1343 @@ +/* + * + * hist.c - history expansion + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +#define HEAPSIZE 4096 + +struct hp { + Hp next; + char *pool,*ptr; + int free,histno; +}; + +static Hp hp_lit, hp_lex; +static Histent curhistent; + +static int lastc; + +/* add a character to the current history word */ + +void hwaddc(c) /**/ +int c; +{ + if (hlastw && hline && (!(errflag || lexstop) || c == HISTSPACE)) { + if (c == '!' && unset(NOBANGHIST)) hwaddc('\\'); + *hptr++ = c; + if (hptr-hline >= hlinesz) { + int ll,flag = 0,oldsiz = hlinesz; + + ll = hptr-hlastw; + if (curhistent->lex == hline) flag = 1; + hline = hp_realloc(&hp_lex,hline,oldsiz,hlinesz = oldsiz+16); + if (flag) curhistent->lex = hline; + hptr = hline+oldsiz; + hlastw = hptr-ll; + } + } +} + +#define habort() { errflag = lexstop = 1; return ' '; } + +/* get a character after performing history substitution */ + +int hgetc() /**/ +{ +int c,ev,farg,larg,argc,marg = -1,cflag = 0,bflag = 0; +char buf[256],*ptr; +char *sline,*eline; + +tailrec: + c = hgetch(); + if (stophist || alstackind) + { + hwaddc(c); + return c; + } + if (isfirstch && c == hatchar) + { + isfirstch = 0; + hungetch(hatchar); + hungets(":s"); + c = bangchar; + goto hatskip; + } + if (c != ' ') + isfirstch = 0; + if (c == '\\') { + int g = hgetch(); + + if (g != bangchar) + hungetch(g); + else { + hwaddc(bangchar); + return bangchar; + } + } + if (c != bangchar) + { + hwaddc(c); + return c; + } +hatskip: + *hptr = '\0'; + if ((c = hgetch()) == '{') + { + bflag = cflag = 1; + c = hgetch(); + } + if (c == '\"') + { + stophist = 1; + goto tailrec; + } + if (!cflag && inblank(c) || c == '=' || c == '(' || lexstop) + { + if (lexstop) + lexstop = 0; + else + hungetch(c); + hwaddc(bangchar); + return bangchar; + } + cflag = 0; + ptr = buf; + + /* get event number */ + + if (c == '?') + { + for(;;) + { + c = hgetch(); + if (c == '?' || c == '\n' || lexstop) + break; + else + *ptr++ = c; + } + if (c != '\n' && !lexstop) + c = hgetch(); + *ptr = '\0'; + ev = hconsearch(hsubl = ztrdup(buf),&marg); + if (ev == -1) + { + herrflush(); + zerr("no such event: %s",buf,0); + habort(); + } + } + else + { + int t0; + + for (;;) + { + if (inblank(c) || c == ';' || c == ':' || c == '^' || c == '$' || + c == '*' || c == '%' || c == '}' || lexstop) + break; + if (ptr != buf) { + if (c == '-') break; + if ((idigit(buf[0]) || buf[0] == '-') && !idigit(c)) break; + } + *ptr++ = c; + if (c == '#' || c == bangchar) + { + c = hgetch(); + break; + } + c = hgetch(); + } + *ptr = 0; + if (!*buf) + ev = defev; + else if (t0 = atoi(buf)) + ev = (t0 < 0) ? curhist+t0 : t0; + else if (*buf == bangchar) + ev = curhist-1; + else if (*buf == '#') + ev = curhist; + else if ((ev = hcomsearch(buf)) == -1) + { + zerr("event not found: %s",buf,0); + while (c != '\n' && !lexstop) + c = hgetch(); + habort(); + } + } + + /* get the event */ + + if (!(eline = getevent(defev = ev))) + habort(); + + /* extract the relevant arguments */ + + argc = getargc(eline); + if (c == ':') + { + cflag = 1; + c = hgetch(); + } + if (c == '*') + { + farg = 1; + larg = argc; + cflag = 0; + } + else + { + hungetch(c); + larg = farg = getargspec(argc,marg); + if (larg == -2) + habort(); + if (farg != -1) + cflag = 0; + c = hgetch(); + if (c == '*') + { + cflag = 0; + larg = argc; + } + else if (c == '-') + { + cflag = 0; + larg = getargspec(argc,marg); + if (larg == -2) + habort(); + if (larg == -1) + larg = argc-1; + } + else + hungetch(c); + } + if (farg == -1) + farg = 0; + if (larg == -1) + larg = argc; + if (!(sline = getargs(eline,farg,larg))) + habort(); + + /* do the modifiers */ + + for(;;) + { + c = (cflag) ? ':' : hgetch(); + cflag = 0; + if (c == ':') + { + int gbal = 0; + + if ((c = hgetch()) == 'g') + { + gbal = 1; + c = hgetch(); + } + switch(c) + { + case 'p': + histdone = HISTFLAG_DONE|HISTFLAG_NOEXEC; + break; + case 'h': + if (!remtpath(&sline)) + { + herrflush(); + zerr("modifier failed: h",NULL,0); + habort(); + } + break; + case 'e': + if (!rembutext(&sline)) + { + herrflush(); + zerr("modifier failed: e",NULL,0); + habort(); + } + break; + case 'r': + if (!remtext(&sline)) + { + herrflush(); + zerr("modifier failed: r",NULL,0); + habort(); + } + break; + case 't': + if (!remlpaths(&sline)) + { + herrflush(); + zerr("modifier failed: t",NULL,0); + habort(); + } + break; + case 's': + { + int del; + char *ptr1,*ptr2; + + del = hgetch(); + ptr1 = hdynread2(del); + if (!ptr1) + habort(); + ptr2 = hdynread2(del); + if (strlen(ptr1)) + { + if (hsubl) + free(hsubl); + hsubl = ptr1; + } + if (hsubr) + free(hsubr); + hsubr = ptr2; + } + case '&': + if (hsubl && hsubr) + subst(&sline,hsubl,hsubr,gbal); + else + { + herrflush(); + zerr("no previous substitution with &",NULL,0); + habort(); + } + break; + case 'q': + quote(&sline); + break; + case 'x': + quotebreak(&sline); + break; + case 'l': + downcase(&sline); + break; + case 'u': + upcase(&sline); + break; + default: + herrflush(); + zerr("illegal modifier: %c",NULL,c); + habort(); + break; + } + } + else + { + if (c != '}' || !bflag) + hungetch(c); + if (c != '}' && bflag) + { + zerr("'}' expected",NULL,0); + habort(); + } + break; + } + } + + /* stuff the resulting string in the input queue and start over */ + + lexstop = 0; + if (alstackind != MAXAL) + { + hungets(HISTMARK); + alstack[alstackind++] = NULL; + } + for (ptr = sline; *ptr; ptr++) { + if (ptr[0] == '\\' && ptr[1] == '!') chuck(ptr); + } + hungets(sline); + histdone |= HISTFLAG_DONE; + if (isset(HISTVERIFY)) histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL; + goto tailrec; +} + +/* reset the alias stack for lexrestore () */ + +void clearalstack() /**/ +{ +Alias ix; + + while (alstackind) + { + ix = alstack[--alstackind]; + ix->inuse = 0; + } +} + +/* get a character without history expansion */ + +int hgetch() /**/ +{ +unsigned char *line,*pmpt,*pmpt2 = NULL; +int plen; + +start: + if (inbufct) + { + inbufct--; + if ((lastc = *inbufptr++) == ALPOP) + { + Alias ix; + char *t; + + if (!alstackind) + { + zerr("alias stack underflow",NULL,0); + errflag = lexstop = 1; + return lastc = ' '; + } + ix = alstack[--alstackind]; + if (ix) + { + ix->inuse = 0; + t = ix->text; + if (*t && t[strlen(t)-1] == ' ') + alstat = ALSTAT_MORE; + else + alstat = ALSTAT_JUNK; + } + goto start; + } + if (itok(lastc)) + goto start; + return lastc; + } + if (strin || errflag) + { + lexstop = 1; + return lastc = ' '; + } + if (interact && isset(SHINSTDIN)) + if (!isfirstln) + pmpt = (unsigned char *)putprompt(prompt2,&plen); + else + { + int foo; + + pmpt = (unsigned char *)putprompt(prompt,&plen); + pmpt2 = (unsigned char *)((rprompt) ? putprompt(rprompt,&foo) : NULL); + } + if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) { + char *lbuf; + if (interact && isset(SHINSTDIN)) + write(2,pmpt,strlen((char *) pmpt)); + line = (unsigned char *)fgets(lbuf = zalloc(256),256,bshin); + if (!line) free(lbuf); + } else + line = zleread(pmpt,pmpt2,plen); + if (!line) { + lexstop = 1; + return lastc = ' '; + } + if (errflag) { + free(line); + lexstop = errflag = 1; + return lastc = ' '; + } + if (interact && isset(SHINSTDIN)) { + char *s = curhistent->lit; + curhistent->lit = hp_concat(s,(char*)line); + } + if (isfirstln) spaceflag = *line == ' '; + if (isset(VERBOSE)) { + fputs((char *) line,stderr); + fflush(stderr); + } + if (*line && line[strlen((char *) line)-1] == '\n') + { + lineno++; + if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) && + SHTTY != -1 && *line && line[1] && + line[strlen((char *) line)-2] == '`') + { + int ct; + unsigned char *ptr; + + for (ct = 0, ptr = line; *ptr; ptr++) + if (*ptr == '`') + ct++; + if (ct & 1) + { + ptr[-2] = '\n'; + ptr[-1] = '\0'; + } + } + } + isfirstch = 1; + hungets((char*)line); + free(line); + goto start; +} + +/* Read one line of at most n-1 chars from the input queue */ + +char *hgets(buf, n) /**/ +char *buf;int n; +{ +int l; + + for (l = 0; l < n-1; l++) + if ((buf[l] = hgetch()) == '\n' || lexstop) + break; + buf[l+(lexstop?0:1)] = 0; + + return (!lexstop || l) ? buf : NULL; +} + +/* put a string in the input queue */ + +void hungets(str) /**/ +char *str; +{ +int slen = strlen(str); + +/* shrink inbuf if it gets too big */ + + if (!inbufct && inbufsz > 65536) + { + free(inbuf); + inbuf = zalloc(inbufsz = 256); + inbufptr = inbuf+inbufsz; + inbufct = 0; + } + if (slen+inbufct > inbufsz) + { + char *x; + + while (slen+inbufct > inbufsz) + inbufsz *= 4; + x = zalloc(inbufsz); + memcpy(x+inbufsz-inbufct,inbufptr,inbufct); + inbufptr = x+inbufsz-inbufct; + free(inbuf); + inbuf = x; + } + memcpy(inbufptr -= slen,str,slen); + inbufct += slen; +} + +/* unget a char and remove it from hline */ + +void hungetc(c) /**/ +int c; +{ + if (lexstop) + return; + if (hlastw) { + if (hlastw == hptr) + zerr("hungetc attempted at buffer start",NULL,0); + else { + hptr--; + if (*hptr == '!' && unset(NOBANGHIST)) hptr--; + } + } + hungetch(c); +} + +void hungetch(c) /**/ +int c; +{ + if (lexstop) + return; + if (inbufct == inbufsz) + { + hungets(" "); + *inbufptr = c; + } + else + { + *--inbufptr = c; + inbufct++; + } +} + +/* begin reading a string */ + +void strinbeg() /**/ +{ + strin = 1; + hbegin(); + lexinit(); +} + +/* done reading a string */ + +void strinend() /**/ +{ + strin = 0; + isfirstch = 1; + histdone = 0; + hend(); +} + +/* stuff a whole file into the input queue and print it */ + +int stuff(fn) /**/ +char *fn; +{ +FILE *in; +char *buf; +int len; + + if (!(in = fopen(fn,"r"))) + { + zerr("can't open %s",fn,0); + return 1; + } + fseek(in,0,2); + len = ftell(in); + fseek(in,0,0); + buf = alloc(len+1); + if (!(fread(buf,len,1,in))) + { + zerr("read error on %s",fn,0); + fclose(in); + free(buf); + return 1; + } + fclose(in); + buf[len] = '\0'; + fwrite(buf,len,1,stdout); + hungets(buf); + return 0; +} + +/* flush input queue */ + +void hflush() /**/ +{ + inbufptr += inbufct; + inbufct = 0; +} + +/* initialize the history mechanism */ + +void hbegin() /**/ +{ + isfirstln = isfirstch = 1; + histremmed = errflag = histdone = spaceflag = 0; + stophist = isset(NOBANGHIST) || unset(SHINSTDIN); + lithist = isset(HISTLIT); + hline = hptr = hp_alloc(&hp_lex,hlinesz = 16); + curhistent = gethistent(curhist); + if (!curhistent->ftim) curhistent->ftim = time(NULL); + if (interact && isset(SHINSTDIN) && !strin) { + inittty(); + defev = curhist++; + if (curhist-histsiz >= 0) gethistent(curhist-histsiz)->lex = NULL; + if (curhist-lithistsiz >= 0) gethistent(curhist-lithistsiz)->lit = NULL; + curhistent = gethistent(curhist); + hp_purge(hp_lex,curhist-histsiz); + hp_purge(hp_lit,curhist-lithistsiz); + curhistent->lex = hline; + *(curhistent->lit = hp_alloc(&hp_lit,1)) = '\0'; + } else + histremmed = 1; +} + +void inittty() /**/ +{ + attachtty(mypgrp); +} + +/* say we're done using the history mechanism */ + +int hend() /**/ +{ +int flag,save = 1; +Histent he; + + if (!hline) + return 1; + if (!interact || strin || unset(SHINSTDIN)) { + hp_free(hp_lex,hline,hlinesz); + return 1; + } + flag = histdone; + histdone = 0; + if (hptr < hline+2) + save = 0; + else { + char *s,*t; + + s = curhistent->lit; + if (*s && *(t = s+strlen(s)-1) == HISTSPACE) *t = '\0'; + hptr[-1] = '\0'; + if (hptr[-2] == '\n') + if (hline[1]) { + if (hptr[-3] == HISTSPACE) hptr[-3] = '\0'; + } else save = 0; + he = gethistent(curhist-1); + if (!strcmp(hline,"\n") || + (isset(HISTIGNOREDUPS) && he->lex && !strcmp(he->lex,hline)) || + (isset(HISTIGNORESPACE) && spaceflag)) + save = 0; + } + if (flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) { + char *ptr,*p; + p = ptr = ztrdup(hline); + for (;*p;p++) if (*p == HISTSPACE) *p = ' '; + if ((flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) == HISTFLAG_DONE) { + fprintf(stderr,"%s\n",ptr); + fflush(stderr); + } + if (flag & HISTFLAG_RECALL) { + permalloc(); + pushnode(bufstack,ptr); + lastalloc(); + save = 0; + } else free(ptr); + } + curhistent->stim = time(NULL); + curhistent->ftim = 0L; + if (!save) remhist(); + if (hline && !curhistent->lex) hp_free(hp_lex,hline,hlinesz); + hline = NULL; + return !(flag & HISTFLAG_NOEXEC || errflag); +} + +/* remove the current line from the history List */ + +void remhist() /**/ +{ + if (!histremmed) { histremmed = 1; curhist--; } +} + +/* begin a word */ + +void hwbegin() /**/ +{ + hlastw = hptr; +} + +/* add a word to the history List */ + +char *hwadd() /**/ +{ +char *ret = hlastw; + + if (hlastw && hline) + { + hwaddc(HISTSPACE); + if (alstackind || strin) + if (!(alstackind == 1 && !alstack[0])) + hptr = hlastw; + } + if (alstat == ALSTAT_JUNK) + alstat = 0; + return ret; +} + +/* get an argument specification */ + +int getargspec(argc,marg) /**/ +int argc;int marg; +{ +int c,ret = -1; + + if ((c = hgetch()) == '0') + return 0; + if (idigit(c)) + { + ret = 0; + while (idigit(c)) + { + ret = ret*10+c-'0'; + c = hgetch(); + } + hungetch(c); + } + else if (c == '^') + ret = 1; + else if (c == '$') + ret = argc; + else if (c == '%') + { + if (marg == -1) + { + herrflush(); + zerr("%% with no previous word matched",NULL,0); + return -2; + } + ret = marg; + } + else + hungetch(c); + return ret; +} + +/* do ?foo? search */ + +int hconsearch(str,marg) /**/ +char *str;int *marg; +{ +int t0,t1 = 0; +char *s,*hs; + + for (t0 = curhist-1; hs = quietgetevent(t0); t0--) + if (s = ztrstr(hs,str)) { + while (s != hs) if (*s-- == HISTSPACE) t1++; + *marg = t1; + return t0; + } + return -1; +} + +/* do !foo search */ + +int hcomsearch(str) /**/ +char *str; +{ +int t0; +char *hs; + + for (t0 = curhist-1; hs = quietgetevent(t0); t0--) + if (!strncmp(hs,str,strlen(str))) return t0; + return -1; +} + +/* various utilities for : modifiers */ + +int remtpath(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr,*cut; + + if (cut = strrchr(str,'/')) { + if (str != cut) *cut = '\0'; + else str[1] = '\0'; + return 1; + } + return 0; +} + +int remtext(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr,*cut; + + if ((cut = strrchr(str,'.')) && cut != str) + { + *cut = '\0'; + return 1; + } + return 0; +} + +int rembutext(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr,*cut; + + if ((cut = strrchr(str,'.')) && cut != str) + { + *junkptr = strdup(cut+1); /* .xx or xx? */ + return 1; + } + return 0; +} + +int remlpaths(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr,*cut; + + if (cut = strrchr(str,'/')) + { + *cut = '\0'; + *junkptr = strdup(cut+1); + return 1; + } + return 0; +} + +int makeuppercase(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr; + + for (; *str; str++) + *str = tuupper(*str); + return 1; +} + +int makelowercase(junkptr) /**/ +char **junkptr; +{ +char *str = *junkptr; + + for (; *str; str++) + *str = tulower(*str); + return 1; +} + +void subst(strptr,in,out,gbal) /**/ +char **strptr;char *in;char *out;int gbal; +{ +char *str = *strptr,*cut,*sptr; +int off; + + while (cut = (char *) ztrstr(str,in)) { + *cut = '\0'; + sptr = convamps(out,in); + off = cut-*strptr+strlen(sptr); + cut += strlen(in); + *strptr = tricat(*strptr,sptr,cut); + if (gbal) { + str = (char *) *strptr+off; + continue; + } + break; + } +} + +char *convamps(out,in) /**/ +char *out;char *in; +{ +char *ptr,*ret,*pp; +int slen,inlen = strlen(in); + + for (ptr = out, slen = 0; *ptr; ptr++,slen++) + if (*ptr == '\\') + ptr++; + else if (*ptr == '&') + slen += inlen-1; + ret = pp = alloc(slen+1); + for (ptr = out; *ptr; ptr++) + if (*ptr == '\\') + *pp++ = *++ptr; + else if (*ptr == '&') + { + strcpy(pp,in); + pp += inlen; + } + else + *pp++ = *ptr; + *pp = '\0'; + return ret; +} + +char *makehstr(s) /**/ +char *s; +{ +char *t; + + t = s = strdup(s); + for (; *t; t++) + if (*t == HISTSPACE) + *t = ' '; + return s; +} + +char *quietgetevent(ev) /**/ +int ev; +{ +Histent ent; + + if (ev < firsthist()) return NULL; + ent = gethistent(ev); + return (lithist) ? ent->lit : ent->lex; +} + +char *getevent(ev) /**/ +int ev; +{ +char *ret; + + ret = quietgetevent(ev); + if (!ret) { + herrflush(); + zerr("no such event: %d",NULL,ev); + } + return ret; +} + +int getargc(list) /**/ +char *list; +{ +int argc = 0; + + for (; *list; list++) if (*list == HISTSPACE) argc++; + return argc; +} + +char *getargs(elist,arg1,arg2) /**/ +char *elist;int arg1;int arg2; +{ +char *ret = elist,*retn; +int acnt = arg2-arg1+1; + + while (arg1--) + while (*ret && *ret++ != HISTSPACE); + if (!*ret) + { + herrflush(); + zerr("no such word in event",NULL,0); + return NULL; + } + retn = ret = strdup(ret); + while (acnt > 0) + { + while (*ret && *ret != HISTSPACE) + ret++; + if (*ret == HISTSPACE) + *ret = ' '; + else + break; + acnt--; + } + if (acnt > 1 && !*ret) + { + herrflush(); + zerr("no such word in event",NULL,0); + return NULL; + } + *ret = '\0'; + return retn; +} + +void upcase(x) /**/ +char **x; +{ +char *pp = *(char **) x; + + for (; *pp; pp++) + *pp = tuupper(*pp); +} + +void downcase(x) /**/ +char **x; +{ +char *pp = *(char **) x; + + for (; *pp; pp++) + *pp = tulower(*pp); +} + +int quote(tr) /**/ +char **tr; +{ +char *ptr,*rptr,**str = (char **) tr; +int len = 3; + + for (ptr = *str; *ptr; ptr++,len++) + if (*ptr == '\'') len += 3; + ptr = *str; + *str = rptr = alloc(len); + *rptr++ = '\''; + for (; *ptr; ptr++) + if (*ptr == '\'') { + *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\''; + } else + *rptr++ = *ptr; + *rptr++ = '\''; + *rptr++ = 0; + str[1] = NULL; + return 0; +} + +int quotebreak(tr) /**/ +char **tr; +{ +char *ptr,*rptr,**str = (char **) tr; +int len = 3; + + for (ptr = *str; *ptr; ptr++,len++) + if (*ptr == '\'') + len += 3; + else if (inblank(*ptr)) + len += 2; + ptr = *str; + *str = rptr = alloc(len); + *rptr++ = '\''; + for (; *ptr; ) + if (*ptr == '\'') { + *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\''; + ptr++; + } else if (inblank(*ptr)) { + *rptr++ = '\''; *rptr++ = *ptr++; *rptr++ = '\''; + } else + *rptr++ = *ptr++; + *rptr++ = '\''; + *rptr++ = '\0'; + return 0; +} + +void herrflush() /**/ +{ + if (strin) + hflush(); + else while (lastc != '\n' && !lexstop) + hgetch(); +} + +/* read an arbitrary amount of data into a buffer until stop is found */ + +char *hdynread(stop) /**/ +int stop; +{ +int bsiz = 256,ct = 0,c; +char *buf = zalloc(bsiz),*ptr; + + ptr = buf; + while ((c = hgetch()) != stop && c != '\n' && !lexstop) + { + if (c == '\\') + c = hgetch(); + *ptr++ = c; + if (++ct == bsiz) + { + buf = realloc(buf,bsiz *= 2); + ptr = buf+ct; + } + } + *ptr = 0; + if (c == '\n') + { + hungetch('\n'); + zerr("delimiter expected",NULL,0); + free(buf); + return NULL; + } + return buf; +} + +char *hdynread2(stop) /**/ +int stop; +{ +int bsiz = 256,ct = 0,c; +char *buf = zalloc(bsiz),*ptr; + + ptr = buf; + while ((c = hgetch()) != stop && c != '\n' && !lexstop) + { + if (c == '\n') + { + hungetch(c); + break; + } + if (c == '\\') + c = hgetch(); + *ptr++ = c; + if (++ct == bsiz) + { + buf = realloc(buf,bsiz *= 2); + ptr = buf+ct; + } + } + *ptr = 0; + if (c == '\n') + hungetch('\n'); + return buf; +} + +void inithist() /**/ +{ + hp_lit = zalloc(sizeof *hp_lit); + hp_lit->next = NULL; + hp_lit->ptr = hp_lit->pool = zalloc(HEAPSIZE); + hp_lit->free = HEAPSIZE; + hp_lex = zalloc(sizeof *hp_lex); + hp_lex->next = NULL; + hp_lex->ptr = hp_lex->pool = zalloc(HEAPSIZE); + hp_lex->free = HEAPSIZE; + histentct = (lithistsiz > histsiz) ? lithistsiz : histsiz; + histentarr = zcalloc(histentct*sizeof *histentarr); +} + +void resizehistents() /**/ +{ +int newentct,t0,t1,firstlit,firstlex; +Histent newarr; + + newentct = (lithistsiz > histsiz) ? lithistsiz : histsiz; + newarr = zcalloc(newentct*sizeof *newarr); + firstlex = curhist-histsiz+1; + firstlit = curhist-lithistsiz+1; + t0 = firsthist(); + if (t0 < curhist-newentct) t0 = curhist-newentct; + t1 = t0 % newentct; + for (; t0 <= curhist; t0++) { + newarr[t1] = *gethistent(t0); + if (t0 < firstlex) newarr[t1].lex = NULL; + if (t0 < firstlit) newarr[t1].lit = NULL; + t1++; if (t1 == newentct) t1 = 0; + } + free(histentarr); + histentarr = newarr; + histentct = newentct; +} + +char *hp_alloc(hp,siz) /**/ +Hp *hp; int siz; +{ +char *ret; +Hp h = *hp; + + if (h->free >= siz) { + ret = h->ptr; + h->ptr += siz; + h->free -= siz; + return ret; + } +#ifdef MEMDEBUG + fprintf(stderr,"new heap (siz = %d, curhist = %d)\n",siz,curhist); +#endif + permalloc(); + h = zalloc(sizeof *h); + h->next = *hp; + h->free = (siz > HEAPSIZE) ? siz : HEAPSIZE; + h->ptr = h->pool = zalloc(h->free); + h->histno = curhist; + *hp = h; + heapalloc(); + return hp_alloc(hp,siz); +} + +char *hp_realloc(hp,ptr,oldsiz,newsiz) /**/ +Hp *hp; char *ptr; int oldsiz; int newsiz; +{ +Hp h = *hp; +int delta = newsiz-oldsiz; +char *ret; + + if (h->ptr-oldsiz == ptr && h->free >= delta) { + h->free -= delta; + h->ptr += delta; + return ptr; + } +#ifdef MEMDEBUG + fprintf(stderr,"realloc copy\n"); +#endif + memcpy(ret = hp_alloc(hp,newsiz),ptr,oldsiz); + return ret; +} + +void hp_free(h,ptr,siz) /**/ +Hp h; char *ptr; int siz; +{ + if (h->ptr-siz == ptr) { + h->free += siz; + h->ptr -= siz; + } +} + +char *hp_concat(old,new) /**/ +char *old; char *new; +{ +int oldlen,newlen; + + oldlen = strlen(old); newlen = strlen(new); + old = hp_realloc(&hp_lit,old,oldlen+1,oldlen+newlen+1); + strcpy(old+oldlen,new); + return old; +} + +void hp_purge(h,lim) /**/ +Hp h; int lim; +{ +Hp hlast; + + if (!h->next) return; + while (h->next) { hlast = h; h = h->next; } + if (h->histno <= lim || h->histno == 0) { +#ifdef MEMDEBUG + fprintf(stderr,"purging %d\n",lim); +#endif + free(h->pool); + free(h); + hlast->next = NULL; + } +} + +void readhistfile(s,err) /**/ +char *s;int err; +{ +char buf[1024]; +FILE *in; +Histent ent; +time_t tim = time(NULL); + + if (!s) return; + if (in = fopen(s,"r")) { + while (fgets(buf,1024,in)) { + int l = strlen(buf); + char *pt = buf; + + while (l && buf[l-1] == '\n') { + buf[l-1] = '\0'; + if (l > 1 && buf[l-2] == '\\') { + buf[l-2] = '\n'; + fgets(buf+l-1,1024-(l-1),in); + l = strlen(buf); + } else break; + } + for (;*pt;pt++) if (*pt == ' ') *pt = HISTSPACE; + + ent = gethistent(++curhist); + ent->lex = hp_alloc(&hp_lex,strlen(buf)+1); + strcpy(ent->lex,buf); + ent->lit = hp_alloc(&hp_lit,strlen(buf)+1); + strcpy(ent->lit,buf); + ent->ftim = ent->stim = tim; + } + fclose(in); + } else if (err) + zerr("can't read history file",s,0); +} + +void savehistfile(s,err,app) /**/ +char *s;int err;int app; +{ +char *t; +FILE *out; +int ev,flag; + + if (!s || !interact) return; + ev = curhist-savehist+1; + flag = (app) ? O_APPEND : O_TRUNC; + if (ev < firsthist()) ev = firsthist(); + if (out = fdopen(open(s,O_CREAT|O_WRONLY|flag,0600),"w")) { + for (; ev <= curhist; ev++) { + t = quietgetevent(ev); + for (; *t; t++) + if (*t == HISTSPACE) fputc(' ',out); + else { + if (*t == '\n') fputc('\\',out); + fputc(*t,out); + } + fputc('\n',out); + } + fclose(out); + } else if (err) zerr("can't write history file: %s",s,0); +} + +int firsthist() /**/ +{ +int ev; +Histent ent; + + ev = curhist-histentct+1; + if (ev < 1) ev = 1; + do { + ent = gethistent(ev); + if ((lithist) ? ent->lit : ent->lex) break; + ev++; + } while (ev < curhist); + return ev; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/hist.pro b/usr/othersrc/public/zsh-2.2/src/hist.pro new file mode 100644 index 0000000000..0e0df5cf97 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/hist.pro @@ -0,0 +1,51 @@ +void hwaddc DCLPROTO((int c)); +int hgetc DCLPROTO((void)); +void clearalstack DCLPROTO((void)); +int hgetch DCLPROTO((void)); +char *hgets DCLPROTO((char *buf,int n)); +void hungets DCLPROTO((char *str)); +void hungetc DCLPROTO((int c)); +void hungetch DCLPROTO((int c)); +void strinbeg DCLPROTO((void)); +void strinend DCLPROTO((void)); +int stuff DCLPROTO((char *fn)); +void hflush DCLPROTO((void)); +void hbegin DCLPROTO((void)); +void inittty DCLPROTO((void)); +int hend DCLPROTO((void)); +void remhist DCLPROTO((void)); +void hwbegin DCLPROTO((void)); +char *hwadd DCLPROTO((void)); +int getargspec DCLPROTO((int argc,int marg)); +int hconsearch DCLPROTO((char *str,int *marg)); +int hcomsearch DCLPROTO((char *str)); +int remtpath DCLPROTO((char **junkptr)); +int remtext DCLPROTO((char **junkptr)); +int rembutext DCLPROTO((char **junkptr)); +int remlpaths DCLPROTO((char **junkptr)); +int makeuppercase DCLPROTO((char **junkptr)); +int makelowercase DCLPROTO((char **junkptr)); +void subst DCLPROTO((char **strptr,char *in,char *out,int gbal)); +char *convamps DCLPROTO((char *out,char *in)); +char *makehstr DCLPROTO((char *s)); +char *quietgetevent DCLPROTO((int ev)); +char *getevent DCLPROTO((int ev)); +int getargc DCLPROTO((char *list)); +char *getargs DCLPROTO((char *elist,int arg1,int arg2)); +void upcase DCLPROTO((char **x)); +void downcase DCLPROTO((char **x)); +int quote DCLPROTO((char **tr)); +int quotebreak DCLPROTO((char **tr)); +void herrflush DCLPROTO((void)); +char *hdynread DCLPROTO((int stop)); +char *hdynread2 DCLPROTO((int stop)); +void inithist DCLPROTO((void)); +void resizehistents DCLPROTO((void)); +char *hp_alloc DCLPROTO((Hp *hp, int siz)); +char *hp_realloc DCLPROTO((Hp *hp, char *ptr, int oldsiz, int newsiz)); +void hp_free DCLPROTO((Hp h, char *ptr, int siz)); +char *hp_concat DCLPROTO((char *old, char *new)); +void hp_purge DCLPROTO((Hp h, int lim)); +void readhistfile DCLPROTO((char *s,int err)); +void savehistfile DCLPROTO((char *s,int err,int app)); +int firsthist DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/init.c b/usr/othersrc/public/zsh-2.2/src/init.c new file mode 100644 index 0000000000..8c899423e8 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/init.c @@ -0,0 +1,533 @@ +/* + * + * init.c - main loop and initialization routines + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define GLOBALS +#include "zsh.h" +#include + +void main(argc,argv,envp) /**/ +int argc; char **argv; char **envp; +{ +int notect = 0; + +#ifdef LC_ALL + setlocale(LC_ALL, ""); +#endif + environ = envp; + meminit(); + setflags(); + parseargs(argv); + setmoreflags(); + setupvals(); + initialize(); + heapalloc(); + runscripts(); + for(;;) + { + do + loop(); + while (tok != ENDINPUT); + if (!(isset(IGNOREEOF) && interact)) + { +#if 0 + if (interact) + fputs(islogin ? "logout\n" : "exit\n",stderr); +#endif + zexit(NULL); + continue; + } + zerrnam("zsh",(!islogin) ? "use 'exit' to exit." + : "use 'logout' to logout.",NULL,0); + notect++; + if (notect == 10) + zexit(NULL); + } +} + +/* keep executing lists until EOF found */ + +void loop() /**/ +{ +List list; +Heap h = (Heap) peekfirst(heaplist); + + pushheap(); + for(;;) + { + freeheap(); + if (interact && isset(SHINSTDIN)) + preprompt(); + hbegin(); /* init history mech */ + intr(); /* interrupts on */ + ainit(); /* init alias mech */ + lexinit(); + errflag = 0; + if (!(list = parse_event())) + { /* if we couldn't parse a list */ + hend(); + if (tok == ENDINPUT && !errflag) + break; + continue; + } + if (hend()) + { + if (stopmsg) /* unset 'you have stopped jobs' flag */ + stopmsg--; + execlist(list); + } + if (ferror(stderr)) + { + zerr("write error",NULL,0); + clearerr(stderr); + } + if (subsh) /* how'd we get this far in a subshell? */ + exit(lastval); + if ((!interact && errflag) || retflag) + break; + if ((opts['t'] == OPT_SET) || (lastval && opts[ERREXIT] == OPT_SET)) + { + if (sigtrapped[SIGEXIT]) + dotrap(SIGEXIT); + exit(lastval); + } + } + while ((Heap) peekfirst(heaplist) != h) + popheap(); +} + +void setflags() /**/ +{ +int c; + + for (c = 0; c != 32; c++) opts[c] = OPT_UNSET; + for (c = 32; c != 128; c++) opts[c] = OPT_INVALID; + for (c = 'a'; c <= 'z'; c++) opts[c] = opts[c-'a'+'A'] = OPT_UNSET; + for (c = '0'; c <= '9'; c++) opts[c] = OPT_UNSET; + opts['A'] = OPT_INVALID; + opts['i'] = (isatty(0)) ? OPT_SET : OPT_UNSET; + opts[BGNICE] = opts[NOTIFY] = OPT_SET; + opts[USEZLE] = (interact && SHTTY != -1) ? OPT_SET : OPT_UNSET; + opts[HASHCMDS] = opts[HASHLISTALL] = opts[HASHDIRS] = OPT_SET; +} + +static char *cmd; + +void parseargs(argv) /**/ +char **argv; +{ +char **x; +int bk = 0,action; +Lklist paramlist; + + hackzero = argzero = *argv; + opts[LOGINSHELL] = (**(argv++) == '-') ? OPT_SET : OPT_UNSET; + SHIN = 0; + while (!bk && *argv && (**argv == '-' || **argv == '+')) + { + action = (**argv == '-') ? OPT_SET : OPT_UNSET; + while (*++*argv) { + if (opts[**argv] == OPT_INVALID) { + zerr("bad option: -%c",NULL,**argv); + exit(1); + } + if (bk = **argv == 'b') break; + if (**argv == 'c') { /* -c command */ + argv++; + if (!*argv) { + zerr("string expected after -c",NULL,0); + exit(1); + } + cmd = *argv; + opts[INTERACTIVE] = OPT_UNSET; + opts['c'] = OPT_SET; + break; + } else if (**argv == 'o') { + int c; + + if (!*++*argv) + argv++; + if (!*argv) { + zerr("string expected after -o",NULL,0); + exit(1); + } + c = optlookup(*argv); + if (c == -1) + zerr("no such option: %s",*argv,0); + else + opts[c] = action; + break; + } else opts[**argv] = action; + } + argv++; + } + paramlist = newlist(); + if (*argv) + { + if (opts[SHINSTDIN] == OPT_UNSET) + { + SHIN = movefd(open(argzero = *argv,O_RDONLY)); + if (SHIN == -1) + { + zerr("can't open input file: %s",*argv,0); + exit(1); + } + opts[INTERACTIVE] = OPT_UNSET; + argv++; + } + while (*argv) + addnode(paramlist,ztrdup(*argv++)); + } + else + opts[SHINSTDIN] = OPT_SET; + pparams = x = zcalloc((countnodes(paramlist)+1)*sizeof(char *)); + while (*x++ = getnode(paramlist)); + free(paramlist); + argzero = ztrdup(argzero); +} + +void setmoreflags() /**/ +{ +int t0; +long ttpgrp; + + /* stdout,stderr fully buffered */ +#ifdef _IOFBF + setvbuf(stdout,malloc(BUFSIZ),_IOFBF,BUFSIZ); + setvbuf(stderr,malloc(BUFSIZ),_IOFBF,BUFSIZ); +#else + setbuffer(stdout,malloc(BUFSIZ),BUFSIZ); + setbuffer(stderr,malloc(BUFSIZ),BUFSIZ); +#endif + subsh = 0; +#ifndef NOCLOSEFUNNYFDS + /* this works around a bug in some versions of in.rshd */ + for (t0 = 3; t0 != 10; t0++) + close(t0); +#endif +#ifdef JOB_CONTROL + opts[MONITOR] = (interact) ? OPT_SET : OPT_UNSET; + if (jobbing) { + SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR)); + if (SHTTY == -1) + opts[MONITOR] = OPT_UNSET; + else { +#ifdef TIOCSETD +#ifdef NTTYDISC + int ldisc = NTTYDISC; + ioctl(SHTTY, TIOCSETD, &ldisc); +#endif +#endif + gettyinfo(&shttyinfo); /* get tty state */ +#ifdef sgi + if (shttyinfo.tio.c_cc[VSWTCH] <= 0) /* hack for irises */ + shttyinfo.tio.c_cc[VSWTCH] = CSWTCH; +#endif + savedttyinfo = shttyinfo; + } +#ifdef sgi + setpgrp(0,getpgrp(0)); +#endif + if ((mypgrp = getpgrp(0)) <= 0) + opts[MONITOR] = OPT_UNSET; + else while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) { + sleep(1); + mypgrp = getpgrp(0); + if (mypgrp == gettygrp()) break; + killpg(mypgrp,SIGTTIN); + mypgrp = getpgrp(0); + } + } else + SHTTY = -1; +#else + opts[MONITOR] = OPT_UNSET; + SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR)); + if (SHTTY != -1) { + gettyinfo(&shttyinfo); + savedttyinfo = shttyinfo; + } +#endif +} + +void setupvals() /**/ +{ +struct passwd *pswd; +char *ptr,*s; +static long bauds[] = { + 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400 + }; + + curhist = 0; + histsiz = DEFAULT_HISTSIZE; + lithistsiz = 5; + inithist(); + mailcheck = logcheck = 60; + dirstacksize = -1; + listmax = 100; + reporttime = -1; + bangchar = '!'; + hashchar = '#'; + hatchar = '^'; + termok = 0; + curjob = prevjob = coprocin = coprocout = -1; + shtimer = time(NULL); /* init $SECONDS */ + srand((unsigned int) shtimer); + /* build various hash tables; argument to newhtable is table size */ + aliastab = newhtable(37); + addreswords(); + paramtab = newhtable(151); + cmdnamtab = newhtable(37); + compctltab = newhtable(13); + initxbindtab(); + nullcmd = ztrdup("cat"); + readnullcmd = ztrdup("more"); + prompt = ztrdup("%m%# "); + prompt2 = ztrdup("> "); + prompt3 = ztrdup("?# "); + prompt4 = ztrdup("+ "); + sprompt = ztrdup("zsh: correct `%R' to `%r' [nyae]? "); + term = ztrdup(""); + ppid = getppid(); +#ifdef TIO +#ifdef HAS_TCCRAP + baud = cfgetospeed(&shttyinfo.tio); + if (baud < 100) baud = bauds[baud]; /* aren't "standards" great?? */ +#else + baud = bauds[shttyinfo.tio.c_cflag & CBAUD]; +#endif +#else + baud = bauds[shttyinfo.sgttyb.sg_ospeed]; +#endif +#ifdef TIOCGWINSZ + if (!(columns = shttyinfo.winsize.ws_col)) + columns = 80; + if (!(lines = shttyinfo.winsize.ws_row)) + lines = 24; +#else + columns = 80; + lines = 24; +#endif + ifs = ztrdup(" \t\n"); + if (pswd = getpwuid(getuid())) { + username = ztrdup(pswd->pw_name); + home = ztrdup(pswd->pw_dir); + } else { + username = ztrdup(""); + home = ztrdup("/"); + } + if (ptr = zgetenv("LOGNAME")) + logname = ztrdup(ptr); + else + logname = ztrdup(username); + timefmt = ztrdup(DEFTIMEFMT); + watchfmt = ztrdup(DEFWATCHFMT); + if (!(ttystrname = ztrdup(ttyname(SHTTY)))) + ttystrname = ztrdup(""); + wordchars = ztrdup(DEFWORDCHARS); + fceditparam = ztrdup(DEFFCEDIT); + tmpprefix = ztrdup(DEFTMPPREFIX); + postedit = ztrdup(""); + if (ispwd(home)) pwd = ztrdup(home); + else if ((ptr = zgetenv("PWD")) && ispwd(ptr)) pwd = ztrdup(ptr); + else pwd = zgetwd(); + oldpwd = ztrdup(pwd); + hostnam = zalloc(256); + underscore = ztrdup(""); + gethostname(hostnam,256); + mypid = getpid(); + cdpath = mkarray(NULL); + manpath = mkarray(NULL); + fignore = mkarray(NULL); + fpath = mkarray(NULL); + mailpath = mkarray(NULL); + watch = mkarray(NULL); + hosts = mkarray(NULL); + compctlsetup(); + userdirs = (char **) zcalloc(sizeof(char *)*2); + usernames = (char **) zcalloc(sizeof(char *)*2); + userdirsz = 2; + userdirct = 0; + optarg = ztrdup(""); + zoptind = 1; + schedcmds = NULL; + path = (char **) zalloc(4*sizeof *path); + path[0] = ztrdup("/bin"); path[1] = ztrdup("/usr/bin"); + path[2] = ztrdup("/usr/ucb"); path[3] = NULL; + inittyptab(); + initlextabs(); + setupparams(); + setparams(); + inittyptab(); + if ((s = zgetenv("EMACS")) && !strcmp(s,"t") && !strcmp(term,"emacs")) + opts[USEZLE] = OPT_UNSET; +#ifndef HAS_RUSAGE + times(&shtms); +#endif +} + +void compctlsetup() /**/ +{ +static char + *hs[] = {"telnet","rlogin","ftp","rup","rusers","rsh",NULL}, + *os[] = {"setopt","unsetopt",NULL}, + *vs[] = {"export","typeset","vared","unset",NULL}, + *cs[] = {"which","builtin",NULL}, + *bs[] = {"bindkey",NULL}; + + compctl_process(hs,CC_HOSTS|CC_FILES,NULL); + compctl_process(os,CC_OPTIONS,NULL); + compctl_process(vs,CC_VARS,NULL); + compctl_process(bs,CC_BINDINGS,NULL); + compctl_process(cs,CC_COMMPATH,NULL); + cc_compos.mask = CC_COMMPATH; + cc_default.mask = CC_FILES; +} + +void initialize() /**/ +{ +int t0; + + breaks = loops = 0; + lastmailcheck = time(NULL); + locallist = NULL; + dirstack = newlist(); + bufstack = newlist(); + newcmdnamtab(); + inbuf = zalloc(inbufsz = 256); + inbufptr = inbuf+inbufsz; + inbufct = 0; +#ifndef QDEBUG + signal(SIGQUIT,SIG_IGN); +#endif +#ifdef RLIM_INFINITY + for (t0 = 0; t0 != RLIM_NLIMITS; t0++) + getrlimit(t0,limits+t0); +#endif + hsubl = hsubr = NULL; + lastpid = 0; + bshin = fdopen(SHIN,"r"); + signal(SIGCHLD,handler); + if (jobbing) + { + int ttypgrp; + for (;;) + { +#ifdef TIOCGPGRP + ioctl(SHTTY, TIOCGPGRP, &ttypgrp); +#else + ttypgrp = tcgetpgrp(SHTTY); +#endif + if (ttypgrp == mypgrp) + break; + kill(0,SIGTTIN); + } + signal(SIGTTOU,SIG_IGN); + signal(SIGTSTP,SIG_IGN); + signal(SIGTTIN,SIG_IGN); + signal(SIGPIPE,SIG_IGN); + attachtty(mypgrp); + } + if (interact) + { + signal(SIGTERM,SIG_IGN); +#ifdef SIGWINCH + signal(SIGWINCH,handler); +#endif + signal(SIGALRM,handler); + intr(); + } +} + +void addreswords() /**/ +{ +static char *reswds[] = { + "do", "done", "esac", "then", "elif", "else", "fi", "for", "case", + "if", "while", "function", "repeat", "time", "until", "exec", "command", + "select", "coproc", "noglob", "-", "nocorrect", "foreach", "end", NULL + }; +int t0; + + for (t0 = 0; reswds[t0]; t0++) + addhperm(reswds[t0],mkanode(NULL,-1-t0),aliastab,NULL); +} + +void runscripts() /**/ +{ +#ifdef GLOBALZSHENV + source(GLOBALZSHENV); +#endif + if (opts[NORCS] == OPT_SET) { +#ifdef GLOBALZPROFILE + if (islogin) source(GLOBALZPROFILE); +#endif +#ifdef GLOBALZSHRC + source(GLOBALZSHRC); +#endif +#ifdef GLOBALZLOGIN + if (islogin) source(GLOBALZLOGIN); +#endif + } else { + sourcehome(".zshenv"); + if (opts[NORCS] == OPT_SET) + return; + if (interact) { + if (islogin) { + sourcehome(".zprofile"); +#ifdef GLOBALZPROFILE + source(GLOBALZPROFILE); +#endif + } +#ifdef GLOBALZSHRC + source(GLOBALZSHRC); +#endif + sourcehome(".zshrc"); + if (islogin) { +#ifdef GLOBALZLOGIN + source(GLOBALZLOGIN); +#endif + sourcehome(".zlogin"); + } + } + } + if (interact) + readhistfile(getsparam("HISTFILE"),0); + if (opts['c'] == OPT_SET) + { + if (SHIN >= 10) + close(SHIN); + SHIN = movefd(open("/dev/null",O_RDONLY)); + execstring(cmd); + stopmsg = 1; + zexit(NULL); + } +#ifdef TIOCSWINSZ + if (!(columns = shttyinfo.winsize.ws_col)) + columns = 80; + if (!(lines = shttyinfo.winsize.ws_row)) + lines = 24; +#endif +} + +void ainit() /**/ +{ + alstackind = 0; /* reset alias stack */ + alstat = 0; + isfirstln = 1; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/init.pro b/usr/othersrc/public/zsh-2.2/src/init.pro new file mode 100644 index 0000000000..ee5292d941 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/init.pro @@ -0,0 +1,11 @@ +void main DCLPROTO((int argc, char **argv, char **envp)); +void loop DCLPROTO((void)); +void setflags DCLPROTO((void)); +void parseargs DCLPROTO((char **argv)); +void setmoreflags DCLPROTO((void)); +void setupvals DCLPROTO((void)); +void compctlsetup DCLPROTO((void)); +void initialize DCLPROTO((void)); +void addreswords DCLPROTO((void)); +void runscripts DCLPROTO((void)); +void ainit DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/jobs.c b/usr/othersrc/public/zsh-2.2/src/jobs.c new file mode 100644 index 0000000000..9b9c23ad93 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/jobs.c @@ -0,0 +1,764 @@ +/* + * + * jobs.c - job control + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include + +/* != 0 means the handler is active */ + +static int handling = 0; + +#ifdef INTHANDTYPE +#define RETURN return 0 +#else +#define RETURN return +#endif + +/* the signal handler */ + +HANDTYPE handler(sig,code) /**/ +int sig;int code; +{ +long pid; +int statusp; +Job jn; +struct process *pn; +#ifdef HAS_RUSAGE +struct rusage ru; +#else +long chlds,chldu; +#endif + +#ifdef RESETHANDNEEDED + signal(sig,handler); +#endif + if (sig == SIGINT) + { + if (sigtrapped[SIGINT]) + dotrap(SIGINT); + else + errflag = 1; + RETURN; + } +#ifdef SIGWINCH + if (sig == SIGWINCH) + adjustwinsize(); +#endif + if (sig != SIGCHLD) + { + dotrap(sig); + if (sig == SIGALRM && !sigtrapped[SIGALRM]) + { + zerr("timeout",NULL,0); + exit(1); + } + RETURN; + } + for (;;) + { +#ifdef HAS_RUSAGE + pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,&ru); +#else +#ifndef WNOHANG + pid = wait(&statusp); +#else + pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,NULL); +#endif + chlds = shtms.tms_cstime; + chldu = shtms.tms_cutime; + times(&shtms); +#endif + if (pid == -1) + { + if (errno != ECHILD) + zerr("wait failed: %e",NULL,errno); + RETURN; + } + if (!pid) + RETURN; + findproc(pid,&jn,&pn); /* find the process of this pid */ + if (jn) + { + pn->statusp = statusp; + handling = 1; +#ifdef HAS_RUSAGE + pn->ti.ru = ru; +#else + pn->ti.st = shtms.tms_cstime-chlds; + pn->ti.ut = shtms.tms_cutime-chldu; +#endif + pn->endtime = time(NULL); + updatestatus(jn); + handling = 0; + } +#if 0 + else if (WIFSTOPPED(statusp)) + kill(pid,SIGKILL); /* kill stopped untraced children */ +#endif + } +} + +/* change job table entry from stopped to running */ + +void makerunning(jn) /**/ +Job jn; +{ +struct process *pn; + + jn->stat &= ~STAT_STOPPED; + for (pn = jn->procs; pn; pn = pn->next) + if (WIFSTOPPED(pn->statusp)) + pn->statusp = SP_RUNNING; +} + +/* update status of job, possibly printing it */ + +void updatestatus(jn) /**/ +Job jn; +{ +struct process *pn; +int notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0; + + for (pn = jn->procs; pn; pn = pn->next) + { + if (pn->statusp == SP_RUNNING) + notrunning = 0; + if (pn->statusp == SP_RUNNING || WIFSTOPPED(pn->statusp)) + alldone = 0; + if (WIFSTOPPED(pn->statusp)) + somestopped = 1; + if (!pn->next && jn) + val = (WIFSIGNALED(pn->statusp)) ? + 0200 | WTERMSIG(pn->statusp) : WEXITSTATUS(pn->statusp); + } + if (!notrunning) + return; + if (somestopped && (jn->stat & STAT_STOPPED)) + return; + jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE : + STAT_CHANGED|STAT_STOPPED; + if (alldone && job == thisjob) + { + if (!ttyfrozen && !val) { + gettyinfo(&shttyinfo); + if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE)) + sanetty(&shttyinfo); +#ifdef TIOCSWINSZ + if (!(columns = shttyinfo.winsize.ws_col)) + columns = 80; + lines = shttyinfo.winsize.ws_row; +#endif + } else + settyinfo(&shttyinfo); + lastval = val; + } + if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) { + prevjob = curjob; + curjob = job; + } + if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED) { + printjob(jn,!!isset(LONGLISTJOBS)); + if (zleactive) refresh(); + } + if (sigtrapped[SIGCHLD] && job != thisjob) + dotrap(SIGCHLD); +} + +/* find process and job associated with pid */ + +void findproc(pid,jptr,pptr) /**/ +int pid;Job *jptr;struct process **pptr; +{ +struct process *pn; +int jn; + + for (jn = 1; jn != MAXJOB; jn++) + for (pn = jobtab[jn].procs; pn; pn = pn->next) + if (pn->pid == pid) + { + *pptr = pn; + *jptr = jobtab+jn; + return; + } + *pptr = NULL; + *jptr = NULL; +} + +/* + lng = 0 means jobs + lng = 1 means jobs -l + lng = 2 means jobs -p +*/ + +void printjob(jn,lng) /**/ +Job jn;int lng; +{ +int job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0; +int conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0; +struct process *pn; + + if (lng < 0) + { + conted = 1; + lng = 0; + } + + /* 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 (pn->statusp != SP_RUNNING) + if (WIFSIGNALED(pn->statusp)) + { + sig = WTERMSIG(pn->statusp); + llen = strlen(sigmsg[sig]); + if (WCOREDUMPED(pn->statusp)) + llen += 14; + if (llen > len) + len = llen; + if (sig != SIGINT && sig != SIGPIPE) + sflag = 1; + else if (sig == SIGINT) + errflag = 1; + if (job == thisjob && sig == SIGINT) + doputnl = 1; + } + else if (WIFSTOPPED(pn->statusp)) + { + sig = WSTOPSIG(pn->statusp); + if (strlen(sigmsg[sig]) > len) + len = strlen(sigmsg[sig]); + if (job == thisjob && sig == SIGTSTP) + doputnl = 1; + } + else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) && + WEXITSTATUS(pn->statusp)) + sflag = 1; + } + + /* print if necessary */ + + if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag || + job != thisjob)) + { + int len2,fline = 1; + struct process *qn; + + trashzle(); + if (doputnl) + putc('\n',stderr); + for (pn = jn->procs; pn;) + { + len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */ + if (lng) + qn = pn->next; + else for (qn = pn->next; qn; qn = qn->next) + { + if (qn->statusp != pn->statusp) + break; + if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng) + break; + len2 += strlen(qn->text)+2; + } + if (job != thisjob) + if (fline) + fprintf(stderr,"[%d] %c ",jn-jobtab,(job == curjob) ? '+' : + (job == prevjob) ? '-' : ' '); + else + fprintf(stderr,(job > 9) ? " " : " "); + else + fprintf(stderr,"zsh: "); + if (lng) + if (lng == 1) + fprintf(stderr,"%d ",pn->pid); + else + { + int x = jn->gleader; + + fprintf(stderr,"%d ",x); + do skip++; while (x /= 10); + skip++; + lng = 0; + } + else + fprintf(stderr,"%*s",skip,""); + if (pn->statusp == SP_RUNNING) + if (!conted) + fprintf(stderr,"running%*s",len-7+2,""); + else + fprintf(stderr,"continued%*s",len-9+2,""); + else if (WIFEXITED(pn->statusp)) + if (WEXITSTATUS(pn->statusp)) + fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(pn->statusp), + len-9+2,""); + else + fprintf(stderr,"done%*s",len-4+2,""); + else if (WIFSTOPPED(pn->statusp)) + fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(pn->statusp)]); + else if (WCOREDUMPED(pn->statusp)) + fprintf(stderr,"%s (core dumped)%*s", + sigmsg[WTERMSIG(pn->statusp)], + len-14+2-strlen(sigmsg[WTERMSIG(pn->statusp)]),""); + else + fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(pn->statusp)]); + for (; pn != qn; pn = pn->next) + fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text); + putc('\n',stderr); + fline = 0; + } + printed = 1; + } + else if (doputnl && interact) + putc('\n',stderr); + fflush(stderr); + + /* print "(pwd now: foo)" messages */ + + if (interact && job==thisjob && strcmp(jn->pwd,pwd)) + { + printf("(pwd now: "); + printdir(pwd); + printf(")\n"); + fflush(stdout); + } + + /* delete job if done */ + + if (jn->stat & STAT_DONE) + { + static struct job zero; + struct process *nx; + char *s; + + if ((jn->stat & STAT_TIMED) || (reporttime != -1 && report(jn))) { + dumptime(jn); + printed = 1; + } + for (pn = jn->procs; pn; pn = nx) + { + nx = pn->next; + free(pn); + } + free(jn->pwd); + if (jn->filelist) + { + while (s = getnode(jn->filelist)) + { + unlink(s); + free(s); + } + free(jn->filelist); + } + *jn = zero; + if (job == curjob) + { + curjob = prevjob; + prevjob = job; + } + if (job == prevjob) + setprevjob(); + } + else + jn->stat &= ~STAT_CHANGED; +} + +/* set the previous job to something reasonable */ + +void setprevjob() /**/ +{ +int t0; + + for (t0 = MAXJOB-1; t0; t0--) + if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) && + t0 != curjob && t0 != thisjob) + break; + if (!t0) + for (t0 = MAXJOB-1; t0; t0--) + if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob) + break; + prevjob = (t0) ? t0 : -1; +} + +/* initialize a job table entry */ + +void initjob() /**/ +{ + jobtab[thisjob].pwd = ztrdup(pwd); + jobtab[thisjob].stat = STAT_INUSE; + jobtab[thisjob].gleader = 0; +} + +/* add a process to the current job */ + +struct process *addproc(pid,text) /**/ +long pid;char *text; +{ +struct process *process; + + if (!jobtab[thisjob].gleader) jobtab[thisjob].gleader = pid; + process = zcalloc(sizeof *process); + process->pid = pid; + if (text) strcpy(process->text,text); + else *process->text = '\0'; + process->next = NULL; + process->statusp = SP_RUNNING; + process->bgtime = time(NULL); + if (jobtab[thisjob].procs) { + struct process *n; + for (n = jobtab[thisjob].procs; n->next; n = n->next); + process->next = NULL; + n->next = process; + } else jobtab[thisjob].procs = process; + return process; +} + +/* determine if it's all right to exec a command without + forking in last component of subshells; it's not ok if we have files + to delete */ + +int execok() /**/ +{ +Job jn; + + if (!exiting) + return 0; + for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++) + if (jn->stat && jn->filelist) + return 0; + return 1; + +} + +void waitforpid(pid) /**/ +long pid; +{ + while (!errflag && (kill(pid,0) >= 0 || errno != ESRCH)) chldsuspend(); +} + +/* wait for a job to finish */ + +void waitjob(job) /**/ +int job; +{ +static struct job zero; +Job jn; + + if (jobtab[job].procs) /* if any forks were done */ + { + jobtab[job].stat |= STAT_LOCKED; + if (jobtab[job].stat & STAT_CHANGED) + printjob(jobtab+job,!!isset(LONGLISTJOBS)); + while (jobtab[job].stat && + !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED))) + chldsuspend(); + } + else /* else do what printjob() usually does */ + { + char *s; + + jn = jobtab+job; + free(jn->pwd); + if (jn->filelist) + { + while (s = getnode(jn->filelist)) + { + unlink(s); + free(s); + } + free(jn->filelist); + } + *jn = zero; + } +} + +/* wait for running job to finish */ + +void waitjobs() /**/ +{ + waitjob(thisjob); + thisjob = -1; +} + +/* clear job table when entering subshells */ + +void clearjobtab() /**/ +{ +static struct job zero; +int t0; + + for (t0 = 1; t0 != MAXJOB; t0++) + jobtab[thisjob] = zero; +} + +/* get a free entry in the job table to use */ + +int getfreejob() /**/ +{ +int t0; + + for (t0 = 1; t0 != MAXJOB; t0++) + if (!jobtab[t0].stat) { + jobtab[t0].stat |= STAT_INUSE; + return t0; + } + zerr("job table full or recursion limit exceeded",NULL,0); + return -1; +} + +/* print pids for & */ + +void spawnjob() /**/ +{ +struct process *pn; + + 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 (interact && jobbing && jobtab[thisjob].procs) + { + fprintf(stderr,"[%d]",thisjob); + for (pn = jobtab[thisjob].procs; pn; pn = pn->next) + fprintf(stderr," %d",pn->pid); + fprintf(stderr,"\n"); + fflush(stderr); + } + } + if (!jobtab[thisjob].procs) + { + char *s; + static struct job zero; + struct job *jn; + + jn = jobtab+thisjob; + free(jn->pwd); + if (jn->filelist) + { + while (s = getnode(jn->filelist)) + { + unlink(s); + free(s); + } + free(jn->filelist); + } + *jn = zero; + } + else + jobtab[thisjob].stat |= STAT_LOCKED; + thisjob = -1; +} + +void fixsigs() /**/ +{ + unblockchld(); +} + +int report(j) /**/ +Job j; +{ + if (!j->procs) return 0; +#ifdef HAS_RUSAGE + return (j->procs->ti.ru.ru_utime.tv_sec+j->procs->ti.ru.ru_stime.tv_sec) + >= reporttime; +#else + return (j->procs->ti.ut+j->procs->ti.st)/HZ >= reporttime; +#endif +} + +void printtime(real,ti,desc) /**/ +time_t real;struct timeinfo *ti;char *desc; +{ +char *s; +#ifdef sun +long ticks = 1; +int pk = getpagesize()/1024; +#else +long sec; +#endif +#ifdef HAS_RUSAGE +struct rusage *ru = &ti->ru; +#endif + + if (!desc) desc = ""; +#ifdef HAS_RUSAGE +#ifdef sun + ticks = (ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)*HZ+ + (ru->ru_utime.tv_usec+ru->ru_stime.tv_usec)*HZ/1000000; + if (!ticks) ticks = 1; +#else + sec = ru->ru_utime.tv_sec + ru->ru_stime.tv_sec; + if (!sec) sec = 1; +#endif +#endif + for (s = timefmt; *s; s++) + if (*s == '%') + switch(s++,*s) + { + case 'E': fprintf(stderr,"%lds",real); break; +#ifndef HAS_RUSAGE + case 'U': fprintf(stderr,"%ld.%03lds", + ti->ut/HZ,ti->ut*1000/60%1000); break; + case 'S': fprintf(stderr,"%ld.%03lds", + ti->st/HZ,ti->st*1000/60%1000); break; + case 'P': + if (real) + fprintf(stderr,"%d%%", + (int) (100*((ti->ut+ti->st)/HZ))/real); + break; +#else + case 'U': fprintf(stderr,"%ld.%03lds", + ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break; + case 'S': fprintf(stderr,"%ld.%03lds", + ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break; + case 'P': + if (real) + fprintf(stderr,"%d%%", + (int) (100*(ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)) + / real); + break; + case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break; +#ifdef sun + case 'K': case 'D': + fprintf(stderr,"%ld",ru->ru_idrss/ticks*pk); break; + case 'M': fprintf(stderr,"%ld",ru->ru_maxrss*pk); break; +#else + case 'X': fprintf(stderr,"%ld",ru->ru_ixrss/sec); break; + case 'D': fprintf(stderr,"%ld", + (ru->ru_idrss+ru->ru_isrss)/sec); break; + case 'K': fprintf(stderr,"%ld", + (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss)/sec); break; + case 'M': fprintf(stderr,"%ld",ru->ru_maxrss/1024); break; +#endif + case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break; + case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break; + case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break; + case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break; + case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break; + case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break; + case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break; + case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break; + case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break; +#endif + case 'J': fprintf(stderr,"%s",desc); break; + default: fprintf(stderr,"%%%c",*s); break; + } + else + putc(*s,stderr); + putc('\n',stderr); + fflush(stderr); +} + +void dumptime(jn) /**/ +Job jn; +{ +struct process *pn = jn->procs; + + if (!jn->procs) + return; + for (pn = jn->procs; pn; pn = pn->next) + printtime(pn->endtime-pn->bgtime,&pn->ti,pn->text); +} + +void shelltime() /**/ +{ +struct timeinfo ti; +#ifdef HAS_RUSAGE +struct rusage ru; + + getrusage(RUSAGE_SELF,&ru); + memcpy(&ti.ru,&ru,sizeof(ru)); + printtime(time(NULL)-shtimer,&ti,"shell"); + + getrusage(RUSAGE_CHILDREN,&ru); + memcpy(&ti.ru,&ru,sizeof(ru)); + printtime(time(NULL)-shtimer,&ti,"children"); +#else +struct tms buf; + + times(&buf); + ti.ut = buf.tms_utime; + ti.st = buf.tms_stime; + printtime(time(NULL)-shtimer,&ti,"shell"); + ti.ut = buf.tms_cutime; + ti.st = buf.tms_cstime; + printtime(time(NULL)-shtimer,&ti,"children"); +#endif +} + +/* SIGHUP any jobs left running */ + +void killrunjobs() /**/ +{ +int t0,killed = 0; + + if (isset(NOHUP)) return; + for (t0 = 1; t0 != MAXJOB; t0++) + if (t0 != thisjob && (jobtab[t0].stat & STAT_LOCKED) && + !(jobtab[t0].stat & STAT_STOPPED)) { + if (killpg(jobtab[t0].gleader,SIGHUP) != -1) killed++; + } + if (killed) zerr("warning: %d jobs SIGHUPed",NULL,killed); +} + +/* check to see if user has jobs running/stopped */ + +void checkjobs() /**/ +{ +int t0; + + scanjobs(); + for (t0 = 1; t0 != MAXJOB; t0++) + if (t0 != thisjob && jobtab[t0].stat & STAT_LOCKED) + break; + if (t0 != MAXJOB) { + if (jobtab[t0].stat & STAT_STOPPED) { +#ifdef USE_SUSPENDED + zerr("you have suspended jobs.",NULL,0); +#else + zerr("you have stopped jobs.",NULL,0); +#endif + } else + zerr("you have running jobs.",NULL,0); + stopmsg = 1; + } +} + +/* send a signal to a job (simply involves kill if monitoring is on) */ + +int killjb(jn,sig) /**/ +Job jn;int sig; +{ +struct process *pn; +int err; + + if (jobbing) + return(killpg(jn->gleader,sig)); + for (pn = jn->procs; pn; pn = pn->next) + if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH) + return -1; + return err; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/jobs.pro b/usr/othersrc/public/zsh-2.2/src/jobs.pro new file mode 100644 index 0000000000..b174219635 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/jobs.pro @@ -0,0 +1,23 @@ +HANDTYPE handler DCLPROTO((int sig,int code)); +void makerunning DCLPROTO((Job jn)); +void updatestatus DCLPROTO((Job jn)); +void findproc DCLPROTO((int pid,Job *jptr,struct process **pptr)); +void printjob DCLPROTO((Job jn,int lng)); +void setprevjob DCLPROTO((void)); +void initjob DCLPROTO((void)); +struct process *addproc DCLPROTO((long pid,char *text)); +int execok DCLPROTO((void)); +void waitforpid DCLPROTO((long pid)); +void waitjob DCLPROTO((int job)); +void waitjobs DCLPROTO((void)); +void clearjobtab DCLPROTO((void)); +int getfreejob DCLPROTO((void)); +void spawnjob DCLPROTO((void)); +void fixsigs DCLPROTO((void)); +int report DCLPROTO((Job j)); +void printtime DCLPROTO((time_t real,struct timeinfo *ti,char *desc)); +void dumptime DCLPROTO((Job jn)); +void shelltime DCLPROTO((void)); +void killrunjobs DCLPROTO((void)); +void checkjobs DCLPROTO((void)); +int killjb DCLPROTO((Job jn,int sig)); diff --git a/usr/othersrc/public/zsh-2.2/src/lex.c b/usr/othersrc/public/zsh-2.2/src/lex.c new file mode 100644 index 0000000000..36c8244bbd --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/lex.c @@ -0,0 +1,828 @@ +/* + * + * lex.c - lexical analysis + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +/* lexical state */ + +static int xincmdpos,xincond,xincasepat,dbparens,xdbparens,xalstat; +static char *xhlastw; + +static int xisfirstln, xisfirstch, xhistremmed, xhistdone, + xspaceflag, xstophist, xlithist, xalstackind,xhlinesz; +static char *xhline, *xhptr; + +/* save the lexical state */ + +/* is this a hack or what? */ + +void lexsave() /**/ +{ + xincmdpos = incmdpos; + xincond = incond; + xincasepat = incasepat; + xdbparens = dbparens; + xalstat = alstat; + xalstackind = alstackind; + xisfirstln = isfirstln; + xisfirstch = isfirstch; + xhistremmed = histremmed; + xhistdone = histdone; + xspaceflag = spaceflag; + xstophist = stophist; + xlithist = lithist; + xhline = hline; + xhptr = hptr; + xhlastw = hlastw; + xhlinesz = hlinesz; + inredir = 0; +} + +/* restore lexical state */ + +void lexrestore() /**/ +{ + incmdpos = xincmdpos; + incond = xincond; + incasepat = xincasepat; + dbparens = xdbparens; + alstat = xalstat; + isfirstln = xisfirstln; + isfirstch = xisfirstch; + histremmed = xhistremmed; + histdone = xhistdone; + spaceflag = xspaceflag; + stophist = xstophist; + lithist = xlithist; + hline = xhline; + hptr = xhptr; + hlastw = xhlastw; + clearalstack(); + alstackind = xalstackind; + hlinesz = xhlinesz; + lexstop = errflag = 0; +} + +void yylex() /**/ +{ + if (tok == LEXERR) return; + do + tok = gettok(); + while (tok != ENDINPUT && exalias()); + if (tok != NEWLIN) isnewlin = 0; + else isnewlin = (inbufct) ? -1 : 1; + if (tok == SEMI || tok == NEWLIN) tok = SEPER; +} + +void ctxtlex() /**/ +{ +static int oldpos; + + yylex(); + switch (tok) { + case SEPER: case NEWLIN: case SEMI: case DSEMI: case AMPER: + case INPAR: case INBRACE: case DBAR: case DAMPER: case BAR: + case BARAMP: case INOUTPAR: case DO: case THEN: case ELIF: + case ELSE: incmdpos = 1; break; + case STRING: /* case ENVSTRING: */ case ENVARRAY: case OUTPAR: + case CASE: incmdpos = 0; break; + } + 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_BANG 4 +#define LX1_AMPER 5 +#define LX1_BAR 6 +#define LX1_INPAR 7 +#define LX1_OUTPAR 8 +#define LX1_INBRACE 9 +#define LX1_OUTBRACE 10 +#define LX1_INBRACK 11 +#define LX1_OUTBRACK 12 +#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_OTHER 17 + +unsigned char lexact1[256],lexact2[256],lextok2[256]; + +void initlextabs() /**/ +{ +int t0; +static char *lx1 = "\\q\n;!&|(){}[]<>xx"; +static char *lx2 = "x)|$[]~({}><=\\\'\"`x"; + + for (t0 = 0; t0 != 256; t0++) { + lexact1[t0] = LX1_OTHER; + lexact2[t0] = LX2_OTHER; + lextok2[t0] = t0; + } + for (t0 = 0; lx1[t0]; t0++) + if (lx1[t0] != 'x') + lexact1[lx1[t0]] = t0; + for (t0 = 0; lx2[t0]; t0++) + if (lx2[t0] != 'x') + lexact2[lx2[t0]] = t0; + lexact2[';'] = LX2_BREAK; + lexact2['&'] = LX2_BREAK; + lextok2[','] = Comma; + lextok2['*'] = Star; + lextok2['?'] = Quest; + lextok2['{'] = Inbrace; + lextok2['['] = Inbrack; + lextok2['$'] = String; +} + +/* initialize lexical state */ + +void lexinit() /**/ +{ + incond = incasepat = nocorrect = + dbparens = alstat = lexstop = 0; + incmdpos = 1; + tok = ENDINPUT; + if (isset(EXTENDEDGLOB)) + { + lextok2['#'] = Pound; + lextok2['^'] = Hat; + } + else + { + lextok2['#'] = '#'; + lextok2['^'] = '^'; + } +} + +int len = 0,bsiz = 256; +char *bptr; + +/* add a char to the string buffer */ + +void add(c) /**/ +int c; +{ + *bptr++ = c; + if (bsiz == ++len) + { + int newbsiz; + + newbsiz = bsiz * 8; + while (newbsiz < inbufct) + newbsiz *= 2; + bptr = len+(tokstr = hrealloc(tokstr,bsiz,newbsiz)); + bsiz = newbsiz; + } +} + +static void unadd() +{ + bptr--; len--; +} + +int gettok() /**/ +{ +int bct = 0,pct = 0,brct = 0; +int c,d,intpos = 1; +int peekfd = -1,peek,ninbracks; + +beginning: + hlastw = NULL; + tokstr = NULL; + parbegin = -1; + while (iblank(c = hgetc()) && !lexstop); + isfirstln = 0; + wordbeg = inbufct; + hwbegin(); + hwaddc(c); + if (dbparens) /* handle ((...)) */ + { + pct = 2; + peek = STRING; + len = dbparens = 0; + bptr = tokstr = ncalloc(bsiz = 256); + for (;;) + { + if (c == '(') + pct++; + else if (c == ')') + pct--; + else if (c == '\n') + { + zerr("parse error: )) expected",NULL,0); + peek = LEXERR; + return peek; + } + else if (c == '$') + c = Qstring; + if (pct >= 2) + add(c); + if (pct) + c = hgetc(); + else + break; + } + *bptr = '\0'; + return peek; + } + if (idigit(c)) /* handle 1< foo */ + { + d = hgetc(); + hungetc(d); + lexstop = 0; + if (d == '>' || d == '<') + { + peekfd = c-'0'; + c = hgetc(); + } + } + + /* chars in initial position in word */ + + if (c == hashchar && + (isset(INTERACTIVECOMMENTS) || + (!zleparse && (!interact || unset(SHINSTDIN) || strin)))) + { + /* changed hgetch to hgetc so comments appear in history */ + stophist = 1; + while ((c = hgetc()) != '\n' && !lexstop); + if (c == '\n') { + hwaddc('\n'); + peek = NEWLIN; + } else { + peek = (errflag) ? LEXERR : ENDINPUT; + errflag = 1; + } + return peek; + } + if (lexstop) + return (errflag) ? LEXERR : ENDINPUT; + switch (lexact1[(unsigned char) c]) + { + case LX1_BKSLASH: + d = hgetc(); + if (d == '\n') + goto beginning; + hungetc(d); + break; + case LX1_NEWLIN: return NEWLIN; + case LX1_SEMI: + d = hgetc(); + if (d != ';') + { + hungetc(d); + return SEMI; + } + return DSEMI; + case LX1_BANG: + d = hgetc(); + hungetc(d); + if (!inblank(d)) + break; + if (incmdpos || incond) + return BANG; + break; + case LX1_AMPER: + d = hgetc(); + if (d != '&') + { + hungetc(d); + return AMPER; + } + return DAMPER; + case LX1_BAR: + d = hgetc(); + if (d == '|') + return DBAR; + else if (d == '&') + return BARAMP; + hungetc(d); + return BAR; + case LX1_INPAR: + d = hgetc(); + if (d == '(' && incmdpos) + { + tokstr = strdup("let"); + dbparens = 1; + return STRING; + } + else if (d == ')') + return INOUTPAR; + hungetc(d); + if (!(incond || incmdpos)) + break; + return INPAR; + case LX1_OUTPAR: return OUTPAR; + case LX1_INBRACE: if (!incmdpos) break; return INBRACE; + case LX1_OUTBRACE: return OUTBRACE; + case LX1_INBRACK: + if (!incmdpos) + break; + d = hgetc(); + if (d == '[') + return DINBRACK; + hungetc(d); + break; + case LX1_OUTBRACK: + if (!incond) + break; + d = hgetc(); + if (d == ']') + return DOUTBRACK; + hungetc(d); + break; + case LX1_INANG: + d = hgetc(); + if ((!incmdpos && d == '(') || incasepat) { + hungetc(d); + break; + } 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); + peek = DINANG; + } + } else if (d == '&') + peek = INANGAMP; + else { + peek = INANG; + hungetc(d); + } + tokfd = peekfd; + return peek; + case LX1_OUTANG: + d = hgetc(); + if (d == '(') + { + hungetc(d); + break; + } + else if (d == '&') + { + d = hgetc(); + if (d == '!') + peek = OUTANGAMPBANG; + else + { + hungetc(d); + peek = OUTANGAMP; + } + } + else if (d == '!') + peek = OUTANGBANG; + else if (d == '>') + { + d = hgetc(); + if (d == '&') + { + d = hgetc(); + if (d == '!') + peek = DOUTANGAMPBANG; + else + { + hungetc(d); + peek = DOUTANGAMP; + } + } + else if (d == '!') + peek = DOUTANGBANG; + else if (d == '(') + { + hungetc(d); + hungetc('>'); + peek = OUTANG; + } + else + { + hungetc(d); + peek = DOUTANG; + if (isset(NOCLOBBER)) hwaddc('!'); + } + } + else + { + hungetc(d); + peek = OUTANG; + if (isset(NOCLOBBER)) hwaddc('!'); + } + tokfd = peekfd; + return peek; + } + + /* we've started a string, now get the rest of it, performing + tokenization */ + + peek = STRING; + len = 0; + bptr = tokstr = ncalloc(bsiz = 256); + for(;;) + { + int act; + int d; + + if (inblank(c)) + act = LX2_BREAK; + else + { + act = lexact2[(unsigned char) c]; + c = lextok2[(unsigned char) c]; + } + switch (act) + { + case LX2_BREAK: goto brk; + case LX2_OUTPAR: + if (!pct) + goto brk; + c = Outpar; + pct--; + break; + case LX2_BAR: + if (!pct && !incasepat) + goto brk; + c = Bar; + break; + case LX2_STRING: + d = hgetc(); + if (d == '[') + { + add(String); + add(Inbrack); + ninbracks = 1; + while (ninbracks && (c = hgetc()) && !lexstop) { + if (c == '[') ninbracks++; + else if (c == ']') ninbracks--; + if (ninbracks) add(c); + } + c = Outbrack; + } + else if (d == '(') + { + add(String); + if (skipcomm()) { peek = LEXERR; goto brk; } + c = Outpar; + } + else + hungetc(d); + break; + case LX2_INBRACK: brct++; break; + case LX2_OUTBRACK: + if (incond && !brct) + goto brk; + brct--; + c = Outbrack; + break; + case LX2_TILDE: /* if (intpos) */ c = Tilde; break; + case LX2_INPAR: + d = hgetc(); + hungetc(d); + if (d == ')' || (incmdpos && peek != ENVSTRING)) + goto brk; + pct++; + c = Inpar; + break; + case LX2_INBRACE: bct++; break; + case LX2_OUTBRACE: + if (!bct) + goto brk; + bct--; + c = Outbrace; + break; + case LX2_OUTANG: + d = hgetc(); + if (d != '(') + { + hungetc(d); + goto brk; + } + add(Outang); + if (skipcomm()) { peek = LEXERR; goto brk; } + c = Outpar; + break; + case LX2_INANG: + d = hgetc(); + if (!(idigit(d) || d == '-' || d == '>' || d == '(' || d == ')')) + { + hungetc(d); + goto brk; + } + c = Inang; + if (d == '(') + { + add(c); + if (skipcomm()) { peek = LEXERR; goto brk; } + c = Outpar; + } + else if (d == ')') + hungetc(d); + else + { + add(c); + c = d; + while (c != '>' && !lexstop) + add(c),c = hgetc(); + c = Outang; + } + break; + case LX2_EQUALS: + if (intpos) + { + d = hgetc(); + if (d != '(') + { + hungetc(d); + c = Equals; + } + else + { + add(Equals); + if (skipcomm()) { peek = LEXERR; goto brk; } + c = Outpar; + } + } + else if (peek != ENVSTRING && incmdpos) + { + d = hgetc(); + if (d == '(' && incmdpos) + { + *bptr = '\0'; + return ENVARRAY; + } + hungetc(d); + peek = ENVSTRING; + intpos = 2; + } + break; + case LX2_BKSLASH: + c = hgetc(); + if (c == '\n') + { + c = hgetc(); + continue; + } + add(c); + c = hgetc(); + continue; + case LX2_QUOTE: + add(Nularg); + + /* we add the Nularg to prevent this: + + echo $PA'TH' + + from printing the path. */ + + for (;;) { + while ((c = hgetc()) != '\'' && !lexstop) { + if (isset(CSHJUNKIEQUOTES) && c == '\n') { + if (bptr[-1] == '\\') unadd(); else break; + } + add(c); + } + if (c != '\'') { + zerr("unmatched \'",NULL,0); + peek = LEXERR; + goto brk; + } + d = hgetc(); + if (d != '\'' || unset(RCQUOTES)) break; + add(c); + } + hungetc(d); + c = Nularg; + break; + case LX2_DQUOTE: + add(Nularg); + while ((c = hgetc()) != '\"' && !lexstop) + if (c == '\\') + { + c = hgetc(); + if (c != '\n') + { + if (c != '$' && c != '\\' && c != '\"' && c != '`') + add('\\'); + add(c); + } + } + else { + if (isset(CSHJUNKIEQUOTES) && c == '\n') { + if (bptr[-1] == '\\') unadd(); else break; + } + if (c == '$') { + d = hgetc(); + if (d == '(') { + add(Qstring); + if (skipcomm()) { peek = LEXERR; goto brk; } + c = Outpar; + } else if (d == '[') { + add(String); + add(Inbrack); + while ((c = hgetc()) != ']' && !lexstop) + add(c); + c = Outbrack; + } else { + c = Qstring; + hungetc(d); + } + } else if (c == '`') + c = Qtick; + add(c); + } + if (c != '\"') { + zerr("unmatched \"",NULL,0); + peek = LEXERR; + goto brk; + } + c = Nularg; + break; + case LX2_BQUOTE: + add(Tick); + parbegin = inbufct; + while ((c = hgetc()) != '`' && !lexstop) + if (c == '\\') + { + c = hgetc(); + if (c != '\n') + { + if (c != '`' && c != '\\' && c != '$') + add('\\'); + add(c); + } + } + else { + if (isset(CSHJUNKIEQUOTES) && c == '\n') { + if (bptr[-1] == '\\') unadd(); else break; + } + add(c); + } + if (c != '`') { + if (!zleparse) zerr("unmatched `",NULL,0); + peek = LEXERR; + goto brk; + } + c = Tick; + parbegin = -1; + break; + } + add(c); + c = hgetc(); + if (intpos) + intpos--; + if (lexstop) + break; + } +brk: + hungetc(c); + *bptr = '\0'; + return peek; +} + +/* expand aliases, perhaps */ + +int exalias() /**/ +{ +struct alias *an; +char *s,*t; + + s = yytext = hwadd(); + for (t = s; *t && *t != HISTSPACE; t++); + if (!*t) + t = NULL; + else + *t = '\0'; + if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING && + (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect) + spckword(&tokstr,&s,&t,!incmdpos,1); + if (zleparse && !alstackind) { + int zp = zleparse; + gotword(s); + if (zp && !zleparse) { + if (t) *t = HISTSPACE; + return 0; + } + } + an = gethnode(s,aliastab); + if (t) *t = HISTSPACE; + if (alstackind != MAXAL && an && !an->inuse) + if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE)) { + if (an->cmd < 0) { + tok = DO-an->cmd-1; + return 0; + } else { + an->inuse = 1; + hungets(ALPOPS); + hungets((alstack[alstackind++] = an)->text); + alstat = 0; + /* remove from history if it begins with space */ + if (isset(HISTIGNORESPACE) && an->text[0] == ' ') remhist(); + lexstop = 0; + return 1; + } + } + return 0; +} + +/* skip (...) */ + +int skipcomm() /**/ +{ +int pct = 1,c; + + parbegin = inbufct; + c = Inpar; + do + { + add(c); + c = hgetc(); + if (itok(c) || lexstop) + break; + else if (c == '(') pct++; + else if (c == ')') pct--; + else if (c == '\\') + { + add(c); + c = hgetc(); + } + else if (c == '\'') + { + add(c); + while ((c = hgetc()) != '\'' && !lexstop) + add(c); + } + else if (c == '\"') + { + add(c); + while ((c = hgetc()) != '\"' && !lexstop) + if (c == '\\') + { + add(c); + add(hgetc()); + } + else add(c); + } + else if (c == '`') + { + add(c); + while ((c = hgetc()) != '`' && !lexstop) + if (c == '\\') add(c), add(hgetc()); + else add(c); + } + } + while(pct); + if (!lexstop) parbegin = -1; + return lexstop; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/lex.pro b/usr/othersrc/public/zsh-2.2/src/lex.pro new file mode 100644 index 0000000000..db0ef95da7 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/lex.pro @@ -0,0 +1,10 @@ +void lexsave DCLPROTO((void)); +void lexrestore DCLPROTO((void)); +void yylex DCLPROTO((void)); +void ctxtlex DCLPROTO((void)); +void initlextabs DCLPROTO((void)); +void lexinit DCLPROTO((void)); +void add DCLPROTO((int c)); +int gettok DCLPROTO((void)); +int exalias DCLPROTO((void)); +int skipcomm DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/loop.c b/usr/othersrc/public/zsh-2.2/src/loop.c new file mode 100644 index 0000000000..d27596b4b1 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/loop.c @@ -0,0 +1,294 @@ +/* + * + * loop.c - loop execution + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +int execfor(cmd) /**/ +Cmd cmd; +{ +List list; +struct forcmd *node; +char *str; +Lklist args; +int cj = thisjob; + + loops++; + exiting = 0; + node = cmd->u.forcmd; + args = cmd->args; + if (!node->inflag) + { + char **x; + + args = newlist(); + for (x = pparams; *x; x++) + addnode(args,ztrdup(*x)); + } + pushheap(); + while (str = ugetnode(args)) + { + setsparam(node->name,ztrdup(str)); + list = dupstruct(node->list); + execlist(list); + if (breaks) + { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (errflag) + { + lastval = 1; + break; + } + freeheap(); + } + popheap(); + thisjob = cj; + loops--; + return lastval; +} + +int execselect(cmd) /**/ +Cmd cmd; +{ +List list; +struct forcmd *node; +char *str,*s; +Lklist args; +Lknode n; +int cj = thisjob,t0; +FILE *inp; + + node = cmd->u.forcmd; + args = cmd->args; + if (!node->inflag) { + char **x; + + args = newlist(); + for (x = pparams; *x; x++) + addnode(args,ztrdup(*x)); + } + if (!full(args)) + return 1; + loops++; + exiting = 0; + pushheap(); + inp = fdopen(dup((SHTTY==-1)?0:SHTTY),"r"); + for (;;) + { + do + { + int pl; + selectlist(args); + str = putprompt(prompt3,&pl); + if (full(bufstack)) str = (char *) getnode(bufstack); + else if (interact && SHTTY != -1 && isset(USEZLE)) { + str = (char *)zleread(str,NULL,pl); + } else { + fprintf(stderr,"%s",str); + fflush(stderr); + str = fgets(zalloc(256),256,inp); + } + if (!str || errflag) + { + fprintf(stderr,"\n"); + fflush(stderr); + goto done; + } + if (s = strchr(str,'\n')) + *s = '\0'; + } + while (!*str); + setsparam("REPLY",ztrdup(str)); + t0 = atoi(str); + if (!t0) + str = ""; + else + { + for (t0--,n = firstnode(args); n && t0; incnode(n),t0--); + if (n) + str = getdata(n); + else + str = ""; + } + setsparam(node->name,ztrdup(str)); + list = dupstruct(node->list); + execlist(list); + freeheap(); + if (breaks) + { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (errflag) + break; + } +done: + popheap(); + fclose(inp); + thisjob = cj; + loops--; + return lastval; +} + +int execwhile(cmd) /**/ +Cmd cmd; +{ +List list; +struct whilecmd *node; +int cj = thisjob; + + node = cmd->u.whilecmd; + exiting = 0; + pushheap(); + loops++; + for(;;) + { + list = dupstruct(node->cont); + execlist(list); + if (!((lastval == 0) ^ node->cond)) + break; + list = dupstruct(node->loop); + execlist(list); + if (breaks) + { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + freeheap(); + if (errflag) + { + lastval = 1; + break; + } + } + popheap(); + thisjob = cj; + loops--; + return lastval; +} + +int execrepeat(cmd) /**/ +Cmd cmd; +{ +List list; +int cj = thisjob,count; + + exiting = 0; + if (!full(cmd->args) || nextnode(firstnode(cmd->args))) + { + zerr("bad argument for repeat",NULL,0); + return 1; + } + count = atoi(peekfirst(cmd->args)); + pushheap(); + loops++; + while (count--) + { + list = dupstruct(cmd->u.list); + execlist(list); + freeheap(); + if (breaks) + { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (lastval) + break; + if (errflag) + { + lastval = 1; + break; + } + } + popheap(); + thisjob = cj; + loops--; + return lastval; +} + +int execif(cmd) /**/ +Cmd cmd; +{ +struct ifcmd *node; +int cj = thisjob; + + node = cmd->u.ifcmd; + exiting = 0; + while (node) + { + if (node->ifl) + { + execlist(node->ifl); + if (lastval) + { + node = node->next; + continue; + } + } + execlist(node->thenl); + break; + } + thisjob = cj; + return lastval; +} + +int execcase(cmd) /**/ +Cmd cmd; +{ +struct casecmd *node; +char *word; +Lklist args; +int cj = thisjob; + + node = cmd->u.casecmd; + args = cmd->args; + exiting = 0; + if (firstnode(args) && nextnode(firstnode(args))) + { + zerr("too many arguments to case",NULL,0); + errflag = 1; + return 1; + } + if (!full(args)) + word = strdup(""); + else + word = peekfirst(args); + while (node) + { + singsub(&(node->pat)); + if (matchpat(word,node->pat)) + break; + else + node = node->next; + } + if (node && node->list) + execlist(node->list); + thisjob = cj; + return lastval; +} diff --git a/usr/othersrc/public/zsh-2.2/src/loop.pro b/usr/othersrc/public/zsh-2.2/src/loop.pro new file mode 100644 index 0000000000..8403a1a423 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/loop.pro @@ -0,0 +1,6 @@ +int execfor DCLPROTO((Cmd cmd)); +int execselect DCLPROTO((Cmd cmd)); +int execwhile DCLPROTO((Cmd cmd)); +int execrepeat DCLPROTO((Cmd cmd)); +int execif DCLPROTO((Cmd cmd)); +int execcase DCLPROTO((Cmd cmd)); diff --git a/usr/othersrc/public/zsh-2.2/src/math.c b/usr/othersrc/public/zsh-2.2/src/math.c new file mode 100644 index 0000000000..cc254390d4 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/math.c @@ -0,0 +1,455 @@ +/* + * + * math.c - mathematical expression evaluation + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +static char *ptr; + +typedef int LV; + +static long yyval; +static LV yylval; + +/* nonzero means we are not evaluating, just parsing */ + +static int noeval = 0; + +/* != 0 means recognize unary plus, minus, etc. */ + +static int unary = 1; + +void mathparse DCLPROTO((int)); + +/* LR = left-to-right associativity + RL = right-to-left associativity + BOO = short-circuiting boolean */ + +#define LR 0 +#define RL 1 +#define BOOL 2 + +#define M_INPAR 0 +#define M_OUTPAR 1 +#define NOT 2 +#define COMP 3 +#define POSTPLUS 4 +#define POSTMINUS 5 +#define UPLUS 6 +#define UMINUS 7 +#define AND 8 +#define XOR 9 +#define OR 10 +#define MUL 11 +#define DIV 12 +#define MOD 13 +#define PLUS 14 +#define MINUS 15 +#define SHLEFT 16 +#define SHRIGHT 17 +#define LES 18 +#define LEQ 19 +#define GRE 20 +#define GEQ 21 +#define DEQ 22 +#define NEQ 23 +#define DAND 24 +#define DOR 25 +#define DXOR 26 +#define QUEST 27 +#define COLON 28 +#define EQ 29 +#define PLUSEQ 30 +#define MINUSEQ 31 +#define MULEQ 32 +#define DIVEQ 33 +#define MODEQ 34 +#define ANDEQ 35 +#define XOREQ 36 +#define OREQ 37 +#define SHLEFTEQ 38 +#define SHRIGHTEQ 39 +#define DANDEQ 40 +#define DOREQ 41 +#define DXOREQ 42 +#define COMMA 43 +#define EOI 44 +#define PREPLUS 45 +#define PREMINUS 46 +#define NUM 47 +#define ID 48 +#define TOKCOUNT 49 + +/* precedences */ + +static int prec[TOKCOUNT] = { + 1,137,2,2,2, + 2,2,2,4,5, + 6,7,7,7,8, + 8,3,3,9,9, + 9,9,10,10,11, + 12,12,13,13,14, + 14,14,14,14,14, + 14,14,14,14,14, + 14,14,14,15,200, + 2,2,0,0, +}; + +#define TOPPREC 15 +#define ARGPREC (15-1) + +static int type[TOKCOUNT] = { + LR,LR,RL,RL,RL, + RL,RL,RL,LR,LR, + LR,LR,LR,LR,LR, + LR,LR,LR,LR,LR, + LR,LR,LR,LR,BOOL, + BOOL,LR,RL,RL,RL, + RL,RL,RL,RL,RL, + RL,RL,RL,RL,RL, + BOOL,BOOL,RL,RL,RL, + RL,RL,LR,LR, +}; + +#define LVCOUNT 32 + +/* list of lvalues (variables) */ + +static int lvc; +static char *lvals[LVCOUNT]; + +int zzlex() /**/ +{ + for(;;) + switch (*ptr++) + { + case '+': + if (*ptr == '+' && (unary || !ialnum(*ptr))) + { + ptr++; + return (unary) ? PREPLUS : POSTPLUS; + } + if (*ptr == '=') { unary = 1; ptr++; return PLUSEQ; } + return (unary) ? UPLUS : PLUS; + case '-': + if (*ptr == '-' && (unary || !ialnum(*ptr))) + { + ptr++; + return (unary) ? PREMINUS : POSTMINUS; + } + if (*ptr == '=') { unary = 1; ptr++; return MINUSEQ; } + return (unary) ? UMINUS : MINUS; + case '(': unary = 1; return M_INPAR; + case ')': return M_OUTPAR; + case '!': if (*ptr == '=') + { unary = 1; ptr++; return NEQ; } + return NOT; + case '~': return COMP; + case '&': unary = 1; + if (*ptr == '&') { if (*++ptr == '=') + { ptr++; return DANDEQ; } return DAND; } + else if (*ptr == '=') { ptr++; return ANDEQ; } return AND; + case '|': unary = 1; + if (*ptr == '|') { if (*++ptr == '=') + { ptr++; return DOREQ; } return DOR; } + else if (*ptr == '=') { ptr++; return OREQ; } return OR; + case '^': unary = 1; + if (*ptr == '^') { if (*++ptr == '=') + { ptr++; return DXOREQ; } return DXOR; } + else if (*ptr == '=') { ptr++; return XOREQ; } return XOR; + case '*': unary = 1; + if (*ptr == '=') { ptr++; return MULEQ; } return MUL; + case '/': unary = 1; + if (*ptr == '=') { ptr++; return DIVEQ; } return DIV; + case '%': unary = 1; + if (*ptr == '=') { ptr++; return MODEQ; } return MOD; + case '<': unary = 1; if (*ptr == '<') + { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; } + else if (*ptr == '=') { ptr++; return LEQ; } return LES; + case '>': unary = 1; if (*ptr == '>') + { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; } + else if (*ptr == '=') { ptr++; return GEQ; } return GRE; + case '=': unary = 1; if (*ptr == '=') { ptr++; return DEQ; } + return EQ; + case '?': unary = 1; return QUEST; + case ':': unary = 1; return COLON; + case ',': unary = 1; return COMMA; + case '\0': unary = 1; ptr--; return EOI; + case '[': unary = 0; + { int base = zstrtol(ptr,&ptr,10); + if (*ptr == ']') ptr++; + yyval = zstrtol(ptr,&ptr,lastbase = base); + return NUM; } + case ' ': case '\t': + break; + default: + if (idigit(*--ptr)) + { unary = 0; yyval = zstrtol(ptr,&ptr,10); return NUM; } + if (iident(*ptr) || *ptr == '$') + { + char *p,q; + + if (*ptr == '$') + ptr++; + p = ptr; + if (lvc == LVCOUNT) + { + zerr("too many identifiers (complain to author)",NULL,0); + return EOI; + } + unary = 0; + while(iident(*++ptr)); + q = *ptr; + *ptr = '\0'; + lvals[yylval = lvc++] = ztrdup(p); + *ptr = q; + return ID; + } + return EOI; + } +} + +/* the value stack */ + +#define STACKSZ 100 +int mtok; /* last token */ +int sp = -1; /* stack pointer */ +struct mathvalue { + LV lval; + long val; + } stack[STACKSZ]; + +void push(val,lval) +long val;LV lval; +{ + if (sp == STACKSZ-1) + zerr("stack overflow",NULL,0); + else + sp++; + stack[sp].val = val; + stack[sp].lval = lval; +} + +long getvar(s) +LV s; +{ +long t; + + if (!(t = getiparam(lvals[s]))) + return 0; + return t; +} + +long setvar(s,v) +LV s;long v; +{ + if (s == -1 || s >= lvc) + { + zerr("lvalue required",NULL,0); + return 0; + } + if (noeval) + return v; + setiparam(lvals[s],v); + return v; +} + +int notzero(a) /**/ +int a; +{ + if (a == 0) + { + zerr("division by zero",NULL,0); + return 0; + } + return 1; +} + +#define pop2() { b = stack[sp--].val; a = stack[sp--].val; } +#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;} +#define nolval() {stack[sp].lval= -1;} +#define pushv(X) { push(X,-1); } +#define pop2lv() { pop2() lv = stack[sp+1].lval; } +#define set(X) { push(setvar(lv,X),lv); } + +void op(what) /**/ +int what; +{ +long a,b,c; +LV lv; + + if (sp < 0) + { + zerr("bad math expression: stack empty",NULL,0); + return; + } + switch(what) { + case NOT: stack[sp].val = !stack[sp].val; nolval(); break; + case COMP: stack[sp].val = ~stack[sp].val; nolval(); break; + case POSTPLUS: ( void ) setvar(stack[sp].lval,stack[sp].val+1); break; + case POSTMINUS: ( void ) setvar(stack[sp].lval,stack[sp].val-1); break; + case UPLUS: nolval(); break; + case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break; + case AND: pop2(); pushv(a&b); break; + case XOR: pop2(); pushv(a^b); break; + case OR: pop2(); pushv(a|b); break; + case MUL: pop2(); pushv(a*b); break; + case DIV: pop2(); if (notzero(b)) pushv(a/b); break; + case MOD: pop2(); if (notzero(b)) pushv(a%b); break; + case PLUS: pop2(); pushv(a+b); break; + case MINUS: pop2(); pushv(a-b); break; + case SHLEFT: pop2(); pushv(a<>b); break; + case LES: pop2(); pushv(ab); break; + case GEQ: pop2(); pushv(a>=b); break; + case DEQ: pop2(); pushv(a==b); break; + case NEQ: pop2(); pushv(a!=b); break; + case DAND: pop2(); pushv(a&&b); break; + case DOR: pop2(); pushv(a||b); break; + case DXOR: pop2(); pushv(a&&!b||!a&&b); break; + case QUEST: pop3(); pushv((a)?b:c); break; + case COLON: break; + case EQ: pop2lv(); set(b); break; + case PLUSEQ: pop2lv(); set(a+b); break; + case MINUSEQ: pop2lv(); set(a-b); break; + case MULEQ: pop2lv(); set(a*b); break; + case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break; + case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break; + case ANDEQ: pop2lv(); set(a&b); break; + case XOREQ: pop2lv(); set(a^b); break; + case OREQ: pop2lv(); set(a|b); break; + case SHLEFTEQ: pop2lv(); set(a<>b); break; + case DANDEQ: pop2lv(); set(a&&b); break; + case DOREQ: pop2lv(); set(a||b); break; + case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break; + case COMMA: pop2(); pushv(b); break; + case PREPLUS: stack[sp].val = setvar(stack[sp].lval, + stack[sp].val+1); break; + case PREMINUS: stack[sp].val = setvar(stack[sp].lval, + stack[sp].val-1); break; + default: zerr("out of integers",NULL,0); exit(1); + } +} + +void bop(tk) /**/ +int tk; +{ + switch (tk) { + case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break; + case DOR: case DOREQ: if (stack[sp].val) noeval++; break; + }; +} + +long mathevall(s,prek,ep) /**/ +char *s;int prek;char **ep; +{ +int t0; + + lastbase = -1; + for (t0 = 0; t0 != LVCOUNT; t0++) + lvals[t0] = NULL; + lvc = 0; + ptr = s; + sp = -1; + unary = 1; + mathparse(prek); + *ep = ptr; + if (sp) + zerr("bad math expression: unbalanced stack",NULL,0); + for (t0 = 0; t0 != lvc; t0++) + free(lvals[t0]); + return stack[0].val; +} + +long matheval(s) /**/ +char *s; +{ +char *junk; +long x; + + if (!*s) + return 0; + x = mathevall(s,TOPPREC,&junk); + if (*junk) + zerr("bad math expression: illegal character: %c",NULL,*junk); + return x; +} + +long mathevalarg(s,ss) /**/ +char *s;char **ss; +{ +long x; + + x = mathevall(s,ARGPREC,ss); + if (mtok == COMMA) + (*ss)--; + return x; +} + +/* operator-precedence parse the string and execute */ + +void mathparse(pc) /**/ +int pc; +{ + if (errflag) + return; + mtok = zzlex(); + while (prec[mtok] <= pc) + { + if (errflag) + return; + if (mtok == NUM) + push(yyval,-1); + else if (mtok == ID) + push(getvar(yylval),yylval); + else if (mtok == M_INPAR) + { + mathparse(TOPPREC); + if (mtok != M_OUTPAR) + exit(1); + } + else if (mtok == QUEST) + { + int q = stack[sp].val; + if (!q) noeval++; + mathparse(prec[QUEST]-1); + if (!q) noeval--; else noeval++; + mathparse(prec[QUEST]); + if (q) noeval--; + op(QUEST); + continue; + } + else + { + int otok = mtok,onoeval = noeval; + + if (type[otok] == BOOL) + bop(otok); + mathparse(prec[otok]-(type[otok] != RL)); + noeval = onoeval; + op(otok); + continue; + } + mtok = zzlex(); + } +} + diff --git a/usr/othersrc/public/zsh-2.2/src/math.pro b/usr/othersrc/public/zsh-2.2/src/math.pro new file mode 100644 index 0000000000..1a0c4c8797 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/math.pro @@ -0,0 +1,8 @@ +int zzlex DCLPROTO((void)); +int notzero DCLPROTO((int a)); +void op DCLPROTO((int what)); +void bop DCLPROTO((int tk)); +long mathevall DCLPROTO((char *s,int prek,char **ep)); +long matheval DCLPROTO((char *s)); +long mathevalarg DCLPROTO((char *s,char **ss)); +void mathparse DCLPROTO((int pc)); diff --git a/usr/othersrc/public/zsh-2.2/src/mem.pro b/usr/othersrc/public/zsh-2.2/src/mem.pro new file mode 100644 index 0000000000..f6e0e6edda --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/mem.pro @@ -0,0 +1,15 @@ +void meminit DCLPROTO((void)); +void heapalloc DCLPROTO((void)); +void permalloc DCLPROTO((void)); +void lastalloc DCLPROTO((void)); +void pushheap DCLPROTO((void)); +void freeheap DCLPROTO((void)); +void popheap DCLPROTO((void)); +void freeh DCLPROTO((Heap h)); +vptr halloc DCLPROTO((int size)); +vptr hcalloc DCLPROTO((int size)); +vptr hrealloc DCLPROTO((char *p,int old,int new)); +vptr zalloc DCLPROTO((int l)); +vptr zcalloc DCLPROTO((int size)); +char *strdup DCLPROTO((char *s)); +char *ztrdup DCLPROTO((char *s)); diff --git a/usr/othersrc/public/zsh-2.2/src/params.c b/usr/othersrc/public/zsh-2.2/src/params.c new file mode 100644 index 0000000000..e8efba6f7e --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/params.c @@ -0,0 +1,1315 @@ +/* + * + * params.c - parameters + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include + +#define new(X) (X=(vptr)alloc(sizeof(*(X)))) + +static Param argvparam; + +struct iparam { + struct hashnode *next; int canfree; char *nam; /* hash data */ + void *value; + int (*func1)(); /* set func */ + int (*func2)(); /* get func */ + int ct; /* output base or field width */ + int flags; + vptr data; /* used by getfns */ + char *env; /* location in environment, if exported */ + char *ename; /* name of corresponding environment var */ + }; + +#define IFN(X) ((int (*)())(X)) + +/* put predefined params in hash table */ + +void setupparams() /**/ +{ +static struct iparam pinit[] = { +#define IPDEF1(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),10,\ + PMFLAG_i|PMFLAG_SPECIAL|D,NULL,NULL,NULL} + IPDEF1("#",poundgetfn,IFN(nullsetfn),PMFLAG_r), + IPDEF1("ARGC",poundgetfn,IFN(nullsetfn),PMFLAG_r), + IPDEF1("ERRNO",errnogetfn,IFN(nullsetfn),PMFLAG_r), + IPDEF1("GID",gidgetfn,IFN(nullsetfn),PMFLAG_r), + IPDEF1("HISTSIZE",histsizegetfn,histsizesetfn,0), + IPDEF1("LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,0), + IPDEF1("RANDOM",randomgetfn,randomsetfn,0), + IPDEF1("SECONDS",secondsgetfn,secondssetfn,0), + IPDEF1("UID",uidgetfn,IFN(nullsetfn),PMFLAG_r), + +#define IPDEF2(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),0,\ + PMFLAG_SPECIAL|D,NULL,NULL,NULL} + IPDEF2("-",dashgetfn,IFN(nullsetfn),PMFLAG_r), + IPDEF2("HISTCHARS",histcharsgetfn,histcharssetfn,0), + IPDEF2("HOME",homegetfn,homesetfn,0), + IPDEF2("TERM",termgetfn,termsetfn,0), + IPDEF2("WORDCHARS",wordcharsgetfn,wordcharssetfn,0), + IPDEF2("IFS",ifsgetfn,ifssetfn,0), + IPDEF2("_",underscoregetfn,IFN(nullsetfn),PMFLAG_r), + +#define IPDEF3(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strconstgetfn),0,PMFLAG_r|\ + PMFLAG_SPECIAL,(vptr)B,NULL,NULL} + IPDEF3("HOSTTYPE",HOSTTYPE), + IPDEF3("VERSION",VERSIONSTR), + +#define IPDEF4(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(intvargetfn),10,\ + PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL} + IPDEF4("!",&lastpid), + IPDEF4("$",&mypid), + IPDEF4("?",&lastval), + IPDEF4("status",&lastval), + IPDEF4("LINENO",&lineno), + IPDEF4("PPID",&ppid), + +#define IPDEF5(A,B) {NULL,0,A,NULL,IFN(intvarsetfn),IFN(intvargetfn),10,\ + PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL} + IPDEF5("BAUD",&baud), + IPDEF5("COLUMNS",&columns), + IPDEF5("DIRSTACKSIZE",&dirstacksize), + IPDEF5("LINES",&lines), + IPDEF5("LISTMAX",&listmax), + IPDEF5("LOGCHECK",&logcheck), + IPDEF5("MAILCHECK",&mailcheck), + IPDEF5("OPTIND",&zoptind), + IPDEF5("PERIOD",&period), + IPDEF5("REPORTTIME",&reporttime), + IPDEF5("SAVEHIST",&savehist), + IPDEF5("SHLVL",&shlvl), + IPDEF5("TMOUT",&tmout), + +#define IPDEF6(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strvargetfn),0,\ + PMFLAG_r|PMFLAG_SPECIAL,(vptr)B,NULL,NULL} + IPDEF6("LOGNAME",&logname), + IPDEF6("PWD",&pwd), + IPDEF6("TTY",&ttystrname), + IPDEF6("USERNAME",&username), + +#define IPDEF7(A,B) {NULL,0,A,NULL,IFN(strvarsetfn),IFN(strvargetfn),0,\ + PMFLAG_SPECIAL,(vptr)B,NULL,NULL} + IPDEF7("FCEDIT",&fceditparam), + IPDEF7("HOST",&hostnam), + IPDEF7("OLDPWD",&oldpwd), + IPDEF7("OPTARG",&optarg), + IPDEF7("MAIL",&mailfile), + IPDEF7("NULLCMD",&nullcmd), + IPDEF7("POSTEDIT",&postedit), + IPDEF7("prompt",&prompt), + IPDEF7("PROMPT",&prompt), + IPDEF7("PROMPT2",&prompt2), + IPDEF7("PROMPT3",&prompt3), + IPDEF7("PROMPT4",&prompt4), + IPDEF7("READNULLCMD",&readnullcmd), + IPDEF7("RPROMPT",&rprompt), + IPDEF7("PS1",&prompt), + IPDEF7("PS2",&prompt2), + IPDEF7("PS3",&prompt3), + IPDEF7("PS4",&prompt4), + IPDEF7("RPS1",&rprompt), + IPDEF7("SPROMPT",&sprompt), + IPDEF7("TIMEFMT",&timefmt), + IPDEF7("TMPPREFIX",&tmpprefix), + IPDEF7("WATCHFMT",&watchfmt), + IPDEF7("0",&argzero), + +#define IPDEF8(A,B,C) {NULL,0,A,NULL,IFN(colonarrsetfn),IFN(colonarrgetfn),0,\ + PMFLAG_SPECIAL,(vptr)C,NULL,B} + IPDEF8("CDPATH","cdpath",&cdpath), + IPDEF8("FIGNORE","fignore",&fignore), + IPDEF8("FPATH","fpath",&fpath), + IPDEF8("MAILPATH","mailpath",&mailpath), + IPDEF8("MANPATH","manpath",&manpath), + IPDEF8("WATCH","watch",&watch), + IPDEF8("HOSTS","hosts",&hosts), + IPDEF8("PATH",NULL,NULL), + +#define IPDEF9(A,B,C) {NULL,0,A,NULL,IFN(arrvarsetfn),IFN(arrvargetfn),0,\ + PMFLAG_A|PMFLAG_SPECIAL|C,(vptr)B,NULL,NULL} + IPDEF9("cdpath",&cdpath,0), + IPDEF9("fignore",&fignore,0), + IPDEF9("fpath",&fpath,0), + IPDEF9("mailpath",&mailpath,0), + IPDEF9("manpath",&manpath,0), + IPDEF9("watch",&watch,0), + IPDEF9("hosts",&hosts,0), + IPDEF9("signals",&sigptr,PMFLAG_r), + IPDEF9("argv",&pparams,0), + IPDEF9("*",&pparams,0), + IPDEF9("@",&pparams,0), + +#define IPDEF10(A,C,D) {NULL,0,A,NULL,IFN(D),IFN(C),0,\ + PMFLAG_A|PMFLAG_SPECIAL,NULL,NULL,NULL} + IPDEF10("path",pathgetfn,pathsetfn), + IPDEF10("hostcmds",nullgetfn,hostcmdssetfn), + IPDEF10("optcmds",nullgetfn,optcmdssetfn), + IPDEF10("bindcmds",nullgetfn,bindcmdssetfn), + IPDEF10("varcmds",nullgetfn,varcmdssetfn), + {NULL,} + }; +struct iparam *ip; + + for (ip = pinit; ip->nam; ip++) addhperm(ip->nam,ip,paramtab,NULL); + argvparam = gethnode("argv",paramtab); +} + +static int unsetflag; + +struct param *createparam(name,value,flags) /**/ +char *name;vptr value;int flags; +{ +struct param *pm; +char buf[20]; + + pm = zcalloc(sizeof *pm); + if (isset(ALLEXPORT)) + flags |= PMFLAG_x; + pm->flags = flags; + if ((flags & PMTYPE) == PMFLAG_s) { + pm->u.str = value; + pm->sets.cfn = strsetfn; + pm->gets.cfn = strgetfn; + } else if ((flags & PMTYPE) == PMFLAG_A) { + pm->u.arr = value; + pm->sets.afn = arrsetfn; + pm->gets.afn = arrgetfn; + } else { + pm->u.val = (value) ? matheval(value) : 0; + pm->sets.ifn = intsetfn; + pm->gets.ifn = intgetfn; + sprintf(buf,"%ld",pm->u.val); + value = buf; + } + if (flags & PMFLAG_x) + pm->env = addenv(name,value); + addhnode(ztrdup(name),pm,paramtab,freepm); + return pm; +} + +int isident(s) /**/ +char *s; +{ +char *ss; + + for (ss = s; *ss; ss++) if (!iident(*ss)) break; + if (!*ss || *ss == '[') return 1; + if (*s == Quest) + *s = '?'; + else if (*s == Pound) + *s = '#'; + else if (*s == String || *s == Qstring) + *s = '$'; + else if (*s == Star) + *s = '*'; + if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' || + *s == '!' || *s == '@' || *s == '*') + return 1; + return 0; +} + +Value getvalue(pptr,bracks) /**/ +char **pptr;int bracks; +{ +char *s = *pptr,*t = *pptr; +char sav; +Value v; + + if (idigit(*s)) while (idigit(*s)) s++; + else if (iident(*s)) while (iident(*s)) s++; + else if (*s == Quest) *s++ = '?'; + else if (*s == Pound) *s++ = '#'; + else if (*s == String) *s++ = '$'; + else if (*s == Qstring) *s++ = '$'; + else if (*s == Star) *s++ = '*'; + else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || + *s == '_' || *s == '!' || *s == '@' || *s == '*') s++; + else return NULL; + if (sav = *s) *s = '\0'; + if (idigit(*t) && *t != '0') { + v = (Value) hcalloc(sizeof *v); + v->pm = argvparam; + v->a = v->b = atoi(t)-1; + if (sav) + *s = sav; + } else { + struct param *pm; + int isvarat = !strcmp(t, "@"); + + pm = gethnode(t,paramtab); + if (sav) + *s = sav; + *pptr = s; + if (!pm) + return NULL; + v = hcalloc(sizeof *v); + if (pmtype(pm) == PMFLAG_A) + v->isarr = isvarat ? -1 : 1; + v->pm = pm; + v->a = 0; v->b = -1; + if (bracks && (*s == '[' || *s == Inbrack)) { + int a,b; + char *olds = s,*t; + + *s++ = '['; + for (t = s; *t && *t != ']' && *t != Outbrack; t++) + if (itok(*t)) + *t = ztokens[*t-Pound]; + if (*t == Outbrack) + *t = ']'; + if ((s[0] == '*' || s[0] == '@') && s[1] == ']') { + if (v->isarr) v->isarr = (s[0] == '*') ? 1 : -1; + v->a = 0; + v->b = -1; + s += 2; + } else { + a = mathevalarg(s,&s); + if (a > 0) a--; + if (*s == ',' || *s == Comma) { + s++; + b = mathevalarg(s,&s); + if (b > 0) b--; + } else + b = a; + if (*s == ']') { + s++; + if (v->isarr && a == b) + v->isarr = 0; + v->a = a; + v->b = b; + } else + s = olds; + } + } + } + if (!bracks && *s) + return NULL; + *pptr = s; + return v; +} + +char *getstrvalue(v) /**/ +Value v; +{ +char *s,**ss; +static char buf[20]; + + if (!v) + return ""; + if (pmtype(v->pm) != PMFLAG_A) { + if ((pmtype(v->pm) == PMFLAG_i)) + convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct); + else + s = v->pm->gets.cfn(v->pm); + if (v->a == 0 && v->b == -1) return s; + if (v->a < 0) v->a += strlen(s); + if (v->b < 0) v->b += strlen(s); + s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a); + if (v->b < v->a) s[0] = '\0'; + else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0'; + return s; + } + if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm)); + + ss = v->pm->gets.afn(v->pm); + if (v->a < 0) v->a += arrlen(ss); + s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a]; + return s; +} + +char **getarrvalue(v) /**/ +Value v; +{ +char **s; +static char *nular[] = { "", NULL }; + + if (!v) + return arrdup(nular); + s = v->pm->gets.afn(v->pm); + if (v->a == 0 && v->b == -1) return s; + if (v->a < 0) v->a += arrlen(s); + if (v->b < 0) v->b += arrlen(s); + if (v->a > arrlen(s) || v->a < 0) + s = arrdup(nular); + else + s = arrdup(s)+v->a; + if (v->b < v->a) s[0] = NULL; + else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL; + return s; +} + +long getintvalue(v) /**/ +Value v; +{ +char **ss; + + if (!v || v->isarr) + return 0; + if (pmtype(v->pm) != PMFLAG_A) { + if (pmtype(v->pm) == PMFLAG_i) + return v->pm->gets.ifn(v->pm); + return atol(v->pm->gets.cfn(v->pm)); + } + ss = v->pm->gets.afn(v->pm); + if (v->a < 0) v->a += arrlen(ss); + if (v->a < 0 || v->a > arrlen(ss)) return 0; + return atol(ss[v->a]); +} + +void setstrvalue(v,val) /**/ +Value v;char *val; +{ +char *s; + + if (v->pm->flags & PMFLAG_r) { + free(val); + return; + } + if ((s = v->pm->env) && val) + v->pm->env = replenv(v->pm->env,val); + switch (pmtype(v->pm)) { + case PMFLAG_s: + if (v->a == 0 && v->b == -1) + (v->pm->sets.cfn)(v->pm,val); + else { + char *z,*y,*x; + + z = strdup((v->pm->gets.cfn)(v->pm)); + if (v->a < 0) { + v->a += strlen(z); + if (v->a < 0) v->a = 0; + } + if (v->a > strlen(z)) v->a = strlen(z); + if (v->b < 0) v->b += strlen(z); + if (v->b < v->a) v->b = v->a; + z[v->a] = '\0'; + y = z+v->b+1; + x = zalloc(strlen(z)+strlen(y)+strlen(val)+1); + strcpy(x,z); + strcat(x,val); + strcat(x,y); + (v->pm->sets.cfn)(v->pm,x); + } + if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct) + v->pm->ct = strlen(val); + break; + case PMFLAG_i: + (v->pm->sets.ifn)(v->pm,matheval(val)); + if (!v->pm->ct && lastbase != 1) + v->pm->ct = lastbase; + free(val); + break; + case PMFLAG_A: + if (v->a != v->b) + zerr("illegal array assignment",NULL,0); + else { + char **ss = (v->pm->gets.afn)(v->pm); + int ac,ad,t0; + + ac = arrlen(ss); + if (v->a < 0) { + v->a += ac; + if (v->a < 0) v->a = 0; + } + if (v->a >= ac) { + char **st = ss; + + ad = v->a+1; + ss = zalloc((ad+1)*sizeof *ss); + memcpy(ss,st,(ad+1)*sizeof *ss); + for (t0 = 0; t0 != ac; t0++) + ss[t0] = ztrdup(ss[t0]); + while (ac < ad) + ss[ac++] = ztrdup(""); + ss[ac] = NULL; + } + if (ss[v->a]) free(ss[v->a]); + ss[v->a] = val; + (v->pm->sets.afn)(v->pm,ss); + } + break; + } +} + +void setintvalue(v,val) /**/ +Value v;long val; +{ +char buf[20]; + + if (v->pm->flags & PMFLAG_r) + return; + if (v->pm->env) { + sprintf(buf,"%ld",val); + v->pm->env = replenv(v->pm->env,buf); + } + switch (pmtype(v->pm)) + { + case PMFLAG_s: + sprintf(buf,"%ld",val); + (v->pm->sets.cfn)(v->pm,ztrdup(buf)); + break; + case PMFLAG_i: + (v->pm->sets.ifn)(v->pm,val); + if (!v->pm->ct && lastbase != -1) + v->pm->ct = lastbase; + break; + case PMFLAG_A: + zerr("attempt to assign integer to array",NULL,0); + break; + } +} + +void setintenv(s,val) /**/ +char *s; long val; +{ +Param pm; +char buf[20]; + + if ((pm = gethnode(s,paramtab)) && pm->env) { + sprintf(buf,"%ld",val); + pm->env = replenv(pm->env,buf); + } +} + +void setarrvalue(v,val) /**/ +Value v;char **val; +{ + if (v->pm->flags & PMFLAG_r) + return; + if (pmtype(v->pm) != PMFLAG_A) + { + zerr("attempt to assign array value to non-array",NULL,0); + return; + } + (v->pm->sets.afn)(v->pm,val); +} + +char *getsparamval(s,l) /**/ +char *s;int l; +{ +char sav,*t = s; +Value v; + + if (sav = t[l]) + t[l] = '\0'; + if (!(v = getvalue(&s,0))) + return NULL; + t[l] = sav; + t = getstrvalue(v); + return t; +} + +long getiparam(s) /**/ +char *s; +{ +Value v; + + if (!(v = getvalue(&s,0))) + return 0; + return getintvalue(v); +} + +char *getsparam(s) /**/ +char *s; +{ +Value v; + + if (!(v = getvalue(&s,0))) + return NULL; + return getstrvalue(v); +} + +char **getaparam(s) /**/ +char *s; +{ +Value v; + + if (!(v = getvalue(&s,0))) return NULL; + return getarrvalue(v); +} + +Param setsparam(s,val) /**/ +char *s;char *val; +{ +Value v; +char *t = s; + + if (!isident(s)) { + zerr("not an identifier: %s",s,0); + free(val); + return NULL; + } + if (!(v = getvalue(&s,1)) || *s) + return createparam(t,val,PMFLAG_s); + if ((v->pm->flags & PMTYPE) != PMFLAG_s && + !(v->pm->flags & PMFLAG_SPECIAL)) { + unsetparam(s); + return createparam(t,val,PMFLAG_s); + } + setstrvalue(v,val); + return v->pm; +} + +Param setaparam(s,val) /**/ +char *s;char **val; +{ +Value v; +char *t = s; + + if (!isident(s)) + { + zerr("not an identifier: %s",s,0); + return NULL; + } + if (!(v = getvalue(&s,1)) || *s) + return createparam(t,val,PMFLAG_A); + if ((v->pm->flags & PMTYPE) != PMFLAG_A && + !(v->pm->flags & PMFLAG_SPECIAL)) { + unsetparam(s); + return createparam(t,val,PMFLAG_A); + } + setarrvalue(v,val); + return v->pm; +} + +Param setiparam(s,val) /**/ +char *s;long val; +{ +Value v; +char *t = s; +Param pm; + + if (!isident(s)) + { + zerr("not an identifier: %s",s,0); + return NULL; + } + if (!(v = getvalue(&s,0))) + { + pm = createparam(t,NULL,PMFLAG_i); + pm->u.val = val; + return pm; + } + setintvalue(v,val); + return v->pm; +} + +void unsetparam(s) /**/ +char *s; +{ +Param pm; + + if (!(pm = gethnode(s,paramtab))) + return; + if (pm->flags & PMFLAG_r) + return; + unsetflag = 1; + switch (pmtype(pm)) + { + case 0: + (pm->sets.cfn)(pm,ztrdup("")); + break; + case PMFLAG_i: + (pm->sets.ifn)(pm,0); + break; + case PMFLAG_A: + (pm->sets.afn)(pm,mkarray(NULL)); + break; + } + if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x)) { + delenv(pm->env); + free(pm->env); + } + if (!(pm->flags & PMFLAG_SPECIAL)) + freepm(remhnode(s,paramtab)); + unsetflag = 0; +} + +void intsetfn(pm,x) /**/ +Param pm;long x; +{ + pm->u.val = x; +} + +long intgetfn(pm) /**/ +Param pm; +{ + return pm->u.val; +} + +void strsetfn(pm,x) /**/ +Param pm;char *x; +{ + if (x) + { + if (pm->u.str) + free(pm->u.str); + pm->u.str = x; + } +} + +char *strgetfn(pm) /**/ +Param pm; +{ + return pm->u.str; +} + +void nullsetfn(pm,x) /**/ +Param pm; char *x; +{ + free(x); +} + +void arrsetfn(pm,x) /**/ +Param pm;char **x; +{ +int ct; + + if (x) + { + if (pm->u.arr && pm->u.arr != x) + freearray(pm->u.arr); + pm->u.arr = x; + for (ct = 0; *x; x++,ct++); + pm->ct = ct; + } +} + +char **arrgetfn(pm) /**/ +Param pm; +{ + return pm->u.arr; +} + +void intvarsetfn(pm,x) /**/ +Param pm;long x; +{ + *((long *) pm->data) = x; +} + +long intvargetfn(pm) /**/ +Param pm; +{ + return *((long *) pm->data); +} + +void strvarsetfn(pm,x) /**/ +Param pm;char *x; +{ +char **q = ((char **) pm->data); + + if (*q) free(*q); + *q = x; +} + +void strvarnonullsetfn(pm,x) /**/ +Param pm;char *x; +{ +char **q = ((char **) pm->data); + + if (*q) free(*q); + *q = (x) ? x : ztrdup(""); +} + +char *strvargetfn(pm) /**/ +Param pm; +{ +char *s; + + s = *((char **) pm->data); + if (!s) return ""; + return s; +} + +char *strconstgetfn(pm) /**/ +Param pm; +{ + return (char *) pm->data; +} + +void colonarrsetfn(pm,x) /**/ +Param pm;char *x; +{ +char **s,**t,*u,*up; + + s = colonsplit(x); + free(x); + if (pm->data != &fignore) + for (t = s; *t; t++) { + u = *t; + if (*u == '~') *u = Tilde; + if (*u == '=') *u = Equals; + up = hcalloc(strlen(u)+1); + strcpy(up,u); + u = up; + filesub(&u); + if (!*u) u = "."; + *t = ztrdup(u); + } + if (pm->data) { + freearray(*((char ***) pm->data)); + *((char ***) pm->data) = s; + if (pm->ename) + arrfixenv(pm->ename,s); + } else { + freearray(path); + path = s; + newcmdnamtab(); + arrfixenv("PATH",s); + } +} + +char *colonarrgetfn(pm) /**/ +Param pm; +{ + if ((char **) pm->data) + return colonjoin(*(char ***) pm->data); + else + return colonjoin(path); +} + +char **arrvargetfn(pm) /**/ +Param pm; +{ + return *((char ***) pm->data); +} + +void arrvarsetfn(pm,x) /**/ +Param pm;char **x; +{ + if ((*(char ***) pm->data) != x) + freearray(*(char ***) pm->data); + *((char ***) pm->data) = x; + if (pm->ename) + arrfixenv(pm->ename,x); +} + +char **pathgetfn(pm) /**/ +Param pm; +{ + return path; +} + +void pathsetfn(pm,x) /**/ +Param pm;char **x; +{ + if (path != x) freearray(path); + path = x; + newcmdnamtab(); + arrfixenv("PATH",x); +} + +void hostcmdssetfn(pm,x) /**/ +Param pm;char **x; +{ + compctl_process(x,CC_HOSTS|CC_FILES,NULL); + freearray(x); +} + +void optcmdssetfn(pm,x) /**/ +Param pm;char **x; +{ + compctl_process(x,CC_OPTIONS,NULL); + freearray(x); +} + +void bindcmdssetfn(pm,x) /**/ +Param pm;char **x; +{ + compctl_process(x,CC_BINDINGS,NULL); + freearray(x); +} + +void varcmdssetfn(pm,x) /**/ +Param pm;char **x; +{ + compctl_process(x,CC_VARS,NULL); + freearray(x); +} + +char **nullgetfn(pm) /**/ +Param pm; +{ +static char *nl = NULL; return &nl; +} + +void unsettablesetfn(pm,x) /**/ +Param pm;char *x; +{ ; } + +long poundgetfn(pm) /**/ +Param pm; +{ + return arrlen(pparams); +} + +long randomgetfn(pm) /**/ +Param pm; +{ + return rand() & 0x7fff; +} + +void randomsetfn(pm,v) /**/ +Param pm;long v; +{ + srand((unsigned int) v); +} + +long secondsgetfn(pm) /**/ +Param pm; +{ + return time(NULL)-shtimer; +} + +void secondssetfn(pm,x) /**/ +Param pm;long x; +{ + shtimer = time(NULL)-x; +} + +long uidgetfn(pm) /**/ +Param pm; +{ + return getuid(); +} + +long gidgetfn(pm) /**/ +Param pm; +{ + return getegid(); +} + +char *usernamegetfn(pm) /**/ +Param pm; +{ +struct passwd *pwd; + + pwd = getpwuid(getuid()); + return pwd->pw_name; +} + +char *hostgetfn(pm) /**/ +Param pm; +{ +static char hostnam[65]; +static int got = 0; + + if (!got) + { + gethostname(hostnam,64); + hostnam[64] = '\0'; + got = 1; + } + return hostnam; +} + +char *ifsgetfn(pm) /**/ +Param pm; +{ + return ifs; +} + +void ifssetfn(pm,x) /**/ +Param pm;char *x; +{ + if (x) { free(ifs); ifs = x; } + inittyptab(); +} + +void histsizesetfn(pm,v) /**/ +Param pm;long v; +{ + if ((histsiz = v) <= 2) histsiz = 2; + resizehistents(); +} + +long histsizegetfn(pm) /**/ +Param pm; +{ + return histsiz; +} + +void lithistsizesetfn(pm,v) /**/ +Param pm;long v; +{ + if ((lithistsiz = v) <= 2) lithistsiz = 2; + resizehistents(); +} + +long lithistsizegetfn(pm) /**/ +Param pm; +{ + return lithistsiz; +} + +void mailchecksetfn(pm,x) /**/ +Param pm;long x; +{ + mailcheck = (unsetflag) ? 600 : x; +} + +void pathasetfn(pm,x) /**/ +Param pm;char **x; +{ + freearray(path); + path = x; + newcmdnamtab(); +} + +char **pathagetfn(pm) /**/ +Param pm; +{ + return path; +} + +long errnogetfn(pm) /**/ +Param pm; +{ + return errno; +} + +char *dashgetfn(pm) /**/ +Param pm; +{ +static char buf[100]; +char *val = buf; +int t0; + + for (val = buf, t0 = ' ';t0 <= 'z'; t0++) + if (opts[t0] == OPT_SET) + *val++ = t0; + *val = '\0'; + return buf; +} + +void histcharssetfn(pm,x) /**/ +Param pm;char *x; +{ + if (x) { + bangchar = x[0]; + hatchar = (bangchar) ? x[1] : '\0'; + hashchar = (hatchar) ? x[2] : '\0'; + free(x); + } +} + +char *histcharsgetfn(pm) /**/ +Param pm; +{ +static char buf[4]; + + buf[0] = bangchar; + buf[1] = hatchar; + buf[2] = hashchar; + buf[3] = '\0'; + return buf; +} + +char *homegetfn(pm) /**/ +Param pm; +{ + return home; +} + +void homesetfn(pm,x) /**/ +Param pm;char *x; +{ + free(home); + if (isset(CHASELINKS) && (home = xsymlink(x))) free(x); + else home = x; +} + +char *wordcharsgetfn(pm) /**/ +Param pm; +{ + return wordchars; +} + +void wordcharssetfn(pm,x) /**/ +Param pm;char *x; +{ + free(wordchars); + if (x) wordchars = x; + else wordchars = ztrdup(DEFWORDCHARS); + inittyptab(); +} + +char *underscoregetfn(pm) /**/ +Param pm; +{ +char *s,*t; + + if (!(s = qgetevent(curhist-1))) + return ""; + for (t = s+strlen(s); t > s; t--) + if (*t == HISTSPACE) + break; + if (t != s) + t++; + return t; +} + +char *termgetfn(pm) /**/ +Param pm; +{ + return term; +} + +void termsetfn(pm,x) /**/ +Param pm;char *x; +{ + if (term) free(term); + term = x; + if (!interact || unset(USEZLE)) + return; + if (tgetent(termbuf,term) != 1) + { + zerr("can't find termcap info for %s",term,0); + errflag = 0; + termok = 0; + } + else + { + char tbuf[1024],*pp; + int t0; + + termok = 1; + for (t0 = 0; t0 != TC_COUNT; t0++) + { + pp = tbuf; + if (tcstr[t0]) + free(tcstr[t0]); + if (!tgetstr(tccapnams[t0],&pp)) + tcstr[t0] = NULL, tclen[t0] = 0; + else + { + tcstr[t0] = zalloc(tclen[t0] = pp-tbuf); + memcpy(tcstr[t0],tbuf,tclen[t0]); + } + } + +/* if there's no termcap entry for cursor left, use \b. */ + + if (!tccan(TCLEFT)) + { + tcstr[TCLEFT] = ztrdup("\b"); + tclen[TCLEFT] = 1; + } + +/* if there's no termcap entry for clear, use ^L. */ + + if (!tccan(TCCLEARSCREEN)) + { + tcstr[TCCLEARSCREEN] = ztrdup("\14"); + tclen[TCCLEARSCREEN] = 1; + } + +/* if the termcap entry for down is \n, don't use it. */ + + if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') + { + tclen[TCDOWN] = 0; + free(tcstr[TCDOWN]); + tcstr[TCDOWN] = NULL; + } + +/* if there's no termcap entry for cursor up, forget it. + Use single line mode. */ + + if (!tccan(TCUP)) + termok = 0; + } +} + +void setparams() /**/ +{ +char **envp,**envp2,**envp3,*str; +char buf[50]; +struct param *pm; +int ct; + + noerrs = 1; + for (envp = environ, ct = 2; *envp; envp++,ct++); + envp = environ; + envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct); + for (; *envp; envp++) + *envp2++ = ztrdup(*envp); + *envp2 = NULL; + envp = environ; + environ = envp2 = envp3; + for (; *envp; envp++,envp2++) { + for (str = *envp; *str && *str != '='; str++); + if (*str == '=') { + char *iname; + + *str = '\0'; + if (isident(*envp)) + pm = setsparam(iname = *envp,ztrdup(str+1)); + if (pm) { + pm->flags |= PMFLAG_x; + pm->env = *envp2; + if (pm->flags & PMFLAG_SPECIAL) + pm->env = replenv(pm->env,getsparam(iname)); + } + *str = '='; + } + } + pm = gethnode("HOME",paramtab); + if (!(pm->flags & PMFLAG_x)) { + pm->flags |= PMFLAG_x; + pm->env = addenv("HOME",home); + } + pm = gethnode("PWD",paramtab); + if (!(pm->flags & PMFLAG_x)) { + pm->flags |= PMFLAG_x; + pm->env = addenv("PWD",pwd); + } + pm = gethnode("LOGNAME",paramtab); + if (!(pm->flags & PMFLAG_x)) { + pm->flags |= PMFLAG_x; + pm->env = addenv("LOGNAME",logname); + } + pm = gethnode("SHLVL",paramtab); + if (!(pm->flags & PMFLAG_x)) + pm->flags |= PMFLAG_x; + sprintf(buf,"%d",++shlvl); + pm->env = addenv("SHLVL",buf); + noerrs = 0; +} + +char *mkenvstr(x,y) /**/ +char *x;char *y; +{ +char *z; +int xl = strlen(x),yl = strlen(y); + + z = zalloc(xl+yl+2); + strcpy(z,x); + z[xl] = '='; + strcpy(z+xl+1,y); + z[xl+yl+1] = '\0'; + return z; +} + +void arrfixenv(s,t) /**/ +char *s;char **t; +{ +char **ep; +int sl = strlen(s); + + for (ep = environ; *ep; ep++) + if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=') { + char *u = colonjoin(t); + replenv(*ep,u); + break; + } +} + +char *replenv(e,value) /**/ +char *e;char *value; +{ +char **ep; + + for (ep = environ; *ep; ep++) + if (*ep == e) + { + char *s = e; + + while (*s++ != '='); + *s = '\0'; + *ep = zalloc(strlen(e)+strlen(value)+2); + strcpy(*ep,e); + strcat(*ep,value); + free(e); + return *ep; + } + return NULL; +} + +char *addenv(name,value) /**/ +char *name;char *value; +{ +char **ep,**ep2,**ep3; +int envct; + + for (ep = environ; *ep; ep++) + { + char *s = *ep,*t = name; + + while (*s && *s == *t) s++,t++; + if (*s == '=' && !*t) + { + free(*ep); + return *ep = mkenvstr(name,value); + } + } + envct = arrlen(environ); + ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3)); + for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++); + *ep2 = mkenvstr(name,value); + ep2[1] = NULL; + free(environ); + environ = ep; + return *ep2; +} + +void delenv(x) /**/ +char *x; +{ +char **ep; + + ep = environ; + for (; *ep; ep++) + if (*ep == x) + break; + if (*ep) + for (; ep[0] = ep[1]; ep++); +} + +void convbase(s,v,base) /**/ +char *s;long v;int base; +{ +int digs = 0; +long x; + + if (base <= 1) + base = 10; + x = v; + if (x < 0) + { + x = -x; + digs++; + } + for (; x; digs++) + x /= base; + if (!digs) + digs = 1; + s[digs--] = '\0'; + x = (v < 0) ? -v : v; + while (digs >= 0) + { + int dig = x%base; + s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A'; + x /= base; + } + if (v < 0) + s[0] = '-'; +} + + diff --git a/usr/othersrc/public/zsh-2.2/src/params.pro b/usr/othersrc/public/zsh-2.2/src/params.pro new file mode 100644 index 0000000000..e5fbdc9549 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/params.pro @@ -0,0 +1,80 @@ +void setupparams DCLPROTO((void)); +struct param *createparam DCLPROTO((char *name,vptr value,int flags)); +int isident DCLPROTO((char *s)); +Value getvalue DCLPROTO((char **pptr,int bracks)); +char *getstrvalue DCLPROTO((Value v)); +char **getarrvalue DCLPROTO((Value v)); +long getintvalue DCLPROTO((Value v)); +void setstrvalue DCLPROTO((Value v,char *val)); +void setintvalue DCLPROTO((Value v,long val)); +void setintenv DCLPROTO((char *s, long val)); +void setarrvalue DCLPROTO((Value v,char **val)); +char *getsparamval DCLPROTO((char *s,int l)); +long getiparam DCLPROTO((char *s)); +char *getsparam DCLPROTO((char *s)); +char **getaparam DCLPROTO((char *s)); +Param setsparam DCLPROTO((char *s,char *val)); +Param setaparam DCLPROTO((char *s,char **val)); +Param setiparam DCLPROTO((char *s,long val)); +void unsetparam DCLPROTO((char *s)); +void intsetfn DCLPROTO((Param pm,long x)); +long intgetfn DCLPROTO((Param pm)); +void strsetfn DCLPROTO((Param pm,char *x)); +char *strgetfn DCLPROTO((Param pm)); +void nullsetfn DCLPROTO((Param pm, char *x)); +void arrsetfn DCLPROTO((Param pm,char **x)); +char **arrgetfn DCLPROTO((Param pm)); +void intvarsetfn DCLPROTO((Param pm,long x)); +long intvargetfn DCLPROTO((Param pm)); +void strvarsetfn DCLPROTO((Param pm,char *x)); +void strvarnonullsetfn DCLPROTO((Param pm,char *x)); +char *strvargetfn DCLPROTO((Param pm)); +char *strconstgetfn DCLPROTO((Param pm)); +void colonarrsetfn DCLPROTO((Param pm,char *x)); +char *colonarrgetfn DCLPROTO((Param pm)); +char **arrvargetfn DCLPROTO((Param pm)); +void arrvarsetfn DCLPROTO((Param pm,char **x)); +char **pathgetfn DCLPROTO((Param pm)); +void pathsetfn DCLPROTO((Param pm,char **x)); +void hostcmdssetfn DCLPROTO((Param pm,char **x)); +void optcmdssetfn DCLPROTO((Param pm,char **x)); +void bindcmdssetfn DCLPROTO((Param pm,char **x)); +void varcmdssetfn DCLPROTO((Param pm,char **x)); +char **nullgetfn DCLPROTO((Param pm)); +void unsettablesetfn DCLPROTO((Param pm,char *x)); +long poundgetfn DCLPROTO((Param pm)); +long randomgetfn DCLPROTO((Param pm)); +void randomsetfn DCLPROTO((Param pm,long v)); +long secondsgetfn DCLPROTO((Param pm)); +void secondssetfn DCLPROTO((Param pm,long x)); +long uidgetfn DCLPROTO((Param pm)); +long gidgetfn DCLPROTO((Param pm)); +char *usernamegetfn DCLPROTO((Param pm)); +char *hostgetfn DCLPROTO((Param pm)); +char *ifsgetfn DCLPROTO((Param pm)); +void ifssetfn DCLPROTO((Param pm,char *x)); +void histsizesetfn DCLPROTO((Param pm,long v)); +long histsizegetfn DCLPROTO((Param pm)); +void lithistsizesetfn DCLPROTO((Param pm,long v)); +long lithistsizegetfn DCLPROTO((Param pm)); +void mailchecksetfn DCLPROTO((Param pm,long x)); +void pathasetfn DCLPROTO((Param pm,char **x)); +char **pathagetfn DCLPROTO((Param pm)); +long errnogetfn DCLPROTO((Param pm)); +char *dashgetfn DCLPROTO((Param pm)); +void histcharssetfn DCLPROTO((Param pm,char *x)); +char *histcharsgetfn DCLPROTO((Param pm)); +char *homegetfn DCLPROTO((Param pm)); +void homesetfn DCLPROTO((Param pm,char *x)); +char *wordcharsgetfn DCLPROTO((Param pm)); +void wordcharssetfn DCLPROTO((Param pm,char *x)); +char *underscoregetfn DCLPROTO((Param pm)); +char *termgetfn DCLPROTO((Param pm)); +void termsetfn DCLPROTO((Param pm,char *x)); +void setparams DCLPROTO((void)); +char *mkenvstr DCLPROTO((char *x,char *y)); +void arrfixenv DCLPROTO((char *s,char **t)); +char *replenv DCLPROTO((char *e,char *value)); +char *addenv DCLPROTO((char *name,char *value)); +void delenv DCLPROTO((char *x)); +void convbase DCLPROTO((char *s,long v,int base)); diff --git a/usr/othersrc/public/zsh-2.2/src/parse.c b/usr/othersrc/public/zsh-2.2/src/parse.c new file mode 100644 index 0000000000..bd97ff635a --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/parse.c @@ -0,0 +1,960 @@ +/* + * + * parse.c - parser + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include "funcs.h" + +#define YYERROR { tok = LEXERR; return NULL; } +#define YYERRORV { tok = LEXERR; return; } + +#define make_list() allocnode(N_LIST) +#define make_sublist() allocnode(N_SUBLIST) +#define make_pline() allocnode(N_PLINE) +#define make_cmd() allocnode(N_CMD) +#define make_forcmd() allocnode(N_FOR) +#define make_casecmd() allocnode(N_CASE) +#define make_ifcmd() allocnode(N_IF) +#define make_whilecmd() allocnode(N_WHILE) +#define make_varnode() allocnode(N_VARASG) +#define make_cond() allocnode(N_COND) + +/* + * event : ENDINPUT + * | SEPER + * | sublist [ SEPER | AMPER ] + */ +List parse_event() /**/ +{ + tok = ENDINPUT; + incmdpos = 1; + yylex(); + return par_event(); +} + +List par_event() /**/ +{ +Sublist sl; +List l = NULL; + + while (tok == SEPER) { + if (isnewlin > 0) return NULL; + yylex(); + } + if (tok == ENDINPUT) return NULL; + if (sl = par_sublist()) + if (tok == ENDINPUT) { + l = make_list(); + l->type = SYNC; l->left = sl; + } else if (tok == SEPER) { + l = make_list(); + l->type = SYNC; l->left = sl; + if (isnewlin <= 0) yylex(); + } else if (tok == AMPER) { + l = make_list(); + l->type = ASYNC; l->left = sl; + yylex(); + } else + l = NULL; + if (!l) { + if (errflag) { yyerror(); return NULL; } + yyerror(); + errflag = 0; + if (isnewlin <= 0) { + int c; + + hwbegin(); + while ((c = hgetc()) != '\n' && !lexstop); + if (c == '\n') hungetc('\n'); + hwaddc(HISTSPACE); + hwadd(); + } + errflag = 1; + return NULL; + } else { + l->right = par_event(); + } + return l; +} + +List parse_list() /**/ +{ + tok = ENDINPUT; + incmdpos = 1; + yylex(); + return par_list(); +} + +/* + * list : { SEPER } [ sublist [ { SEPER | AMPER } list ] ] + */ +List par_list() /**/ +{ +Sublist sl; +List l = NULL; + + while (tok == SEPER) yylex(); + if (sl = par_sublist()) + if (tok == SEPER || tok == AMPER) { + l = make_list(); + l->left = sl; + l->type = (tok == SEPER) ? SYNC : ASYNC; + incmdpos = 1; + while (tok == SEPER || tok == AMPER) yylex(); + l->right = par_list(); + } else { + l = make_list(); + l->left = sl; + l->type = SYNC; + } + return l; +} + +List par_list1() /**/ +{ +Sublist sl; +List l = NULL; + + if (sl = par_sublist()) { + l = make_list(); + l->type = SYNC; + l->left = sl; + } + return l; +} + +/* + * sublist : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ] + */ +Sublist par_sublist() /**/ +{ +Sublist sl; + + if (sl = par_sublist2()) + if (tok == DBAR || tok == DAMPER) { + int qtok = tok; + yylex(); + while (tok == SEPER) yylex(); + sl->right = par_sublist(); + sl->type = (qtok == DBAR) ? ORNEXT : ANDNEXT; + } + return sl; +} + +/* + * sublist2 : [ COPROC | BANG ] pline + */ +Sublist par_sublist2() /**/ +{ +Sublist sl; +Pline p; + + sl = make_sublist(); + if (tok == COPROC) { sl->flags |= PFLAG_COPROC; yylex(); } + else if (tok == BANG) { sl->flags |= PFLAG_NOT; yylex(); } + if (!(p = par_pline()) && !sl->flags) + return NULL; + sl->left = p; + return sl; +} + +/* + * pline : cmd [ ( BAR | BARAMP ) { SEPER } pline ] + */ +Pline par_pline() /**/ +{ +Cmd c; +Pline p,p2; + + if (!(c = par_cmd())) + return NULL; + if (tok == BAR) { + yylex(); + while (tok == SEPER) yylex(); + p2 = par_pline(); + p = make_pline(); + p->left = c; p->right = p2; p->type = PIPE; + return p; + } else if (tok == BARAMP) { + struct redir *rdr = alloc(sizeof *rdr); + rdr->type = MERGE; rdr->fd1 = 2; rdr->fd2 = 1; + addnode(c->redir,rdr); + + yylex(); + p2 = par_pline(); + p = make_pline(); + p->left = c; p->right = p2; p->type = PIPE; + return p; + } else { + p = make_pline(); + p->left = c; p->type = END; + return p; + } +} + +/* + * cmd : { redir } ( for | case | if | while | repeat | + * subsh | funcdef | time | dinbrack | simple ) { redir } + */ +Cmd par_cmd() /**/ +{ +Cmd c; + + c = make_cmd(); + c->args = newlist(); + c->redir = newlist(); + c->vars = newlist(); + while (IS_REDIROP(tok)) + par_redir(c->redir); + switch (tok) { + case FOR: case FOREACH: case SELECT: par_for(c); break; + case CASE: par_case(c); break; + case IF: par_if(c); break; + case WHILE: case UNTIL: par_while(c); break; + case REPEAT: par_repeat(c); break; + case INPAR: case INBRACE: par_subsh(c); break; + case FUNC: par_funcdef(c); break; + case TIME: par_time(c); break; + case DINBRACK: par_dinbrack(c); break; + default: if (!par_simple(c)) return NULL; break; + } + while (IS_REDIROP(tok)) + par_redir(c->redir); + incmdpos = 1; + incasepat = 0; + incond = 0; + return c; +} + +/* + * for : ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR ) + { SEPER } ( DO list DONE | INBRACE list OUTBRACE | + list ZEND | list1 ) + */ +void par_for(c) /**/ +Cmd c; +{ +struct forcmd *f; +int csh = (tok == FOREACH || isset(CSHJUNKIELOOPS)); + + f = make_forcmd(); + c->type = (tok == SELECT) ? CSELECT : CFOR; + incmdpos = 0; + yylex(); + if (tok != STRING) YYERRORV; + f->name = tokstr; + incmdpos = 1; + yylex(); + if (tok == STRING && !strcmp(tokstr,"in")) { + f->inflag = 1; + incmdpos = 0; + yylex(); + c->args = par_wordlist(); + if (tok != SEPER) YYERRORV; + } else if (tok == INPAR) { + f->inflag = 1; + incmdpos = 0; + yylex(); + c->args = par_nl_wordlist(); + if (tok != OUTPAR) YYERRORV; + incmdpos = 1; + yylex(); + } + incmdpos = 1; + while (tok == SEPER) yylex(); + if (tok == DO) { + yylex(); + f->list = par_list(); + if (tok != DONE) YYERRORV; + yylex(); + } else if (tok == INBRACE) { + yylex(); + f->list = par_list(); + if (tok != OUTBRACE) YYERRORV; + yylex(); + } else if (csh) { + f->list = par_list(); + if (tok != ZEND) YYERRORV; + yylex(); + } else if (isset(NOSHORTLOOPS)) { + YYERRORV; + } else + f->list = par_list1(); + c->u.forcmd = f; +} + +/* + * case : CASE STRING { SEPER } ( "in" | INBRACE ) + { { SEPER } STRING { BAR STRING } OUTPAR list [ DSEMI ] } + { SEPER } ( "esac" | OUTBRACE ) + */ +void par_case(c) /**/ +Cmd c; +{ +struct casecmd **ccp; +int brflag; + + c->type = CCASE; + incmdpos = 0; + yylex(); + if (tok != STRING) YYERRORV; + addnode(c->args,tokstr); + incmdpos = 1; + yylex(); + while (tok == SEPER) yylex(); + if (!(tok == STRING && !strcmp(tokstr,"in")) && tok != INBRACE) YYERRORV; + brflag = (tok == INBRACE); + incasepat = 1; + incmdpos = 0; + yylex(); + ccp = &c->u.casecmd; + for (;;) { + char *str; + struct casecmd *cc; + + *ccp = cc = make_casecmd(); + while (tok == SEPER) yylex(); + if (tok == OUTBRACE) { + yylex(); + break; + } + if (tok != STRING) YYERRORV; + if (!strcmp(tokstr,"esac")) { + yylex(); + break; + } + str = tokstr; + yylex(); + while (tok == BAR) { + char *str2; + int sl = strlen(str); + + yylex(); + if (tok != STRING) YYERRORV; + str2 = alloc(sl+strlen(tokstr)+1); + strcpy(str2,str); + str2[sl] = Bar; + strcpy(str2+sl+1,tokstr); + str = str2; + yylex(); + } + if (tok != OUTPAR) YYERRORV; + incasepat = 0; + incmdpos = 1; + yylex(); + cc->pat = str; + cc->list = par_list(); + ccp = &cc->next; + if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag)) { + yylex(); + break; + } + if (tok != DSEMI) YYERRORV; + incasepat = 1; + incmdpos = 0; + yylex(); + } + *ccp = NULL; +} + +/* + * 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...?) + */ +void par_if(c) /**/ +Cmd c; +{ +struct ifcmd *i,**ip; +int xtok; + + c->type = CIF; + ip = &c->u.ifcmd; + for (;;) { + xtok = tok; + yylex(); + if (xtok == FI) + break; + while (tok == SEPER) yylex(); + if (xtok == ELSE) + break; + if (!(xtok == IF || xtok == ELIF)) YYERRORV; + *ip = i = make_ifcmd(); + ip = &i->next; + if (tok == INPAR) { + yylex(); + i->ifl = par_list(); + if (tok != OUTPAR) YYERRORV; + incmdpos = 1; + yylex(); + } else { + i->ifl = par_list(); + incmdpos = 1; + } + while (tok == SEPER) yylex(); + xtok = FI; + if (tok == THEN) { + yylex(); + i->thenl = par_list(); + incmdpos = 1; + } else if (tok == INBRACE) { + yylex(); + i->thenl = par_list(); + if (tok != OUTBRACE) YYERRORV; + yylex(); + incmdpos = 1; + if (tok == SEPER) break; + } else if (isset(NOSHORTLOOPS)) { + YYERRORV; + } else { + i->thenl = par_list1(); + incmdpos = 1; + break; + } + } + if (xtok == ELSE) { + *ip = i = make_ifcmd(); + if (tok == INBRACE) { + yylex(); + i->thenl = par_list(); + if (tok != OUTBRACE) YYERRORV; + yylex(); + } else { + i->thenl = par_list(); + if (tok != FI) YYERRORV; + yylex(); + } + } +} + +/* + * while : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER } + ( DO list DONE | INBRACE list OUTBRACE | list ZEND ) + */ +void par_while(c) /**/ +Cmd c; +{ +struct whilecmd *w; + + c->type = CWHILE; + w = c->u.whilecmd = make_whilecmd(); + w->cond = (tok == UNTIL); + yylex(); + if (tok == INPAR) { + yylex(); + w->cont = par_list(); + if (tok != OUTPAR) YYERRORV; + yylex(); + } else { + w->cont = par_list(); + } + incmdpos = 1; + while (tok == SEPER) yylex(); + if (tok == DO) { + yylex(); + w->loop = par_list(); + if (tok != DONE) YYERRORV; + yylex(); + } else if (tok == INBRACE) { + yylex(); + w->loop = par_list(); + if (tok != OUTBRACE) YYERRORV; + yylex(); + } else if (isset(CSHJUNKIELOOPS)) { + w->loop = par_list(); + if (tok != ZEND) YYERRORV; + yylex(); + } else + YYERRORV; +} + +/* + * repeat : REPEAT STRING { SEPER } ( DO list DONE | list1 ) + */ +void par_repeat(c) /**/ +Cmd c; +{ + c->type = CREPEAT; + incmdpos = 0; + yylex(); + if (tok != STRING) YYERRORV; + addnode(c->args,tokstr); + incmdpos = 1; + yylex(); + while (tok == SEPER) yylex(); + if (tok == DO) { + yylex(); + c->u.list = par_list(); + if (tok != DONE) YYERRORV; + yylex(); + } else { + c->u.list = par_list1(); + } +} + +/* + * subsh : ( INPAR | INBRACE ) list ( OUTPAR | OUTBRACE ) + */ +void par_subsh(c) /**/ +Cmd c; +{ + c->type = (tok == INPAR) ? SUBSH : CURSH; + yylex(); + c->u.list = par_list(); + if (tok != ((c->type == SUBSH) ? OUTPAR : OUTBRACE)) YYERRORV; + yylex(); +} + +/* + * funcdef : FUNCTION wordlist [ INOUTPAR ] { SEPER } + * ( list1 | INBRACE list OUTBRACE ) + */ +void par_funcdef(c) /**/ +Cmd c; +{ + nocorrect = 1; + incmdpos = 0; + yylex(); + c->type = FUNCDEF; + c->args = newlist(); + while (tok == STRING) { + if (*tokstr == Inbrace && !tokstr[1]) { tok = INBRACE; break; } + addnode(c->args,tokstr); + yylex(); + } + nocorrect = 0; + incmdpos = 1; + if (tok == INOUTPAR) yylex(); + while (tok == SEPER) yylex(); + if (tok == INBRACE) { + yylex(); + c->u.list = par_list(); + if (tok != OUTBRACE) YYERRORV; + yylex(); + } else if (isset(NOSHORTLOOPS)) { + YYERRORV; + } else + c->u.list = par_list1(); +} + +/* + * time : TIME sublist2 + */ +void par_time(c) /**/ +Cmd c; +{ + yylex(); + c->type = ZCTIME; + c->u.pline = par_sublist2(); +} + +/* + * dinbrack : DINBRACK cond DOUTBRACK + */ +void par_dinbrack(c) /**/ +Cmd c; +{ + c->type = COND; + incond = 1; + incmdpos = 0; + yylex(); + c->u.cond = par_cond(); + if (tok != DOUTBRACK) YYERRORV; + incond = 0; + incmdpos = 1; + yylex(); +} + +/* + * simple : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH } + { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir } + [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ] + */ +Cmd par_simple(c) /**/ +Cmd c; +{ +int isnull = 1; + + c->type = SIMPLE; + for (;;) { + if (tok == COMMAND) c->flags |= CFLAG_COMMAND; + else if (tok == EXEC) c->flags |= CFLAG_EXEC; + else if (tok == NOGLOB) c->flags |= CFLAG_NOGLOB; + else if (tok == NOCORRECT) nocorrect = 1; + else if (tok == DASH) c->flags = CFLAG_DASH; + else break; + yylex(); + } + if (tok == AMPER) YYERROR; + for (;;) { + if (tok == STRING) { + incmdpos = 0; + addnode(c->args,tokstr); + yylex(); + } else if (tok == ENVSTRING) { + struct varasg *v = make_varnode(); + v->type = PMFLAG_s; + equalsplit(v->name = tokstr,&v->str); + addnode(c->vars,v); + yylex(); + } else if (tok == ENVARRAY) { + struct varasg *v = make_varnode(); + int oldcmdpos = incmdpos; + v->type = PMFLAG_A; + incmdpos = 0; + v->name = tokstr; + yylex(); + v->arr = par_nl_wordlist(); + if (tok != OUTPAR) YYERROR; + incmdpos = oldcmdpos; + yylex(); + addnode(c->vars,v); + } else if (IS_REDIROP(tok)) { + par_redir(c->redir); + } else if (tok == INOUTPAR) { + incmdpos = 1; + yylex(); + while (tok == SEPER) yylex(); + if (tok == INBRACE) { + yylex(); + c->u.list = par_list(); + if (tok != OUTBRACE) YYERROR; + yylex(); + } else if (isset(NOSHORTLOOPS)) { + YYERROR; + } else + c->u.list = par_list1(); + c->type = FUNCDEF; + } else break; + isnull = 0; + } + if (isnull && !full(c->redir)) return NULL; + if (full(c->args)) { + if (underscore) + free(underscore); + underscore = ztrdup(getdata(lastnode(c->args))); + untokenize(underscore); + } + incmdpos = 1; + return c; +} + +/* + * cond : cond_1 { SEPER } [ DBAR { SEPER } cond ] + */ +Cond par_cond() /**/ +{ +Cond c,c2; + + c = par_cond_1(); + while (tok == SEPER) yylex(); + if (tok == DBAR) { + yylex(); + while (tok == SEPER) yylex(); + c2 = make_cond(); + c2->left = c; + c2->right = par_cond(); + c2->type = COND_OR; + return c2; + } + return c; +} + +/* + * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ] + */ +Cond par_cond_1() /**/ +{ +Cond c,c2; + + c = par_cond_2(); + while (tok == SEPER) yylex(); + if (tok == DAMPER) { + yylex(); + while (tok == SEPER) yylex(); + c2 = make_cond(); + c2->left = c; + c2->right = par_cond_1(); + c2->type = COND_AND; + return c2; + } + return c; +} + +/* + * cond_2 : BANG cond_2 + | INPAR { SEPER } cond_2 { SEPER } OUTPAR + | STRING STRING STRING + | STRING STRING + | STRING ( INANG | OUTANG ) STRING + */ +Cond par_cond_2() /**/ +{ +Cond c,c2; +char *s1,*s2,*s3; +int xtok; + + if (tok == BANG) { + yylex(); + c = par_cond_2(); + c2 = make_cond(); + c2->left = c; + c2->type = COND_NOT; + return c2; + } + if (tok == INPAR) { + yylex(); + while (tok == SEPER) yylex(); + c = par_cond(); + while (tok == SEPER) yylex(); + if (tok != OUTPAR) YYERROR; + yylex(); + return c; + } + if (tok != STRING) YYERROR; + s1 = tokstr; + yylex(); + xtok = tok; + if (tok == INANG || tok == OUTANG) { + yylex(); + if (tok != STRING) YYERROR; + s3 = tokstr; + yylex(); + c = make_cond(); + c->left = s1; + c->right = s3; + c->type = (xtok == INANG) ? COND_STRLT : COND_STRGTR; + c->types[0] = c->types[1] = NT_STR; + return c; + } + if (tok != STRING) YYERROR; + s2 = tokstr; + yylex(); + if (tok == STRING) { + s3 = tokstr; + yylex(); + return par_cond_triple(s1,s2,s3); + } else + return par_cond_double(s1,s2); +} + +/* + * redir : ( OUTANG | ... | TRINANG ) STRING + */ +void par_redir(l) /**/ +Lklist l; +{ +char *toks; +struct redir *fn = allocnode(N_REDIR); +int mergerror = 0; +int oldcmdpos,oldnc; + + oldcmdpos = incmdpos; + incmdpos = 0; + oldnc = nocorrect; + if (tok != INANG) nocorrect = 1; + fn->type = redirtab[tok-OUTANG]; + fn->fd1 = tokfd; + yylex(); + if (tok != STRING && tok != ENVSTRING) YYERRORV; + toks = tokstr; + incmdpos = oldcmdpos; + nocorrect = oldnc; + yylex(); + +/* assign default fd */ + + if (fn->fd1 == -1) + fn->fd1 = IS_READFD(fn->type) ? 0 : 1; + +/* > >(...) or < <(...) */ + + if ((*toks == Inang || *toks == Outang) && toks[1] == Inpar) { + if ((fn->type & ~1) == WRITE) fn->type = OUTPIPE; + else if (fn->type == READ) fn->type = INPIPE; + else YYERRORV; + fn->name = toks; + +/* <<[-] name */ + + } else if (fn->type == HEREDOC || fn->type == HEREDOCDASH) { + char tbuf[256], *tlin; + int tsiz = 0, l; + /* Save the rest of the current line for later tokenization */ + if (!isnewlin) { + while (hgets(tbuf, 256) != NULL) { + l = strlen(tbuf); + if (tsiz == 0) { + tlin = ztrdup(tbuf); /* Test for failure? */ + tsiz = l; + } else { + tlin = realloc(tlin,tsiz+l+1); /* Test for failure? */ + strcpy(&tlin[tsiz], tbuf); + tsiz += l; + } + if (tbuf[l-1] == '\n') break; + } + } + /* Now grab the document */ + fn->name = gethere(toks,fn->type); + fn->type = HERESTR; + /* Put back the saved line to resume tokenizing */ + if (tsiz > 0) { + hungets(tlin); + free(tlin); + } + +/* >& name or >>& name */ + + } else if (IS_ERROR_REDIR(fn->type) && getfdstr(toks) == FD_WORD) { + mergerror = 1; + fn->name = toks; + fn->type = UN_ERROR_REDIR(fn->type); + +/* >>& and >>&! are only valid with a name after them */ + + } else if (fn->type == ERRAPP || fn->type == ERRAPPNOW) { + YYERRORV; + +/* >& # */ + + } else if (fn->type == MERGE || fn->type == MERGEOUT) { + fn->fd2 = getfdstr(toks); + if (fn->fd2 == FD_CLOSE) fn->type = CLOSE; + else if (fn->fd2 == FD_WORD) fn->fd2 = (fn->type==MERGEOUT) ? 1 : 0; + } else + fn->name = toks; + addnode(l,fn); + if (mergerror) + { + struct redir *fe = allocnode(N_REDIR); + + fe->fd1 = 2; + fe->fd2 = fn->fd1; + fe->type = MERGEOUT; + addnode(l,fe); + } +} + +/* + * wordlist : { STRING } + */ +Lklist par_wordlist() /**/ +{ +Lklist l; + + l = newlist(); + while (tok == STRING) { + addnode(l,tokstr); + yylex(); + } + return l; +} + +/* + * nl_wordlist : { STRING | SEPER } + */ +Lklist par_nl_wordlist() /**/ +{ +Lklist l; + + l = newlist(); + while (tok == STRING || tok == SEPER) { + if (tok != SEPER) + addnode(l,tokstr); + yylex(); + } + return l; +} + +/* get fd associated with str */ + +int getfdstr(s) /**/ +char *s; +{ + if (s[1]) return FD_WORD; + if (idigit(*s)) return *s-'0'; + if (*s == 'p') return FD_COPROC; + if (*s == '-') return FD_CLOSE; + return FD_WORD; +} + +Cond par_cond_double(a,b) /**/ +char *a;char *b; +{ +Cond n = make_cond(); + + if (a[0] != '-' || !a[1] || a[2]) + { + zerr("parse error: condition expected: %s",a,0); + return NULL; + } + n->left = b; + n->type = a[1]; + n->types[0] = n->types[1] = NT_STR; + return n; +} + +Cond par_cond_triple(a,b,c) /**/ +char *a;char *b;char *c; +{ +Cond n = make_cond(); +static char *condstrs[] = { + "nt","ot","ef","eq","ne","lt","gt","le","ge",NULL + }; +int t0; + + if ((b[0] == Equals || b[0] == '=') && !b[1]) + n->type = COND_STREQ; + else if (b[0] == '!' && b[1] == '=' && !b[2]) + n->type = COND_STRNEQ; + else if (b[0] == '-') + { + for (t0 = 0; condstrs[t0]; t0++) + if (!strcmp(condstrs[t0],b+1)) + break; + if (condstrs[t0]) + n->type = t0+COND_NT; + else + zerr("unrecognized condition: %s",b,0); + } + else + zerr("condition expected: %s",b,0); + n->left = a; + n->right = c; + n->types[0] = n->types[1] = NT_STR; + return n; +} + +void yyerror() /**/ +{ +int t0; + + for (t0 = 0; t0 != 20; t0++) + if (!yytext[t0] || yytext[t0] == '\n' || yytext[t0] == HISTSPACE) + break; + if (t0 == 20) + zerr("parse error near `%l...'",yytext,20); + else if (t0) + zerr("parse error near `%l'",yytext,t0); + else + zerr("parse error",NULL,0); +} + diff --git a/usr/othersrc/public/zsh-2.2/src/parse.pro b/usr/othersrc/public/zsh-2.2/src/parse.pro new file mode 100644 index 0000000000..8837fa27ff --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/parse.pro @@ -0,0 +1,29 @@ +List parse_event DCLPROTO((void)); +List par_event DCLPROTO((void)); +List parse_list DCLPROTO((void)); +List par_list DCLPROTO((void)); +List par_list1 DCLPROTO((void)); +Sublist par_sublist DCLPROTO((void)); +Sublist par_sublist2 DCLPROTO((void)); +Pline par_pline DCLPROTO((void)); +Cmd par_cmd DCLPROTO((void)); +void par_for DCLPROTO((Cmd c)); +void par_case DCLPROTO((Cmd c)); +void par_if DCLPROTO((Cmd c)); +void par_while DCLPROTO((Cmd c)); +void par_repeat DCLPROTO((Cmd c)); +void par_subsh DCLPROTO((Cmd c)); +void par_funcdef DCLPROTO((Cmd c)); +void par_time DCLPROTO((Cmd c)); +void par_dinbrack DCLPROTO((Cmd c)); +Cmd par_simple DCLPROTO((Cmd c)); +Cond par_cond DCLPROTO((void)); +Cond par_cond_1 DCLPROTO((void)); +Cond par_cond_2 DCLPROTO((void)); +void par_redir DCLPROTO((Lklist l)); +Lklist par_wordlist DCLPROTO((void)); +Lklist par_nl_wordlist DCLPROTO((void)); +int getfdstr DCLPROTO((char *s)); +Cond par_cond_double DCLPROTO((char *a,char *b)); +Cond par_cond_triple DCLPROTO((char *a,char *b,char *c)); +void yyerror DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/signals.h.sample b/usr/othersrc/public/zsh-2.2/src/signals.h.sample new file mode 100644 index 0000000000..a35537a238 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/signals.h.sample @@ -0,0 +1,105 @@ +Your signals.h file should look something like this. If it doesn't, +perhaps your csh or ed is different. + +/* this file is created automatically by buildzsh */ +/* if all this is wrong, blame csh ;-) */ + +#define SIGCOUNT 31 + +#ifdef GLOBALS + +char *sigmsg[SIGCOUNT+2] = { + "done", + "hangup", + "interrupt", + "quit", + "illegal instruction", + "trace trap", + "abort", + "EMT instruction", + "floating point exception", + "killed", + "bus error", + "segmentation fault", + "bad system call", + "broken pipe", + "SIGALRM", + "terminated", + "SIGURG", +#ifdef USE_SUSPENDED + "suspended (signal)", +#else + "stopped (signal)", +#endif +#ifdef USE_SUSPENDED + "suspended", +#else + "stopped", +#endif + "continued", + "SIGCHLD", +#ifdef USE_SUSPENDED + "suspended (tty input)", +#else + "stopped (tty input)", +#endif +#ifdef USE_SUSPENDED + "suspended (tty output)", +#else + "stopped (tty output)", +#endif + "SIGIO", + "cpu limit exceeded", + "filesize limit exceeded", + "virtual time alarm", + "SIGPROF", + "SIGWINCH", + "SIGLOST", + "SIGUSR1", + "SIGUSR2", + NULL +}; + +char *sigs[SIGCOUNT+4] = { + "EXIT", + "HUP", + "INT", + "QUIT", + "ILL", + "TRAP", + "ABRT", + "EMT", + "FPE", + "KILL", + "BUS", + "SEGV", + "SYS", + "PIPE", + "ALRM", + "TERM", + "URG", + "STOP", + "TSTP", + "CONT", + "CHLD", + "TTIN", + "TTOU", + "IO", + "XCPU", + "XFSZ", + "VTALRM", + "PROF", + "WINCH", + "LOST", + "USR1", + "USR2", + "ERR", + "DEBUG", + NULL +}; + +#else + +extern char *sigs[SIGCOUNT+4],*sigmsg[SIGCOUNT+2]; + +#endif diff --git a/usr/othersrc/public/zsh-2.2/src/subst.c b/usr/othersrc/public/zsh-2.2/src/subst.c new file mode 100644 index 0000000000..15d2493c81 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/subst.c @@ -0,0 +1,764 @@ +/* + * + * subst.c - various substitutions + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include + +/* do substitutions before fork */ + +void prefork(list) /**/ +Lklist list; +{ +Lknode node = firstnode(list); +int qt; + + while (node) + { + char *str,*str3; + + str = str3 = getdata(node); + if ((*str == Inang || *str == Outang || *str == Equals) && + str[1] == Inpar) + { + if (*str == Inang) + setdata(node,getoutproc(str+2)); /* <(...) */ + else if (*str == Equals) + setdata(node,getoutputfile(str+2)); /* =(...) */ + else + setdata(node,getinproc(str+2)); /* >(...) */ + if (!getdata(node)) + { + zerr("parse error in process substitution",NULL,0); + return; + } + } + else while (*str) + { + if ((qt = *str == Qstring) || *str == String) + if (str[1] != Inpar) + if (str[1] == Inbrack) + { + arithsubst((vptr*) &str,&str3); /* $[...] */ + setdata(node,str3); + str = str3; + continue; + } + else + { + paramsubst(list,node,str,str3,qt); + if (errflag) + return; + str3 = str = getdata(node); + continue; + } + str++; + if (errflag) + return; + } + if (*(char *) getdata(node)) + remnulargs(getdata(node)); + if (unset(IGNOREBRACES)) + while (hasbraces(getdata(node))) + xpandbraces(list,&node); + filesub((char **) getaddrdata(node)); + if (errflag) + return; + incnode(node); + } +} + +void postfork(list,doglob) /**/ +Lklist list;int doglob; +{ +Lknode node = firstnode(list); +int glb = 1; + + badcshglob = 0; + if (isset(NOGLOBOPT) || !doglob) + glb = 0; + while (node) + { + char *str3,*str; + + str = str3 = getdata(node); + while (*str) + { + if (((*str == String || *str == Qstring) && str[1] == Inpar) || + *str == Tick || *str == Qtick) + { + Lknode n = prevnode(node); + + commsubst(list,node,str,str3, + (*str == Qstring || *str == Qtick)); /* `...`,$(...) */ + if (errflag) + return; + str = str3 = getdata(node = nextnode(n)); + } + str++; + } + if (glb) + { + if (haswilds(getdata(node))) + glob(list,&node); + if (errflag) + return; + } + incnode(node); + } + if (badcshglob == 1) zerr("no match",NULL,0); +} + +/* perform substitution on a single word */ + +void singsub(s) /**/ +char **s; +{ +Lklist foo; +char *t; + + for (t = *s; *t; t++) + if (*t == String) + *t = Qstring; + else if (*t == Tick) + *t = Qtick; + foo = newlist(); + addnode(foo,*s); + prefork(foo); + if (errflag) + return; + postfork(foo,0); + if (errflag) + return; + *s = ugetnode(foo); + if (firstnode(foo)) + zerr("ambiguous: %s",*s,0); +} + +/* strdup, but returns "Nularg" if this is a null string */ + +vptr nstrdup(s) /**/ +vptr s; +{ +char *t = s; +char u[2]; + + u[0] = Nularg; u[1] = '\0'; + if (!*t) + return strdup(u); + return strdup(t); +} + +char *dynread(stop) /**/ +int stop; +{ +int bsiz = 256,ct = 0,c; +char *buf = zalloc(bsiz),*ptr; + + ptr = buf; + while ((c = hgetc()) != stop) + { + *ptr++ = c; + if (++ct == bsiz) + { + buf = realloc(buf,bsiz *= 2); + ptr = buf+ct; + } + } + *ptr = 0; + return buf; +} + +int filesub(namptr) /**/ +char **namptr; +{ +char *str = *namptr,*cnam; + + if (*str == Tilde && str[1] != '=') + { + if (str[1] == '+' && (str[2] == '/' || str[2] == '\0')) + { + char *foo = strdup(pwd); /* ~+ */ + + str+=2; + modify(&foo,&str); + *namptr = dyncat(pwd,str); + return 1; + } + else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0')) + { + char *foo; /* ~- */ + + if (cnam = oldpwd) + foo = cnam; + else + foo = pwd; + str += 2; + foo = strdup(foo); + modify(&foo,&str); + *namptr = dyncat(foo,str); + return 1; + } + if (ialpha(str[1])) /* ~foo */ + { + char *ptr,*hom; + + for (ptr = ++str; *ptr && iuser(*ptr); ptr++) + if (*ptr == '-') + *ptr = '-'; + if (*ptr && *ptr != '/') return 0; + if (!(hom = gethome(str,ptr-str))) + { + zerr("user not found: %l",str,ptr-str); + errflag = 1; + return 0; + } + modify(&hom,&ptr); + *namptr = dyncat(hom,ptr); + return 1; + } + else if (str[1] == '/') /* ~/foo */ + { + *namptr = dyncat(home,str+1); + return 1; + } + else if (!str[1]) /* ~ by itself */ + { + *namptr = strdup(home); + return 1; + } + } + if (*str == Equals && iuser(str[1]) && unset(NOEQUALS)) + { + char *ptr,*s,*ds; + int val; + + if (ialpha(str[1])) /* =foo */ + { + char sav,*pp; + + for (pp = str+1; *pp && *pp != ':'; pp++); + sav = *pp; + *pp = '\0'; + if (!(cnam = findcmd(str+1))) + { + zerr("%s not found",str+1,0); + errflag = 1; + return 0; + } + *namptr = cnam; + if ((*pp = sav) == ':') + { + modify(namptr,&pp); + s = *namptr; + *namptr = dyncat(*namptr,pp); + } + return 1; + } + if (str[1] == '-') /* =- */ + { + val = -1; + ptr = str+2; + } + else + val = zstrtol(str+1,&ptr,10); /* =# */ + ds = dstackent(val); + if (!ds) + return 1; + s = strdup(ds); + modify(&s,&ptr); + *namptr = dyncat(s,ptr); + return 1; + } + return 0; +} + +/* get a named directory */ + +char *gethome(user,len) /**/ +char *user;int len; +{ +char sav,*str; +struct passwd *pw; + + if (len == 0) + return strdup(home); + sav = user[len]; + user[len] = '\0'; + if ((str = getsparamval(user,len)) && *str == '/') + { + str = strdup(str); + adduserdir(user,str); + user[len] = sav; + return str; + } + permalloc(); /* fixes iris bug--getpwnam calls strdup! */ + pw = getpwnam(user); + lastalloc(); + if (!pw) { + user[len] = sav; + return NULL; + } + str = xsymlink(pw->pw_dir); + adduserdir(user,str); + user[len] = sav; + return str; +} + +/* `...`, $(...) */ + +void commsubst(l,n,str3,str,qt) /**/ +Lklist l;Lknode n;char *str3;char *str;int qt; +{ +char *str2; +Lknode where = prevnode(n); +Lklist pl; + + if (*str3 == Tick || *str3 == Qtick) + { + *str3 = '\0'; + for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++); + *str3++ = '\0'; + } + else + { + *str3++ = '\0'; + for (str2 = ++str3; *str3 != Outpar; str3++); + *str3++ = '\0'; + } + uremnode(l,n); + if (!(pl = getoutput(str2,qt))) + { + zerr("parse error in command substitution",NULL,0); + errflag = 1; + return; + } + if (full(pl)) + { + setdata(firstnode(pl),dyncat(str,peekfirst(pl))); + setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3)); + inslist(pl,where,l); + } + else + insnode(l,where,dyncat(str,str3)); +} + +/* parameter substitution */ + +void paramsubst(l,n,aptr,bptr,qt) /**/ +Lklist l;Lknode n;char *aptr;char *bptr;int qt; +{ +char *s = aptr,*u,*idbeg,*idend,*ostr = bptr; +int brs; /* != 0 means ${...}, otherwise $... */ +int colf; /* != 0 means we found a colon after the name */ +int doub = 0; /* != 0 means we have %%, not %, or ##, not # */ +int isarr = 0; +int wasnularr = 0; +int plan9 = isset(RCEXPANDPARAM); +int getlen = 0; +int vunset = 0; +int spbreak = isset(SHWORDSPLIT) && !qt; +char *val = NULL,**aval = NULL; +int fwidth = 0; +Value v; + + *s++ = '\0'; + if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' && + *s != '!' && *s != '$' && *s != String && *s != Qstring && + *s != '?' && *s != Quest && *s != '_' && + *s != '*' && *s != Star && *s != '@' && *s != '{' && + *s != Inbrace && *s != '=' && *s != Hat && *s != '^') { + s[-1] = '$'; + return; + } + if (brs = (*s == '{' || *s == Inbrace)) s++; + for (;;) + if (*s == '^' || *s == Hat) + plan9 ^= 1,s++; + else if (*s == '=') + spbreak ^= 1,s++; + else if ((*s == '#' || *s == Pound) && iident(s[1])) + getlen = 1,s++; + else + break; + + idbeg = s; + if (!(v = getvalue(&s,1))) { + vunset = 1; + idend = s; + } else + if (isarr = v->isarr) + aval = getarrvalue(v); + else { + val = getstrvalue(v); + fwidth = v->pm->ct; + switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z)) { + char *t; + int t0; + + case PMFLAG_L: + case PMFLAG_L|PMFLAG_Z: + t = val; + if (v->pm->flags & PMFLAG_Z) + while (*t == '0') t++; + else + while (isep(*t)) t++; + val = ncalloc(fwidth+1); + val[fwidth] = '\0'; + if ((t0 = strlen(t)) > fwidth) + t0 = fwidth; + memset(val,' ',fwidth); + strncpy(val,t,t0); + break; + case PMFLAG_R: + case PMFLAG_Z: + case PMFLAG_Z|PMFLAG_R: + if (strlen(val) < fwidth) { + t = ncalloc(fwidth+1); + memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth); + if ((t0 = strlen(val)) > fwidth) + t0 = fwidth; + strcpy(t+(fwidth-t0),val); + val = t; + } else { + t = ncalloc(fwidth+1); + t[fwidth] = '\0'; + strncpy(t,val+strlen(val)-fwidth,fwidth); + val = t; + } + break; + } + switch (v->pm->flags & (PMFLAG_l | PMFLAG_u)) { + char *t; + + case PMFLAG_l: + t = val; + for (;*t;t++) + *t = tulower(*t); + break; + case PMFLAG_u: + t = val; + for (;*t;t++) + *t = tuupper(*t); + break; + } + } + if (colf = *s == ':') s++; + + /* check for ${..?...} or ${..=..} or one of those. Only works + if the name is in braces. */ + + if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' || + *s == '%' || *s == Quest || *s == Pound)) { + if (v && v->isarr && (*s == '%' || *s == '#' || *s == Pound)) { + zerr("operator requires a scalar",NULL,0); + return; + } + if (*s == s[1]) { + s++; + doub = 1; + } + u = ++s; + if (brs) { + int bct = 1; + + for (;;) { + if (*s == '{' || *s == Inbrace) + bct++; + else if (*s == '}' || *s == Outbrace) + bct--; + if (!bct || !*s) + break; + s++; + } + } else { + while (*s++); + s--; + } + if (*s) *s++ = '\0'; + if (colf && !vunset) + vunset = (isarr) ? !*aval : !*val; + switch ((int)(unsigned char)u[-1]) { + case '-': + if (vunset) + val = strdup(u), isarr = 0; + break; + case '=': + if (vunset) { + char sav = *idend; + + *idend = '\0'; + setsparam(idbeg,ztrdup(val = strdup(u))); + *idend = sav; + isarr = 0; + } + break; + case '?': + case (int)(unsigned char)Quest: + if (vunset) { + zerr("%s",(*u) ? u : "parameter not set",0); + if (!interact) + exit(1); + return; + } + break; + case '+': + if (vunset) + val = strdup(""); + else + val = strdup(u); + isarr = 0; + break; + case '#': + case (int)(unsigned char)Pound: + if (vunset) + val = strdup(""); + singsub(&u); + getmatch(&val,u,doub); + break; + case '%': + if (vunset) + val = strdup(""); + singsub(&u); + getmatch(&val,u,doub+2); + break; + } + } else { /* no ${...=...} or anything, but possible modifiers. */ + if (vunset) { + if (isset(NOUNSET)) { + zerr("parameter not set",NULL,0); + return; + } + val = strdup(""); + } + if (colf) { + s--; + if (!isarr) modify(&val,&s); + else { + char *ss = s; + char **ap = aval; + while (*ap) { + ss = s; + modify(ap,&ss); + } + } + } + if (brs) { + if (*s != '}' && *s != Outbrace) { + zerr("closing brace expected",NULL,0); + errflag = 1; + return; + } + s++; + } + } + if (errflag) + return; + if (getlen) { + long len = 0; + char buf[14]; + + if (isarr) { + char **ctr; + for (ctr = aval; *ctr; ctr++,len++); + } else + len = strlen(val); + sprintf(buf,"%ld",len); + val = strdup(buf); + isarr = 0; + } + if (isarr) + if (!aval || !aval[0]) { + if (isarr < 0) + wasnularr = 1; + val = strdup(""); + isarr = 0; + } else if (!aval[1]) { + val = aval[0]; + isarr = 0; + } + if (qt) { + if (isarr > 0) { + val = spacejoin(aval); + isarr = 0; + } + } else if (spbreak) { + if (isarr) + val = spacejoin(aval); + isarr = 1; + aval = spacesplit(val); + if (!aval || !aval[0]) { + val = strdup(""); + isarr = 0; + } else if (!aval[1]) { + val = aval[0]; + isarr = 0; + } + /* if only one member, not really an array */ + if (!aval[1]) + isarr = 0; + } + if (isarr) + if (plan9) { + int dlen; + char *y; + + y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+strlen(aval[0])); + setdata(n,y); + strcpy(y,ostr); + strcat(y,aval[0]); + strcat(y,s); + while (*++aval) { + char *x = ncalloc(dlen+strlen(*aval)); + + strcpy(x,ostr); + strcat(x,*aval); + strcat(x,s); + insnode(l,n,x), incnode(n); + } + } else { + char *zz; + + zz = ncalloc((char *) aptr-(bptr)+strlen(aval[0])+1); + setdata(n,zz); + strcpy(zz,ostr); + strcat(zz,*aval++); + while (aval[1]) + insnode(l,n,*aval++), incnode(n); + zz = ncalloc(strlen(*aval)+strlen(s)+1); + strcpy(zz,*aval); + strcat(zz,s); + insnode(l,n,zz); + } + else { + bptr = ncalloc((char *) aptr-bptr+strlen(val)+strlen(s)+1); + setdata(n,bptr); + strcpy(bptr,ostr); + strcat(bptr,val); + strcat(bptr,s); + } +} + +/* arithmetic substitution */ + +void arithsubst(aptr,bptr) /**/ +vptr *aptr;char **bptr; +{ +char *s = *aptr,*t,buf[16]; +long v; + + *s = '\0'; + for (; *s != Outbrack; s++); + *s++ = '\0'; + v = matheval((char *) *aptr+2); + sprintf(buf,"%ld",v); + t = ncalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1); + strcpy(t,*bptr); + strcat(t,buf); + strcat(t,s); + *bptr = t; +} + +void modify(str,ptr) /**/ +char **str;char **ptr; +{ +char *ptr1,*ptr2,*ptr3,del,*lptr; +int gbal; + + if (**ptr == ':') + *str = strdup(*str); + while (**ptr == ':') + { + lptr = *ptr; + (*ptr)++; + gbal = 0; +here: + switch(*(*ptr)++) + { + case 'h': remtpath(str); break; + case 'r': remtext(str); break; + case 'e': rembutext(str); break; + case 't': remlpaths(str); break; + case 'l': downcase(str); break; + case 'u': upcase(str); break; + case 's': + if (hsubl) + free(hsubl); + if (hsubr) + free(hsubr); + ptr1 = *ptr; + del = *ptr1++; + for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++); + if (!*ptr2) + { + zerr("bad subtitution",NULL,0); + errflag = 1; + return; + } + *ptr2++ = '\0'; + for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++); + if (*ptr3) + *ptr3++ = '\0'; + hsubl = ztrdup(ptr1); + hsubr = ztrdup(ptr2); + *ptr = ptr3; + case '&': + if (hsubl && hsubr) + subst(str,hsubl,hsubr,gbal); + break; + case 'g': gbal = 1; goto here; + default: *ptr = lptr; return; + } + } +} + +/* get a directory stack entry */ + +char *dstackent(val) /**/ +int val; +{ +Lknode node; + + if ((val < 0 && !firstnode(dirstack)) || !val--) + return pwd; + if (val < 0) + node = lastnode(dirstack); + else + for (node = firstnode(dirstack); node && val; val--,incnode(node)); + if (!node) + { + zerr("not enough dir stack entries.",NULL,0); + errflag = 1; + return NULL; + } + return getdata(node); +} + +/* make an alias hash table node */ + +struct alias *mkanode(txt,cmflag) /**/ +char *txt;int cmflag; +{ +struct alias *ptr = (Alias) zcalloc(sizeof *ptr); + + ptr->text = txt; + ptr->cmd = cmflag; + ptr->inuse = 0; + return ptr; +} diff --git a/usr/othersrc/public/zsh-2.2/src/subst.pro b/usr/othersrc/public/zsh-2.2/src/subst.pro new file mode 100644 index 0000000000..6ba21dfc92 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/subst.pro @@ -0,0 +1,13 @@ +void prefork DCLPROTO((Lklist list)); +void postfork DCLPROTO((Lklist list,int doglob)); +void singsub DCLPROTO((char **s)); +vptr nstrdup DCLPROTO((vptr s)); +char *dynread DCLPROTO((int stop)); +int filesub DCLPROTO((char **namptr)); +char *gethome DCLPROTO((char *user,int len)); +void commsubst DCLPROTO((Lklist l,Lknode n,char *str3,char *str,int qt)); +void paramsubst DCLPROTO((Lklist l,Lknode n,char *aptr,char *bptr,int qt)); +void arithsubst DCLPROTO((vptr *aptr,char **bptr)); +void modify DCLPROTO((char **str,char **ptr)); +char *dstackent DCLPROTO((int val)); +struct alias *mkanode DCLPROTO((char *txt,int cmflag)); diff --git a/usr/othersrc/public/zsh-2.2/src/table.c b/usr/othersrc/public/zsh-2.2/src/table.c new file mode 100644 index 0000000000..304fe10112 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/table.c @@ -0,0 +1,349 @@ +/* + * + * table.c - linked lists and hash tables + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define TABLE_C +#include "zsh.h" + +/* get an empty linked list header */ + +Lklist newlist() /**/ +{ +Lklist list; + + list = (Lklist) alloc(sizeof *list); + list->first = 0; + list->last = (Lknode) list; + return list; +} + +/* get an empty hash table */ + +Hashtab newhtable(size) /**/ +int size; +{ +Hashtab ret; + + ret = (Hashtab) zcalloc(sizeof *ret); + ret->hsize = size; + ret->nodes = (Hashnode*) zcalloc(size*sizeof(Hashnode)); + return ret; +} + +/* Peter Weinberger's hash function */ + +int hasher(s) /**/ +char *s; +{ +unsigned hash = 0,g; + + for (; *s; s++) { + hash = (hash << 4) + *s; + if (g = hash & 0xf0000000) { + hash ^= g; + hash ^= g >> 24; + } + } + return hash; +} + +/* add a node to a hash table */ + +void Addhnode(nam,dat,ht,freefunc,canfree) /**/ +char *nam;vptr dat;Hashtab ht;FFunc freefunc;int canfree; +{ +int hval = hasher(nam) % ht->hsize; +struct hashnode **hp = ht->nodes+hval,*hn; + + for (; *hp; hp = &(*hp)->next) + if (!strcmp((*hp)->nam,nam)) { + if ((*hp)->canfree) free((*hp)->nam); + hn = dat; + hn->next = (*hp)->next; + if (!freefunc) zerr("attempt to call NULL freefunc",NULL,0); + else freefunc(*hp); + *hp = hn; + hn->nam = nam; + hn->canfree = canfree; + return; + } + hn = (Hashnode) dat; + hn->nam = nam; + hn->canfree = canfree; + hn->next = ht->nodes[hval]; + ht->nodes[hval] = hn; + if (++ht->ct == ht->hsize*4) expandhtab(ht); +} + +/* add a node to command hash table */ + +void addhcmdnode(nam,pnam) /**/ +char *nam;char **pnam; +{ +int hval = hasher(nam) % cmdnamtab->hsize; +struct hashnode *hp = cmdnamtab->nodes[hval],*hn; +Cmdnam cc; + + for (; hp; hp = hp->next) if (!strcmp(hp->nam,nam)) return; + cc = (Cmdnam) zcalloc(sizeof *cc); + cc->type = EXCMD; + cc->u.nam = tricat(*pnam,"/",nam); + cc->pcomp = pnam; + hn = (Hashnode) cc; + hn->nam = ztrdup(nam); + hn->canfree = 1; + hn->next = cmdnamtab->nodes[hval]; + cmdnamtab->nodes[hval] = hn; + if (++cmdnamtab->ct == cmdnamtab->hsize*4) expandhtab(cmdnamtab); +} + +/* expand hash tables when they get too many entries */ + +void expandhtab(ht) /**/ +Hashtab ht; +{ +struct hashnode **arr,**ha,*hn,*hp; +int osize = ht->hsize,nsize = osize*8; + + ht->hsize = nsize; + arr = ht->nodes; + ht->nodes = (Hashnode*) zcalloc(nsize*sizeof(struct hashnode *)); + for (ha = arr; osize; osize--,ha++) + for (hn = *ha; hn; ) { + hp = hn->next; + Addhnode(hn->nam,(vptr)hn,ht,NULL,hn->canfree); + hn = hp; + } + free(arr); +} + +/* get an entry in a hash table */ + +vptr gethnode(nam,ht) /**/ +char *nam;Hashtab ht; +{ +int hval = hasher(nam) % ht->hsize; +struct hashnode *hn = ht->nodes[hval]; + + for (; hn; hn = hn->next) if (!strcmp(hn->nam,nam)) return (vptr)hn; + return NULL; +} + +void freehtab(ht,freefunc) /**/ +Hashtab ht;FFunc freefunc; +{ +int val; +struct hashnode *hn,**hp = &ht->nodes[0],*next; + + for (val = ht->hsize; val; val--,hp++) + for (hn = *hp; hn; ) { + next = hn->next; + if (hn->canfree) free(hn->nam); + freefunc(hn); + hn = next; + } + free(ht->nodes); + free(ht); +} + +/* remove a hash table entry and return a pointer to it */ + +vptr remhnode(nam,ht) /**/ +char *nam;Hashtab ht; +{ +int hval = hasher(nam) % ht->hsize; +struct hashnode *hn = ht->nodes[hval],*hp; + + if (!hn) return NULL; + if (!strcmp(hn->nam,nam)) { + ht->nodes[hval] = hn->next; + if (hn->canfree) free(hn->nam); + ht->ct--; + return (vptr)hn; + } + for (hp = hn, hn = hn->next; hn; hn = (hp = hn)->next) + if (!strcmp(hn->nam,nam)) { + hp->next = hn->next; + if (hn->canfree) free(hn->nam); + ht->ct--; + return (vptr)hn; + } + return NULL; +} + +/* insert a node in a linked list after 'llast' */ + +void insnode(list,llast,dat) /**/ +Lklist list;Lknode llast;vptr dat; +{ +Lknode tmp; + + tmp = llast->next; + llast->next = (Lknode) alloc(sizeof *tmp); + llast->next->last = llast; + llast->next->dat = dat; + llast->next->next = tmp; + if (tmp) tmp->last = llast->next; + else list->last = llast->next; +} + +void addnodeinorder(x,dat) /**/ +Lklist x; char *dat; +{ +Lknode y, l = NULL; +int val = 123; + + for (y = firstnode(x); y; incnode(y)) { + if ((val = forstrcmp((char **) &y->dat, &dat)) >= 0) break; + l = y; + } + if (!val) return; + if (l == NULL) insnode(x, (Lknode) x, dat); + else insnode(x, l, dat); +} + + +/* remove a node from a linked list */ + +vptr remnode(list,nd) /**/ +Lklist list;Lknode nd; +{ +vptr dat; + + nd->last->next = nd->next; + if (nd->next) nd->next->last = nd->last; + else list->last = nd->last; + dat = nd->dat; + free(nd); + return dat; +} + +/* remove a node from a linked list */ + +vptr uremnode(list,nd) /**/ +Lklist list;Lknode nd; +{ +vptr dat; + + nd->last->next = nd->next; + if (nd->next) nd->next->last = nd->last; + else list->last = nd->last; + dat = nd->dat; + return dat; +} + +/* delete a character in a string */ + +void chuck(str) /**/ +char *str; +{ + while (str[0] = str[1]) str++; +} + +/* get top node in a linked list */ + +vptr getnode(list) /**/ +Lklist list; +{ +vptr dat; +Lknode node = list->first; + + if (!node) + return NULL; + dat = node->dat; + list->first = node->next; + if (node->next) + node->next->last = (Lknode) list; + else + list->last = (Lknode) list; + free(node); + return dat; +} + +/* get top node in a linked list without freeing */ + +vptr ugetnode(list) /**/ +Lklist list; +{ +vptr dat; +Lknode node = list->first; + + if (!node) + return NULL; + dat = node->dat; + list->first = node->next; + if (node->next) + node->next->last = (Lknode) list; + else + list->last = (Lknode) list; + return dat; +} + +void freetable(tab,freefunc) /**/ +Lklist tab;FFunc freefunc; +{ +Lknode node = tab->first,next; + + while (node) { + next = node->next; + if (freefunc) freefunc(node->dat); + free(node); + node = next; + } + free(tab); +} + +char *ztrstr(s,t) /**/ +char *s;char *t; +{ +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; +} + +/* insert a list in another list */ + +void inslist(l,where,x) /**/ +Lklist l;Lknode where;Lklist x; +{ +Lknode nx = where->next; + + if (!l->first) return; + where->next = l->first; + l->last->next = nx; + l->first->last = where; + if (nx) nx->last = l->last; + else x->last = l->last; +} + +int countnodes(x) /**/ +Lklist x; +{ +Lknode y; +int ct = 0; + + for (y = firstnode(x); y; incnode(y),ct++); + return ct; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/table.pro b/usr/othersrc/public/zsh-2.2/src/table.pro new file mode 100644 index 0000000000..8628ed935d --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/table.pro @@ -0,0 +1,20 @@ +Lklist newlist DCLPROTO((void)); +Hashtab newhtable DCLPROTO((int size)); +int hasher DCLPROTO((char *s)); +void Addhnode DCLPROTO((char *nam,vptr dat,Hashtab ht,FFunc freefunc,int canfree)); +void addhcmdnode DCLPROTO((char *nam,char **pnam)); +void expandhtab DCLPROTO((Hashtab ht)); +vptr gethnode DCLPROTO((char *nam,Hashtab ht)); +void freehtab DCLPROTO((Hashtab ht,FFunc freefunc)); +vptr remhnode DCLPROTO((char *nam,Hashtab ht)); +void insnode DCLPROTO((Lklist list,Lknode llast,vptr dat)); +void addnodeinorder DCLPROTO((Lklist x, char *dat)); +vptr remnode DCLPROTO((Lklist list,Lknode nd)); +vptr uremnode DCLPROTO((Lklist list,Lknode nd)); +void chuck DCLPROTO((char *str)); +vptr getnode DCLPROTO((Lklist list)); +vptr ugetnode DCLPROTO((Lklist list)); +void freetable DCLPROTO((Lklist tab,FFunc freefunc)); +char *ztrstr DCLPROTO((char *s,char *t)); +void inslist DCLPROTO((Lklist l,Lknode where,Lklist x)); +int countnodes DCLPROTO((Lklist x)); diff --git a/usr/othersrc/public/zsh-2.2/src/text.c b/usr/othersrc/public/zsh-2.2/src/text.c new file mode 100644 index 0000000000..102615f679 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/text.c @@ -0,0 +1,465 @@ +/* + * + * text.c - textual representations of syntax trees + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" + +static char *tptr,*tbuf,*tlim; +static int tsiz,tindent,tnewlins; + +/* add a character to the text buffer */ + +void taddchr(c) /**/ +int c; +{ + *tptr++ = c; + if (tptr == tlim) { + if (!tbuf) { tptr--; return; } + tbuf = realloc(tbuf,tsiz *= 2); + tlim = tbuf+tsiz; + tptr = tbuf+tsiz/2; + } +} + +/* add a string to the text buffer */ + +void taddstr(s) /**/ +char *s; +{ +int sl = strlen(s); + + while (tptr+sl >= tlim) { + int x = tptr-tbuf; + + if (!tbuf) return; + tbuf = realloc(tbuf,tsiz *= 2); + tlim = tbuf+tsiz; + tptr = tbuf+x; + } + strcpy(tptr,s); + tptr += sl; +} + +/* add an integer to the text buffer */ + +void taddint(x) /**/ +int x; +{ +char buf[10]; + + sprintf(buf,"%d",x); + taddstr(buf); +} + +/* add a newline, or something equivalent, to the text buffer */ + +void taddnl() /**/ +{ +int t0; + + if (tnewlins) + { + taddchr('\n'); + for (t0 = 0; t0 != tindent; t0++) + taddchr('\t'); + } + else + taddstr("; "); +} + +/* get a permanent textual representation of n */ + +char *getpermtext(n) /**/ +struct node *n; +{ + tnewlins = 1; + tbuf = zalloc(tsiz = 32); + tptr = tbuf; + tlim = tbuf+tsiz; + tindent = 1; + gettext2(n); + *tptr = '\0'; + untokenize(tbuf); + return tbuf; +} + +/* get a representation of n in a job text buffer */ + +char *getjobtext(n) /**/ +struct node *n; +{ +static char jbuf[JOBTEXTSIZE]; + + tnewlins = 0; + tbuf = NULL; + tptr = jbuf; + tlim = tptr+JOBTEXTSIZE-1; + tindent = 1; + gettext2(n); + *tptr = '\0'; + untokenize(jbuf); + return jbuf; +} + +#define gt2(X) gettext2((struct node *) (X)) + +/* + "gettext2" or "type checking and how to avoid it" + an epic function by Paul Falstad +*/ + +#define _Cond(X) ((Cond) (X)) +#define _Cmd(X) ((Cmd) (X)) +#define _Pline(X) ((Pline) (X)) +#define _Sublist(X) ((Sublist) (X)) +#define _List(X) ((List) (X)) +#define _casecmd(X) ((struct casecmd *) (X)) +#define _ifcmd(X) ((struct ifcmd *) (X)) +#define _whilecmd(X) ((struct whilecmd *) (X)) + +void gettext2(n) /**/ +struct node *n; +{ +Cmd nn; +Cond nm; + + if (!n) + return; + switch (n->type) + { + case N_LIST: + gt2(_List(n)->left); + if (_List(n)->type == ASYNC) + taddstr(" &"); + simplifyright(_List(n)); + if (_List(n)->right) + { + if (tnewlins) + taddnl(); + else + taddstr((_List(n)->type == ASYNC) ? " " : "; "); + gt2(_List(n)->right); + } + break; + case N_SUBLIST: + if (_Sublist(n)->flags & PFLAG_NOT) + taddstr("! "); + if (_Sublist(n)->flags & PFLAG_COPROC) + taddstr("coproc "); + gt2(_Sublist(n)->left); + if (_Sublist(n)->right) + { + taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && "); + gt2(_Sublist(n)->right); + } + break; + case N_PLINE: + gt2(_Pline(n)->left); + if (_Pline(n)->type == PIPE) + { + taddstr(" | "); + gt2(_Pline(n)->right); + } + break; + case N_CMD: + nn = _Cmd(n); + if (nn->flags & CFLAG_EXEC) + taddstr("exec "); + if (nn->flags & CFLAG_COMMAND) + taddstr("command "); + switch (nn->type) + { + case SIMPLE: + getsimptext(nn); + break; + case SUBSH: + taddstr("( "); + tindent++; + gt2(nn->u.list); + tindent--; + taddstr(" )"); + break; + case ZCTIME: + taddstr("time "); + tindent++; + gt2(nn->u.pline); + tindent--; + break; + case FUNCDEF: + taddlist(nn->args); + taddstr(" () {"); + tindent++; + taddnl(); + gt2(nn->u.list); + tindent--; + taddnl(); + taddstr("}"); + break; + case CURSH: + taddstr("{ "); + tindent++; + gt2(nn->u.list); + tindent--; + taddstr(" }"); + break; + case CFOR: + case CSELECT: + taddstr((nn->type == CFOR) ? "for " : "select "); + taddstr(nn->u.forcmd->name); + if (nn->u.forcmd->inflag) + { + taddstr(" in "); + taddlist(nn->args); + } + taddnl(); + taddstr("do"); + tindent++; + taddnl(); + gt2(nn->u.forcmd->list); + taddnl(); + tindent--; + taddstr("done"); + break; + case CIF: + gt2(nn->u.ifcmd); + taddstr("fi"); + break; + case CCASE: + taddstr("case "); + taddlist(nn->args); + taddstr(" in"); + tindent++; + taddnl(); + gt2(nn->u.casecmd); + tindent--; + if (tnewlins) + taddnl(); + else + taddchr(' '); + taddstr("esac"); + break; + case COND: + taddstr("[[ "); + gt2(nn->u.cond); + taddstr(" ]]"); + break; + case CREPEAT: + taddstr("repeat "); + taddlist(nn->args); + taddnl(); + taddstr("do"); + tindent++; + taddnl(); + gt2(nn->u.list); + tindent--; + taddnl(); + taddstr("done"); + break; + case CWHILE: + gt2(nn->u.whilecmd); + break; + } + getredirs(nn); + break; + case N_COND: + nm = _Cond(n); + switch (nm->type) + { + case COND_NOT: + taddstr("! "); + gt2(nm->left); + break; + case COND_AND: + taddstr("( "); + gt2(nm->left); + taddstr(" && "); + gt2(nm->right); + taddstr(" )"); + break; + case COND_OR: + taddstr("( "); + gt2(nm->left); + taddstr(" || "); + gt2(nm->right); + taddstr(" )"); + break; + default: + { + static char *c1[] = { + " = "," != "," < "," > "," -nt "," -ot "," -ef "," -eq ", + " -ne "," -lt "," -gt "," -le "," -ge " + }; + if (nm->right) + taddstr(nm->left); + if (nm->type <= COND_GE) + taddstr(c1[nm->type-COND_STREQ]); + else + { + char c2[5]; + c2[0] = ' '; c2[1] = '-'; + c2[2] = nm->type; + c2[3] = ' '; c2[4] = '\0'; + taddstr(c2); + } + taddstr((nm->right) ? nm->right : nm->left); + } + break; + } + break; + case N_CASE: + taddstr(_casecmd(n)->pat); + taddstr(") "); + tindent++; + gt2(_casecmd(n)->list); + tindent--; + taddstr(";;"); + if (tnewlins) + taddnl(); + else + taddchr(' '); + gt2(_casecmd(n)->next); + break; + case N_IF: + if (_ifcmd(n)->ifl) + { + taddstr("if "); + tindent++; + gt2(_ifcmd(n)->ifl); + tindent--; + taddnl(); + taddstr("then"); + } + else + taddchr('e'); + tindent++; + taddnl(); + gt2(_ifcmd(n)->thenl); + tindent--; + taddnl(); + if (_ifcmd(n)->next) + { + taddstr("els"); + gt2(_ifcmd(n)->next); + } + break; + case N_WHILE: + taddstr((_whilecmd(n)->cond) ? "until " : "while "); + tindent++; + gt2(_whilecmd(n)->cont); + tindent--; + taddnl(); + taddstr("do"); + tindent++; + taddnl(); + gt2(_whilecmd(n)->loop); + tindent--; + taddnl(); + taddstr("done"); + break; + } +} + +void getsimptext(cmd) /**/ +Cmd cmd; +{ +Lknode n; + + for (n = firstnode(cmd->vars); n; incnode(n)) + { + struct varasg *v = getdata(n); + + taddstr(v->name); + taddchr('='); + if ((v->type & PMTYPE) == PMFLAG_A) + { + taddchr('('); + taddlist(v->arr); + taddstr(") "); + } + else + { + taddstr(v->str); + taddchr(' '); + } + } + taddlist(cmd->args); +} + +void getredirs(cmd) /**/ +Cmd cmd; +{ +Lknode n; +static char *fstr[] = { + ">",">!",">>",">>!",">&",">&!",">>&",">>&!","<","<<", + "<<-","<<<","<&",">&-","..",".." + }; + + taddchr(' '); + for (n = firstnode(cmd->redir); n; incnode(n)) + { + struct redir *f = getdata(n); + + switch(f->type) + { + case WRITE: case WRITENOW: case APP: case APPNOW: case READ: + case HERESTR: + if (f->fd1 != ((f->type == READ) ? 0 : 1)) + taddchr('0'+f->fd1); + taddstr(fstr[f->type]); + taddchr(' '); + taddstr(f->name); + taddchr(' '); + break; + case MERGE: case MERGEOUT: + if (f->fd1 != ((f->type == MERGEOUT) ? 1 : 0)) + taddchr('0'+f->fd1); + taddstr(fstr[f->type]); + taddchr(' '); + taddint(f->fd2); + taddchr(' '); + break; + case CLOSE: + taddchr(f->fd1+'0'); + taddstr(">&- "); + break; + case INPIPE: + case OUTPIPE: + if (f->fd1 != ((f->type == INPIPE) ? 0 : 1)) + taddchr('0'+f->fd1); + taddstr((f->type == INPIPE) ? "< " : "> "); + taddstr(f->name); + taddchr(' '); + break; + } + } + tptr--; +} + +void taddlist(l) /**/ +Lklist l; +{ +Lknode n; + + for (n = firstnode(l); n; incnode(n)) + { + taddstr(getdata(n)); + taddchr(' '); + } + tptr--; +} diff --git a/usr/othersrc/public/zsh-2.2/src/text.pro b/usr/othersrc/public/zsh-2.2/src/text.pro new file mode 100644 index 0000000000..e433133dec --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/text.pro @@ -0,0 +1,10 @@ +void taddchr DCLPROTO((int c)); +void taddstr DCLPROTO((char *s)); +void taddint DCLPROTO((int x)); +void taddnl DCLPROTO((void)); +char *getpermtext DCLPROTO((struct node *n)); +char *getjobtext DCLPROTO((struct node *n)); +void gettext2 DCLPROTO((struct node *n)); +void getsimptext DCLPROTO((Cmd cmd)); +void getredirs DCLPROTO((Cmd cmd)); +void taddlist DCLPROTO((Lklist l)); diff --git a/usr/othersrc/public/zsh-2.2/src/utils.pro b/usr/othersrc/public/zsh-2.2/src/utils.pro new file mode 100644 index 0000000000..b8cffc8526 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/utils.pro @@ -0,0 +1,83 @@ +int source DCLPROTO((char *s)); +void sourcehome DCLPROTO((char *s)); +void zerrnam DCLPROTO((char *cmd, char *fmt, char *str,int num)); +void zerr DCLPROTO((char *fmt, char *str,int num)); +void niceputc DCLPROTO((int c,FILE *f)); +void intr DCLPROTO((void)); +void noholdintr DCLPROTO((void)); +void holdintr DCLPROTO((void)); +char *fgetline DCLPROTO((char *buf,int len,FILE *in)); +char *findpwd DCLPROTO((char *s)); +char *fixpwd DCLPROTO((char *s)); +int ispwd DCLPROTO((char *s)); +char *xsymlink DCLPROTO((char *s)); +char **slashsplit DCLPROTO((char *s)); +int islink DCLPROTO((char *s)); +int xsymlinks DCLPROTO((char *s,int flag)); +void fprintdir DCLPROTO((char *s, FILE *f)); +void printdir DCLPROTO((char *s)); +void printdircr DCLPROTO((char *s)); +int finddir DCLPROTO((char *s)); +void adduserdir DCLPROTO((char *s,char *t)); +int dircmp DCLPROTO((char *s,char *t)); +int ddifftime DCLPROTO((time_t t1,time_t t2)); +void scanjobs DCLPROTO((void)); +void preprompt DCLPROTO((void)); +int arrlen DCLPROTO((char **s)); +void checkmailpath DCLPROTO((char **s)); +void saveoldfuncs DCLPROTO((char *x,Cmdnam y)); +void newcmdnamtab DCLPROTO((void)); +void freecmdnam DCLPROTO((vptr a)); +void freecompctl DCLPROTO((vptr a)); +void freestr DCLPROTO((vptr a)); +void freeanode DCLPROTO((vptr a)); +void freepm DCLPROTO((vptr a)); +void restoretty DCLPROTO((void)); +void gettyinfo DCLPROTO((struct ttyinfo *ti)); +void settyinfo DCLPROTO((struct ttyinfo *ti)); +void sanetty DCLPROTO((struct ttyinfo *ti)); +void adjustwinsize DCLPROTO((void)); +int zyztem DCLPROTO((char *s,char *t)); +int waitfork DCLPROTO((void)); +int movefd DCLPROTO((int fd)); +void redup DCLPROTO((int x,int y)); +void settrap DCLPROTO((int t0,List l)); +void unsettrap DCLPROTO((int t0)); +void dotrap DCLPROTO((int sig)); +void ztrncpy DCLPROTO((char *s,char *t,int len)); +void strucpy DCLPROTO((char **s,char *t)); +void struncpy DCLPROTO((char **s,char *t,int n)); +void checkrmall DCLPROTO((char *s)); +int getquery DCLPROTO((void)); +void spscannodis DCLPROTO((char *s,char *cn)); +void spscan DCLPROTO((char *s,char *junk)); +void spckword DCLPROTO((char **s,char **s2,char **tptr,int cmd,int ask)); +int ztrftime DCLPROTO((char *buf,int bufsize,char *fmt,struct tm *tm)); +char *join DCLPROTO((char **arr,int delim)); +char *spacejoin DCLPROTO((char **s)); +char *colonjoin DCLPROTO((char **s)); +char **colonsplit DCLPROTO((char *s)); +char **spacesplit DCLPROTO((char *s)); +List getshfunc DCLPROTO((char *nam)); +vptr allocnode DCLPROTO((int type)); +vptr dupstruct DCLPROTO((vptr a)); +void freestruct DCLPROTO((vptr a)); +Lklist duplist DCLPROTO((Lklist l,VFunc func)); +char **mkarray DCLPROTO((char *s)); +void feep DCLPROTO((void)); +void freearray DCLPROTO((char **s)); +int equalsplit DCLPROTO((char *s,char **t)); +void simplifyright DCLPROTO((List l)); +void inittyptab DCLPROTO((void)); +char **arrdup DCLPROTO((char **s)); +char *spname DCLPROTO((char *oldname)); +int mindist DCLPROTO((char *dir,char *guess,char *best)); +int spdist DCLPROTO((char *s,char *t,int thresh)); +char *zgetenv DCLPROTO((char *s)); +int tulower DCLPROTO((int c)); +int tuupper DCLPROTO((int c)); +void setcbreak DCLPROTO((void)); +int getlineleng DCLPROTO((void)); +void unsetcbreak DCLPROTO((void)); +void attachtty DCLPROTO((long pgrp)); +long gettygrp DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/watch.c b/usr/othersrc/public/zsh-2.2/src/watch.c new file mode 100644 index 0000000000..b3e66a7860 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/watch.c @@ -0,0 +1,363 @@ +/* + * + * watch.c - login/logout watching + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "zsh.h" +#include + +static int wtabsz; +struct utmp *wtab; + +/* get the time of login/logout for WATCH */ + +time_t getlogtime(u,inout) /**/ +struct utmp *u;int inout; +{ +FILE *in; +struct utmp uu; +int first = 1; +int srchlimit = 50; /* max number of wtmp records to search */ + + if (inout) + return u->ut_time; + if (!(in = fopen(WTMP_FILE,"r"))) + return time(NULL); + fseek(in,0,2); + do + { + if (fseek(in,((first) ? -1 : -2)*sizeof(struct utmp),1)) + { + fclose(in); + return time(NULL); + } + first = 0; + if (!fread(&uu,sizeof(struct utmp),1,in)) + { + fclose(in); + return time(NULL); + } + if (uu.ut_time < lastwatch || !srchlimit--) + { + fclose(in); + return time(NULL); + } + } + while (memcmp(&uu,u,sizeof(struct utmp))); + do + if (!fread(&uu,sizeof(struct utmp),1,in)) + { + fclose(in); + return time(NULL); + } + while (strncmp(uu.ut_line,u->ut_line,8)); + fclose(in); + return uu.ut_time; +} + +/* print a login/logout event */ + +void watchlog2(inout,u,fmt) /**/ +int inout;struct utmp *u;char *fmt; +{ +char *p,buf[40],*bf; +int i; +time_t timet; +struct tm *tm = NULL; + + while (*fmt) + if (*fmt != '%') + putchar(*fmt++); + else + { + fmt++; + switch(*fmt++) + { + case 'n': + printf("%.*s",8,u->ut_name); + break; + case 'a': + printf("%s",(!inout) ? "logged off" : "logged on"); + break; + case 'l': + if (u->ut_line[0] == 't') + printf("%.*s",5,u->ut_line+3); + else + printf("%.*s",8,u->ut_line); + break; +#ifdef UTMP_HOST + case 'm': + for (p = u->ut_host,i = 16; i && *p;i--,p++) + { + if (*p == '.' && !idigit(p[1])) + break; + putchar(*p); + } + break; + case 'M': + printf("%.*s",16,u->ut_host); + break; +#endif + case 't': + case '@': + timet = getlogtime(u,inout); + tm = localtime(&timet); + ztrftime(buf,40,"%l:%M%p",tm); + printf("%s",(*buf == ' ') ? buf+1 : buf); + break; + case 'T': + timet = getlogtime(u,inout); + tm = localtime(&timet); + ztrftime(buf,40,"%k:%M",tm); + printf("%s",buf); + break; + case 'w': + timet = getlogtime(u,inout); + tm = localtime(&timet); + ztrftime(buf,40,"%a %e",tm); + printf("%s",buf); + break; + case 'W': + timet = getlogtime(u,inout); + tm = localtime(&timet); + ztrftime(buf,40,"%m/%d/%y",tm); + printf("%s",buf); + break; + case 'D': + timet = getlogtime(u,inout); + tm = localtime(&timet); + ztrftime(buf,40,"%y-%m-%d",tm); + printf("%s",buf); + break; + case '%': + putchar('%'); + break; + case 'S': + bf = buf; + if (tgetstr("so",&bf)) + fputs(buf,stdout); + break; + case 's': + bf = buf; + if (tgetstr("se",&bf)) + fputs(buf,stdout); + break; + case 'B': + bf = buf; + if (tgetstr("md",&bf)) + fputs(buf,stdout); + break; + case 'b': + bf = buf; + if (tgetstr("me",&bf)) + fputs(buf,stdout); + break; + case 'U': + bf = buf; + if (tgetstr("us",&bf)) + fputs(buf,stdout); + break; + case 'u': + bf = buf; + if (tgetstr("ue",&bf)) + fputs(buf,stdout); + break; + default: + putchar('%'); + putchar(fmt[-1]); + break; + } + } + putchar('\n'); +} + +/* check the List for login/logouts */ + +void watchlog(inout,u,w,fmt) /**/ +int inout;struct utmp *u;char **w;char *fmt; +{ +char *v,*vv,sav; +int bad; + + if (*w && !strcmp(*w,"all")) + { + watchlog2(inout,u,fmt); + return; + } + for (; *w; w++) + { + bad = 0; + v = *w; + if (*v != '@' && *v != '%') + { + for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++); + sav = *vv; + *vv = '\0'; + if (strncmp(u->ut_name,v,8)) + bad = 1; + *vv = sav; + v = vv; + } + for (;;) + if (*v == '%') + { + for (vv = ++v; *vv && *vv != '@'; vv++); + sav = *vv; + *vv = '\0'; + if (strncmp(u->ut_line,v,8)) + bad = 1; + *vv = sav; + v = vv; + } +#ifdef UTMP_HOST + else if (*v == '@') + { + for (vv = ++v; *vv && *vv != '%'; vv++); + sav = *vv; + *vv = '\0'; + if (strncmp(u->ut_host,v,strlen(v))) + bad = 1; + *vv = sav; + v = vv; + } +#endif + else + break; + if (!bad) + { + watchlog2(inout,u,fmt); + return; + } + } +} + +/* compare 2 utmp entries */ + +int ucmp(u,v) /**/ +struct utmp *u;struct utmp *v; +{ + if (u->ut_time == v->ut_time) + return strncmp(u->ut_line,v->ut_line,8); + return u->ut_time - v->ut_time; +} + +/* initialize the user List */ + +void readwtab() /**/ +{ +struct utmp *uptr; +int wtabmax = 32; +FILE *in; + + wtabsz = 0; + if (!(in = fopen(UTMP_FILE,"r"))) return; + uptr = wtab = (struct utmp *) zalloc(wtabmax*sizeof(struct utmp)); + while (fread(uptr,sizeof(struct utmp),1,in)) +#ifdef USER_PROCESS + if (uptr->ut_type == USER_PROCESS) +#else + if (uptr->ut_name[0]) +#endif + { + uptr++; + if (++wtabsz == wtabmax) + uptr = (wtab = (struct utmp *) realloc((vptr) wtab,(wtabmax*=2)* + sizeof(struct utmp)))+wtabsz; + } + fclose(in); + if (wtabsz) + qsort(wtab,wtabsz,sizeof(struct utmp),ucmp); +} + +/* check for login/logout events; executed before each prompt + if WATCH is set */ + +void dowatch() /**/ +{ +char **s = watch; +char *fmt = (watchfmt) ? watchfmt : DEFWATCHFMT; +FILE *in; +int utabsz = 0,utabmax = wtabsz+4,uct,wct; +struct utmp *utab,*uptr,*wptr; + + holdintr(); + if (!fmt) + fmt = "%n has %a %l from %m."; + if (!wtab) { + readwtab(); + noholdintr(); + return; + } + uptr = utab = (struct utmp *) zalloc(utabmax*sizeof(struct utmp)); + if (!(in = fopen(UTMP_FILE,"r"))) { + free(utab); + return; + } + while (fread(uptr,sizeof *uptr,1,in)) +#ifdef USER_PROCESS + if (uptr->ut_type == USER_PROCESS) +#else + if (uptr->ut_name[0]) +#endif + { + uptr++; + if (++utabsz == utabmax) + uptr = (utab = (struct utmp *) realloc((vptr) utab,(utabmax*=2)* + sizeof(struct utmp)))+utabsz; + } + fclose(in); + noholdintr(); + if (errflag) { + free(utab); + return; + } + if (utabsz) + qsort(utab,utabsz,sizeof(struct utmp),ucmp); + + wct = wtabsz; uct = utabsz; + uptr = utab; wptr = wtab; + if (errflag) { + free(utab); + return; + } + while ((uct || wct) && !errflag) + if (!uct || (wct && ucmp(uptr,wptr) > 0)) + wct--,watchlog(0,wptr++,s,fmt); + else if (!wct || (uct && ucmp(uptr,wptr) < 0)) + uct--,watchlog(1,uptr++,s,fmt); + else + uptr++,wptr++,wct--,uct--; + free(wtab); + wtab = utab; + wtabsz = utabsz; + fflush(stdout); +} + +int bin_log(nam,argv,ops,func) /**/ +char *nam;char **argv;char *ops;int func; +{ + if (!watch) + return 1; + if (wtab) + free(wtab); + wtab = (struct utmp *) zalloc(1); + wtabsz = 0; + dowatch(); + return 0; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/watch.pro b/usr/othersrc/public/zsh-2.2/src/watch.pro new file mode 100644 index 0000000000..be940366a4 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/watch.pro @@ -0,0 +1,7 @@ +time_t getlogtime DCLPROTO((struct utmp *u,int inout)); +void watchlog2 DCLPROTO((int inout,struct utmp *u,char *fmt)); +void watchlog DCLPROTO((int inout,struct utmp *u,char **w,char *fmt)); +int ucmp DCLPROTO((struct utmp *u,struct utmp *v)); +void readwtab DCLPROTO((void)); +void dowatch DCLPROTO((void)); +int bin_log DCLPROTO((char *nam,char **argv,char *ops,int func)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle.h b/usr/othersrc/public/zsh-2.2/src/zle.h new file mode 100644 index 0000000000..04e07df3f8 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle.h @@ -0,0 +1,343 @@ +/* + * + * zle.h - header file for line editor + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#ifdef ZLEGLOBALS +#define ZLEXTERN +#else +#define ZLEXTERN extern +#endif + +#ifdef ZLE + +/* cursor position */ +ZLEXTERN int cs; + +/* line length */ +ZLEXTERN int ll; + +/* size of line buffer */ +ZLEXTERN int linesz; + +/* location of mark */ +ZLEXTERN int mark; + +/* last character pressed */ +ZLEXTERN int c; + +/* the z_ binding id for this key */ +ZLEXTERN int bindk; + +/* command argument */ +ZLEXTERN int mult; + +/* insert mode/overwrite mode flag */ +ZLEXTERN int insmode; + +/* cost of last update */ +ZLEXTERN int cost; + +/* flags associated with last command */ +ZLEXTERN int lastcmd; + +/* column position before last LINEMOVE movement */ +ZLEXTERN int lastcol; + +/* != 0 if we're getting a vi range */ +ZLEXTERN int virangeflag; + +/* kludge to get cw and dw to work right */ +ZLEXTERN int wordflag; + +#endif + +/* last named command done */ +ZLEXTERN int lastnamed; + +/* != 0 if we're done editing */ +ZLEXTERN int done; + +/* length of prompt on screen */ +ZLEXTERN int pptlen; + +/* current history line number */ +ZLEXTERN int histline; + +ZLEXTERN int eofsent; + +/* != 0 if we need to call resetvideo() */ +ZLEXTERN int resetneeded; + +/* != 0 if the line editor is active */ +ZLEXTERN int zleactive; + +/* the line buffer */ +ZLEXTERN unsigned char *line; + +/* the cut buffer */ +ZLEXTERN char *cutbuf; + +/* prompt and rprompt */ +ZLEXTERN char *pmpt, *pmpt2; + +/* the last line in the history (the current one) */ +ZLEXTERN char *curhistline; + +/* the status line */ +ZLEXTERN char *statusline; + +/* 1 if a complete added a slash at the end of a directory name */ +ZLEXTERN int addedslash; + +/* + the current history line and cursor position for the top line + on the buffer stack +*/ + +ZLEXTERN int stackhist,stackcs; + +/* != 0 if we are in the middle of a menu completion */ +ZLEXTERN int menucmp; + +/* != 0 if we are making undo records */ +ZLEXTERN int undoing; + +/* last vi change buffer */ +ZLEXTERN int vichgbufsz,vichgbufptr,vichgflag; +ZLEXTERN char *vichgbuf; + +ZLEXTERN int viinsbegin; + +typedef void bindfunc DCLPROTO((void)); +typedef bindfunc *F; + +struct key { + struct hashnode *next; int canfree; char *nam; /* hash data */ + int func; /* function code for this key */ + char *str; /* string corresponding to this key, + if func = z_sequenceleadin */ + int len; /* length of string */ + }; +struct zlecmd { + char *name; /* name of function */ + F func; /* handler function */ + int flags; + }; + +/* undo event */ + +struct undoent { + int pref; /* number of initial chars unchanged */ + int suff; /* number of trailing chars unchanged */ + int len; /* length of changed chars */ + int cs; /* cursor pos before change */ + char *change; /* NOT null terminated */ + }; + +#define UNDOCT 64 + +struct undoent undos[UNDOCT]; + +/* the line before last mod (for undo purposes) */ +ZLEXTERN unsigned char *lastline; + +/* buffer specified with "x */ +ZLEXTERN int vibufspec; + +ZLEXTERN int undoct,lastcs; + +ZLEXTERN char *visrchstr; +ZLEXTERN int visrchsense; + +#define ZLE_MOVEMENT 1 +#define ZLE_MENUCMP 2 +#define ZLE_UNDO 4 +#define ZLE_YANK 8 +#define ZLE_LINEMOVE 16 +#define ZLE_ARG 32 +#define ZLE_NAMEDBUFFER 128 +#define ZLE_KILL (64|ZLE_NAMEDBUFFER) +#define ZLE_HISTSEARCH 256 +#define ZLE_NEGARG 512 +#define ZLE_INSERT 1024 + +typedef struct key *Key; + +ZLEXTERN int *bindtab; +extern int emacsbind[256]; +ZLEXTERN int altbindtab[256],mainbindtab[256]; +extern int viinsbind[],vicmdbind[]; +ZLEXTERN int vimarkcs[27],vimarkline[27]; + +#define KRINGCT 8 +ZLEXTERN char *kring[KRINGCT]; +ZLEXTERN int kringnum; +ZLEXTERN char *vibuf[36]; + +#define z_acceptandhold 0 +#define z_acceptandinfernexthistory 1 +#define z_acceptandmenucomplete 2 +#define z_acceptline 3 +#define z_acceptlineanddownhistory 4 +#define z_backwardchar 5 +#define z_backwarddeletechar 6 +#define z_backwarddeleteword 7 +#define z_backwardkillline 8 +#define z_backwardkillword 9 +#define z_backwardword 10 +#define z_beginningofbufferorhistory 11 +#define z_beginningofhistory 12 +#define z_beginningofline 13 +#define z_beginningoflinehist 14 +#define z_capitalizeword 15 +#define z_clearscreen 16 +#define z_completeword 17 +#define z_copyprevword 18 +#define z_copyregionaskill 19 +#define z_deletechar 20 +#define z_deletecharorlist 21 +#define z_deleteword 22 +#define z_digitargument 23 +#define z_downcaseword 24 +#define z_downhistory 25 +#define z_downlineorhistory 26 +#define z_endofbufferorhistory 27 +#define z_endofhistory 28 +#define z_endofline 29 +#define z_endoflinehist 30 +#define z_exchangepointandmark 31 +#define z_executelastnamedcmd 32 +#define z_executenamedcmd 33 +#define z_expandhistory 34 +#define z_expandorcomplete 35 +#define z_expandword 36 +#define z_forwardchar 37 +#define z_forwardword 38 +#define z_getline 39 +#define z_gosmacstransposechars 40 +#define z_historyincrementalsearchbackward 41 +#define z_historyincrementalsearchforward 42 +#define z_historysearchbackward 43 +#define z_historysearchforward 44 +#define z_infernexthistory 45 +#define z_insertlastword 46 +#define z_killbuffer 47 +#define z_killline 48 +#define z_killregion 49 +#define z_killwholeline 50 +#define z_listchoices 51 +#define z_listexpand 52 +#define z_magicspace 53 +#define z_menucompleteword 54 +#define z_menuexpandorcomplete 55 +#define z_overwritemode 56 +#define z_pushline 57 +#define z_quotedinsert 58 +#define z_quoteline 59 +#define z_quoteregion 60 +#define z_redisplay 61 +#define z_reversemenucomplete 62 +#define z_runhelp 63 +#define z_selfinsert 64 +#define z_selfinsertunmeta 65 +#define z_sendbreak 66 +#define z_sendstring 67 +#define z_sequenceleadin 68 +#define z_setmarkcommand 69 +#define z_spellword 70 +#define z_toggleliteralhistory 71 +#define z_transposechars 72 +#define z_transposewords 73 +#define z_undefinedkey 74 +#define z_undo 75 +#define z_universalargument 76 +#define z_upcaseword 77 +#define z_uphistory 78 +#define z_uplineorhistory 79 +#define z_viaddeol 80 +#define z_viaddnext 81 +#define z_vibackwardblankword 82 +#define z_vibackwardchar 83 +#define z_vibackwarddeletechar 84 +#define z_vibeginningofline 85 +#define z_vicapslockpanic 86 +#define z_vichange 87 +#define z_vichangeeol 88 +#define z_vichangewholeline 89 +#define z_vicmdmode 90 +#define z_videlete 91 +#define z_videletechar 92 +#define z_vidigitorbeginningofline 93 +#define z_viendofline 94 +#define z_vifetchhistory 95 +#define z_vifindnextchar 96 +#define z_vifindnextcharskip 97 +#define z_vifindprevchar 98 +#define z_vifindprevcharskip 99 +#define z_vifirstnonblank 100 +#define z_viforwardblankword 101 +#define z_viforwardblankwordend 102 +#define z_viforwardchar 103 +#define z_viforwardwordend 104 +#define z_vigotocolumn 105 +#define z_vigotomark 106 +#define z_vigotomarkline 107 +#define z_vihistorysearchbackward 108 +#define z_vihistorysearchforward 109 +#define z_viindent 110 +#define z_viinsert 111 +#define z_viinsertbol 112 +#define z_vijoin 113 +#define z_vimatchbracket 114 +#define z_viopenlineabove 115 +#define z_viopenlinebelow 116 +#define z_vioperswapcases 117 +#define z_viputafter 118 +#define z_virepeatchange 119 +#define z_virepeatfind 120 +#define z_virepeatsearch 121 +#define z_vireplace 122 +#define z_vireplacechars 123 +#define z_virevrepeatfind 124 +#define z_virevrepeatsearch 125 +#define z_visetbuffer 126 +#define z_visetmark 127 +#define z_visubstitute 128 +#define z_viswapcase 129 +#define z_viundochange 130 +#define z_viunindent 131 +#define z_viyank 132 +#define z_viyankeol 133 +#define z_whichcommand 134 +#define z_yank 135 +#define z_yankpop 136 +#define z_emacsbackwardword 137 +#define z_emacsforwardword 138 +#define z_killword 139 +#define z_vikillline 140 +#define z_vibackwardkillword 141 +#define z_expandcmdpath 142 +#define z_negargument 143 +#define z_poundinsert 144 +#define z_viforwardword 145 +#define z_vibackwardword 146 +#define ZLECMDCOUNT 147 + +extern struct zlecmd zlecmds[]; + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_bindings.c b/usr/othersrc/public/zsh-2.2/src/zle_bindings.c new file mode 100644 index 0000000000..286d3ad7fe --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_bindings.c @@ -0,0 +1,600 @@ +/* + * + * zle_bindings.c - commands and keymaps + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + + +struct zlecmd zlecmds[] = { +"accept-and-hold",acceptandhold,0, +"accept-and-infer-next-history",acceptandinfernexthistory,0, +"accept-and-menu-complete", acceptandmenucomplete, ZLE_MENUCMP, +"accept-line",acceptline,0, +"accept-line-and-down-history",acceptlineanddownhistory,0, +"backward-char",backwardchar,ZLE_MOVEMENT, +"backward-delete-char",backwarddeletechar,0, +"backward-delete-word",backwarddeleteword,0, +"backward-kill-line",backwardkillline,ZLE_KILL, +"backward-kill-word",backwardkillword,ZLE_KILL, +"backward-word",backwardword,ZLE_MOVEMENT, +"beginning-of-buffer-or-history",beginningofbufferorhistory,ZLE_MOVEMENT, +"beginning-of-history",beginningofhistory,0, +"beginning-of-line",beginningofline,ZLE_MOVEMENT, +"beginning-of-line-hist",beginningoflinehist,ZLE_MOVEMENT, +"capitalize-word",capitalizeword,0, +"clear-screen",clearscreen,0, +"complete-word",completeword,ZLE_MENUCMP, +"copy-prev-word",copyprevword,0, +"copy-region-as-kill",copyregionaskill,ZLE_KILL, +"delete-char",deletechar,0, +"delete-char-or-list",deletecharorlist,ZLE_MENUCMP, +"delete-word",deleteword,0, +"digit-argument",digitargument,ZLE_ARG, +"down-case-word",downcaseword,0, +"down-history",downhistory,0, +"down-line-or-history",downlineorhistory,ZLE_MOVEMENT|ZLE_LINEMOVE, +"end-of-buffer-or-history",endofbufferorhistory,ZLE_MOVEMENT, +"end-of-history",endofhistory,0, +"end-of-line",endofline,ZLE_MOVEMENT, +"end-of-line-hist",endoflinehist,ZLE_MOVEMENT, +"exchange-point-and-mark",exchangepointandmark,ZLE_MOVEMENT, +"execute-last-named-cmd",NULL,0, +"execute-named-cmd",NULL,0, +"expand-history",expandhistory,0, +"expand-or-complete",expandorcomplete,ZLE_MENUCMP, +"expand-word",expandword,0, +"forward-char",forwardchar,ZLE_MOVEMENT, +"forward-word",forwardword,ZLE_MOVEMENT, +"get-line",getline,0, +"gosmacs-transpose-chars",gosmacstransposechars,0, +"history-incremental-search-backward",historyincrementalsearchbackward,0, +"history-incremental-search-forward",historyincrementalsearchforward,0, +"history-search-backward",historysearchbackward,ZLE_HISTSEARCH, +"history-search-forward",historysearchforward,ZLE_HISTSEARCH, +"infer-next-history",infernexthistory,0, +"insert-last-word",insertlastword,ZLE_INSERT, +"kill-buffer",killbuffer,ZLE_KILL, +"kill-line",killline,ZLE_KILL, +"kill-region",killregion,ZLE_KILL, +"kill-whole-line",killwholeline,ZLE_KILL, +"list-choices",listchoices,0, +"list-expand",listexpand,ZLE_MENUCMP, +"magic-space",magicspace,0, +"menu-complete",menucompleteword,ZLE_MENUCMP, +"menu-expand-or-complete",menuexpandorcomplete,ZLE_MENUCMP, +"overwrite-mode",overwritemode,0, +"push-line",pushline,0, +"quoted-insert",quotedinsert,ZLE_INSERT, +"quote-line",quoteline,0, +"quote-region",quoteregion,0, +"redisplay",redisplay,0, +"reverse-menu-complete",reversemenucomplete,ZLE_MENUCMP, +"run-help",processcmd,0, +"self-insert",selfinsert,ZLE_INSERT, +"self-insert-unmeta",selfinsertunmeta,ZLE_INSERT, +"send-break",sendbreak,0, +"send-string",sendstring,0, +"",NULL,0, +"set-mark-command",setmarkcommand,0, +"spell-word",spellword,0, +"toggle-literal-history",toggleliteralhistory,0, +"transpose-chars",transposechars,0, +"transpose-words",transposewords,0, +"undefined-key",undefinedkey,0, +"undo",undo,ZLE_UNDO, +"universal-argument",universalargument,ZLE_ARG, +"up-case-word",upcaseword,0, +"up-history",uphistory,0, +"up-line-or-history",uplineorhistory,ZLE_LINEMOVE|ZLE_MOVEMENT, +"vi-add-eol",viaddeol,0, +"vi-add-next",viaddnext,0, +"vi-backward-blank-word",vibackwardblankword,ZLE_MOVEMENT, +"vi-backward-char",vibackwardchar,ZLE_MOVEMENT, +"vi-backward-delete-char",vibackwarddeletechar,ZLE_KILL, +"vi-beginning-of-line",vibeginningofline,ZLE_MOVEMENT, +"vi-caps-lock-panic",vicapslockpanic,0, +"vi-change",vichange,0, +"vi-change-eol",vichangeeol,0, +"vi-change-whole-line",vichangewholeline,0, +"vi-cmd-mode",vicmdmode,0, +"vi-delete",videlete,ZLE_KILL, +"vi-delete-char",videletechar,ZLE_KILL, +"vi-digit-or-beginning-of-line",NULL,0, +"vi-end-of-line",viendofline,ZLE_MOVEMENT, +"vi-fetch-history",vifetchhistory,0, +"vi-find-next-char",vifindnextchar,ZLE_MOVEMENT, +"vi-find-next-char-skip",vifindnextcharskip,ZLE_MOVEMENT, +"vi-find-prev-char",vifindprevchar,ZLE_MOVEMENT, +"vi-find-prev-char-skip",vifindprevcharskip,ZLE_MOVEMENT, +"vi-first-non-blank",vifirstnonblank,ZLE_MOVEMENT, +"vi-forward-blank-word",viforwardblankword,ZLE_MOVEMENT, +"vi-forward-blank-word-end",viforwardblankwordend,ZLE_MOVEMENT, +"vi-forward-char",viforwardchar,ZLE_MOVEMENT, +"vi-forward-word-end",viforwardwordend,ZLE_MOVEMENT, +"vi-goto-column",vigotocolumn,ZLE_MOVEMENT, +"vi-goto-mark",vigotomark,ZLE_MOVEMENT, +"vi-goto-mark-line",vigotomarkline,ZLE_MOVEMENT, +"vi-history-search-backward",vihistorysearchbackward,0, +"vi-history-search-forward",vihistorysearchforward,0, +"vi-indent",viindent,0, +"vi-insert",viinsert,0, +"vi-insert-bol",viinsertbol,0, +"vi-join",vijoin,0, +"vi-match-bracket",vimatchbracket,ZLE_MOVEMENT, +"vi-open-line-above",viopenlineabove,0, +"vi-open-line-below",viopenlinebelow,0, +"vi-oper-swap-case",vioperswapcase,0, +"vi-put-after",viputafter,ZLE_YANK, +"vi-repeat-change",virepeatchange,0, +"vi-repeat-find",virepeatfind,ZLE_MOVEMENT, +"vi-repeat-search",virepeatsearch,ZLE_MOVEMENT, +"vi-replace",vireplace,0, +"vi-replace-chars",vireplacechars,0, +"vi-rev-repeat-find",virevrepeatfind,ZLE_MOVEMENT, +"vi-rev-repeat-search",virevrepeatsearch,ZLE_MOVEMENT, +"vi-set-buffer",visetbuffer,0, +"vi-set-mark",visetmark,0, +"vi-substitute",visubstitute,0, +"vi-swap-case",viswapcase,0, +"vi-undo-change",undo,0, +"vi-unindent",viunindent,0, +"vi-yank",viyank,0, +"vi-yank-eol",viyankeol,0, +"which-command",processcmd,0, +"yank",yank,ZLE_YANK|ZLE_NAMEDBUFFER, +"yank-pop",yankpop,ZLE_YANK, +"emacs-forward-word",emacsforwardword,ZLE_MOVEMENT, +"emacs-backward-word",emacsbackwardword,ZLE_MOVEMENT, +"kill-word",killword,ZLE_KILL, +"vi-kill-line",vikillline,0, +"vi-backward-kill-word",vibackwardkillword,0, +"expand-cmd-path",expandcmdpath,0, +"neg-argument",negargument,ZLE_NEGARG, +"pound-insert",poundinsert,0, +"vi-forward-word",viforwardword,ZLE_MOVEMENT, +"vi-backward-word",vibackwardword,ZLE_MOVEMENT, +"",NULL,0 +}; + +int emacsbind[256] = { +/* ^@ */ z_setmarkcommand, +/* ^A */ z_beginningofline, +/* ^B */ z_backwardchar, +/* ^C */ z_sendbreak, +/* ^D */ z_deletecharorlist, +/* ^E */ z_endofline, +/* ^F */ z_forwardchar, +/* ^G */ z_undefinedkey, +/* ^H */ z_backwarddeletechar, +/* ^I */ z_expandorcomplete, +/* ^J */ z_acceptline, +/* ^K */ z_killline, +/* ^L */ z_clearscreen, +/* ^M */ z_acceptline, +/* ^N */ z_downlineorhistory, +/* ^O */ z_acceptlineanddownhistory, +/* ^P */ z_uplineorhistory, +/* ^Q */ z_pushline, +/* ^R */ z_historyincrementalsearchbackward, +/* ^S */ z_historyincrementalsearchforward, +/* ^T */ z_transposechars, +/* ^U */ z_killwholeline, +/* ^V */ z_quotedinsert, +/* ^W */ z_backwardkillword, +/* ^X */ z_sequenceleadin, +/* ^Y */ z_yank, +/* ^Z */ z_undefinedkey, +/* ^[ */ z_sequenceleadin, +/* ^\ */ z_undefinedkey, +/* ^] */ z_undefinedkey, +/* ^^ */ z_undefinedkey, +/* ^_ */ z_undo, +/* */ z_selfinsert, +/* ! */ z_selfinsert, +/* " */ z_selfinsert, +/* # */ z_selfinsert, +/* $ */ z_selfinsert, +/* % */ z_selfinsert, +/* & */ z_selfinsert, +/* ' */ z_selfinsert, +/* ( */ z_selfinsert, +/* ) */ z_selfinsert, +/* * */ z_selfinsert, +/* + */ z_selfinsert, +/* , */ z_selfinsert, +/* - */ z_selfinsert, +/* . */ z_selfinsert, +/* / */ z_selfinsert, +/* 0 */ z_selfinsert, +/* 1 */ z_selfinsert, +/* 2 */ z_selfinsert, +/* 3 */ z_selfinsert, +/* 4 */ z_selfinsert, +/* 5 */ z_selfinsert, +/* 6 */ z_selfinsert, +/* 7 */ z_selfinsert, +/* 8 */ z_selfinsert, +/* 9 */ z_selfinsert, +/* : */ z_selfinsert, +/* ; */ z_selfinsert, +/* < */ z_selfinsert, +/* = */ z_selfinsert, +/* > */ z_selfinsert, +/* ? */ z_selfinsert, +/* @ */ z_selfinsert, +/* A */ z_selfinsert, +/* B */ z_selfinsert, +/* C */ z_selfinsert, +/* D */ z_selfinsert, +/* E */ z_selfinsert, +/* F */ z_selfinsert, +/* G */ z_selfinsert, +/* H */ z_selfinsert, +/* I */ z_selfinsert, +/* J */ z_selfinsert, +/* K */ z_selfinsert, +/* L */ z_selfinsert, +/* M */ z_selfinsert, +/* N */ z_selfinsert, +/* O */ z_selfinsert, +/* P */ z_selfinsert, +/* Q */ z_selfinsert, +/* R */ z_selfinsert, +/* S */ z_selfinsert, +/* T */ z_selfinsert, +/* U */ z_selfinsert, +/* V */ z_selfinsert, +/* W */ z_selfinsert, +/* X */ z_selfinsert, +/* Y */ z_selfinsert, +/* Z */ z_selfinsert, +/* [ */ z_selfinsert, +/* \ */ z_selfinsert, +/* ] */ z_selfinsert, +/* ^ */ z_selfinsert, +/* _ */ z_selfinsert, +/* ` */ z_selfinsert, +/* a */ z_selfinsert, +/* b */ z_selfinsert, +/* c */ z_selfinsert, +/* d */ z_selfinsert, +/* e */ z_selfinsert, +/* f */ z_selfinsert, +/* g */ z_selfinsert, +/* h */ z_selfinsert, +/* i */ z_selfinsert, +/* j */ z_selfinsert, +/* k */ z_selfinsert, +/* l */ z_selfinsert, +/* m */ z_selfinsert, +/* n */ z_selfinsert, +/* o */ z_selfinsert, +/* p */ z_selfinsert, +/* q */ z_selfinsert, +/* r */ z_selfinsert, +/* s */ z_selfinsert, +/* t */ z_selfinsert, +/* u */ z_selfinsert, +/* v */ z_selfinsert, +/* w */ z_selfinsert, +/* x */ z_selfinsert, +/* y */ z_selfinsert, +/* z */ z_selfinsert, +/* { */ z_selfinsert, +/* | */ z_selfinsert, +/* } */ z_selfinsert, +/* ~ */ z_selfinsert, +/* ^? */ z_backwarddeletechar, +/* M-^@ */ z_undefinedkey, +/* M-^A */ z_undefinedkey, +/* M-^B */ z_undefinedkey, +/* M-^C */ z_undefinedkey, +/* M-^D */ z_listchoices, +/* M-^E */ z_undefinedkey, +/* M-^F */ z_undefinedkey, +/* M-^G */ z_undefinedkey, +/* M-^H */ z_backwardkillword, +/* M-^I */ z_selfinsertunmeta, +/* M-^J */ z_selfinsertunmeta, +/* M-^K */ z_undefinedkey, +/* M-^L */ z_clearscreen, +/* M-^M */ z_selfinsertunmeta, +/* M-^N */ z_undefinedkey, +/* M-^O */ z_undefinedkey, +/* M-^P */ z_undefinedkey, +/* M-^Q */ z_undefinedkey, +/* M-^R */ z_undefinedkey, +/* M-^S */ z_undefinedkey, +/* M-^T */ z_undefinedkey, +/* M-^U */ z_undefinedkey, +/* M-^V */ z_undefinedkey, +/* M-^W */ z_undefinedkey, +/* M-^X */ z_undefinedkey, +/* M-^Y */ z_undefinedkey, +/* M-^Z */ z_undefinedkey, +/* M-^[ */ z_undefinedkey, +/* M-^\ */ z_undefinedkey, +/* M-^] */ z_undefinedkey, +/* M-^^ */ z_undefinedkey, +/* M-^_ */ z_copyprevword, +/* M- */ z_expandhistory, +/* M-! */ z_expandhistory, +/* M-" */ z_quoteregion, +/* M-# */ z_undefinedkey, +/* M-$ */ z_spellword, +/* M-% */ z_undefinedkey, +/* M-& */ z_undefinedkey, +/* M-' */ z_quoteline, +/* M-( */ z_undefinedkey, +/* M-) */ z_undefinedkey, +/* M-* */ z_undefinedkey, +/* M-+ */ z_undefinedkey, +/* M-, */ z_undefinedkey, +/* M-- */ z_negargument, +/* M-. */ z_insertlastword, +/* M-/ */ z_undefinedkey, +/* M-0 */ z_digitargument, +/* M-1 */ z_digitargument, +/* M-2 */ z_digitargument, +/* M-3 */ z_digitargument, +/* M-4 */ z_digitargument, +/* M-5 */ z_digitargument, +/* M-6 */ z_digitargument, +/* M-7 */ z_digitargument, +/* M-8 */ z_digitargument, +/* M-9 */ z_digitargument, +/* M-: */ z_undefinedkey, +/* M-; */ z_undefinedkey, +/* M-< */ z_beginningofbufferorhistory, +/* M-= */ z_undefinedkey, +/* M-> */ z_endofbufferorhistory, +/* M-? */ z_whichcommand, +/* M-@ */ z_undefinedkey, +/* M-A */ z_acceptandhold, +/* M-B */ z_backwardword, +/* M-C */ z_capitalizeword, +/* M-D */ z_deleteword, +/* M-E */ z_undefinedkey, +/* M-F */ z_forwardword, +/* M-G */ z_getline, +/* M-H */ z_runhelp, +/* M-I */ z_undefinedkey, +/* M-J */ z_undefinedkey, +/* M-K */ z_undefinedkey, +/* M-L */ z_downcaseword, +/* M-M */ z_undefinedkey, +/* M-N */ z_historysearchforward, +/* M-O */ z_undefinedkey, +/* M-P */ z_historysearchbackward, +/* M-Q */ z_pushline, +/* M-R */ z_toggleliteralhistory, +/* M-S */ z_spellword, +/* M-T */ z_transposewords, +/* M-U */ z_upcaseword, +/* M-V */ z_undefinedkey, +/* M-W */ z_copyregionaskill, +/* M-X */ z_undefinedkey, +/* M-Y */ z_undefinedkey, +/* M-Z */ z_undefinedkey, +/* M-[ */ z_sequenceleadin, +/* M-\ */ z_undefinedkey, +/* M-] */ z_undefinedkey, +/* M-^ */ z_undefinedkey, +/* M-_ */ z_insertlastword, +/* M-` */ z_undefinedkey, +/* M-a */ z_acceptandhold, +/* M-b */ z_backwardword, +/* M-c */ z_capitalizeword, +/* M-d */ z_deleteword, +/* M-e */ z_undefinedkey, +/* M-f */ z_forwardword, +/* M-g */ z_getline, +/* M-h */ z_runhelp, +/* M-i */ z_undefinedkey, +/* M-j */ z_undefinedkey, +/* M-k */ z_undefinedkey, +/* M-l */ z_downcaseword, +/* M-m */ z_undefinedkey, +/* M-n */ z_historysearchforward, +/* M-o */ z_undefinedkey, +/* M-p */ z_historysearchbackward, +/* M-q */ z_pushline, +/* M-r */ z_toggleliteralhistory, +/* M-s */ z_spellword, +/* M-t */ z_transposewords, +/* M-u */ z_upcaseword, +/* M-v */ z_undefinedkey, +/* M-w */ z_copyregionaskill, +/* M-x */ z_executenamedcmd, +/* M-y */ z_yankpop, +/* M-z */ z_executelastnamedcmd, +/* M-{ */ z_undefinedkey, +/* M-| */ z_vigotocolumn, +/* M-} */ z_undefinedkey, +/* M-~ */ z_undefinedkey, +/* M-^? */ z_backwardkillword, +}; + +int viinsbind[32] = { +/* ^@ */ z_undefinedkey, +/* ^A */ z_selfinsert, +/* ^B */ z_selfinsert, +/* ^C */ z_sendbreak, +/* ^D */ z_listchoices, +/* ^E */ z_selfinsert, +/* ^F */ z_selfinsert, +/* ^G */ z_selfinsert, +/* ^H */ z_vibackwarddeletechar, +/* ^I */ z_expandorcomplete, +/* ^J */ z_acceptline, +/* ^K */ z_killline, +/* ^L */ z_clearscreen, +/* ^M */ z_acceptline, +/* ^N */ z_selfinsert, +/* ^O */ z_selfinsert, +/* ^P */ z_selfinsert, +/* ^Q */ z_selfinsert, +/* ^R */ z_redisplay, +/* ^S */ z_selfinsert, +/* ^T */ z_selfinsert, +/* ^U */ z_vikillline, +/* ^V */ z_quotedinsert, +/* ^W */ z_vibackwardkillword, +/* ^X */ z_selfinsert, +/* ^Y */ z_selfinsert, +/* ^Z */ z_selfinsert, +/* ^[ */ z_vicmdmode, +/* ^\ */ z_selfinsert, +/* ^] */ z_selfinsert, +/* ^^ */ z_selfinsert, +/* ^_ */ z_selfinsert, +}; + +int vicmdbind[128] = { +/* ^@ */ z_undefinedkey, +/* ^A */ z_beginningofline, +/* ^B */ z_undefinedkey, +/* ^C */ z_sendbreak, +/* ^D */ z_listchoices, +/* ^E */ z_endofline, +/* ^F */ z_undefinedkey, +/* ^G */ z_listexpand, +/* ^H */ z_backwarddeletechar, +/* ^I */ z_completeword, +/* ^J */ z_acceptline, +/* ^K */ z_killline, +/* ^L */ z_clearscreen, +/* ^M */ z_acceptline, +/* ^N */ z_downhistory, +/* ^O */ z_undefinedkey, +/* ^P */ z_uphistory, +/* ^Q */ z_undefinedkey, +/* ^R */ z_redisplay, +/* ^S */ z_undefinedkey, +/* ^T */ z_undefinedkey, +/* ^U */ z_killbuffer, +/* ^V */ z_undefinedkey, +/* ^W */ z_backwardkillword, +/* ^X */ z_expandorcomplete, +/* ^Y */ z_undefinedkey, +/* ^Z */ z_undefinedkey, +/* ^[ */ z_sequenceleadin, +/* ^\ */ z_undefinedkey, +/* ^] */ z_undefinedkey, +/* ^^ */ z_undefinedkey, +/* ^_ */ z_undefinedkey, +/* */ z_viforwardchar, +/* ! */ z_undefinedkey, +/* " */ z_visetbuffer, +/* # */ z_poundinsert, +/* $ */ z_viendofline, +/* % */ z_vimatchbracket, +/* & */ z_undefinedkey, +/* ' */ z_vigotomarkline, +/* ( */ z_undefinedkey, +/* ) */ z_undefinedkey, +/* * */ z_undefinedkey, +/* + */ z_downlineorhistory, +/* , */ z_virevrepeatfind, +/* - */ z_uplineorhistory, +/* . */ z_virepeatchange, +/* / */ z_vihistorysearchbackward, +/* 0 */ z_vidigitorbeginningofline, +/* 1 */ z_digitargument, +/* 2 */ z_digitargument, +/* 3 */ z_digitargument, +/* 4 */ z_digitargument, +/* 5 */ z_digitargument, +/* 6 */ z_digitargument, +/* 7 */ z_digitargument, +/* 8 */ z_digitargument, +/* 9 */ z_digitargument, +/* : */ z_undefinedkey, +/* ; */ z_virepeatfind, +/* < */ z_viunindent, +/* = */ z_listchoices, +/* > */ z_viindent, +/* ? */ z_vihistorysearchforward, +/* @ */ z_undefinedkey, +/* A */ z_viaddeol, +/* B */ z_vibackwardblankword, +/* C */ z_vichangeeol, +/* D */ z_killline, +/* E */ z_viforwardblankwordend, +/* F */ z_vifindprevchar, +/* G */ z_vifetchhistory, +/* H */ z_vicapslockpanic, +/* I */ z_viinsertbol, +/* J */ z_historysearchforward, +/* K */ z_historysearchbackward, +/* L */ z_undefinedkey, +/* M */ z_undefinedkey, +/* N */ z_virevrepeatsearch, +/* O */ z_viopenlineabove, +/* P */ z_yank, +/* Q */ z_undefinedkey, +/* R */ z_vireplace, +/* S */ z_vichangewholeline, +/* T */ z_vifindprevcharskip, +/* U */ z_undefinedkey, +/* V */ z_undefinedkey, +/* W */ z_viforwardblankword, +/* X */ z_vibackwarddeletechar, +/* Y */ z_viyankeol, +/* Z */ z_undefinedkey, +/* [ */ z_undefinedkey, +/* \ */ z_completeword, +/* ] */ z_undefinedkey, +/* ^ */ z_vifirstnonblank, +/* _ */ z_undefinedkey, +/* ` */ z_vigotomark, +/* a */ z_viaddnext, +/* b */ z_vibackwardword, +/* c */ z_vichange, +/* d */ z_videlete, +/* e */ z_viforwardwordend, +/* f */ z_vifindnextchar, +/* g */ z_undefinedkey, +/* h */ z_vibackwardchar, +/* i */ z_viinsert, +/* j */ z_downlineorhistory, +/* k */ z_uplineorhistory, +/* l */ z_viforwardchar, +/* m */ z_visetmark, +/* n */ z_virepeatsearch, +/* o */ z_viopenlinebelow, +/* p */ z_viputafter, +/* q */ z_undefinedkey, +/* r */ z_vireplacechars, +/* s */ z_visubstitute, +/* t */ z_vifindnextcharskip, +/* u */ z_viundochange, +/* v */ z_undefinedkey, +/* w */ z_viforwardword, +/* x */ z_videletechar, +/* y */ z_viyank, +/* z */ z_undefinedkey, +/* { */ z_undefinedkey, +/* | */ z_vigotocolumn, +/* } */ z_undefinedkey, +/* ~ */ z_viswapcase, +/* ^? */ z_backwarddeletechar, +}; + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_hist.c b/usr/othersrc/public/zsh-2.2/src/zle_hist.c new file mode 100644 index 0000000000..f599f24a81 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_hist.c @@ -0,0 +1,620 @@ +/* + * + * zle_hist.c - history editing + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + +void toggleliteralhistory() /**/ +{ +char *s; + + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + lithist ^= 1; + if (!(s = qgetevent(histline))) + feep(); + else + sethistline(s); +} + +void uphistory() /**/ +{ +char *s; + + if (mult < 0) { mult = -mult; downhistory(); return; } + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + histline -= mult; + if (!(s = qgetevent(histline))) + { + if (unset(NOHISTBEEP)) feep(); + histline += mult; + } + else + sethistline(s); +} + +void uplineorhistory() /**/ +{ +int ocs = cs; + + if (mult < 0) { mult = -mult; downlineorhistory(); return; } + if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE) + lastcol = cs-findbol(); + cs = findbol(); + while (mult) { + if (!cs) + break; + cs--; + cs = findbol(); + mult--; + } + if (mult) { + cs = ocs; + if (virangeflag) { + feep(); + return; + } + uphistory(); + } else { + int x = findeol(); + if ((cs += lastcol) > x) + cs = x; + } +} + +void downlineorhistory() /**/ +{ +int ocs = cs; + + if (mult < 0) { mult = -mult; uplineorhistory(); return; } + if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE) + lastcol = cs-findbol(); + while (mult) { + int x = findeol(); + if (x == ll) + break; + cs = x+1; + mult--; + } + if (mult) { + cs = ocs; + if (virangeflag) { + feep(); + return; + } + downhistory(); + } else { + int x = findeol(); + if ((cs += lastcol) > x) + cs = x; + } +} + +void acceptlineanddownhistory() /**/ +{ +char *s,*t; + + if (!(s = qgetevent(histline+1))) + { + feep(); + return; + } + pushnode(bufstack,t = ztrdup(s)); + for (; *t; t++) + if (*t == HISTSPACE) + *t = ' '; + done = 1; + stackhist = histline+1; +} + +void downhistory() /**/ +{ +char *s; + + if (mult < 0) { mult = -mult; uphistory(); return; } + histline += mult; + if (!(s = qgetevent(histline))) + { + if (unset(NOHISTBEEP)) feep(); + histline -= mult; + return; + } + sethistline(s); +} + +static int histpos; + +void historysearchbackward() /**/ +{ +int t0,ohistline = histline; +char *s; + + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + if (lastcmd & ZLE_HISTSEARCH) t0 = histpos; + else for (t0 = 0; line[t0] && iword(line[t0]); t0++); + histpos = t0; + for (;;) + { + histline--; + if (!(s = qgetevent(histline))) + { + feep(); + histline = ohistline; + return; + } + if (!hstrncmp(s,line,t0) && hstrcmp(s,line)) + break; + } + sethistline(s); +} + +void historysearchforward() /**/ +{ +int t0,ohistline = histline; +char *s; + + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + if (lastcmd & ZLE_HISTSEARCH) t0 = histpos; + else for (t0 = 0; line[t0] && iword(line[t0]); t0++); + histpos = t0; + for (;;) + { + histline++; + if (!(s = qgetevent(histline))) + { + feep(); + histline = ohistline; + return; + } + if (!hstrncmp(s,line,t0) && hstrcmp(s,line)) + break; + } + sethistline(s); +} + +void beginningofbufferorhistory() /**/ +{ + if (findbol()) + cs = 0; + else + beginningofhistory(); +} + +void beginningofhistory() /**/ +{ +char *s; + + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + if (!(s = qgetevent(firsthist()))) + { + if (unset(NOHISTBEEP)) feep(); + return; + } + histline = firsthist(); + sethistline(s); +} + +void endofbufferorhistory() /**/ +{ + if (findeol() != ll) + cs = ll; + else + endofhistory(); +} + +void endofhistory() /**/ +{ + if (histline == curhist) { + if (unset(NOHISTBEEP)) feep(); + } else + { + histline = curhist; + sethistline(curhistline); + } +} + +void insertlastword() /**/ +{ +char *s,*t; +int len,z = lithist; + + /* multiple calls will now search back through the history, pem */ + static char *lastinsert; + static int lasthist, lastpos; + int evhist = curhist - 1; + + if (lastinsert) { + int len = strlen(lastinsert); + int pos = cs; + if ( lastpos <= pos && + len == pos - lastpos && + strncmp(lastinsert, (char *) &line[lastpos], len) == 0) { + evhist = --lasthist; + cs = lastpos; + foredel(pos-cs); + } + free(lastinsert); + lastinsert = NULL; + } + lithist = 0; + if (!(s = qgetevent(evhist), lithist = z, s)) + { + feep(); + return; + } + for (t = s+strlen(s); t > s; t--) + if (*t == HISTSPACE) + break; + if (t != s) + t++; + lasthist = evhist; + lastpos = cs; + lastinsert = ztrdup(t); + spaceinline(len = strlen(t)); + strncpy((char *) line+cs,t,len); + cs += len; +} + +char *qgetevent(ev) /**/ +int ev; +{ + if (ev > curhist) + return NULL; + return ((ev == curhist) ? curhistline : quietgetevent(ev)); +} + +void pushline() /**/ +{ + if (mult < 0) return; + pushnode(bufstack,ztrdup(line)); + while (--mult) + pushnode(bufstack,ztrdup("")); + stackcs = cs; + *line = '\0'; + ll = cs = 0; +} + +void getline() /**/ +{ +char *s = getnode(bufstack); + + if (!s) + feep(); + else + { + int cc; + + cc = strlen(s); + spaceinline(cc); + strncpy((char *) line+cs,s,cc); + cs += cc; + free(s); + } +} + +void historyincrementalsearchbackward() /**/ +{ + doisearch(-1); +} + +void historyincrementalsearchforward() /**/ +{ + doisearch(1); +} + +void doisearch(dir) /**/ +int dir; +{ +char *s,*oldl; +char ibuf[256],*sbuf = ibuf+10; +int sbptr = 0,ch,ohl = histline,ocs = cs; +int nomatch = 0,chequiv = 0; + + strcpy(ibuf,"i-search: "); + statusline = ibuf; + oldl = ztrdup(line); + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + for (;;) + { + nomatch = 0; + if (sbptr > 1 || (sbptr == 1 && sbuf[0] != '^')) + { + int ohistline = histline; + + for (;;) + { + char *t; + + if (!(s = qgetevent(histline))) + { + feep(); + nomatch = 1; + histline = ohistline; + break; + } + if ((sbuf[0] == '^') ? + (t = (hstrncmp(s,sbuf+1,sbptr-1)) ? NULL : s) : + (t = hstrnstr(s,sbuf,sbptr))) + if (!(chequiv && !hstrcmp(line,s))) + { + sethistline(s); + cs = t-s+sbptr-(sbuf[0] == '^'); + break; + } + histline += dir; + } + chequiv = 0; + } + refresh(); + if ((ch = getkey(1)) == -1) + break; + if (ch == 22 || ch == 17) { + if ((ch = getkey(1)) == -1) + break; + } else if (ch == 24) { /* ^XS and ^XR */ + if ((ch = getkey(1)) == -1) + break; + if (ch != 's' && ch != 'r') { + ungetkey(24); + ungetkey(ch); + break; + } + ungetkey(ch & 0x1f); + continue; + } else if (ch == 8 || ch == 127) { + if (sbptr) + sbuf[--sbptr] = '\0'; + else + feep(); + histline = ohl; + continue; + } else if (ch == 7 || ch == 3) { + setline(oldl); + cs = ocs; + histline = ohl; + statusline = NULL; + break; + } else if (ch == 27) + break; + else if (ch == 10 || ch == 13) { + ungetkey(ch); + break; + } else if (ch == 18) { + ohl = (histline += (dir = -1)); + chequiv = 1; + continue; + } else if (ch == 19) { + ohl = (histline += (dir = 1)); + chequiv = 1; + continue; + } else if (!(ch & 0x60)) { + ungetkey(ch); + break; + } + if (!nomatch && sbptr != 39 && !icntrl(ch)) { + sbuf[sbptr++] = ch; + sbuf[sbptr] = '\0'; + } + } + free(oldl); + statusline = NULL; +} + +void acceptandinfernexthistory() /**/ +{ +int t0; +char *s,*t; + + done = 1; + for (t0 = histline-2;;t0--) + { + if (!(s = qgetevent(t0))) + return; + if (!hstrncmp(s,line,ll)) + break; + } + if (!(s = qgetevent(t0+1))) + return; + pushnode(bufstack,t = ztrdup(s)); + for (; *t; t++) + if (*t == HISTSPACE) + *t = ' '; + stackhist = t0+1; +} + +void infernexthistory() /**/ +{ +int t0; +char *s,*t; + + if (!(t = qgetevent(histline-1))) + { + feep(); + return; + } + for (t0 = histline-2;;t0--) + { + if (!(s = qgetevent(t0))) + { + feep(); + return; + } + if (!strcmp(s,t)) + break; + } + if (!(s = qgetevent(t0+1))) + { + feep(); + return; + } + histline = t0+1; + sethistline(s); +} + +void vifetchhistory() /**/ +{ +char *s; + + if (mult < 0) return; + if (histline == curhist) { + if (!(lastcmd & ZLE_ARG)) { + cs = ll; + cs = findbol(); + return; + } + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + if (!(lastcmd & ZLE_ARG)) mult = curhist; + if (!(s = qgetevent(mult))) + feep(); + else { + histline = mult; + sethistline(s); + } +} + +int getvisrchstr() /**/ +{ +char sbuf[80]; +int sptr = 1; + + if (visrchstr) + { + free(visrchstr); + visrchstr = NULL; + } + statusline = sbuf; + sbuf[0] = c; + sbuf[1] = '\0'; + while (sptr) + { + refresh(); + c = getkey(0); + if (c == '\r' || c == '\n' || c == '\033') + { + visrchstr = ztrdup(sbuf+1); + return 1; + } + if (c == '\b' || c == 127) + { + sbuf[--sptr] = '\0'; + continue; + } + if (sptr != 79) + { + sbuf[sptr++] = c; + sbuf[sptr] = '\0'; + } + } + return 0; +} + +void vihistorysearchforward() /**/ +{ + visrchsense = 1; + if (getvisrchstr()) + virepeatsearch(); +} + +void vihistorysearchbackward() /**/ +{ + visrchsense = -1; + if (getvisrchstr()) + virepeatsearch(); +} + +void virepeatsearch() /**/ +{ +int ohistline = histline,t0; +char *s; + + if (!visrchstr) + { + feep(); + return; + } + t0 = strlen(visrchstr); + if (histline == curhist) + { + if (curhistline) + free(curhistline); + curhistline = ztrdup(line); + } + for (;;) + { + histline += visrchsense; + if (!(s = qgetevent(histline))) + { + feep(); + histline = ohistline; + return; + } + if (!hstrcmp(line,s)) + continue; + if (*visrchstr == '^') + { + if (!hstrncmp(s,visrchstr+1,t0-1)) + break; + } + else + if (hstrnstr(s,visrchstr,t0)) + break; + } + sethistline(s); +} + +void virevrepeatsearch() /**/ +{ + visrchsense = -visrchsense; + virepeatsearch(); + visrchsense = -visrchsense; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_hist.pro b/usr/othersrc/public/zsh-2.2/src/zle_hist.pro new file mode 100644 index 0000000000..e213d91d4d --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_hist.pro @@ -0,0 +1,27 @@ +void toggleliteralhistory DCLPROTO((void)); +void uphistory DCLPROTO((void)); +void uplineorhistory DCLPROTO((void)); +void downlineorhistory DCLPROTO((void)); +void acceptlineanddownhistory DCLPROTO((void)); +void downhistory DCLPROTO((void)); +void historysearchbackward DCLPROTO((void)); +void historysearchforward DCLPROTO((void)); +void beginningofbufferorhistory DCLPROTO((void)); +void beginningofhistory DCLPROTO((void)); +void endofbufferorhistory DCLPROTO((void)); +void endofhistory DCLPROTO((void)); +void insertlastword DCLPROTO((void)); +char *qgetevent DCLPROTO((int ev)); +void pushline DCLPROTO((void)); +void getline DCLPROTO((void)); +void historyincrementalsearchbackward DCLPROTO((void)); +void historyincrementalsearchforward DCLPROTO((void)); +void doisearch DCLPROTO((int dir)); +void acceptandinfernexthistory DCLPROTO((void)); +void infernexthistory DCLPROTO((void)); +void vifetchhistory DCLPROTO((void)); +int getvisrchstr DCLPROTO((void)); +void vihistorysearchforward DCLPROTO((void)); +void vihistorysearchbackward DCLPROTO((void)); +void virepeatsearch DCLPROTO((void)); +void virevrepeatsearch DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_main.c b/usr/othersrc/public/zsh-2.2/src/zle_main.c new file mode 100644 index 0000000000..0469fc8e26 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_main.c @@ -0,0 +1,724 @@ +/* + * + * zle_main.c - main routines for line editor + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLEGLOBALS +#define ZLE +#include "zsh.h" +#include +#include +#ifdef HAS_SYS_SELECT +#include +#endif + +static Key cky; + +/* set up terminal */ + +void setterm() /**/ +{ +struct ttyinfo ti; +#ifdef FIONREAD +long val; +#endif + +#ifdef CLOBBERS_TYPEAHEAD +#ifdef FIONREAD + ioctl(SHTTY, FIONREAD, &val); + if (val) return; +#endif +#endif + inittty(); + ti = shttyinfo; +#ifdef TIO + ti.tio.c_lflag &= ~(ICANON|ECHO +#ifdef FLUSHO + |FLUSHO +#endif + ); + ti.tio.c_cc[VQUIT] = +#ifdef VDISCARD + ti.tio.c_cc[VDISCARD] = +#endif +#ifdef VSUSP + ti.tio.c_cc[VSUSP] = +#endif +#ifdef VDSUSP + ti.tio.c_cc[VDSUSP] = +#endif +#ifdef VSWTCH + ti.tio.c_cc[VSWTCH] = +#endif + VDISABLEVAL; + ti.tio.c_cc[VMIN] = 1; + ti.tio.c_cc[VTIME] = 0; + ti.tio.c_iflag &= ~(INLCR|ICRNL); +#else + ti.sgttyb.sg_flags = (ti.sgttyb.sg_flags | CBREAK) & ~ECHO; + ti.lmodes &= ~LFLUSHO; + ti.tchars.t_quitc = + ti.ltchars.t_suspc = + ti.ltchars.t_flushc = + ti.ltchars.t_dsuspc = ti.ltchars.t_lnextc = -1; +#endif +#ifdef TTY_NEEDS_DRAINING + drainoutput(); +#endif + settyinfo(&ti); +} + +void unsetterm() /**/ +{ + settyinfo(&shttyinfo); +} + +static char *kungetbuf; +static int kungetct,kungetsz; + +void ungetkey(ch) /**/ +int ch; +{ + if (kungetct == kungetsz) + kungetbuf = realloc(kungetbuf,kungetsz *= 2); + kungetbuf[kungetct++] = ch; +} + +void ungetkeys(s,len) /**/ +char *s;int len; +{ + s += len; + while (len--) + ungetkey(*--s); +} + +unsigned int getkey(tmok) /**/ +int tmok; +{ +char cc; +unsigned int ret = 0; +int die = 0; +#ifdef HAS_SELECT +fd_set foofd; +#endif + + if (kungetct) + ret = (unsigned int) (unsigned char) kungetbuf[--kungetct]; + else { + while ( +#ifdef HAS_SELECT + FD_SET(0,&foofd), select(1,&foofd,NULL,NULL,NULL) != 1 || +#endif + read(0,&cc,1) != 1) + if (errno == EINTR) { + if (!errflag) + continue; + errflag = 0; + if (tmok) + return -1; + return 3; + } else if (errno == EWOULDBLOCK) { + fcntl(0,F_SETFL,0); + } else if (errno == EIO && !die) { + ret = jobbing; + jobbing = 1; + attachtty(mypgrp); + refresh(); /* kludge! */ + jobbing = ret; + die = 1; + } else { + zerr("error on TTY read: %e",NULL,errno); + exit(1); + } + ret = (unsigned int) (unsigned char) cc; + } + if (vichgflag) { + if (vichgbufptr == vichgbufsz) + vichgbuf = realloc(vichgbuf,vichgbufsz *= 2); + vichgbuf[vichgbufptr++] = ret; + } + return ret; +} + +/* read a line */ + +unsigned char *zleread(ppt,ppt2,plen) /**/ +unsigned char *ppt;unsigned char *ppt2;int plen; +{ +int z; +long costmult; +unsigned char *s; +#ifdef HAS_SELECT +struct timeval tv; +fd_set foofd; + + tv.tv_sec = 0; +#endif + fflush(stdout); + fflush(stderr); + intr(); + costmult = 3840000L/((baud) ? baud : 2400); + insmode = unset(OVERSTRIKE); eofsent = 0; resetneeded =0 ; + pmpt = (char *)ppt; + pmpt2 = (char *)ppt2; + permalloc(); + histline = curhist; + pptlen = plen; + resetneeded = 1; +#ifdef HAS_SELECT + FD_ZERO(&foofd); +#endif + undoing = 1; + line = zalloc(linesz = 256); + *line = '\0'; + virangeflag = lastcmd = done = cs = ll = mark = 0; + curhistline = NULL; + mult = 1; + vibufspec = 0; + bindtab = mainbindtab; + addedslash = vichgflag = 0; + viinsbegin = 0; + statusline = NULL; + if (s = getnode(bufstack)) + { + setline((char *) s); + free(s); + if (stackcs != -1) + { + cs = stackcs; + stackcs = -1; + if (cs > ll) + cs = ll; + } + if (stackhist != -1) + { + histline = stackhist; + stackhist = -1; + } + } + initundo(); + if (unset(NOPROMPTCR)) + putchar('\r'); + if (tmout) + alarm(tmout); + refresh(); + errflag = 0; + while (!done && !errflag) + { + struct zlecmd *zc; + + statusline = NULL; + bindk = getkeycmd(); + if (c == 4 && !ll) + { + eofsent = 1; + break; + } + if (bindk != -1) + { + zc = zlecmds+bindk; + if (!(lastcmd & ZLE_ARG)) + mult = 1; + if ((lastcmd & ZLE_UNDO) != (zc->flags & ZLE_UNDO) && undoing) + addundo(); + if (!(zc->flags & ZLE_MENUCMP)) { + if (menucmp) freemenu(); + if (addedslash && + !((zc->flags & ZLE_INSERT) && c != ' ')) { + backdel(1); + } + addedslash = 0; + } + if (zc->func) + (*zc->func)(); + lastcmd = zc->flags; + if (!(lastcmd & ZLE_UNDO) && undoing) addundo(); + } + else + { + errflag = 1; + break; + } +#ifdef HAS_SELECT + FD_SET(0,&foofd); + if ((tv.tv_usec = cost*costmult) > 500000) + tv.tv_usec = 500000; +#endif + if (!kungetct +#ifdef HAS_SELECT + && select(1,&foofd,NULL,NULL,&tv) <= 0 +#endif + ) + refresh(); + } + if (menucmp) + freemenu(); + statusline = NULL; + trashzle(); + alarm(0); + z = strlen((char *)line); + line[z] = '\n'; + line[z+1] = 0; + heapalloc(); + if (curhistline) + free(curhistline); + if (eofsent) + { + free(line); + line = NULL; + } + zleactive = 0; + freeundo(); + return line; +} + +int getkeycmd() /**/ +{ +char buf[10]; +int t0,ret; +Key ky; + + t0 = 1; + cky = NULL; + if ((c = getkey(1)) == -1) + return -1; + if ((ret = bindtab[c]) == z_sequenceleadin) + { + buf[0] = (c) ? c : 0x80; + for (;;) + { + c = getkey(0); + buf[t0++] = (c) ? c : 0x80; + buf[t0] = '\0'; + if (!(ky = (Key) gethnode(buf,xbindtab))) + return z_undefinedkey; + if (ky->func != z_sequenceleadin) + { + cky = ky; + ret = ky->func; + break; + } + } + } + if (ret == z_vidigitorbeginningofline) + ret = (lastcmd & ZLE_ARG) ? z_digitargument : z_beginningofline; + else if (ret == z_executenamedcmd) + ret = executenamedcommand(); + else if (ret == z_executelastnamedcmd) + ret = lastnamed; + return ret; +} + +void sendstring() /**/ +{ +char buf[2]; + + buf[0] = c; + buf[1] = '\0'; + if (!cky) + cky = (Key) gethnode(buf,xbindtab); + ungetkeys(cky->str,cky->len); +} + +Key makefunckey(fun) /**/ +int fun; +{ +Key ky = zcalloc(sizeof *ky); + + ky->func = fun; + return ky; +} + +/* initialize the bindings */ + +void initxbindtab() /**/ +{ +int t0,vi = 0; +char buf[3],*s; + + lastnamed = z_undefinedkey; + if (s = zgetenv("VISUAL")) { + if (ztrstr(s,"vi")) + vi = 1; + } + else if ((s = zgetenv("EDITOR")) && ztrstr(s,"vi")) + vi = 1; + if (vi) { + for (t0 = 0; t0 != 32; t0++) + mainbindtab[t0] = viinsbind[t0]; + for (t0 = 32; t0 != 256; t0++) + mainbindtab[t0] = z_selfinsert; + mainbindtab[127] = z_backwarddeletechar; + } else { + for (t0 = 0; t0 != 128; t0++) + mainbindtab[t0] = emacsbind[t0]; + for (t0 = 128; t0 != 256; t0++) + mainbindtab[t0] = z_selfinsert; + } + for (t0 = 0200; t0 != 0240; t0++) + mainbindtab[t0] = z_undefinedkey; + for (t0 = 0; t0 != 128; t0++) + altbindtab[t0] = vicmdbind[t0]; + for (t0 = 128; t0 != 256; t0++) + altbindtab[t0] = emacsbind[t0]; + bindtab = mainbindtab; + kungetbuf = zalloc(kungetsz = 32); + kungetct = 0; + xbindtab = newhtable(67); + addhperm("\33\133C",makefunckey(z_forwardchar),xbindtab,NULL); + addhperm("\33\133D",makefunckey(z_backwardchar),xbindtab,NULL); + addhperm("\33\133A",makefunckey(z_uplineorhistory),xbindtab,NULL); + addhperm("\33\133B",makefunckey(z_downlineorhistory),xbindtab,NULL); + addhperm("\30*",makefunckey(z_expandword),xbindtab,NULL); + addhperm("\30g",makefunckey(z_listexpand),xbindtab,NULL); + addhperm("\30G",makefunckey(z_listexpand),xbindtab,NULL); + addhperm("\30\16",makefunckey(z_infernexthistory),xbindtab,NULL); + addhperm("\30\13",makefunckey(z_killbuffer),xbindtab,NULL); + addhperm("\30\6",makefunckey(z_vifindnextchar),xbindtab,NULL); + addhperm("\30\17",makefunckey(z_overwritemode),xbindtab,NULL); + addhperm("\30\25",makefunckey(z_undo),xbindtab,NULL); + addhperm("\30\26",makefunckey(z_vicmdmode),xbindtab,NULL); + addhperm("\30\12",makefunckey(z_vijoin),xbindtab,NULL); + addhperm("\30\2",makefunckey(z_vimatchbracket),xbindtab,NULL); + addhperm("\30s",makefunckey(z_historyincrementalsearchforward), + xbindtab,NULL); + addhperm("\30r",makefunckey(z_historyincrementalsearchbackward), + xbindtab,NULL); + addhperm("\30u",makefunckey(z_undo),xbindtab,NULL); + addhperm("\30\30",makefunckey(z_exchangepointandmark), + xbindtab,NULL); + addhperm("run-help",mkanode(ztrdup("man"),1),aliastab,NULL); + addhperm("which-command",mkanode(ztrdup("whence"),1),aliastab,NULL); + strcpy(buf,"\33q"); + for (t0 = 128; t0 != 256; t0++) + if (emacsbind[t0] != z_undefinedkey) { + buf[1] = t0 & 0x7f; + addhnode(ztrdup(buf),makefunckey(emacsbind[t0]),xbindtab,NULL); + } + for (t0 = 0; t0 != 36; t0++) vibuf[t0] = NULL; + for (t0 = 0; t0 != 26; t0++) vimarkline[t0] = 0; + stackhist = stackcs = -1; + vichgbufsz = 0; + vichgbuf = NULL; +} + +char *getkeystring(s,len) /**/ +char *s;int *len; +{ +static char buf[512]; +char *t = buf; +int x,first = 1,metanext = 0; + + for (;*s;s++) + { + if (*s == '\\' && s[1]) + switch(*++s) + { + case 'a': *t++ = '\07'; break; + case 'n': *t++ = '\n'; break; + case 'b': *t++ = '\010'; break; + case 't': *t++ = '\t'; break; + case 'v': *t++ = '\v'; break; + case 'f': *t++ = '\f'; break; + case 'r': *t++ = '\r'; break; + case 'e': *t++ = '\033'; break; + case 'M': + if (s[1] == '-') + s++; + metanext = 2; + break; + default: + if (idigit(*s)) + { + for (x = 0; idigit(*s); s++) + x = x*8+(*s-'0'); + s--; + *t++ = x; + } + else + *t++ = *s; + break; + } + else if (*s == '^') + if (*++s == '?') + *t++ = 0x7f; + else + *t++ = *s & 0x9f; + else + *t++ = *s; + if (metanext && !(--metanext)) + { + t[-1] |= 0x80; + metanext = 0; + } + if (t > buf+500) + break; + first = 0; + } + *t = '\0'; + *len = t-buf; + return buf; +} + +void printbind(s,len) /**/ +char *s;int len; +{ +int ch; + + while (len--) + { + ch = (unsigned char) *s++; + if (ch & 0x80) + { + printf("\\M-"); + ch &= 0x7f; + } + if (icntrl(ch)) + switch(ch) + { + case 0x7f: printf("^?"); break; + default: printf("^%c",(ch|0x40)); break; + } + else + putchar(ch); + } +} + +void printbinding(str,k) /**/ +char *str;Key k; +{ + if (k->func == z_sequenceleadin) + return; + putchar('\"'); + printbind(str,strlen(str)); + printf("\"\t"); + if (k->func == z_sendstring) + { + putchar('\"'); + printbind(k->str,k->len); + printf("\"\n"); + } + else + printf("%s\n",zlecmds[k->func].name); +} + +int bin_bindkey(name,argv,ops,junc) /**/ +char *name;char **argv;char *ops;int junc; +{ +int t0,len; +char *s; +int func,*tab; + + tab = (ops['a']) ? altbindtab : mainbindtab; + if (ops['v'] || ops['e'] || ops['d']) + { + if (*argv) + { + zerrnam(name,"too many arguments",NULL,0); + return 1; + } + if (ops['d'] || ops['e']) + if (ops['m']) + for (t0 = 0; t0 != 256; t0++) + tab[t0] = emacsbind[t0]; + else + { + for (t0 = 0; t0 != 128; t0++) + tab[t0] = emacsbind[t0]; + for (t0 = 128; t0 != 256; t0++) + tab[t0] = z_selfinsert; + } + else + { + for (t0 = 0; t0 != 32; t0++) + mainbindtab[t0] = viinsbind[t0]; + for (t0 = 32; t0 != 256; t0++) + mainbindtab[t0] = z_selfinsert; + mainbindtab[127] = z_backwarddeletechar; + } + for (t0 = 0; t0 != 128; t0++) + altbindtab[t0] = vicmdbind[t0]; + for (t0 = 128; t0 != 256; t0++) + altbindtab[t0] = emacsbind[t0]; + for (t0 = 0200; t0 != 0240; t0++) + tab[t0] = z_undefinedkey; + return 0; + } + if (!*argv) + { + char buf[2]; + + buf[0] = 'x'; buf[1] = '\0'; + for (t0 = 0; t0 != 256; t0++) + { + buf[0] = t0; + putchar('\"'); + printbind(buf,1); + if (t0 < 254 && tab[t0] == tab[t0+1] && tab[t0] == tab[t0+2]) + { + printf("\" to \""); + while (tab[t0] == tab[t0+1]) t0++; + buf[0] = t0; + printbind(buf,1); + } + printf("\"\t%s\n",zlecmds[tab[t0]].name); + } + listhtable(xbindtab,(HFunc) printbinding); + return 0; + } + while (*argv) + { + s = getkeystring(*argv++,&len); + if (len > 8) + { + zerrnam(name,"in-string too long",NULL,0); + return 1; + } + if (!*argv || ops['r']) + { + Key ky; + + ky = gethnode(s,xbindtab); + if (len == 1) + func = tab[(unsigned char) *s]; + else + func = (ky) ? ky->func : z_undefinedkey; + if (func == z_undefinedkey) + { + zerrnam(name,"in-string is not bound",NULL,0); + return 1; + } + if (ops['r']) + { + if (len == 1) + tab[(unsigned char) *s] = z_undefinedkey; + else + { + while (strlen(s) > 1) + { + free(remhnode(s,xbindtab)); + s[strlen(s)-1] = '\0'; + } + } + continue; + } + if (func == z_sendstring) + { + printbind(ky->str,ky->len); + putchar('\n'); + return 0; + } + printf("%s\n",zlecmds[func].name); + return 0; + } + if (!ops['s']) + { + for (t0 = 0; t0 != ZLECMDCOUNT; t0++) + if (!strcmp(*argv,zlecmds[t0].name)) + break; + if (t0 == ZLECMDCOUNT) + { + zerr("undefined function: %s",*argv,0); + return 1; + } + func = t0; + } + else + func = z_sendstring; + if (len == 1) + { + Key ky; + + tab[(unsigned char) *s] = (ops['s']) ? z_sendstring : t0; + if (ops['s']) + { + addhnode(ztrdup(s),ky = makefunckey(z_sendstring),xbindtab,freekey); + ky->str = ztrdup(getkeystring(*argv,&ky->len)); + } + } + else + { + int t1; + Key ky; + + if (tab[(unsigned char) *s] != z_undefinedkey && + tab[(unsigned char) *s] != z_sequenceleadin) + { + zerrnam(name,"in-string has already bound prefix",NULL,0); + return 1; + } + tab[(unsigned char) *s] = z_sequenceleadin; + if (!s[1]) + s[1] = 0x80; + for (t1 = 1; t1 != len-1; t1++) + { + char sav; + + sav = s[t1+1]; + s[t1+1] = '\0'; + ky = gethnode(s,xbindtab); + if (ky && ky->func != z_sequenceleadin) + { + zerrnam(name,"in-string has already bound prefix",NULL,0); + return 1; + } + if (!ky) + addhnode(ztrdup(s),makefunckey(z_sequenceleadin),xbindtab, + freekey); + if (!sav) + sav = 0x80; + s[t1+1] = sav; + } + addhnode(ztrdup(s),ky = makefunckey(func),xbindtab,freekey); + if (ops['s']) + ky->str = ztrdup(getkeystring(*argv,&ky->len)); + } + argv++; + } + return 0; +} + +void freekey(x) /**/ +vptr x; +{ +Key k = x; + + if (k->str) + free(k->str); + free(k); +} + +/* this is mostly stolen from bash's draino() */ + +void drainoutput() /**/ +{ +int n = 0; + + if (!baud) return; +#ifdef TIOCOUTQ +#ifdef HAS_SELECT + while ((ioctl(SHTTY,TIOCOUTQ,&n) >= 0) && n) { + struct timeval tv; + tv.tv_sec = n/baud; + tv.tv_usec = ((n%baud)*1000000)/baud; + select (0,(fd_set *)0,(fd_set *)0,(fd_set *)0,&tv); + } +#endif +#endif +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_main.pro b/usr/othersrc/public/zsh-2.2/src/zle_main.pro new file mode 100644 index 0000000000..79f62a5192 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_main.pro @@ -0,0 +1,16 @@ +void setterm DCLPROTO((void)); +void unsetterm DCLPROTO((void)); +void ungetkey DCLPROTO((int ch)); +void ungetkeys DCLPROTO((char *s,int len)); +unsigned int getkey DCLPROTO((int tmok)); +unsigned char *zleread DCLPROTO((unsigned char *ppt,unsigned char *ppt2,int plen)); +int getkeycmd DCLPROTO((void)); +void sendstring DCLPROTO((void)); +Key makefunckey DCLPROTO((int fun)); +void initxbindtab DCLPROTO((void)); +char *getkeystring DCLPROTO((char *s,int *len)); +void printbind DCLPROTO((char *s,int len)); +void printbinding DCLPROTO((char *str,Key k)); +int bin_bindkey DCLPROTO((char *name,char **argv,char *ops,int junc)); +void freekey DCLPROTO((vptr x)); +void drainoutput DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_misc.c b/usr/othersrc/public/zsh-2.2/src/zle_misc.c new file mode 100644 index 0000000000..8552c0e5b3 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_misc.c @@ -0,0 +1,829 @@ +/* + * + * zle_misc.c - miscellaneous editor routines + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + + +void selfinsert() /**/ +{ +int ncs = cs+mult; + + if (mult < 0) { mult = -mult; ncs = cs; } + if (insmode || ll == cs) + spaceinline(mult); + else if (mult+cs > ll) + spaceinline(ll-(mult+cs)); + while (mult--) + line[cs++] = c; + cs = ncs; +} + +void selfinsertunmeta() /**/ +{ + c &= 0x7f; + if (c == '\r') c = '\n'; + selfinsert(); +} + +void deletechar() /**/ +{ + if (mult < 0) { mult = -mult; backwarddeletechar(); return; } + if (c == 4 && !ll) + { + eofsent = 1; + return; + } + if (!(cs+mult > ll || line[cs] == '\n')) + { + cs += mult; + backdel(mult); + } + else + feep(); +} + +void backwarddeletechar() /**/ +{ + if (mult < 0) { mult = -mult; deletechar(); return; } + if (mult > cs) + mult = cs; + backdel(mult); +} + +void videletechar() /**/ +{ + if (mult < 0) { mult = -mult; vibackwarddeletechar(); return; } + if (c == 4 && !ll) { + eofsent = 1; + return; + } + if (!(cs+mult > ll || line[cs] == '\n')) { + cs += mult; + backkill(mult,0); + if (cs && (cs == ll || line[cs] == '\n')) cs--; + } else + feep(); +} + +void vibackwarddeletechar() /**/ +{ + if (mult < 0) { mult = -mult; videletechar(); return; } + if (mult > cs) + mult = cs; + if (cs-mult < viinsbegin) { feep(); return; } + backkill(mult,1); +} + +void vikillline() /**/ +{ + if (viinsbegin > cs) { feep(); return; } + backdel(cs-viinsbegin); +} + +void killwholeline() /**/ +{ +int i,fg; + + if (mult < 0) return; + while (mult--) + { + if (fg = (cs && cs == ll)) + cs--; + while (cs && line[cs-1] != '\n') cs--; + for (i = cs; i != ll && line[i] != '\n'; i++); + forekill(i-cs+(i != ll),fg); + } +} + +void killbuffer() /**/ +{ + cs = 0; + forekill(ll,0); +} + +void backwardkillline() /**/ +{ +int i = 0; + + if (mult < 0) { mult = -mult; killline(); return; } + while (mult--) + { + while (cs && line[cs-1] != '\n') cs--,i++; + if (mult && cs && line[cs-1] == '\n') + cs--,i++; + } + forekill(i,1); +} + +void gosmacstransposechars() /**/ +{ +int cc; + + if (cs < 2 || line[cs-1] == '\n' || line[cs-2] == '\n') + { + if (line[cs] == '\n' || line[cs+1] == '\n') + { + feep(); + return; + } + cs += (cs == 0 || line[cs-1] == '\n') ? 2 : 1; + } + cc = line[cs-2]; + line[cs-2] = line[cs-1]; + line[cs-1] = cc; +} + +void transposechars() /**/ +{ +int cc; +int neg = mult < 0; + + if (neg) mult = -mult; + while (mult--) { + if (cs == 0 || line[cs-1] == '\n') { + if (ll == cs || line[cs] == '\n' || line[cs+1] == '\n') { + feep(); + return; + } + cs++; + } + if (!neg) { + if (cs != ll && line[cs] != '\n') cs++; + } else { + if (cs != 0 && line[cs-1] != '\n') cs--; + } + cc = line[cs-2]; + line[cs-2] = line[cs-1]; + line[cs-1] = cc; + } +} + +void poundinsert() /**/ +{ + if (*line != '#') { + cs = 0; + spaceinline(1); + *line = '#'; + } else { + cs = 0; + foredel(1); + } + done = 1; +} + +void acceptline() /**/ +{ + done = 1; +} + +void acceptandhold() /**/ +{ + pushnode(bufstack,ztrdup((char *) line)); + stackcs = cs; + done = 1; +} + +void killline() /**/ +{ +int i = 0; + + if (mult < 0) { mult = -mult; backwardkillline(); return; } + while (mult--) { + if (line[cs] == '\n') + cs++,i++; + while (cs != ll && line[cs] != '\n') cs++,i++; + } + backkill(i,0); +} + +void killregion() /**/ +{ + if (mark > ll) + mark = ll; + if (mark > cs) + forekill(mark-cs,0); + else + backkill(cs-mark,1); +} + +void copyregionaskill() /**/ +{ + if (mark > ll) + mark = ll; + if (mark > cs) + cut(cs,mark-cs,0); + else + cut(mark,cs-mark,1); +} + +static int kct,yankb,yanke; + +void yank() /**/ +{ +int cc; +char *buf = cutbuf; + + if (!cutbuf) { + feep(); + return; + } + if (mult < 0) return; + if (vibufspec) { + vibufspec = tolower(vibufspec); + vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a'; + if (!(buf = vibuf[vibufspec])) { + feep(); + vibufspec = 0; + return; + } + vibufspec = 0; + } + yankb = cs; + while (mult--) { + kct = kringnum; + cc = strlen(buf); + spaceinline(cc); + strncpy((char *) line+cs,buf,cc); + cs += cc; + yanke = cs; + } +} + +void viputafter() /**/ +{ +int cc; +char *buf = cutbuf; + + if (!cutbuf) { + feep(); + return; + } + if (mult < 0) return; + if (vibufspec) { + vibufspec = tolower(vibufspec); + vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a'; + if (!(buf = vibuf[vibufspec])) { + feep(); + vibufspec = 0; + return; + } + vibufspec = 0; + } + if (strchr(buf,'\n')) { + cs = findeol(); + if (cs == ll) { spaceinline(1); line[cs] = '\n'; } + } + if (cs != ll) cs++; + yankb = cs; + while (mult--) { + kct = kringnum; + cc = strlen(buf); + spaceinline(cc); + strncpy((char *) line+cs,buf,cc); + cs += cc; + yanke = cs; + } + cs = yankb; +} + +void yankpop() /**/ +{ +int cc; + + if (!(lastcmd & ZLE_YANK) || !kring[kct]) { + feep(); + return; + } + cs = yankb; + foredel(yanke-yankb); + cc = strlen(kring[kct]); + spaceinline(cc); + strncpy((char *) line+cs,kring[kct],cc); + cs += cc; + yanke = cs; + kct = (kct-1) & (KRINGCT-1); +} + +void overwritemode() /**/ +{ + insmode ^= 1; +} + +void undefinedkey() /**/ +{ + feep(); +} + +void quotedinsert() /**/ +{ +#ifndef TIO +struct sgttyb sob; + sob = shttyinfo.sgttyb; + sob.sg_flags = (sob.sg_flags|RAW) & ~ECHO; + ioctl(SHTTY,TIOCSETN,&sob); +#endif + c = getkey(0); +#ifndef TIO + setterm(); +#endif + if (c) selfinsert(); else feep(); +} + +void digitargument() /**/ +{ + if (!(lastcmd & ZLE_ARG)) + mult = 0; + mult = mult*10+(c&0xf); + if (lastcmd & ZLE_NEGARG) mult = -mult; +} + +void negargument() /**/ +{ + if (lastcmd & ZLE_ARG) feep(); +} + +void universalargument() /**/ +{ + if (!(lastcmd & ZLE_ARG)) + mult = 4; + else + mult *= 4; +} + +void copyprevword() /**/ +{ +int len,t0; + + for (t0 = cs-1; t0 >= 0; t0--) + if (iword(line[t0])) + break; + for (; t0 >= 0; t0--) + if (!iword(line[t0])) + break; + if (t0) + t0++; + len = cs-t0; + spaceinline(len); + strncpy((char *) line+cs,(char *) line+t0,len); + cs += len; +} + +void sendbreak() /**/ +{ + errflag = done = 1; +} + +void undo() /**/ +{ +char *s; +struct undoent *ue; + + ue = undos+undoct; + if (!ue->change) + { + feep(); + return; + } + line[ll] = '\0'; + s = ztrdup((char *) line+ll-ue->suff); + sizeline((ll = ue->pref+ue->suff+ue->len)+1); + strncpy((char *) line+ue->pref,ue->change,ue->len); + strcpy((char *) line+ue->pref+ue->len,s); + free(s); + ue->change = NULL; + undoct = (undoct-1) & (UNDOCT-1); + cs = ue->cs; +} + +void quoteregion() /**/ +{ +char *s,*t; +int x,y; + + if (mark > ll) + mark = ll; + if (mark < cs) + { + x = mark; + mark = cs; + cs = x; + } + s = hcalloc((y = mark-cs)+1); + strncpy(s,(char *) line+cs,y); + s[y] = '\0'; + foredel(mark-cs); + t = makequote(s); + spaceinline(x = strlen(t)); + strncpy((char *) line+cs,t,x); + mark = cs; + cs += x; +} + +void quoteline() /**/ +{ +char *s; + + line[ll] = '\0'; + s = makequote((char *) line); + setline(s); +} + +char *makequote(s) /**/ +char *s; +{ +int qtct = 0; +char *l,*ol; + + for (l = s; *l; l++) + if (*l == '\'') + qtct++; + l = ol = halloc((qtct*3)+3+strlen(s)); + *l++ = '\''; + for (; *s; s++) + if (*s == '\'') + { + *l++ = '\''; + *l++ = '\\'; + *l++ = '\''; + *l++ = '\''; + } + else + *l++ = *s; + *l++ = '\''; + *l = '\0'; + return ol; +} + +#define NAMLEN 70 + +int executenamedcommand() /**/ +{ +char buf[NAMLEN],*ptr; +int len,ch,t0; + + strcpy(buf,"execute: "); + ptr = buf+9; + len = 0; + statusline = buf; + refresh(); + for (;ch = getkey(1);refresh()) + { + switch (ch) + { + case 8: case 127: + if (len) + { + len--; + *--ptr = '\0'; + } + break; + case 23: + while (len && (len--, *--ptr != '-')) + *ptr = '\0'; + break; + case 21: + len = 0; + ptr = buf+9; + *ptr = '\0'; + break; + case 10: case 13: goto brk; + case 7: case -1: statusline = NULL; return z_undefinedkey; + case 9: case 32: + { + Lklist ll; + int ambig = 100; + + heapalloc(); + ll = newlist(); + for (t0 = 0; t0 != ZLECMDCOUNT; t0++) + if (strpfx(buf+9,zlecmds[t0].name)) + { + int xx; + + addnode(ll,zlecmds[t0].name); + xx = pfxlen(peekfirst(ll),zlecmds[t0].name); + if (xx < ambig) + ambig = xx; + } + permalloc(); + if (!full(ll)) + feep(); + else if (!nextnode(firstnode(ll))) + { + strcpy(buf+9,peekfirst(ll)); + ptr = buf+(len = strlen(buf)); + } + else + { + strcpy(buf+9,peekfirst(ll)); + len = ambig; + ptr = buf+9+len; + *ptr = '\0'; + feep(); + listmatches(ll,NULL); + } + break; + } + default: + if (len == NAMLEN-10 || icntrl(ch)) + feep(); + else + *ptr++ = ch, *ptr = '\0', len++; + break; + } + } +brk: + statusline = NULL; + ptr = buf+9; + for (t0 = 0; t0 != ZLECMDCOUNT; t0++) + if (!strcmp(ptr,zlecmds[t0].name)) + break; + if (t0 != ZLECMDCOUNT) + return lastnamed = t0; + else + return z_undefinedkey; +} + +void vijoin() /**/ +{ +int x; + + if ((x = findeol()) == ll) + { + feep(); + return; + } + cs = x+1; + for (x = 1; cs != ll && iblank(line[cs]); cs++,x++); + backdel(x); + spaceinline(1); + line[cs] = ' '; +} + +void viswapcase() /**/ +{ + if (cs < ll) + { + int ch = line[cs]; + + if (islower(ch)) + ch = tuupper(ch); + else if (isupper(ch)) + ch = tulower(ch); + line[cs++] = ch; + } +} + +void vicapslockpanic() /**/ +{ +char ch; + + statusline = "press a lowercase key to continue"; + refresh(); + do + ch = getkey(0); + while (!islower(ch)); +} + +void visetbuffer() /**/ +{ +int ch; + + ch = getkey(1); + if (!ialnum(ch)) { + feep(); + return; + } + vibufspec = ch; +} + +static char *bp; +static int lensb,countp; + +void stradd(d) /**/ +char *d; +{ + while (*bp++ = *d++); + bp--; +} + +int putstr(d) /**/ +int d; +{ + *bp++ = d; + if (countp) + lensb++; + return 0; +} + +#define tstradd(X) \ + if (termok && unset(SINGLELINEZLE)) { \ + char tbuf[2048],*tptr = tbuf; \ + if (tgetstr(X,&tptr)) \ + tputs(tbuf,1,putstr); \ + } \ + break + +/* get a prompt string */ + +char *putprompt(fm,lenp) /**/ +char *fm;int *lenp; +{ +char *ss,*bl0; +static char buf1[256],buf2[256],*buf; +char buf3[MAXPATHLEN]; +int t0,bracepos = 0; +struct tm *tm = NULL; +time_t timet; + + lensb = 0; countp = 1; + if (!fm) { *lenp = 0; return ""; } + /* kludge alert! */ + buf = (buf == buf1) ? buf2 : buf1; + bp = bl0 = buf; + if (!columns) columns = 80; + clearerr(stdin); + for(;*fm;fm++) { + if (bp-buf >= 220) + break; + if (*fm == '%') + switch (*++fm) { + case '~': + t0 = finddir(pwd); + if (t0 != -1) { + *bp++ = '~'; + stradd(usernames[t0]); + stradd(pwd+strlen(userdirs[t0])); + break; + } + if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) { + *bp++ = '~'; + stradd(pwd+t0); + break; + } + case 'd': case '/': stradd(pwd); break; + case 'c': case '.': + t0 = finddir(pwd); + if (t0 != -1) { + sprintf(buf3,"~%s%s",usernames[t0], + pwd+strlen(userdirs[t0])); + } else if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) { + sprintf(buf3,"~%s",pwd+t0); + } else { + strcpy(buf3,pwd); + } + t0 = 1; + if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; } + for (ss = buf3+strlen(buf3); ss > buf3; ss--) + if (*ss == '/' && !--t0) { + ss++; + break; + } + if (*ss == '/' && ss[1] && (ss != buf3)) ss++; + stradd(ss); + break; + case 'C': + strcpy(buf3,pwd); + t0 = 1; + if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; } + for (ss = buf3+strlen(buf3); ss > buf3; ss--) + if (*ss == '/' && !--t0) { + ss++; + break; + } + if (*ss == '/' && ss[1] && (ss != buf3)) ss++; + stradd(ss); + break; + case 'h': case '!': + sprintf(bp,"%d",curhist); + bp += strlen(bp); + break; + case 'M': stradd(hostnam); break; + case 'm': + if (idigit(fm[1])) + t0 = (*++fm)-'0'; + else + t0 = 1; + for (ss = hostnam; *ss; ss++) + if (*ss == '.' && !--t0) + break; + t0 = *ss; + *ss = '\0'; + stradd(hostnam); + *ss = t0; + break; + case 'S': tstradd("so"); /* <- this is a macro */ + case 's': tstradd("se"); + case 'B': tstradd("md"); + case 'b': tstradd("me"); + case 'U': tstradd("us"); + case 'u': tstradd("ue"); + case '{': bracepos = bp-buf; countp = 0; break; + case '}': lensb += (bp-buf)-bracepos; countp = 1; break; + case 't': case '@': + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,"%l:%M%p",tm); + if (*bp == ' ') + chuck(bp); + bp += strlen(bp); + break; + case 'T': + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,"%k:%M",tm); + bp += strlen(bp); + break; + case '*': + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,"%k:%M:%S",tm); + bp += strlen(bp); + break; + case 'n': stradd(username); break; + case 'w': + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,"%a %e",tm); + bp += strlen(bp); + break; + case 'W': + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,"%m/%d/%y",tm); + bp += strlen(bp); + break; + case 'D': + strcpy(buf3, "%y-%m-%d"); + if (fm[1] == '{') { + for (ss = fm + 1, t0 = 0; *ss; ++ss) + if (*ss == '{') + ++t0; + else if (*ss == '}') + if (--t0 == 0) + break; + if (*ss == '}' && t0 == 0) { + t0 = (ss - 1) - (fm + 1); + strncpy(buf3, fm + 2, t0); + buf3[t0] = 0; + fm = ss; + } + } + timet = time(NULL); + tm = localtime(&timet); + ztrftime(bp,16,buf3,tm); + bp += strlen(bp); + break; + case 'l': + if (*ttystrname) stradd((strncmp(ttystrname,"/dev/tty",8) ? + ttystrname+5 : ttystrname+8)); + else stradd("()"); + break; + case '?': + sprintf(bp,"%d",lastval); + bp += strlen(bp); + break; + case '%': *bp++ = '%'; break; + case '#': *bp++ = (geteuid()) ? '%' : '#'; break; + case 'r': stradd(rstring); break; + case 'R': stradd(Rstring); break; + default: *bp++ = '%'; *bp++ = *fm; break; + } + else if (*fm == '!') { + sprintf(bp,"%d",curhist); + bp += strlen(bp); + } else { + if (fm[0] == '\\' && fm[1]) + fm++; + if ((*bp++ = *fm) == '\n') + bl0 = bp, lensb = 0; + } + } + *lenp = (bp-bl0)-lensb; + *lenp %= columns; + if (*lenp == columns-1) { + *lenp = 0; + *bp++ = ' '; + } + *bp = '\0'; + return buf; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_misc.pro b/usr/othersrc/public/zsh-2.2/src/zle_misc.pro new file mode 100644 index 0000000000..47ac3abf75 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_misc.pro @@ -0,0 +1,41 @@ +void selfinsert DCLPROTO((void)); +void selfinsertunmeta DCLPROTO((void)); +void deletechar DCLPROTO((void)); +void backwarddeletechar DCLPROTO((void)); +void videletechar DCLPROTO((void)); +void vibackwarddeletechar DCLPROTO((void)); +void vikillline DCLPROTO((void)); +void killwholeline DCLPROTO((void)); +void killbuffer DCLPROTO((void)); +void backwardkillline DCLPROTO((void)); +void gosmacstransposechars DCLPROTO((void)); +void transposechars DCLPROTO((void)); +void poundinsert DCLPROTO((void)); +void acceptline DCLPROTO((void)); +void acceptandhold DCLPROTO((void)); +void killline DCLPROTO((void)); +void killregion DCLPROTO((void)); +void copyregionaskill DCLPROTO((void)); +void yank DCLPROTO((void)); +void viputafter DCLPROTO((void)); +void yankpop DCLPROTO((void)); +void overwritemode DCLPROTO((void)); +void undefinedkey DCLPROTO((void)); +void quotedinsert DCLPROTO((void)); +void digitargument DCLPROTO((void)); +void negargument DCLPROTO((void)); +void universalargument DCLPROTO((void)); +void copyprevword DCLPROTO((void)); +void sendbreak DCLPROTO((void)); +void undo DCLPROTO((void)); +void quoteregion DCLPROTO((void)); +void quoteline DCLPROTO((void)); +char *makequote DCLPROTO((char *s)); +int executenamedcommand DCLPROTO((void)); +void vijoin DCLPROTO((void)); +void viswapcase DCLPROTO((void)); +void vicapslockpanic DCLPROTO((void)); +void visetbuffer DCLPROTO((void)); +void stradd DCLPROTO((char *d)); +int putstr DCLPROTO((int d)); +char *putprompt DCLPROTO((char *fm,int *lenp)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_move.c b/usr/othersrc/public/zsh-2.2/src/zle_move.c new file mode 100644 index 0000000000..fb5d5b5ac5 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_move.c @@ -0,0 +1,328 @@ +/* + * + * zle_move.c - editor movement + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + +void beginningofline() /**/ +{ + if (mult < 0) { mult = -mult; endofline(); return; } + while (mult--) { + if (cs == 0) + return; + if (line[cs-1] == '\n') + if (!--cs) + return; + while (cs && line[cs-1] != '\n') cs--; + } +} + +void endofline() /**/ +{ + if (mult < 0) { mult = -mult; beginningofline(); return; } + while (mult--) { + if (cs >= ll) { + cs = ll; + return; + } + if (line[cs] == '\n') + if (++cs == ll) + return; + while (cs != ll && line[cs] != '\n') cs++; + } +} + +void beginningoflinehist() /**/ +{ + if (mult < 0) { mult = -mult; endoflinehist(); return; } + while (mult) { + if (cs == 0) + break; + if (line[cs-1] == '\n') + if (!--cs) + break; + while (cs && line[cs-1] != '\n') cs--; + mult--; + } + if (mult) { + uphistory(); + cs = 0; + } +} + +void endoflinehist() /**/ +{ + if (mult < 0) { mult = -mult; beginningoflinehist(); return; } + while (mult) { + if (cs >= ll) { + cs = ll; + break; + } + if (line[cs] == '\n') + if (++cs == ll) + break; + while (cs != ll && line[cs] != '\n') cs++; + mult--; + } + if (mult) + downhistory(); +} + +void forwardchar() /**/ +{ + cs += mult; + if (cs > ll) cs = ll; + if (cs < 0) cs = 0; +} + +void backwardchar() /**/ +{ + cs -= mult; + if (cs > ll) cs = ll; + if (cs < 0) cs = 0; +} + +void setmarkcommand() /**/ +{ + mark = cs; +} + +void exchangepointandmark() /**/ +{ +int x; + + x = mark; + mark = cs; + cs = x; + if (cs > ll) + cs = ll; +} + +void vigotocolumn() /**/ +{ +int x,y,ocs = cs; + + if (mult > 0) mult--; + findline(&x,&y); + if (mult >= 0) cs = x+mult; else cs = y+mult; + if (cs < x || cs > y) { + feep(); + cs = ocs; + } +} + +void vimatchbracket() /**/ +{ +int ocs = cs,dir,ct; +char oth,me; + +otog: + if (cs == ll) + { + feep(); + cs = ocs; + return; + } + switch(me = line[cs]) + { + case '{': dir = 1; oth = '}'; break; + case '}': dir = -1; oth = '{'; break; + case '(': dir = 1; oth = ')'; break; + case ')': dir = -1; oth = '('; break; + case '[': dir = 1; oth = ']'; break; + case ']': dir = -1; oth = '['; break; + default: cs++; goto otog; + } + ct = 1; + while (cs >= 0 && cs < ll && ct) + { + cs += dir; + if (line[cs] == oth) + ct--; + else if (line[cs] == me) + ct++; + } + if (cs < 0 || cs >= ll) + { + feep(); + cs = ocs; + } +} + +void viforwardchar() /**/ +{ + if (mult < 0) { mult = -mult; vibackwardchar(); return; } + while (mult--) { + cs++; + if (cs >= ll || line[cs] == '\n') { + cs--; + break; + } + } +} + +void vibackwardchar() /**/ +{ + if (mult < 0) { mult = -mult; viforwardchar(); return; } + while (mult--) { + cs--; + if (cs < 0 || line[cs] == '\n') { + cs++; + break; + } + } +} + +void viendofline() /**/ +{ + cs = findeol(); + if (!virangeflag && cs != 0 && line[cs-1] != '\n') cs--; +} + +void vibeginningofline() /**/ +{ + cs = findbol(); +} + + +static int vfindchar,vfinddir,tailadd; + +void vifindnextchar() /**/ +{ + if (vfindchar = vigetkey()) + { + vfinddir = 1; + tailadd = 0; + virepeatfind(); + } +} + +void vifindprevchar() /**/ +{ + if (vfindchar = vigetkey()) + { + vfinddir = -1; + tailadd = 0; + virepeatfind(); + } +} + +void vifindnextcharskip() /**/ +{ + if (vfindchar = vigetkey()) + { + vfinddir = 1; + tailadd = -1; + virepeatfind(); + } +} + +void vifindprevcharskip() /**/ +{ + if (vfindchar = vigetkey()) + { + vfinddir = -1; + tailadd = 1; + virepeatfind(); + } +} + +void virepeatfind() /**/ +{ +int ocs = cs; + + if (!vfinddir) { feep(); return; } + if (mult < 0) { mult = -mult; virevrepeatfind(); return; } + while (mult--) + { + do + cs += vfinddir; + while (cs >= 0 && cs < ll && line[cs] != vfindchar && line[cs] != '\n'); + if (cs < 0 || cs >= ll || line[cs] == '\n') + { + feep(); + cs = ocs; + return; + } + } + cs += tailadd; + if (vfinddir == 1 && virangeflag) cs++; +} + +void virevrepeatfind() /**/ +{ + if (mult < 0) { mult = -mult; virepeatfind(); return; } + vfinddir = -vfinddir; + virepeatfind(); + vfinddir = -vfinddir; +} + +void vifirstnonblank() /**/ +{ + cs = findbol(); + while (cs != ll && iblank(line[cs])) + cs++; +} + +void visetmark() /**/ +{ +int ch; + + ch = getkey(1); + if (ch < 'a' || ch > 'z') { + feep(); + return; + } + ch -= 'a'; + vimarkcs[ch] = cs; + vimarkline[ch] = histline; +} + +void vigotomark() /**/ +{ +int ch; + + ch = getkey(1); + if (ch == c) ch = 26; + else { + if (ch < 'a' || ch > 'z') { + feep(); + return; + } + ch -= 'a'; + } + if (!vimarkline[ch]) { + feep(); + return; + } + if (curhist != vimarkline[ch]) { + mult = vimarkline[ch]; + vifetchhistory(); + if (curhist != vimarkline[ch]) return; + } + cs = vimarkcs[ch]; + if (cs > ll) ch = ll; +} + +void vigotomarkline() /**/ +{ + vigotomark(); + cs = findbol(); +} diff --git a/usr/othersrc/public/zsh-2.2/src/zle_move.pro b/usr/othersrc/public/zsh-2.2/src/zle_move.pro new file mode 100644 index 0000000000..9813929162 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_move.pro @@ -0,0 +1,24 @@ +void beginningofline DCLPROTO((void)); +void endofline DCLPROTO((void)); +void beginningoflinehist DCLPROTO((void)); +void endoflinehist DCLPROTO((void)); +void forwardchar DCLPROTO((void)); +void backwardchar DCLPROTO((void)); +void setmarkcommand DCLPROTO((void)); +void exchangepointandmark DCLPROTO((void)); +void vigotocolumn DCLPROTO((void)); +void vimatchbracket DCLPROTO((void)); +void viforwardchar DCLPROTO((void)); +void vibackwardchar DCLPROTO((void)); +void viendofline DCLPROTO((void)); +void vibeginningofline DCLPROTO((void)); +void vifindnextchar DCLPROTO((void)); +void vifindprevchar DCLPROTO((void)); +void vifindnextcharskip DCLPROTO((void)); +void vifindprevcharskip DCLPROTO((void)); +void virepeatfind DCLPROTO((void)); +void virevrepeatfind DCLPROTO((void)); +void vifirstnonblank DCLPROTO((void)); +void visetmark DCLPROTO((void)); +void vigotomark DCLPROTO((void)); +void vigotomarkline DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_refresh.c b/usr/othersrc/public/zsh-2.2/src/zle_refresh.c new file mode 100644 index 0000000000..0043570544 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_refresh.c @@ -0,0 +1,641 @@ +/* + * + * zle_refresh.c - screen update + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + +char **obuf = NULL,**nbuf = NULL; +int olnct,nlnct; +int winw,winh,winpos; + +int vcs,vln,vmaxln; + +void resetvideo() /**/ +{ +int ln; +static int lwinw = -1,lwinh = -1; + + setterm(); + winw = columns-1; + if (isset(SINGLELINEZLE) || !termok) + winh = 1; + else + winh = (lines < 2) ? 24 : lines; + winpos = vln = vmaxln = 0; + if (lwinw != winw || lwinh != winh) + { + if (nbuf) + { + for (ln = 0; ln != lwinh; ln++) + { + free(nbuf[ln]); + free(obuf[ln]); + } + free(nbuf); + free(obuf); + } + nbuf = (char **) zalloc((winh+1)*sizeof(char *)); + obuf = (char **) zalloc((winh+1)*sizeof(char *)); + for (ln = 0; ln != winh+1; ln++) + { + nbuf[ln] = zalloc(winw+1); + obuf[ln] = zalloc(winw+1); + } + lwinw = winw; + lwinh = winh; + } + for (ln = 0; ln != winh+1; ln++) + { + *nbuf[ln] = '\0'; + *obuf[ln] = '\0'; + } + if (!pptlen) + nbuf[0][0] = obuf[0][0] = '\0'; + else + { + for (ln = 0; ln != pptlen-1; ln++) + nbuf[0][ln] = obuf[0][ln] = ' '; + nbuf[0][ln] = obuf[0][ln] = '>'; + nbuf[0][pptlen] = obuf[0][pptlen] = '\0'; + } + vcs = pptlen; + olnct = nlnct = 1; +} + +int scrollwindow() /**/ +{ +int t0,hwinh = winh/2; + + for (t0 = 0; t0 != winh-hwinh; t0++) + { + char *s; + + s = nbuf[t0]; + nbuf[t0] = nbuf[t0+hwinh]; + nbuf[t0+hwinh] = s; + } + for (t0 = 0; t0 != pptlen-1; t0++) + nbuf[0][t0] = ' '; + strcpy(nbuf[0]+t0,"> ..."); + return winh-hwinh; +} + +/* this is the messy part. */ +/* this define belongs where it's used!!! */ + +#define nextline { *s = (unsigned char)'\0'; \ + if (winh == ln+1) if (nvln != -1) break; else ln = scrollwindow()-1; \ + s = (unsigned char *)nbuf[++ln]; sen = s+winw; \ + } + +void refresh() /**/ +{ +unsigned char *s,*t,*sen,*scs = line+cs; char **qbuf; +int ln = 0,nvcs,nvln = -1,t0; + + cost = 0; + if (resetneeded) + { + resetvideo(); + resetneeded = 0; + if (isset(SINGLELINEZLE) || !termok) + vcs = 0; + else + printf("%s",pmpt); + } + zleactive = 1; + if (isset(SINGLELINEZLE) || !termok) + { + singlerefresh(); + return; + } + +/* first, we generate the video line buffers so we know what to + put on the screen. + + s = ptr into the video buffer. + t = ptr into the real buffer. + sen = end of the video buffer (eol) +*/ + + s = (unsigned char *)(nbuf[ln = 0]+pptlen); + t = line; + sen = (unsigned char *)(*nbuf+winw); + for (; *t; t++) + { + if (icntrl((char)*t)) + if (*t == '\n') + { + if (t == scs) + { + nvcs = (char *)s-nbuf[nvln = ln]; + scs = (unsigned char *)NULL; + } + nextline + } + else if ((char)*t == '\t') + { + int t1 = (char *)s-nbuf[ln]; + + if ((t1|7)+1 >= winw) nextline + else + do + *s++ = ' '; + while ((++t1) & 7); + } + else + { + if (s == sen) nextline + *s++ = '^'; + if (s == sen) nextline + *s++ = (*t == 127) ? '?' : (*t | '@'); + } + else + { + if (s == sen) nextline + *s++ = *t; + } +/* if the cursor is here, remember it */ + + if (t == scs) + nvcs = s-(unsigned char *)nbuf[nvln = ln]-1; + } + if (scs == t) + nvcs = s-(unsigned char *)nbuf[nvln = ln]; + *s = '\0'; + nlnct = ln+1; + if (statusline) + strcpy(nbuf[(nlnct == winh) ? winh-1 : nlnct++],statusline); + +/* do RPROMPT */ + + if (pmpt2 && ln == 0 && strlen(nbuf[0])+strlen(pmpt2) < winw) + { + for (t0 = strlen(nbuf[0]); t0 != winw; t0++) + nbuf[0][t0] = ' '; + strcpy(nbuf[0]+winw-strlen(pmpt2),pmpt2); + } + for (ln = 0; ln < nlnct; ln++) + { + +/* if old line and new line are different, + see if we can insert/delete a line */ + + if (ln < olnct && strncmp(nbuf[ln],obuf[ln],16)) + { + if (tccan(TCDELLINE) && !strncmp(nbuf[ln],obuf[ln+1],16) + && obuf[ln+1][0] && ln != olnct) + { + int t0; + + moveto(ln,0); + tcout(TCDELLINE); + for (t0 = ln; t0 != olnct; t0++) + strcpy(obuf[t0],obuf[t0+1]); + olnct--; + } + +/* don't try to insert a line if olnct < vmaxln (vmaxln is the number + of lines that have been displayed by this routine) so that we don't + go off the end of the screen. */ + + else if (tccan(TCINSLINE) && !strncmp(nbuf[ln+1],obuf[ln],16) && + olnct < vmaxln && nbuf[ln+1][0] && ln != olnct) + { + int t0; + + moveto(ln,0); + tcout(TCINSLINE); + for (t0 = olnct; t0 != ln; t0--) + strcpy(obuf[t0],obuf[t0-1]); + *obuf[ln] = '\0'; + olnct++; + } + } + refreshline(ln); + } + +/* if old buffer had extra lines, do a clear-end-of-display if we can, + otherwise, just fill new buffer with blank lines and refresh them */ + + if (olnct > nlnct) + { + for (ln = nlnct; ln < olnct; ln++) + nbuf[ln][0] = '\0'; + if (tccan(TCCLEAREOD)) + { + moveto(nlnct,0); + tcout(TCCLEAREOD); + } + else + for (ln = nlnct; ln < olnct; ln++) + refreshline(ln); + } + +/* move to the new cursor position */ + + moveto(nvln,nvcs); + qbuf = nbuf; + nbuf = obuf; + obuf = qbuf; + olnct = nlnct; + if (nlnct > vmaxln) + vmaxln = nlnct; + fflush(stdout); +} + +#define tcinscost(X) (tccan(TCMULTINS) ? tclen[TCMULTINS] : (X)*tclen[TCINS]) +#define tcdelcost(X) (tccan(TCMULTDEL) ? tclen[TCMULTDEL] : (X)*tclen[TCDEL]) +#define tc_delchars(X) tcmultout(TCDEL,TCMULTDEL,(X)) +#define tc_inschars(X) tcmultout(TCINS,TCMULTINS,(X)) +#define tc_upcurs(X) tcmultout(TCUP,TCMULTUP,(X)) +#define tc_leftcurs(X) tcmultout(TCLEFT,TCMULTLEFT,(X)) + +void refreshline(ln) /**/ +int ln; +{ +char *nl = nbuf[ln],*ol = obuf[ln]; +char *p1; +char junk,*truncptr = &junk; +int ccs = 0; + + if (ln >= olnct) + *ol = '\0'; + for (;;) + { + while (*nl && *nl == *ol) + { + nl++,ol++,ccs++; + } + if (!*nl && !*ol) + { *truncptr = '\0'; return; } + +/* if this is the end of the new buffer but the old buffer has stuff + here, clear to end of line if we can, otherwise fill the new buffer + with blanks and continue. */ + + if (!*nl) + { + if (tccan(TCCLEAREOL) && strlen(ol) > tclen[TCCLEAREOL]) + { + moveto(ln,ccs); + tcout(TCCLEAREOL); + *ol = '\0'; + *truncptr = '\0'; + return; + } + else + { + int x = strlen(ol); + char *p = nl; + + truncptr = p; + while (x--) + *p++ = ' '; + *p = '\0'; + continue; + } + } + +/* if this is the end of the old buffer, just dump the rest of the + new buffer. */ + + if (!*ol) + { + while (*nl == ' ') + nl++,ccs++; + if (*nl) + { + moveto(ln,ccs); + fwrite(nl,strlen(nl),1,stdout); + cost += strlen(nl); + ccs = (vcs += strlen(nl)); + } + *truncptr = 0; + return; + } + moveto(ln,ccs); + +/* try to insert/delete characters */ + + if (ol[1] != nl[1] && tccan(TCDEL)) + { + int ct = 0; + + for (p1 = ol; *p1; p1++,ct++) + if (tcdelcost(ct) < streqct(p1,nl)) + { + tc_delchars(ct); + ol = p1; + break; + } + if (*p1) + continue; + } + + if (ol[1] != nl[1] && tccan(TCINS)) + { + int ct = 0; + + for (p1 = nl; *p1; p1++,ct++) + if (tcinscost(ct) < streqct(p1,ol)+ct) + { +#if 0 +/* make sure we aren't inserting characters off the end of the screen; + if we are, jump to the end and truncate the line, if we can do + it quickly (gee, clever idea, Paul!) */ + if (ct+ccs+strlen(ol) >= winw-1) + { + if (!tccan(TCMULTRIGHT) || ccs > winw-tclen[TCMULTRIGHT]) + continue; + moveto(ln,winw-1-ct); + if (!tccan(TCCLEAREOL) || ct < tclen[TCCLEAREOL]) + { + int x = ct; + + while (vcs++,x--) + putchar(' '); + } + else + tcout(TCCLEAREOL); + moveto(ln,ccs); + } +#endif + if (ct+ccs+strlen(ol) < winw-1) + { + tc_inschars(ct = p1-nl); + ccs = (vcs += p1-nl); + cost += ct; + fwrite(nl,ct,1,stdout); + nl += ct; + break; + } + } + if (*p1) + continue; + } + +/* if we can't do anything fancy, just write the new character and + keep going. */ + + putchar(*nl); + cost++; + nl++,ol++,ccs = ++vcs; + } +} + +void moveto(ln,cl) /**/ +int ln;int cl; +{ + +/* move up */ + + if (ln < vln) + { + tc_upcurs(vln-ln); + vln = ln; + } + +/* move down; if we might go off the end of the screen, use newlines + instead of TCDOWN */ + + while (ln > vln) + if (cl < (vcs/2) || ln >= vmaxln || !tccan(TCLEFT)) + { + putchar('\r'); + putchar('\n'); + cost+=2; + vln++; + vcs = 0; + } + else + { + tc_downcurs(ln-vln); + vln = ln; + } + if (cl < (vcs/2) || !tccan(TCLEFT)) + { + putchar('\r'); + cost++; + vcs = 0; + } + if (vcs < cl) + tc_rightcurs(cl-vcs); + else if (vcs > cl) + tc_leftcurs(vcs-cl); + vcs = cl; +} + +void tcmultout(cap,multcap,ct) /**/ +int cap;int multcap;int ct; +{ + if (tccan(multcap) && (!tccan(cap) || tclen[multcap] < tclen[cap]*ct)) + tcoutarg(multcap,ct); + else while (ct--) + tcout(cap); +} + +void tc_rightcurs(ct) /**/ +int ct; +{ + +/* do a multright if it's cheaper or if we're walking over the prompt. */ + + if (tccan(TCMULTRIGHT) && + (ct > tclen[TCMULTRIGHT] || vln == 0 && vcs < pptlen)) + tcoutarg(TCMULTRIGHT,ct); + +/* if we're walking over the prompt and we can do a bunch of cursor rights, + do them, even though they're more expensive. (We can't redraw the + prompt very easily in general.) */ + + else if (vln == 0 && vcs < pptlen && tccan(TCRIGHT)) + while (ct--) + tcout(TCRIGHT); + +/* otherwise write the contents of the video buffer. */ + + else + fwrite(nbuf[vln]+vcs,ct,1,stdout); +} + +void tc_downcurs(ct) /**/ +int ct; +{ + if (tccan(TCMULTDOWN) && + (!tccan(TCDOWN) || tclen[TCMULTDOWN] < tclen[TCDOWN]*ct)) + tcoutarg(TCMULTDOWN,ct); + else if (tccan(TCDOWN)) + while (ct--) + tcout(TCDOWN); + else + { + while (ct--) + putchar('\n'); + vcs = 0; + } +} + +/* I'm NOT going to worry about padding unless anyone complains. */ + +void tcout(cap) /**/ +int cap; +{ + tputs(tcstr[cap],1,putraw); +} + +void tcoutarg(cap,arg) /**/ +int cap;int arg; +{ + tputs(tgoto(tcstr[cap],arg,arg),1,putraw); +} + +void clearscreen() /**/ +{ + tcout(TCCLEARSCREEN); + resetneeded = 1; +} + +void redisplay() /**/ +{ + trashzle(); +} + +void trashzle() /**/ +{ + if (zleactive) + { + refresh(); + moveto(nlnct,0); + printf("%s",postedit); + fflush(stdout); + unsetterm(); + resetneeded = 1; + } +} + +void singlerefresh() /**/ +{ +char *vbuf,*vp,**qbuf,*op; +int t0,vsiz,nvcs; + + for (vsiz = 1+pptlen, t0 = 0; t0 != ll; t0++,vsiz++) + if (line[t0] == '\t') + vsiz += 7; + else if (icntrl(line[t0])) + vsiz++; + vbuf = zalloc(vsiz); + strcpy(vbuf,pmpt); + vp = vbuf+pptlen; + for (t0 = 0; t0 != ll; t0++) + { + if (line[t0] == '\t') + do + *vp++ = ' '; + while ((vp-vbuf) & 7); + else if (line[t0] == '\n') + { + *vp++ = '\\'; + *vp++ = 'n'; + } + else if (line[t0] == 0x7f) + { + *vp++ = '^'; + *vp++ = '?'; + } + else if (icntrl(line[t0])) + { + *vp++ = '^'; + *vp++ = line[t0] | '@'; + } + else + *vp++ = line[t0]; + if (t0 == cs) + nvcs = vp-vbuf-1; + } + if (t0 == cs) + nvcs = vp-vbuf; + *vp = '\0'; + if ((winpos && nvcs < winpos+1) || (nvcs > winpos+winw-1)) + { + if ((winpos = nvcs-(winw/2)) < 0) + winpos = 0; + } + if (winpos) + vbuf[winpos] = '<'; + if (strlen(vbuf+winpos) > winw) + { + vbuf[winpos+winw-1] = '>'; + vbuf[winpos+winw] = '\0'; + } + strcpy(nbuf[0],vbuf+winpos); + free(vbuf); + nvcs -= winpos; + for (t0 = 0,vp = *nbuf,op = *obuf; *vp; t0++,vp++) + { + if (*vp != *op && !(*vp == ' ' && !*op)) + { + singmoveto(t0); + putchar(*vp); + vcs++; + } + if (*op) + op++; + } + if (*op) + { + singmoveto(t0); + for (; *op; op++) + { + putchar(' '); + vcs++; + } + } + singmoveto(nvcs); + qbuf = nbuf; + nbuf = obuf; + obuf = qbuf; + fflush(stdout); +} + +void singmoveto(pos) /**/ +int pos; +{ + while (pos < vcs) + { + vcs--; + putchar('\b'); + } + while (pos > vcs) + { + putchar(nbuf[0][vcs]); + vcs++; + } +} + +int streqct(s,t) /**/ +char *s;char *t; +{ +int ct = 0; + + while (*s && *s == *t) s++,t++,ct++; + return ct; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_refresh.pro b/usr/othersrc/public/zsh-2.2/src/zle_refresh.pro new file mode 100644 index 0000000000..75f186cd3d --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_refresh.pro @@ -0,0 +1,16 @@ +void resetvideo DCLPROTO((void)); +int scrollwindow DCLPROTO((void)); +void refresh DCLPROTO((void)); +void refreshline DCLPROTO((int ln)); +void moveto DCLPROTO((int ln,int cl)); +void tcmultout DCLPROTO((int cap,int multcap,int ct)); +void tc_rightcurs DCLPROTO((int ct)); +void tc_downcurs DCLPROTO((int ct)); +void tcout DCLPROTO((int cap)); +void tcoutarg DCLPROTO((int cap,int arg)); +void clearscreen DCLPROTO((void)); +void redisplay DCLPROTO((void)); +void trashzle DCLPROTO((void)); +void singlerefresh DCLPROTO((void)); +void singmoveto DCLPROTO((int pos)); +int streqct DCLPROTO((char *s,char *t)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_tricky.c b/usr/othersrc/public/zsh-2.2/src/zle_tricky.c new file mode 100644 index 0000000000..b08c56d390 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_tricky.c @@ -0,0 +1,1282 @@ +/* + * + * zle_tricky.c - expansion and completion + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" +#ifdef __hpux +#include +#else +#ifdef SYSV +#define direct dirent +#else +#include +#endif +#endif +#include + +static int we,wb,usemenu,useglob; + +static int menub,menue,menuw; +static Lklist menulist; +static Lknode menunode; + +#define inststr(X) inststrlen((X),-1) + +int usetab() /**/ +{ +unsigned char *s = line+cs-1; + + for (; s >= line && *s != '\n'; s--) + if (*s != '\t' && *s != ' ') + return 0; + return 1; +} + +#define COMP_COMPLETE 0 +#define COMP_LIST_COMPLETE 1 +#define COMP_SPELL 2 +#define COMP_EXPAND 3 +#define COMP_EXPAND_COMPLETE 4 +#define COMP_LIST_EXPAND 5 +#define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND) + +void completeword() /**/ +{ + usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE)); + if (c == '\t' && usetab()) + selfinsert(); + else + docomplete(COMP_COMPLETE); +} + +void menucompleteword() /**/ +{ + usemenu = 1; useglob = isset(GLOBCOMPLETE); + if (c == '\t' && usetab()) + selfinsert(); + else + docomplete(COMP_COMPLETE); +} + +void listchoices() /**/ +{ + usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE)); + docomplete(COMP_LIST_COMPLETE); +} + +void spellword() /**/ +{ + usemenu = useglob = 0; + docomplete(COMP_SPELL); +} + +void deletecharorlist() /**/ +{ + usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE)); + if (cs != ll) + deletechar(); + else + docomplete(COMP_LIST_COMPLETE); +} + +void expandword() /**/ +{ + usemenu = useglob = 0; + if (c == '\t' && usetab()) + selfinsert(); + else + docomplete(COMP_EXPAND); +} + +void expandorcomplete() /**/ +{ + usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE)); + if (c == '\t' && usetab()) + selfinsert(); + else + docomplete(COMP_EXPAND_COMPLETE); +} + +void menuexpandorcomplete() /**/ +{ + usemenu = 1; useglob = isset(GLOBCOMPLETE); + if (c == '\t' && usetab()) + selfinsert(); + else + docomplete(COMP_EXPAND_COMPLETE); +} + +void listexpand() /**/ +{ + usemenu = isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); + docomplete(COMP_LIST_EXPAND); +} + +void reversemenucomplete() /**/ +{ +char *s; + + if (!menucmp) + menucompleteword(); /* better than just feep'ing, pem */ + if (!menucmp) return; + cs = menub; + foredel(menue-menub); + if (menunode == firstnode(menulist)) + menunode = lastnode(menulist); + else + menunode = prevnode(menunode); + inststr(s = menunode->dat); + menue = cs; +} + +/* + * Accepts the current completion and starts a new arg, + * with the next completions. This gives you a way to accept + * several selections from the list of matches. + */ +void acceptandmenucomplete() /**/ +{ +int t0,t1; + + if (!menucmp) { + feep(); + return; + } + spaceinline(1); + line[cs++] = ' '; + spaceinline(menub-menuw); + t1 = cs; + for (t0 = menuw; t0 != menub; t0++) + line[cs++] = line[t0]; + menue = menub = cs; + menuw = t1; + menucompleteword(); +} + +static char *lastmenu = NULL; +static int lastmenupos = -1; +static int lincmd,linredir,lastambig; +static char *cmdstr; + +void docomplete(lst) /**/ +int lst; +{ +char *s; + + if (isset(AUTOMENU) && !menucmp && c == '\t' && + (lastcmd & ZLE_MENUCMP) && lastambig) usemenu = 1; + if (menucmp) { do_menucmp(lst); return; } + if (doexpandhist()) return; + s = get_comp_string(); + if (s) { + if (lst == COMP_EXPAND_COMPLETE) { + char *q = s; + + if (*q == Tilde) q++; + else if (*q == Equals) { + q = s+1; + if (gethnode(q,cmdnamtab) || hashcmd(q,pathchecked)) + lst = COMP_EXPAND; + } else { + for (; *q && *q != String; q++); + if (*q == String && q[1] != Inpar) { + if (getsparam(q+1)) lst = COMP_EXPAND; + else lst = COMP_COMPLETE; + } + q = s; + } + if (lst == COMP_EXPAND_COMPLETE) { + for (; *q; q++) + if (itok(*q)) + break; + if (!*q) + lst = COMP_COMPLETE; + } + } + if (lst == COMP_SPELL) { + char **x = &s; + untokenize(s); + cs = wb; + foredel(we-wb); + /* call the real spell checker, ash@aaii.oz.zu */ + spckword(x, NULL, NULL, !lincmd, 0); + inststr(*x); + } else if (COMP_ISEXPAND(lst)) + doexpansion(s,lst,lincmd); + else { + docompletion(s,lst,lincmd); + } + free(s); + } + popheap(); + lexrestore(); +} + +void do_menucmp(lst) /**/ +int lst; +{ +char *s; + + if (isset(LASTMENU) && lastmenu) { + if (COMP_ISEXPAND(lst) || cs != lastmenupos || + strcmp((char *) line, lastmenu) != 0) { + free(lastmenu); + lastmenu = NULL; + lastmenupos = -1; + freemenu(); + } + } + if (lst == COMP_LIST_COMPLETE) { + listmatches(menulist, NULL); + return; + } + cs = menub; + foredel(menue-menub); + incnode(menunode); + if (!menunode) + menunode = firstnode(menulist); + s = menunode->dat; + if (*s == '~' || *s == '=' || *s == '$') { + spaceinline(1); + line[cs++] = *s++; + } + inststr(s = menunode->dat); + if (isset(LASTMENU)) { + if (lastmenu) free(lastmenu); + lastmenu = ztrdup(line); + lastmenupos = cs; + } + menue = cs; +} + +char *get_comp_string() /**/ +{ +int t0; +unsigned char *s,*linptr; + + linptr = line; +start: + lincmd = incmdpos; + linredir = inredir; + cmdstr = NULL; + zleparse = 1; + lexsave(); + hungets(" "); /* KLUDGE! */ + hungets(linptr); + strinbeg(); + pushheap(); + do { + lincmd = incmdpos; + linredir = inredir; + ctxtlex(); + if (tok == ENDINPUT) break; + if (lincmd && tok == STRING) cmdstr = strdup(tokstr); + } while (tok != ENDINPUT && zleparse); + t0 = tok; + if (t0 == ENDINPUT) { + s = (unsigned char *)ztrdup(""); + we = wb = cs; + t0 = STRING; + } else if (t0 == STRING) { + s = (unsigned char *)ztrdup(tokstr); + } else if (t0 == ENVSTRING) { + for (s = (unsigned char *)tokstr; *s && *s != (unsigned char)'='; s++, wb++); + if (*s) { s++; wb++; t0 = STRING; s = (unsigned char *)ztrdup(s); } + lincmd = 1; + } + hflush(); + strinend(); + errflag = zleparse = 0; + if (we > ll) we = ll; + if (t0 == LEXERR && parbegin != -1) { + linptr += ll+1-parbegin; + popheap(); + lexrestore(); + goto start; + } + if (t0 != STRING) { feep(); return NULL; } + return (char *)s; +} + +void doexpansion(s,lst,lincmd) /**/ +char *s;int lst;int lincmd; +{ +Lklist vl = newlist(); +char *ss; + + pushheap(); + addnode(vl,s); + prefork(vl); + if (errflag) + goto end; + postfork(vl,1); + if (errflag) + goto end; + if (!full(vl) || !*(char *) peekfirst(vl)) { + feep(); + goto end; + } + if (lst == COMP_LIST_EXPAND) { + listmatches(vl,NULL); + goto end; + } else if (peekfirst(vl) == s) { + if (lst == COMP_EXPAND_COMPLETE) { + docompletion(s,COMP_COMPLETE,lincmd); + } else + feep(); + goto end; + } + cs = wb; + foredel(we-wb); + while (ss = ugetnode(vl)) { + untokenize(ss); + inststr(ss); +#if 0 + if (full(vl)) { + spaceinline(1); + line[cs++] = ' '; + } +#endif + spaceinline(1); + line[cs++] = ' '; + } +end: + popheap(); + setterm(); +} + +void gotword(s) /**/ +char *s; +{ + we = ll+1-inbufct; + if (cs <= we) + { + wb = ll-wordbeg; + zleparse = 0; + /* major hack ahead */ + if (wb && line[wb] == '!' && line[wb-1] == '\\') + wb--; + } +} + +void inststrlen(s,l) /**/ +char *s;int l; +{ +char *t,*u,*v; + + t = halloc(strlen(s)*2+2); + u = s; + v = t; + for (; *u; u++) + { + if (l != -1 && !l--) + break; + if (ispecial(*u)) + if (*u == '\n') + { + *v++ = '\''; + *v++ = '\n'; + *v++ = '\''; + continue; + } + else + *v++ = '\\'; + *v++ = *u; + } + *v = '\0'; + spaceinline(strlen(t)); + strncpy((char *) line+cs,t,strlen(t)); + cs += strlen(t); +} + +static int ambig,haspath,exact; +static Lklist matches; +static char *pat,*exactstr; +static int typechar; + +void addmatch(s) /**/ +char *s; +{ + if (full(matches)) + { + int y = pfxlen(peekfirst(matches),s); + + if (y < ambig) + ambig = y; + } + else + ambig = strlen(s); + if (!strcmp(pat,s)) { exact = 1; exactstr = pat; } + addnodeinorder(matches,strdup(s)); +} + + +void addcmdmatch(s,t) /**/ +char *s;char *t; +{ + if (strpfx(pat,s)) addmatch(s); +} + +void addcmddirparam(s,t) /**/ +char *s;char *t; +{ +Param pm = (Param) t; + + if (strpfx(pat,s) && pmtype(pm) == PMFLAG_s) { + t = pm->gets.cfn(pm); + if (t && *t == '/') addmatch(s); + } +} + +void addcmdnodis(s,t) /**/ +char *s;char *t; +{ + if (strpfx(pat,s) && ((Cmdnam) t)->type != DISABLED) addmatch(s); +} + +void maketildelist(s) /**/ +char *s; +{ + struct passwd *pwd; + int len; + + s++; + len = strlen(s); + if (len < 1) { + addmatch(s); + *s = 0; + return; + } + while ((pwd = getpwent()) != NULL && !errflag) + if (strncmp(pwd->pw_name, s, len) == 0) + addmatch(pwd->pw_name); + endpwent(); + *s = 0; +} + +/* + * opendir that handles '~' and '=' and '$'. + * orig. by ash@aaii.oz.au, mod. by pf + */ +DIR *OPENDIR(s) +char *s; +{ + if (*s != '~' && *s != '=' && *s != '$') + return(opendir(s)); + s = strdup(s); + *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String; + singsub(&s); + return(opendir(s)); +} +char *dirname(s) +char *s; +{ + if (*s == '~' || *s == '=' || *s == '$') { + s = strdup(s); + *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String; + singsub(&s); + } + return(s); +} + +int Isdir(s) /**/ +char *s; +{ +struct stat sbuf; + + if (!*s) return 0; + if (stat(s,&sbuf) == -1) return 0; + return S_ISDIR(sbuf.st_mode); +} + +/* this will work whether s is tokenized or not */ +int isdir(t,s) /**/ +char *t;char *s; +{ +char buf[MAXPATHLEN]; + + if (typechar != '$') + sprintf(buf,"%s/%s",(s) ? s : ".",t); + else + sprintf(buf,"$%s",t); + s = buf; + if (*s != '~' && *s != '=' && *s != Tilde && *s != Equals && + *s != '$' && *s != String) + return(Isdir(s)); + s = strdup(s); + if (*s == '~' || *s == '=' || *s == '$') + *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String; + singsub(&s); + return(Isdir(s)); +} + +#define SLASH_YES 0 +#define SLASH_NO 1 +#define SLASH_MAYBE 2 + +int slashflag; +int addedstar; +char *pathprefix; + +void docompletion(s,lst,incmd) /**/ +char *s;int lst;int incmd; +{ +char *tokorigs; +char *origs; +Compctl cc; +char *pfx = s; + + slashflag = SLASH_MAYBE; + addedstar = 0; + lastambig = 0; + + heapalloc(); + pushheap(); + if (useglob) + tokorigs = strdup(s); + untokenize(s); + origs = strdup(s); + matches = newlist(); + if (incmd) + cc = &cc_compos; + else if (linredir || !(cmdstr && (cc = gethnode(cmdstr,compctltab)))) + cc = &cc_default; + exact = 0; + if (cc->mask & CC_COMMPATH) gen_matches_reg(s,1,(cc->mask & CC_FILES)); + else if (cc->mask & CC_FILES) gen_matches_reg(s,0,1); + else { + haspath = 0; + slashflag = SLASH_NO; + } + if (cc->mask & (CC_FILES|CC_COMMPATH)) { + /* only do "globbed" completion if regular completion fails. + pem, 7Oct91 */ + if ((!full(matches) || errflag) && useglob) { + gen_matches_glob(tokorigs,incmd); + /* + * gen_matches_glob changes the insert line to be correct up + * to the match, so the prefix string must be "". ash, 7Oct91 + */ + *s = 0; + } + } + pat = s; + if ((cc->mask & CC_HOSTS) && !haspath) { + char **x; + for (x = hosts; *x; x++) addcmdmatch(*x,NULL); + } + if ((cc->mask & CC_OPTIONS) && !haspath) { + struct option *o; + for (o = optns; o->name; o++) addcmdmatch(o->name,NULL); + } + if ((cc->mask & CC_VARS) && !haspath) listhtable(paramtab,addcmdmatch); + if ((cc->mask & CC_BINDINGS) && !haspath) { + int t0; + for (t0 = 0; t0 != ZLECMDCOUNT; t0++) + if (*zlecmds[t0].name) addcmdmatch(zlecmds[t0].name,NULL); + } + if (cc->mask & CC_USRKEYS) { + char **usr = get_user_var(cc->keyvar); + if (usr) while (*usr) addcmdmatch(*usr++,NULL); + } + if (lst != COMP_LIST_COMPLETE) do_fignore(origs); + if (!full(matches) || errflag) { + feep(); + } else if (lst == COMP_LIST_COMPLETE) { + listmatches(matches, + unset(LISTTYPES) ? NULL : + (haspath) ? pathprefix : "./"); + } else if (nextnode(firstnode(matches))) { + do_ambiguous(pfx); + } else { + do_single(pfx); + } + ll = strlen((char *) line); + setterm(); + popheap(); + permalloc(); +} + +char **get_user_var(nam) /**/ +char *nam; +{ + return (nam) ? getaparam(nam) : NULL; +} + +void gen_matches_glob(s,incmd) /**/ +char *s;int incmd; +{ +char *pt,*u; +int hasp = 0; +DIR *d; +struct direct *de; + + /* + * Find the longest prefix string without any + * chars special to glob - ash. + */ + for (pt = s; *pt; pt++) { + if (pt == s && (*pt == Tilde || *pt == Equals)) continue; + if (ispecial(*pt) || itok(*pt)) break; + } + for (; pt > s && *pt != '/'; pt--) ; + if (*pt == '/') { + *pt = 0; + u = pt + 1; + wb += strlen(s); + hasp = 1; + } else u = s; + if (!hasp && (*s == Tilde || *s == Equals)) { + /* string contains only ~xx, so do tilde expansion */ + maketildelist(s); + wb++; + pathprefix = s; + slashflag = SLASH_YES; + } else if (incmd && !hasp) { + slashflag = SLASH_NO; + pat = s; + listhtable(aliastab ,addcmdmatch); + if (isset(HASHLISTALL)) fullhash(); + listhtable(cmdnamtab,addcmdnodis); + if (isset(AUTOCD)) listhtable(paramtab ,addcmddirparam); + if (d = opendir(".")) { + char *q; + + readdir(d); readdir(d); + while ((de = readdir(d)) && !errflag) + if (strpfx(pat,q = de->d_name) && + (*q != '.' || *u == '.' || isset(GLOBDOTS))) + addmatch(q); + closedir(d); + } + } else { + int commonprefix = 0; + char *prefix; + Lknode n; + int nonomatch = isset(NONOMATCH); + + opts[NONOMATCH] = 1; + if (hasp) { + /* Find the longest common prefix string + * after globbing the input. All expansions + * ~foo/bar/* will turn into something like + * /tmp_mnt/hosts/somehost/home/foo/... + * We will remove this common prefix from the matches. + * ash, 7 May '91 + */ + pathprefix = s; + addnode(matches,s); + prefork(matches); + if (!errflag) postfork(matches,1); + if (!errflag) { + prefix = peekfirst(matches); + if (prefix) commonprefix = strlen(prefix) + 1; + *pt = '/'; + } + } + if (s[strlen(s) - 1] == '/') { + /* if strings ends in a '/' always add a '*' */ + s = dyncat(s,"x"); + s[strlen(s)-1] = Star; + addedstar = 1; + } + matches = newlist(); + addnode(matches,s); + prefork(matches); + if (!errflag) postfork(matches,1); + opts[NONOMATCH] = nonomatch; + if (errflag || !full(matches) || !nextnode(firstnode(matches))) { + /* if there were no matches (or only one) + add a trailing * and try again */ + s = dyncat(s,"x"); + s[strlen(s)-1] = Star; + addedstar = 1; + matches = newlist(); + addnode(matches,s); + prefork(matches); + if (errflag) return; + postfork(matches,1); + if (errflag) return; + } + /* remove the common prefix from all the matches */ + if (commonprefix) + for (n = firstnode(matches); n; incnode(n)) + n->dat = (char *) n->dat+commonprefix; + s = pt; + *s = 0; + } +} + +void gen_matches_reg(s,incmd,regfiles) /**/ +char *s;int incmd;int regfiles; +{ +char *u; +DIR *d; +struct direct *de; + + haspath = 0; + for (u = s+strlen(s); u >= s; u--) + if (*u == '/' || *u == '@' || *u == '$') break; + if (u >= s) { + typechar = *u; + *u++ = '\0'; + haspath = 1; + } else if (*s == '=') { + typechar = '='; + *s = '\0'; u = s+1; + haspath = 1; + } else u = s; + pat = u; + if (typechar == '$' && haspath) { + /* slashflag = SLASH_NO; */ + listhtable(paramtab,addcmdmatch); + } else if (typechar == '=' && haspath) { + slashflag = SLASH_NO; + if (isset(HASHLISTALL)) fullhash(); + listhtable(cmdnamtab,addcmdnodis); + } else if (typechar == '@' && haspath) { + char **x; + slashflag = SLASH_NO; + for (x = hosts; *x; x++) addcmdmatch(*x,NULL); + } else if (*s == '~' && !haspath) { + maketildelist(s); + pathprefix = s; + slashflag = SLASH_YES; + } else if (incmd && !haspath) { + slashflag = SLASH_NO; + listhtable(aliastab ,addcmdmatch); + if (isset(HASHLISTALL)) fullhash(); + listhtable(cmdnamtab,addcmdnodis); + if (isset(AUTOCD) && isset(CDABLEVARS)) + listhtable(paramtab ,addcmddirparam); + if (d = opendir(".")) { + char *q; + struct stat buf; + + readdir(d); readdir(d); + if (regfiles) { + while ((de = readdir(d)) && !errflag) + if (strpfx(pat,q = de->d_name) && + (*q != '.' || *u == '.' || isset(GLOBDOTS))) addmatch(q); + } else if (isset(AUTOCD)) { + while ((de = readdir(d)) && !errflag) + if (strpfx(pat,q = de->d_name) && + (*q != '.' || *u == '.' || isset(GLOBDOTS)) && + stat(q,&buf) >= 0 && + (buf.st_mode & S_IEXEC) == S_IEXEC) addmatch(q); + } else { + while ((de = readdir(d)) && !errflag) + if (strpfx(pat,q = de->d_name) && + (*q != '.' || *u == '.' || isset(GLOBDOTS)) && + stat(q,&buf) >= 0 && + (buf.st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC)) + addmatch(q); + } + closedir(d); + } + } else if (d = OPENDIR(pathprefix = + ((haspath || *s == '~') ? ((*s) ? s : "/") : "."))) { + char *q,buf2[MAXPATHLEN]; + struct stat buf; + char dn[MAXPATHLEN]; + + strcpy(dn,dirname(pathprefix)); + readdir(d); readdir(d); + while ((de = readdir(d)) && !errflag) + if (strpfx(pat,q = de->d_name) && + (*q != '.' || *u == '.' || isset(GLOBDOTS))) { + if (incmd) { + sprintf(buf2,"%s/%s",dn,q); + if (stat(buf2,&buf) < 0 || + (buf.st_mode & S_IEXEC) == S_IEXEC) { + addmatch(q); + } + } else { + addmatch(q); + } + } + closedir(d); + } +} + +void do_fignore(origstr) /**/ +char *origstr; +{ + if (full(matches) && nextnode(firstnode(matches))) { + Lknode z,zn; + + z = firstnode(matches); + ambig = 1000; + for (z = firstnode(matches); z; z = zn) { + char *q = getdata(z); + int namlen = strlen(q); + int slen = strlen(origstr); + int slpt; + char **pt = fignore; + + zn = nextnode(z); + for (; *pt; pt++) { + /* We try to be smart here and override the + fignore variable if the user has explicity + used the ignored prefix, pem, 7 May 1991 */ + slpt = strlen(*pt); + if (!addedstar && slen > slpt && + strcmp(origstr+slen-slpt, *pt) == 0) + continue; + if (slpt < namlen && !strcmp(q+namlen-slpt,*pt)) { + uremnode(matches,z); + break; + } + } + if (!*pt) { + int y = pfxlen(peekfirst(matches),q); + if (y < ambig) ambig = y; + } + } + } +} + +void do_ambiguous(s) /**/ +char *s; +{ + lastambig = 1; + if (usemenu) { do_ambig_menu(s); return; } + if (useglob) { + feep(); + if (isset(AUTOLIST)) + listmatches(matches, + unset(LISTTYPES) ? NULL : (haspath) ? pathprefix : "./"); + return; + } + cs = wb; + foredel(we-wb); + if (*s == '~' || *s == '=' || *s == '$') { + spaceinline(1); + line[cs++] = *s++; + } + if (haspath) { + inststr(s); + spaceinline(1); + line[cs++] = typechar; + } + if (isset(RECEXACT) && exact) { + lastambig = 0; + if ((*pat == '~' || *pat == '=' || *pat == '$') && !haspath) { + spaceinline(1); + line[cs++] = *s++; + } + inststr(exactstr); + spaceinline(1); + switch (slashflag) { + case SLASH_YES: line[cs++] = '/'; break; + case SLASH_NO : line[cs++] = ' '; break; + case SLASH_MAYBE: line[cs++] = + isdir(exactstr,pathprefix) ? '/' : ' '; break; + } + return; + } + s = peekfirst(matches); + if ((*s == '~' || *s == '=' || *s == '$') && !haspath) { + spaceinline(1); + line[cs++] = *s++; + ambig--; + } + inststrlen(s,ambig); + refresh(); + if (isset(AUTOLIST)) { + if (unset(NOLISTBEEP)) feep(); + listmatches(matches, + unset(LISTTYPES) ? NULL : (haspath) ? pathprefix : "./"); + } else feep(); +} + +void do_single(s) /**/ +char *s; +{ + cs = wb; + foredel(we-wb); + if (*s == '~' || *s == '=' || *s == '$') { + spaceinline(1); + line[cs++] = *s++; + } + if (haspath) { + inststr(s); + spaceinline(1); + line[cs++] = typechar; + } + s = peekfirst(matches); + if ((*s == '~' || *s == '=' || *s == '$') && !haspath) { + spaceinline(1); + line[cs++] = *s++; + } + inststr(s); + spaceinline(1); + switch (slashflag) { + case SLASH_YES: line[cs++] = '/'; break; + case SLASH_NO : line[cs++] = ' '; break; + case SLASH_MAYBE: line[cs++] = isdir(s,pathprefix) ? '/' : ' '; break; + } + if (isset(AUTOREMOVESLASH) && line[cs-1] == '/') addedslash = 1; +} + +void do_ambig_menu(s) /**/ +char *s; +{ + menucmp = 1; + if (isset(MENUCOMPLETEBEEP)) feep(); + cs = wb; + menuw = cs; + foredel(we-wb); + if (*s == '~' || *s == '=' || *s == '$') { + spaceinline(1); + line[cs++] = *s++; + } + if (haspath) { + inststr(s); + spaceinline(1); + line[cs++] = typechar; + } + menub = cs; + s = peekfirst(matches); + if ((*s == '~' || *s == '=' || *s == '$') && !haspath) { + spaceinline(1); + line[cs++] = *s++; + } + inststr(s); + menue = cs; + permalloc(); + menulist = duplist(matches,(VFunc)ztrdup); + heapalloc(); + menunode = firstnode(menulist); + permalloc(); + if (isset(LASTMENU)) { + if (lastmenu) + free(lastmenu); + lastmenu = ztrdup(line); + lastmenupos = cs; + } +} + +int strpfx(s,t) /**/ +char *s;char *t; +{ + while (*s && *s == *t) s++,t++; + return !*s; +} + +int pfxlen(s,t) /**/ +char *s;char *t; +{ +int i = 0; + + while (*s && *s == *t) s++,t++,i++; + return i; +} + +void listmatches(l,apps) /**/ +Lklist l;char *apps; +{ +int longest = 1,fct,fw = 0,colsz,t0,t1,ct; +Lknode n; +char **arr,**ap; + + trashzle(); + ct = countnodes(l); + if (listmax && ct > listmax) + { + fprintf(stdout,"zsh: do you wish to see all %d possibilities? ",ct); + fflush(stdout); + if (getquery() != 'y') + return; + } + ap = arr = alloc((countnodes(l)+1)*sizeof(char **)); + for (n = firstnode(l); n; incnode(n)) + *ap++ = getdata(n); + *ap = NULL; + for (ap = arr; *ap; ap++) + if (strlen(*ap) > longest) + longest = strlen(*ap); + if (apps) + { + apps = strdup(apps); + if (*apps == '~') + *apps = Tilde; + else if (*apps == '=') + *apps = Equals; + else if (*apps == '$') + *apps = String; + singsub(&apps); + longest++; + } + qsort(arr,ct,sizeof(char *),forstrcmp); + fct = (columns-1)/(longest+2); + if (fct == 0) + fct = 1; + else + fw = (columns-1)/fct; + colsz = (ct+fct-1)/fct; + for (t1 = 0; t1 != colsz; t1++) + { + ap = arr+t1; + if (apps) + { + do + { + int t2 = strlen(*ap)+1; + char pbuf[MAXPATHLEN]; + struct stat buf; + + printf("%s",*ap); + sprintf(pbuf,"%s/%s",apps,*ap); + if (lstat(pbuf,&buf)) putchar(' '); + else switch (buf.st_mode & S_IFMT) /* screw POSIX */ + { + case S_IFDIR: putchar('/'); break; +#ifdef S_IFIFO + case S_IFIFO: putchar('|'); break; +#endif + case S_IFCHR: putchar('%'); break; + case S_IFBLK: putchar('#'); break; +#ifdef S_IFLNK + case S_IFLNK: putchar( + (access(pbuf,F_OK) == -1) ? '&' : '@'); break; +#endif +#ifdef S_IFSOCK + case S_IFSOCK: putchar('='); break; +#endif + default: + if (buf.st_mode & 0111) + putchar('*'); + else + putchar(' '); + break; + } + for (; t2 < fw; t2++) putchar(' '); + for (t0 = colsz; t0 && *ap; t0--,ap++); + } + while (*ap); + } + else + do + { + int t2 = strlen(*ap); + + printf("%s",*ap); + for (; t2 < fw; t2++) putchar(' '); + for (t0 = colsz; t0 && *ap; t0--,ap++); + } + while (*ap); + putchar('\n'); + } + resetneeded = 1; + fflush(stdout); +} + +void selectlist(l) /**/ +Lklist l; +{ +int longest = 1,fct,fw = 0,colsz,t0,t1,ct; +Lknode n; +char **arr,**ap; + + trashzle(); + ct = countnodes(l); + ap = arr = alloc((countnodes(l)+1)*sizeof(char **)); + for (n = firstnode(l); n; incnode(n)) + *ap++ = getdata(n); + *ap = NULL; + for (ap = arr; *ap; ap++) + if (strlen(*ap) > longest) + longest = strlen(*ap); + t0 = ct; + longest++; + while (t0) + t0 /= 10, longest++; + fct = (columns-1)/(longest+3); /* to compensate for added ')' */ + if (fct == 0) + fct = 1; + else + fw = (columns-1)/fct; + colsz = (ct+fct-1)/fct; + for (t1 = 0; t1 != colsz; t1++) { + ap = arr+t1; + do { + int t2 = strlen(*ap)+2,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);*/ + resetneeded = 1; + fflush(stderr); +} + +int doexpandhist() /**/ +{ +unsigned char *cc,*ce; +int t0,oldcs,oldll; + + for (cc = line, ce = line+ll; cc < ce; cc++) + if (*cc == '\\' && cc[1]) + cc++; + else if (*cc == bangchar || + (*cc == hatchar && *line == hatchar && cc != line)) + break; + if (*cc == bangchar && cc[1] == '"') return 0; + if (cc == ce) return 0; + oldcs = cs; + oldll = ll; + zleparse = 1; + lexsave(); + hungets(line); + strinbeg(); + pushheap(); + ll = cs = 0; + for(;;) + { + t0 = hgetc(); + if (lexstop) + break; + spaceinline(1); + line[cs++] = t0; + } + hflush(); + popheap(); + strinend(); + errflag = zleparse = 0; + t0 = histdone; + lexrestore(); + line[ll = cs] = '\0'; + if (ll == oldll) cs = oldcs; + return t0; +} + +void magicspace() /**/ +{ + c = ' '; + selfinsert(); + doexpandhist(); +} + +void expandhistory() /**/ +{ + if (!doexpandhist()) + feep(); +} + +static int cmdwb,cmdwe; + +char *getcurcmd() /**/ +{ +int lincmd = incmdpos; +char *s = NULL; + + zleparse = 1; + lexsave(); + hungets(" "); /* KLUDGE! */ + hungets(line); + strinbeg(); + pushheap(); + do { + lincmd = incmdpos; + ctxtlex(); + if (tok == ENDINPUT) break; + if (tok == STRING && lincmd) { + if (s) free(s); + s = ztrdup(tokstr); + cmdwb = ll-wordbeg; cmdwe = ll+1-inbufct; + } + lincmd = incmdpos; + } while (tok != ENDINPUT && zleparse); + hflush(); + popheap(); + strinend(); + errflag = zleparse = 0; + lexrestore(); + return s; +} + +void processcmd() /**/ +{ +char *s,*t; + + s = getcurcmd(); + if (!s) { feep(); return; } + t = zlecmds[bindk].name; + mult = 1; + pushline(); + sizeline(strlen(s)+strlen(t)+1); + strcpy((char *) line,t); + strcat((char *) line," "); + cs = ll = strlen((char *) line); + inststr(s); + free(s); + done = 1; +} + +void expandcmdpath() /**/ +{ +int oldcs = cs; +char *s,*str; + + s = getcurcmd(); + if (!s) { feep(); return; } + str = findcmd(s); + free(s); + if (!str) { feep(); return; } + cs = cmdwb; + foredel(cmdwe-cmdwb); + spaceinline(strlen(str)); + strncpy((char *) line+cs,str,strlen(str)); + cs = oldcs; + if (cs >= cmdwe) cs += cmdwe-cmdwb+strlen(str); + if (cs > ll) cs = ll; + free(str); +} + +void freemenu() /**/ +{ + if (menucmp && (unset(LASTMENU) || lastmenu == NULL)) { + menucmp = 0; + freetable(menulist,freestr); + } +} + +int inarray(s,a) /**/ +char *s; char **a; +{ + for (; *a; a++) if (!strcmp(*a,s)) return 1; + return 0; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_tricky.pro b/usr/othersrc/public/zsh-2.2/src/zle_tricky.pro new file mode 100644 index 0000000000..6ae6c0997b --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_tricky.pro @@ -0,0 +1,45 @@ +int usetab DCLPROTO((void)); +void completeword DCLPROTO((void)); +void menucompleteword DCLPROTO((void)); +void listchoices DCLPROTO((void)); +void spellword DCLPROTO((void)); +void deletecharorlist DCLPROTO((void)); +void expandword DCLPROTO((void)); +void expandorcomplete DCLPROTO((void)); +void menuexpandorcomplete DCLPROTO((void)); +void listexpand DCLPROTO((void)); +void reversemenucomplete DCLPROTO((void)); +void acceptandmenucomplete DCLPROTO((void)); +void docomplete DCLPROTO((int lst)); +void do_menucmp DCLPROTO((int lst)); +char *get_comp_string DCLPROTO((void)); +void doexpansion DCLPROTO((char *s,int lst,int lincmd)); +void gotword DCLPROTO((char *s)); +void inststrlen DCLPROTO((char *s,int l)); +void addmatch DCLPROTO((char *s)); +void addcmdmatch DCLPROTO((char *s,char *t)); +void addcmddirparam DCLPROTO((char *s,char *t)); +void addcmdnodis DCLPROTO((char *s,char *t)); +void maketildelist DCLPROTO((char *s)); +int Isdir DCLPROTO((char *s)); +int isdir DCLPROTO((char *t,char *s)); +void docompletion DCLPROTO((char *s,int lst,int incmd)); +char **get_user_var DCLPROTO((char *nam)); +void gen_matches_glob DCLPROTO((char *s,int incmd)); +void gen_matches_reg DCLPROTO((char *s,int incmd,int regfiles)); +void do_fignore DCLPROTO((char *origstr)); +void do_ambiguous DCLPROTO((char *s)); +void do_single DCLPROTO((char *s)); +void do_ambig_menu DCLPROTO((char *s)); +int strpfx DCLPROTO((char *s,char *t)); +int pfxlen DCLPROTO((char *s,char *t)); +void listmatches DCLPROTO((Lklist l,char *apps)); +void selectlist DCLPROTO((Lklist l)); +int doexpandhist DCLPROTO((void)); +void magicspace DCLPROTO((void)); +void expandhistory DCLPROTO((void)); +char *getcurcmd DCLPROTO((void)); +void processcmd DCLPROTO((void)); +void expandcmdpath DCLPROTO((void)); +void freemenu DCLPROTO((void)); +int inarray DCLPROTO((char *s, char **a)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_utils.c b/usr/othersrc/public/zsh-2.2/src/zle_utils.c new file mode 100644 index 0000000000..6d870a566f --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_utils.c @@ -0,0 +1,249 @@ +/* + * + * zle_utils.c - miscellaneous line editor utilities + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + +/* make sure that the line buffer has at least sz chars */ + +void sizeline(sz) /**/ +int sz; +{ + while (sz > linesz) + line = (unsigned char *)realloc(line,(linesz *= 4)+1); +} + +/* insert space for ct chars at cursor position */ + +void spaceinline(ct) /**/ +int ct; +{ +int i; + + while (ct+ll > linesz) + line = (unsigned char *)realloc(line,(linesz *= 4)+1); + for (i = ll; i >= cs; i--) + line[i+ct] = line[i]; + ll += ct; + line[ll] = '\0'; +} + +void backkill(ct,dir) /**/ +int ct;int dir; +{ +int i = (cs -= ct); + + cut(i,ct,dir); + while (line[i] = line[i+ct]) + i++; + ll -= ct; +} + +void forekill(ct,dir) /**/ +int ct;int dir; +{ +int i = cs; + + cut(i,ct,dir); + while (line[i] = line[i+ct]) + i++; + ll -= ct; +} + +void cut(i,ct,dir) /**/ +int i;int ct;int dir; +{ + if (vibufspec) { + int owrite = 1; + if (vibufspec >= 'A' && vibufspec <= 'Z') { + owrite = 0; vibufspec = tolower(vibufspec); + } + vibufspec += (idigit(vibufspec)) ? - '1' +26 : - 'a'; + if (owrite || !vibuf[vibufspec]) { + if (vibuf[vibufspec]) free(vibuf[vibufspec]); + vibuf[vibufspec] = zalloc(ct+1); + ztrncpy(vibuf[vibufspec],line+i,ct); + } else { + int len = strlen(vibuf[vibufspec]); + vibuf[vibufspec] = realloc(vibuf[vibufspec],ct+len); + ztrncpy(vibuf[vibufspec]+len,line+i,ct); + } + vibufspec = 0; + return; + } + if (!cutbuf) + cutbuf = ztrdup(""); + else if (!(lastcmd & ZLE_KILL)) { + kringnum = (kringnum+1)&(KRINGCT-1); + if (kring[kringnum]) + free(kring[kringnum]); + kring[kringnum] = cutbuf; + cutbuf = ztrdup(""); + } + if (dir) { + char *s = zalloc(strlen(cutbuf)+ct+1); + strncpy(s,(char *) line+i,ct); + strcpy(s+ct,cutbuf); + free(cutbuf); + cutbuf = s; + } else { + int x; + + cutbuf = realloc(cutbuf,(x = strlen(cutbuf))+ct+1); + ztrncpy(cutbuf+x,line+i,ct); + } +} + +void backdel(ct) /**/ +int ct; +{ +int i = (cs -= ct); + + while (line[i] = line[i+ct]) + i++; + ll -= ct; +} + +void foredel(ct) /**/ +int ct; +{ +int i = cs; + + while (line[i] = line[i+ct]) + i++; + ll -= ct; +} + +void setline(s) /**/ +char *s; +{ + sizeline(strlen(s)); + strcpy((char *) line,s); + cs = ll = strlen(s); + if (cs && bindtab == altbindtab) cs--; +} + +void sethistline(s) /**/ +unsigned char *s; +{ + setline(s); + for (s = line; *s; s++) + if (*s == (unsigned char)HISTSPACE) + *s = ' '; +} + +int findbol() /**/ +{ +int x = cs; + + while (x > 0 && line[x-1] != '\n') x--; + return x; +} + +int findeol() /**/ +{ +int x = cs; + + while (x != ll && line[x] != '\n') x++; + return x; +} + +void findline(a,b) /**/ +int *a;int *b; +{ + *a = findbol(); + *b = findeol(); +} + +static int lastlinelen; + +void initundo() /**/ +{ +int t0; + + for (t0 = 0; t0 != UNDOCT; t0++) + undos[t0].change = NULL; + undoct = 0; + lastline = zalloc(lastlinelen = (ll+1 < 32) ? 32 : ll+1); + strcpy((char *) lastline,(char *) line); + lastcs = cs; +} + +void addundo() /**/ +{ +int pf,sf; +unsigned char *s,*s2,*t,*t2; +struct undoent *ue; + + for (s = line, t = lastline; *s && *s==*t; s++,t++); + if (!*s && !*t) + return; + pf = s-line; + for (s2 = (unsigned char *)line+strlen((char *) line), + t2 = lastline+strlen((char *) lastline); + s2 > s && t > t2 && s2[-1] == t2[-1]; s2--,t2--); + sf = strlen((char *) s2); + ue = undos+(undoct = (UNDOCT-1) & (undoct+1)); + ue->pref = pf; + ue->suff = sf; + ue->len = t2-t; + ue->cs = lastcs; + strncpy(ue->change = halloc(ue->len),(char *) t,ue->len); + while (ll+1 > lastlinelen) + { + free(lastline); + lastline = zalloc(lastlinelen *= 2); + } + strcpy((char *) lastline,(char *) line); + lastcs = cs; +} + +void freeundo() /**/ +{ + free(lastline); +} + +int hstrncmp(s,t,len) /**/ +char *s;char *t;int len; +{ + while (len && *s && (*s == *t || (*s == ' ' && *t == HISTSPACE) || + (*s == HISTSPACE && *t == ' '))) + s++,t++,len--; + return len; +} + +int hstrcmp(s,t) /**/ +char *s;char *t; +{ + while (*s && (*s == *t || (*s == ' ' && *t == HISTSPACE) || + (*s == HISTSPACE && *t == ' '))) + s++,t++; + return !(*s == '\0' && *t == '\0'); +} + +char *hstrnstr(s,t,len) /**/ +char *s;char *t;int len; +{ + for (; *s; s++) + if (!hstrncmp(t,s,len)) + return s; + return NULL; +} + diff --git a/usr/othersrc/public/zsh-2.2/src/zle_utils.pro b/usr/othersrc/public/zsh-2.2/src/zle_utils.pro new file mode 100644 index 0000000000..a87181a1d1 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_utils.pro @@ -0,0 +1,18 @@ +void sizeline DCLPROTO((int sz)); +void spaceinline DCLPROTO((int ct)); +void backkill DCLPROTO((int ct,int dir)); +void forekill DCLPROTO((int ct,int dir)); +void cut DCLPROTO((int i,int ct,int dir)); +void backdel DCLPROTO((int ct)); +void foredel DCLPROTO((int ct)); +void setline DCLPROTO((char *s)); +void sethistline DCLPROTO((unsigned char *s)); +int findbol DCLPROTO((void)); +int findeol DCLPROTO((void)); +void findline DCLPROTO((int *a,int *b)); +void initundo DCLPROTO((void)); +void addundo DCLPROTO((void)); +void freeundo DCLPROTO((void)); +int hstrncmp DCLPROTO((char *s,char *t,int len)); +int hstrcmp DCLPROTO((char *s,char *t)); +char *hstrnstr DCLPROTO((char *s,char *t,int len)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_vi.c b/usr/othersrc/public/zsh-2.2/src/zle_vi.c new file mode 100644 index 0000000000..3f1d93abf5 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_vi.c @@ -0,0 +1,310 @@ +/* + * + * zle_vi.c - vi-specific functions + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + + +static void startvichange(im) +int im; +{ + insmode = im; + if (vichgbuf) free(vichgbuf); + vichgbuf = zalloc(vichgbufsz = 16); + vichgbuf[0] = c; + vichgbufptr = 1; + vichgflag = 1; + viinsbegin = cs; +} + +static void startvitext(im) +{ + startvichange(im); + bindtab = mainbindtab; + undoing = 0; +} + +int vigetkey() /**/ +{ +int ch; + + if ((ch = getkey(0)) == -1) + return 0; + if (ch == 22) + { + if ((ch = getkey(0)) == -1) + return 0; + return ch; + } + else if (ch == 27) + return 0; + return ch; +} + +int getvirange(wf) /**/ +int wf; +{ +int k2,t0,startline,endline; + + startline = findbol(); + endline = findeol(); + for (;;) { + k2 = getkeycmd(); + if (k2 == -1) { + feep(); + return -1; + } + if (zlecmds[k2].flags & ZLE_ARG) + (*zlecmds[k2].func)(); + else + break; + } + if (k2 == bindk) { + findline(&cs,&t0); + return (t0 == ll) ? t0 : t0+1; + } + if (!(zlecmds[k2].flags & ZLE_MOVEMENT)) { + feep(); + return -1; + } + t0 = cs; + + virangeflag = 1; + wordflag = wf; + (*zlecmds[k2].func)(); + wordflag = virangeflag = 0; + if (cs == t0) { + feep(); + return -1; + } + if (startline != findbol()) { + if (zlecmds[k2].flags & ZLE_LINEMOVE) { + if (cs < t0) { + cs = startline; + t0 = findeol()+1; + } else { + t0 = startline; + cs = findeol()+1; + } + } else { + if (cs < startline) cs = startline; + else if (cs >= endline) cs = endline-1; + } + } + if (cs > t0) { + k2 = cs; + cs = t0; + t0 = k2; + } + return t0; +} + +void viaddnext() /**/ +{ + if (cs != ll) + cs++; + startvitext(1); +} + +void viaddeol() /**/ +{ + cs = findeol(); + startvitext(1); +} + +void viinsert() /**/ +{ + startvitext(1); +} + +void viinsertbol() /**/ +{ + cs = findbol(); + startvitext(1); +} + +void videlete() /**/ +{ +int c2; + + startvichange(1); + if ((c2 = getvirange(0)) == -1) + { vichgflag = 0; return; } + forekill(c2-cs,0); + vichgflag = 0; +} + +void vichange() /**/ +{ +int c2; + + startvichange(1); + if ((c2 = getvirange(1)) == -1) + { vichgflag = 0; return; } + forekill(c2-cs,0); + bindtab = mainbindtab; + undoing = 0; +} + +void visubstitute() /**/ +{ + if (mult < 0) return; + if (findeol()-cs < mult) mult = findeol()-cs; + if (mult) { + foredel(mult); + startvitext(1); + } +} + +void vichangeeol() /**/ +{ + killline(); + startvitext(1); +} + +void vichangewholeline() /**/ +{ +int cq; + + findline(&cs,&cq); + foredel(cq-cs); + startvitext(1); +} + +void viyank() /**/ +{ +int c2; + + if ((c2 = getvirange(0)) == -1) return; + cut(cs,c2-cs,0); +} + +void viyankeol() /**/ +{ +int x = findeol(); + + if (x == cs) + feep(); + else + cut(cs,x-cs,0); +} + +void vireplace() /**/ +{ + startvitext(0); +} + +void vireplacechars() /**/ +{ +int ch; + + if (mult < 0) return; + if (mult+cs > ll) { + feep(); + return; + } + startvichange(1); + if (ch = vigetkey()) while (mult--) line[cs++] = ch; + vichgflag = 0; + cs--; +} + +void vicmdmode() /**/ +{ + bindtab = altbindtab; + if (cs) cs--; + undoing = 1; + if (vichgflag) vichgflag = 0; +} + +void viopenlinebelow() /**/ +{ + cs = findeol(); + spaceinline(1); + line[cs++] = '\n'; + startvitext(1); +} + +void viopenlineabove() /**/ +{ + cs = findbol(); + spaceinline(1); + line[cs] = '\n'; + startvitext(1); +} + +void vioperswapcase() /**/ +{ +int c2; + + if ((c2 = getvirange(0)) == -1) + return; + while (cs < c2) + { + int ch = line[cs]; + + if (islower(ch)) + ch = tuupper(ch); + else if (isupper(ch)) + ch = tulower(ch); + line[cs++] = ch; + } +} + +void virepeatchange() /**/ +{ + if (!vichgbuf || bindtab == mainbindtab || vichgflag) feep(); + else ungetkeys(vichgbuf,vichgbufptr); +} + +void viindent() /**/ +{ +int c2,endcs,t0,rmult; + + if (mult < 0) { mult = -mult; viunindent(); return; } + rmult = mult; + if ((c2 = getvirange(0)) == -1) + return; + if (cs != findbol()) { feep(); return; } + endcs = cs+rmult; + while (cs < c2) { + spaceinline(rmult); + for (t0 = 0; t0 != rmult; t0++) line[cs++] = '\t'; + cs = findeol()+1; + } + cs = endcs; +} + +void viunindent() /**/ +{ +int c2,endcs,t0,rmult; + + rmult = mult; + if (mult < 0) { mult = -mult; viindent(); return; } + if ((c2 = getvirange(0)) == -1) + return; + if (cs != findbol()) { feep(); return; } + endcs = cs; + while (cs < c2) { + for (t0 = 0; t0 != rmult && line[cs] == '\t'; t0++) foredel(1); + cs = findeol()+1; + } + cs = endcs; +} diff --git a/usr/othersrc/public/zsh-2.2/src/zle_vi.pro b/usr/othersrc/public/zsh-2.2/src/zle_vi.pro new file mode 100644 index 0000000000..2387d8d54e --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_vi.pro @@ -0,0 +1,22 @@ +int vigetkey DCLPROTO((void)); +int getvirange DCLPROTO((int wf)); +void viaddnext DCLPROTO((void)); +void viaddeol DCLPROTO((void)); +void viinsert DCLPROTO((void)); +void viinsertbol DCLPROTO((void)); +void videlete DCLPROTO((void)); +void vichange DCLPROTO((void)); +void visubstitute DCLPROTO((void)); +void vichangeeol DCLPROTO((void)); +void vichangewholeline DCLPROTO((void)); +void viyank DCLPROTO((void)); +void viyankeol DCLPROTO((void)); +void vireplace DCLPROTO((void)); +void vireplacechars DCLPROTO((void)); +void vicmdmode DCLPROTO((void)); +void viopenlinebelow DCLPROTO((void)); +void viopenlineabove DCLPROTO((void)); +void vioperswapcase DCLPROTO((void)); +void virepeatchange DCLPROTO((void)); +void viindent DCLPROTO((void)); +void viunindent DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/zle_word.c b/usr/othersrc/public/zsh-2.2/src/zle_word.c new file mode 100644 index 0000000000..40c6072f54 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_word.c @@ -0,0 +1,272 @@ +/* + * + * zle_word.c - word-related editor functions + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define ZLE +#include "zsh.h" + + +void forwardword() /**/ +{ + if (mult < 0) { mult = -mult; backwardword(); return; } + while (mult--) { + while (cs != ll && iword(line[cs])) cs++; + if (wordflag && !mult) return; + while (cs != ll && !iword(line[cs])) cs++; + } +} + +void viforwardword() /**/ +{ + if (mult < 0) { mult = -mult; backwardword(); return; } + while (mult--) { + if (iident(line[cs])) while (cs != ll && iident(line[cs])) cs++; + else while (cs != ll && !iident(line[cs]) && !iblank(line[cs])) cs++; + if (wordflag && !mult) return; + while (cs != ll && iblank(line[cs])) cs++; + } +} + +void viforwardblankword() /**/ +{ + if (mult < 0) { mult = -mult; vibackwardblankword(); return; } + while (mult--) { + while (cs != ll && !iblank(line[cs])) cs++; + if (wordflag && !mult) return; + while (cs != ll && iblank(line[cs])) cs++; + } +} + +void emacsforwardword() /**/ +{ + if (mult < 0) { mult = -mult; emacsbackwardword(); return; } + while (mult--) + { + while (cs != ll && !iword(line[cs])) cs++; + if (wordflag && !mult) return; + while (cs != ll && iword(line[cs])) cs++; + } +} + +void viforwardblankwordend() /**/ +{ + if (mult < 0) return; + while (mult--) { + while (cs != ll && iblank(line[cs+1])) cs++; + while (cs != ll && !iblank(line[cs+1])) cs++; + } + if (cs != ll && virangeflag) cs++; +} + +void viforwardwordend() /**/ +{ + if (mult < 0) { mult = -mult; backwardword(); return; } + while (mult--) { + if (iblank(line[cs+1])) while (cs != ll && iblank(line[cs+1])) cs++; + if (iident(line[cs+1])) while (cs != ll && iident(line[cs+1])) cs++; + else while (cs != ll && !iident(line[cs+1]) && !iblank(line[cs+1])) cs++; + } + if (cs != ll && virangeflag) cs++; +} + +void backwardword() /**/ +{ + if (mult < 0) { mult = -mult; forwardword(); return; } + while (mult--) { + while (cs && !iword(line[cs-1])) cs--; + while (cs && iword(line[cs-1])) cs--; + } +} + +void vibackwardword() /**/ +{ + if (mult < 0) { mult = -mult; backwardword(); return; } + while (mult--) { + while (cs && iblank(line[cs-1])) cs--; + if (iident(line[cs-1])) while (cs && iident(line[cs-1])) cs--; + else while (cs && !iident(line[cs-1]) && !iblank(line[cs-1])) cs--; + } +} + +void vibackwardblankword() /**/ +{ + if (mult < 0) { mult = -mult; viforwardblankword(); return; } + while (mult--) { + while (cs && iblank(line[cs-1])) cs--; + while (cs && !iblank(line[cs-1])) cs--; + } +} + +void emacsbackwardword() /**/ +{ + if (mult < 0) { mult = -mult; emacsforwardword(); return; } + while (mult--) { + while (cs && !iword(line[cs-1])) cs--; + while (cs && iword(line[cs-1])) cs--; + } +} + +void backwarddeleteword() /**/ +{ +int x = cs; + + if (mult < 0) { mult = -mult; deleteword(); return; } + while (mult--) { + while (x && !iword(line[x-1])) x--; + while (x && iword(line[x-1])) x--; + } + backdel(cs-x); +} + +void vibackwardkillword() /**/ +{ +int x = cs; + + if (mult < 0) { feep(); return; } + while (mult--) { + while (x > viinsbegin && !iword(line[x-1])) x--; + while (x > viinsbegin && iword(line[x-1])) x--; + } + backkill(cs-x,1); +} + +void backwardkillword() /**/ +{ +int x = cs; + + if (mult < 0) { mult = -mult; killword(); return; } + while (mult--) { + while (x && !iword(line[x-1])) x--; + while (x && iword(line[x-1])) x--; + } + backkill(cs-x,1); +} + +void upcaseword() /**/ +{ +int neg = mult < 0, ocs = cs; + + if (neg) mult = -mult; + while (mult--) { + while (cs != ll && !iword(line[cs])) cs++; + while (cs != ll && iword(line[cs])) { + line[cs] = tuupper(line[cs]); + cs++; + } + } + if (neg) cs = ocs; +} + +void downcaseword() /**/ +{ +int neg = mult < 0, ocs = cs; + + if (neg) mult = -mult; + while (mult--) { + while (cs != ll && !iword(line[cs])) cs++; + while (cs != ll && iword(line[cs])) { + line[cs] = tulower(line[cs]); + cs++; + } + } + if (neg) cs = ocs; +} + +void capitalizeword() /**/ +{ +int first; +int neg = mult < 0, ocs = cs; + + if (neg) mult = -mult; + while (mult--) { + first = 1; + while (cs != ll && !iword(line[cs])) cs++; + while (cs != ll && iword(line[cs])) { + line[cs] = (first) ? tuupper(line[cs]) : tulower(line[cs]); + first = 0; + cs++; + } + } + if (neg) cs = ocs; +} + +void deleteword() /**/ +{ +int x = cs; + + if (mult < 0) { mult = -mult; backwarddeleteword(); return; } + while (mult--) { + while (x != ll && !iword(line[x])) x++; + while (x != ll && iword(line[x])) x++; + } + foredel(x-cs); +} + +void killword() /**/ +{ +int x = cs; + + if (mult < 0) { mult = -mult; backwardkillword(); return; } + while (mult--) { + while (x != ll && !iword(line[x])) x++; + while (x != ll && iword(line[x])) x++; + } + forekill(x-cs,0); +} + +void transposewords() /**/ +{ +int p1,p2,p3,p4,x = cs; +char *temp,*pp; +int neg = mult < 0, ocs = cs; + + if (neg) mult = -mult; + while (mult--) { + while (x != ll && line[x] != '\n' && !iword(line[x])) + x++; + if (x == ll || line[x] == '\n') { + x = cs; + while (x && line[x-1] != '\n' && !iword(line[x])) + x--; + if (!x || line[x-1] == '\n') { + feep(); + return; + } + } + for (p4 = x; p4 != ll && iword(line[p4]); p4++); + for (p3 = p4; p3 && iword(line[p3-1]); p3--); + if (!p3) { + feep(); + return; + } + for (p2 = p3; p2 && !iword(line[p2-1]); p2--); + if (!p2) { + feep(); + return; + } + for (p1 = p2; p1 && iword(line[p1-1]); p1--); + pp = temp = halloc(p4-p1+1); + struncpy(&pp,line+p3,p4-p3); + struncpy(&pp,line+p2,p3-p2); + struncpy(&pp,line+p1,p2-p1); + strncpy((char *) line+p1,temp,p4-p1); + cs = p4; + } + if (neg) cs = ocs; +} diff --git a/usr/othersrc/public/zsh-2.2/src/zle_word.pro b/usr/othersrc/public/zsh-2.2/src/zle_word.pro new file mode 100644 index 0000000000..646b0486c2 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zle_word.pro @@ -0,0 +1,19 @@ +void forwardword DCLPROTO((void)); +void viforwardword DCLPROTO((void)); +void viforwardblankword DCLPROTO((void)); +void emacsforwardword DCLPROTO((void)); +void viforwardblankwordend DCLPROTO((void)); +void viforwardwordend DCLPROTO((void)); +void backwardword DCLPROTO((void)); +void vibackwardword DCLPROTO((void)); +void vibackwardblankword DCLPROTO((void)); +void emacsbackwardword DCLPROTO((void)); +void backwarddeleteword DCLPROTO((void)); +void vibackwardkillword DCLPROTO((void)); +void backwardkillword DCLPROTO((void)); +void upcaseword DCLPROTO((void)); +void downcaseword DCLPROTO((void)); +void capitalizeword DCLPROTO((void)); +void deleteword DCLPROTO((void)); +void killword DCLPROTO((void)); +void transposewords DCLPROTO((void)); diff --git a/usr/othersrc/public/zsh-2.2/src/zsh.h b/usr/othersrc/public/zsh-2.2/src/zsh.h new file mode 100644 index 0000000000..2cfa6621df --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/zsh.h @@ -0,0 +1,1544 @@ +/* + * + * zsh.h - standard header file + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#include "config.h" + +#include +#include + +#ifdef HAS_STRING +#include +#else +#include +#endif + +#ifdef HAS_LOCALE +#include +#endif + +#ifdef HAS_STDLIB +#include +#endif + +#ifdef SYSV +#include +#define _POSIX_SOURCE +#include +#include +#define MAXPATHLEN PATH_MAX +#define lstat stat +extern int gethostname(); +#define sigmask(m) m +#include +#else +#include /* this is the key to the whole thing */ +#endif + +#ifdef _IBMR2 +#undef _BSD /* union wait SUCKS! */ +#include +#define _BSD +#else +#include +#endif + +#include + +#ifndef SYSV +#include +#endif + +#include +#include + +#ifdef TERMIO +#define VDISABLEVAL -1 +#define TIO 1 +#include +#else +#ifdef TERMIOS +#define VDISABLEVAL 0 +#define TIO 1 +#include +#else +#include +#endif +#endif + +#ifdef SYSV +#undef TIOCGWINSZ +#endif + +#include +#include + +#ifdef SYSV +#undef _POSIX_SOURCE +#endif + +#ifdef __hp9000s800 +#include +#endif + +#ifndef sun +#include +#else +#include +#endif + +#define VERSIONSTR "zsh v2.2.0" + +#if 0 /* __STDC__ */ +#include +#include +#include +#define DCLPROTO(X) X +#undef NULL +#define NULL ((void *)0) +#else /* not __STDC__ */ +#include +#define DCLPROTO(X) () +#ifndef NULL +#define NULL 0 +#endif +#endif /* __STDC__ */ + +#ifdef QDEBUG +#define DCLPROTO(X) X +#endif + +#define DEFWORDCHARS "*?_-.[]~=/&;!#$%^(){}<>" +#define DEFTIMEFMT "%E real %U user %S system %P %J" +#ifdef UTMP_HOST +#define DEFWATCHFMT "%n has %a %l from %m." +#else +#define DEFWATCHFMT "%n has %a %l." +#endif + +#ifdef GLOBALS +#define EXTERN +#else +#define EXTERN extern +#endif + +#ifdef HAS_STRING +#define killpg(pgrp,sig) kill(-(pgrp),sig) +#endif + +#ifndef F_OK +#define F_OK 00 +#define R_OK 04 +#define W_OK 02 +#define X_OK 01 +#endif + +#include "zle.h" + +/* size of job list */ + +#define MAXJOB 80 + +/* memory allocation routines - changed with permalloc()/heapalloc() */ + +vptr (*alloc)DCLPROTO((int)); +vptr (*ncalloc)DCLPROTO((int)); + +#define addhnode(A,B,C,D) Addhnode(A,B,C,D,1) +#define addhperm(A,B,C,D) Addhnode(A,B,C,D,0) + +/* character tokens */ + +#define ALPOP ((char) 0x81) +#define HISTSPACE ((char) 0x83) +#define Pound ((char) 0x84) +#define String ((char) 0x85) +#define Hat ((char) 0x86) +#define Star ((char) 0x87) +#define Inpar ((char) 0x88) +#define Outpar ((char) 0x89) +#define Qstring ((char) 0x8a) +#define Equals ((char) 0x8b) +#define Bar ((char) 0x8c) +#define Inbrace ((char) 0x8d) +#define Outbrace ((char) 0x8e) +#define Inbrack ((char) 0x8f) +#define Outbrack ((char) 0x90) +#define Tick ((char) 0x91) +#define Inang ((char) 0x92) +#define Outang ((char) 0x93) +#define Quest ((char) 0x94) +#define Tilde ((char) 0x95) +#define Qtick ((char) 0x96) +#define Comma ((char) 0x97) +#define Nularg ((char) 0x98) + +/* chars that need to be quoted if meant literally */ + +#define SPECCHARS "#$^*()$=|{}[]`<>?~;&!\n\t \\\'\"" + +/* ALPOP in the form of a string */ + +#define ALPOPS " \201" +#define HISTMARK "\201" + +#define SEPER 1 +#define NEWLIN 2 +#define LEXERR 3 +#define SEMI 4 +#define DSEMI 5 +#define AMPER 6 +#define INPAR 7 +#define INBRACE 8 +#define OUTPAR 9 +#define DBAR 10 +#define DAMPER 11 +#define BANG 12 +#define OUTBRACE 13 +#define OUTANG 14 +#define OUTANGBANG 15 +#define DOUTANG 16 +#define DOUTANGBANG 17 +#define INANG 18 +#define DINANG 19 +#define DINANGDASH 20 +#define INANGAMP 21 +#define OUTANGAMP 22 +#define OUTANGAMPBANG 23 +#define DOUTANGAMP 24 +#define DOUTANGAMPBANG 25 +#define TRINANG 26 +#define BAR 27 +#define BARAMP 28 +#define DINBRACK 29 +#define DOUTBRACK 30 +#define STRING 31 +#define ENVSTRING 32 +#define ENVARRAY 33 +#define ENDINPUT 34 +#define INOUTPAR 35 +#define DO 36 +#define DONE 37 +#define ESAC 38 +#define THEN 39 +#define ELIF 40 +#define ELSE 41 +#define FI 42 +#define FOR 43 +#define CASE 44 +#define IF 45 +#define WHILE 46 +#define FUNC 47 +#define REPEAT 48 +#define TIME 49 +#define UNTIL 50 +#define EXEC 51 +#define COMMAND 52 +#define SELECT 53 +#define COPROC 54 +#define NOGLOB 55 +#define DASH 56 +#define NOCORRECT 57 +#define FOREACH 58 +#define ZEND 59 + +#define WRITE 0 +#define WRITENOW 1 +#define APP 2 +#define APPNOW 3 +#define MERGEOUT 4 +#define MERGEOUTNOW 5 +#define ERRAPP 6 +#define ERRAPPNOW 7 +#define READ 8 +#define HEREDOC 9 +#define HEREDOCDASH 10 +#define HERESTR 11 +#define MERGE 12 +#define CLOSE 13 +#define INPIPE 14 +#define OUTPIPE 15 +#define NONE 16 + +#ifdef GLOBALS +int redirtab[TRINANG-OUTANG+1] = { + WRITE, + WRITENOW, + APP, + APPNOW, + READ, + HEREDOC, + HEREDOCDASH, + MERGE, + MERGEOUT, + MERGEOUTNOW, + ERRAPP, + ERRAPPNOW, + HERESTR, +}; +#else +int redirtab[TRINANG-OUTANG+1]; +#endif + +#define IS_READFD(X) ((X)>=READ && (X)<=MERGE) +#define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG) +#define IS_ERROR_REDIR(X) ((X)>=MERGEOUT && (X)<=ERRAPPNOW) +#define UN_ERROR_REDIR(X) ((X)-MERGEOUT+WRITE) + +#define FD_WORD -1 +#define FD_COPROC -2 +#define FD_CLOSE -3 + +EXTERN char **environ; + +typedef struct hashtab *Hashtab; +typedef struct hashnode *Hashnode; +typedef struct schedcmd *Schedcmd; +typedef struct alias *Alias; +typedef struct process *Process; +typedef struct job *Job; +typedef struct value *Value; +typedef struct arrind *Arrind; +typedef struct varasg *Varasg; +typedef struct param *Param; +typedef struct cmdnam *Cmdnam; +typedef struct cond *Cond; +typedef struct cmd *Cmd; +typedef struct pline *Pline; +typedef struct sublist *Sublist; +typedef struct list *List; +typedef struct lklist *Lklist; +typedef struct lknode *Lknode; +typedef struct comp *Comp; +typedef struct redir *Redir; +typedef struct complist *Complist; +typedef struct heap *Heap; +typedef struct histent *Histent; +typedef struct hp *Hp; +typedef struct compctl *Compctl; +typedef void (*FFunc)DCLPROTO((vptr)); +typedef vptr (*VFunc)DCLPROTO((vptr)); +typedef void (*HFunc)DCLPROTO((char *,char *)); + +/* linked list abstract data type */ + +struct lknode; +struct lklist; + +struct lknode { + Lknode next,last; + vptr dat; + }; +struct lklist { + Lknode first,last; + }; + +#define addnode(X,Y) insnode(X,(X)->last,Y) +#define full(X) ((X)->first != NULL) +#define firstnode(X) ((X)->first) +#define getaddrdata(X) (&((X)->dat)) +#define getdata(X) ((X)->dat) +#define setdata(X,Y) ((X)->dat = (Y)) +#define lastnode(X) ((X)->last) +#define nextnode(X) ((X)->next) +#define prevnode(X) ((X)->last) +#define peekfirst(X) ((X)->first->dat) +#define pushnode(X,Y) insnode(X,(Lknode) X,Y) +#define incnode(X) (X = nextnode(X)) +#define gethistent(X) (histentarr+((X)%histentct)) + +/* node structure for syntax trees */ + +/* struct list, struct sublist, struct pline, etc. all fit the form + of this structure and are used interchangably +*/ + +struct node { + int data[4]; /* arbitrary integer data */ + vptr ptrs[4]; /* arbitrary pointer data */ + int types[4]; /* what ptrs[] are pointing to */ + int type; /* node type */ + }; + +#define N_LIST 0 +#define N_SUBLIST 1 +#define N_PLINE 2 +#define N_CMD 3 +#define N_REDIR 4 +#define N_COND 5 +#define N_FOR 6 +#define N_CASE 7 +#define N_IF 8 +#define N_WHILE 9 +#define N_VARASG 10 +#define N_COUNT 11 + +/* values for types[4] */ + +#define NT_EMPTY 0 +#define NT_NODE 1 +#define NT_STR 2 +#define NT_LIST 4 +#define NT_MALLOC 8 + +/* tree element for lists */ + +struct list { + int type; + int ifil[3]; /* to fit struct node */ + Sublist left; + List right; + }; + +#define SYNC 0 /* ; */ +#define ASYNC 1 /* & */ +#define TIMED 2 + +/* tree element for sublists */ + +struct sublist { + int type; + int flags; /* see PFLAGs below */ + int ifil[2]; + Pline left; + Sublist right; + }; + +#define ORNEXT 10 /* || */ +#define ANDNEXT 11 /* && */ + +#define PFLAG_NOT 1 /* ! ... */ +#define PFLAG_COPROC 32 /* coproc ... */ + +/* tree element for pipes */ + +struct pline { + int type; + int ifil[3]; + Cmd left; + Pline right; + }; + +#define END 0 /* pnode *right is null */ +#define PIPE 1 /* pnode *right is the rest of the pipeline */ + +/* tree element for commands */ + +struct cmd { + int type; + int flags; /* see CFLAGs below */ + int ifil[2]; + Lklist args; /* command & argmument List (char *'s) */ + union { + List list; /* for SUBSH/CURSH/SHFUNC */ + struct forcmd *forcmd; + struct casecmd *casecmd; + struct ifcmd *ifcmd; + struct whilecmd *whilecmd; + Sublist pline; + Cond cond; + } u; + Lklist redir; /* i/o redirections (struct redir *'s) */ + Lklist vars; /* param assignments (struct varasg *'s) */ + }; + +#define SIMPLE 0 +#define SUBSH 1 +#define CURSH 2 +#define ZCTIME 3 +#define FUNCDEF 4 +#define CFOR 5 +#define CWHILE 6 +#define CREPEAT 7 +#define CIF 8 +#define CCASE 9 +#define CSELECT 10 +#define COND 11 + +#define CFLAG_EXEC 1 /* exec ... */ +#define CFLAG_COMMAND 2 /* command ... */ +#define CFLAG_NOGLOB 4 /* noglob ... */ +#define CFLAG_DASH 8 /* - ... */ + +/* tree element for redirection lists */ + +struct redir { + int type,fd1,fd2,ifil; + char *name; + }; + +/* tree element for conditionals */ + +struct cond { + int type; /* can be cond_type, or a single letter (-a, -b, ...) */ + int ifil[3]; + vptr left,right,vfil[2]; + int types[4],typ; /* from struct node. DO NOT REMOVE */ + }; + +#define COND_NOT 0 +#define COND_AND 1 +#define COND_OR 2 +#define COND_STREQ 3 +#define COND_STRNEQ 4 +#define COND_STRLT 5 +#define COND_STRGTR 6 +#define COND_NT 7 +#define COND_OT 8 +#define COND_EF 9 +#define COND_EQ 10 +#define COND_NE 11 +#define COND_LT 12 +#define COND_GT 13 +#define COND_LE 14 +#define COND_GE 15 + +struct forcmd { /* for/select */ + /* Cmd->args contains list of words to loop thru */ + int inflag; /* if there is an in ... clause */ + int ifil[3]; + char *name; /* parameter to assign values to */ + List list; /* list to look through for each name */ + }; +struct casecmd { + /* Cmd->args contains word to test */ + int ifil[4]; + struct casecmd *next; + char *pat; + List list; /* list to execute */ + }; + +/* + + a command like "if foo then bar elif baz then fubar else fooble" + generates a tree like: + + struct ifcmd a = { next = &b, ifl = "foo", thenl = "bar" } + struct ifcmd b = { next = &c, ifl = "baz", thenl = "fubar" } + struct ifcmd c = { next = NULL, ifl = NULL, thenl = "fooble" } + +*/ + +struct ifcmd { + int ifil[4]; + struct ifcmd *next; + List ifl; + List thenl; + }; + +struct whilecmd { + int cond; /* 0 for while, 1 for until */ + int ifil[3]; + List cont; /* condition */ + List loop; /* list to execute until condition met */ + }; + +/* 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[NOFILE]; /* list of src/dests redirected to/from this fd */ + }; + +/* node used in command path hash table (cmdnamtab) */ + +struct cmdnam +{ + struct hashnode *next; int canfree; char *nam; /* hash data */ + int type,flags; + union { + char *nam; /* full pathname if type != BUILTIN */ + int binnum; /* func to exec if type == BUILTIN */ + List list; /* list to exec if type == SHFUNC */ + } u; + char **pcomp; /* location in path for EXCMD's */ + }; + +#define EXCMD 0 +#define BUILTIN 2 +#define SHFUNC 3 +#define DISABLED 4 +#define ISEXCMD(X) ((X)==EXCMD) + +/* node used in parameter hash table (paramtab) */ + +struct param { + struct hashnode *next; int canfree; char *nam; /* hash data */ + union { + char **arr; /* value if declared array */ + char *str; /* value if declared string (scalar) */ + long val; /* value if declared integer */ + } u; + union { /* functions to call to set value */ + void (*cfn)DCLPROTO((Param,char *)); + void (*ifn)DCLPROTO((Param,long)); + void (*afn)DCLPROTO((Param,char **)); + } sets; + union { /* functions to call to get value */ + char *(*cfn)DCLPROTO((Param)); + long (*ifn)DCLPROTO((Param)); + char **(*afn)DCLPROTO((Param)); + } gets; + int ct; /* output base or field width */ + int flags; + vptr data; /* used by getfns */ + char *env; /* location in environment, if exported */ + char *ename; /* name of corresponding environment var */ + }; + +#define PMFLAG_s 0 /* scalar */ +#define PMFLAG_L 1 /* left justify and remove leading blanks */ +#define PMFLAG_R 2 /* right justify and fill with leading blanks */ +#define PMFLAG_Z 4 /* right justify and fill with leading zeros */ +#define PMFLAG_i 8 /* integer */ +#define PMFLAG_l 16 /* all lower case */ +#define PMFLAG_u 32 /* all upper case */ +#define PMFLAG_r 64 /* readonly */ +#define PMFLAG_t 128 /* tagged */ +#define PMFLAG_x 256 /* exported */ +#define PMFLAG_A 512 /* array */ +#define PMFLAG_SPECIAL 1024 +#define PMTYPE (PMFLAG_i|PMFLAG_A) +#define pmtype(X) ((X)->flags & PMTYPE) + +/* variable assignment tree element */ + +struct varasg { + int type; /* nonzero means array */ + int ifil[3]; + char *name; + char *str; /* should've been a union here. oh well */ + Lklist arr; + }; + +/* lvalue for variable assignment/expansion */ + +struct value { + int isarr; + struct param *pm; /* parameter node */ + int a; /* first element of array slice, or -1 */ + int b; /* last element of array slice, or -1 */ + }; + +struct fdpair { + int fd1,fd2; + }; + +/* tty state structure */ + +struct ttyinfo { +#ifdef TERMIOS + struct termios tio; +#else +#ifdef TERMIO + struct termio tio; +#else + struct sgttyb sgttyb; + int lmodes; + struct tchars tchars; + struct ltchars ltchars; +#endif +#endif +#ifdef TIOCGWINSZ + struct winsize winsize; +#endif + }; + +EXTERN struct ttyinfo savedttyinfo; + +/* entry in job table */ + +struct job { + long gleader; /* process group leader of this job */ + int stat; + char *pwd; /* current working dir of shell when + this job was spawned */ + struct process *procs; /* list of processes */ + Lklist filelist; /* list of files to delete when done */ + }; + +#define STAT_CHANGED 1 /* status changed and not reported */ +#define STAT_STOPPED 2 /* all procs stopped or exited */ +#define STAT_TIMED 4 /* job is being timed */ +#define STAT_DONE 8 +#define STAT_LOCKED 16 /* shell is finished creating this job, + may be deleted from job table */ +#define STAT_INUSE 64 /* this job entry is in use */ + +#define SP_RUNNING -1 /* fake statusp for running jobs */ + +#ifndef RUSAGE_CHILDREN +#undef HAS_RUSAGE +#endif + +struct timeinfo { +#ifdef HAS_RUSAGE + struct rusage ru; +#else + long ut, st; +#endif +}; + +/* node in job process lists */ + +#define JOBTEXTSIZE 80 + +struct process { + struct process *next; + long pid; + char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */ + int statusp; /* return code from wait3() */ + struct timeinfo ti; + time_t bgtime; /* time job was spawned */ + time_t endtime; /* time job exited */ + }; + +/* node in alias hash table */ + +struct alias { + struct hashnode *next; int canfree; char *nam; /* hash data */ + char *text; /* expansion of alias */ + int cmd; /* one for regular aliases, + zero for global aliases, + negative for reserved words */ + int inuse; /* alias is being expanded */ + }; + +/* node in sched list */ + +struct schedcmd { + struct schedcmd *next; + char *cmd; /* command to run */ + time_t time; /* when to run it */ + }; + +#define MAXAL 20 /* maximum number of aliases expanded at once */ + +/* hash table node */ + +struct hashnode { + struct hashnode *next; + int canfree; /* nam is free()able */ + char *nam; + }; + +/* hash table */ + +struct hashtab { + int hsize; /* size of nodes[] */ + int ct; /* # of elements */ + struct hashnode **nodes; /* array of size hsize */ + }; + +/* history entry */ + +struct histent { + char *lex; /* lexical history line */ + char *lit; /* literal history line */ + time_t stim; /* command started time (datestamp) */ + time_t ftim; /* command finished time */ + }; + +/* completion control */ + +struct compctl { + struct hashnode *next; int canfree; char *nam; /* hash data */ + int mask; + char *keyvar; + }; + +#define CC_FILES 1 +#define CC_COMMPATH 2 +#define CC_HOSTS 4 +#define CC_OPTIONS 8 +#define CC_VARS 16 +#define CC_BINDINGS 32 +#define CC_USRKEYS 64 + +extern char *sys_errlist[]; +extern int errno; + +/* values in opts[] array */ + +#define OPT_INVALID 1 /* opt is invalid, like -$ */ +#define OPT_UNSET 0 +#define OPT_SET 2 + +/* the options */ + +struct option { + char *name; + char id; /* corresponding letter */ + }; + +#define CORRECT '0' +#define NOCLOBBER '1' +#define NOBADPATTERN '2' +#define NONOMATCH '3' +#define GLOBDOTS '4' +#define NOTIFY '5' +#define BGNICE '6' +#define IGNOREEOF '7' +#define MARKDIRS '8' +#define AUTOLIST '9' +#define NOBEEP 'B' +#define PRINTEXITVALUE 'C' +#define PUSHDTOHOME 'D' +#define PUSHDSILENT 'E' +#define NOGLOBOPT 'F' +#define NULLGLOB 'G' +#define RMSTARSILENT 'H' +#define IGNOREBRACES 'I' +#define AUTOCD 'J' +#define NOBANGHIST 'K' +#define SUNKEYBOARDHACK 'L' +#define SINGLELINEZLE 'M' +#define AUTOPUSHD 'N' +#define CORRECTALL 'O' +#define RCEXPANDPARAM 'P' +#define PATHDIRS 'Q' +#define LONGLISTJOBS 'R' +#define RECEXACT 'S' +#define CDABLEVARS 'T' +#define MAILWARNING 'U' +#define NOPROMPTCR 'V' +#define AUTORESUME 'W' +#define LISTTYPES 'X' +#define MENUCOMPLETE 'Y' +#define USEZLE 'Z' +#define ALLEXPORT 'a' +#define ERREXIT 'e' +#define NORCS 'f' +#define HISTIGNORESPACE 'g' +#define HISTIGNOREDUPS 'h' +#define INTERACTIVE 'i' +#define HISTLIT 'j' +#define INTERACTIVECOMMENTS 'k' +#define LOGINSHELL 'l' +#define MONITOR 'm' +#define NOEXEC 'n' +#define SHINSTDIN 's' +#define NOUNSET 'u' +#define VERBOSE 'v' +#define CHASELINKS 'w' +#define XTRACE 'x' +#define SHWORDSPLIT 'y' +#define MENUCOMPLETEBEEP '\2' +#define HISTNOSTORE '\3' +#define EXTENDEDGLOB '\5' +#define GLOBCOMPLETE '\6' +#define CSHJUNKIEQUOTES '\7' +#define PUSHDMINUS '\10' +#define CSHJUNKIELOOPS '\11' +#define RCQUOTES '\12' +#define KSHOPTIONPRINT '\13' +#define NOSHORTLOOPS '\14' +#define LASTMENU '\15' +#define AUTOMENU '\16' +#define HISTVERIFY '\17' +#define NOLISTBEEP '\20' +#define NOHUP '\21' +#define NOEQUALS '\22' +#define CSHNULLGLOB '\23' +#define HASHCMDS '\24' +#define HASHDIRS '\25' +#define NUMERICGLOBSORT '\26' +#define BRACECCL '\27' +#define HASHLISTALL '\30' +#define OVERSTRIKE '\31' +#define NOHISTBEEP '\32' +#define PUSHDIGNOREDUPS '\33' +#define AUTOREMOVESLASH '\34' + +#ifndef GLOBALS +extern struct option optns[]; +#else +struct option optns[] = { + "correct",CORRECT, + "noclobber",NOCLOBBER, + "nobadpattern",NOBADPATTERN, + "nonomatch",NONOMATCH, + "globdots",GLOBDOTS, + "notify",NOTIFY, + "bgnice",BGNICE, + "ignoreeof",IGNOREEOF, + "markdirs",MARKDIRS, + "autolist",AUTOLIST, + "nobeep",NOBEEP, + "printexitvalue",PRINTEXITVALUE, + "pushdtohome",PUSHDTOHOME, + "pushdsilent",PUSHDSILENT, + "noglob",NOGLOBOPT, + "nullglob",NULLGLOB, + "rmstarsilent",RMSTARSILENT, + "ignorebraces",IGNOREBRACES, + "braceccl",BRACECCL, + "autocd",AUTOCD, + "nobanghist",NOBANGHIST, + "sunkeyboardhack",SUNKEYBOARDHACK, + "singlelinezle",SINGLELINEZLE, + "autopushd",AUTOPUSHD, + "correctall",CORRECTALL, + "rcexpandparam",RCEXPANDPARAM, + "pathdirs",PATHDIRS, + "longlistjobs",LONGLISTJOBS, + "recexact",RECEXACT, + "cdablevars",CDABLEVARS, + "mailwarning",MAILWARNING, + "nopromptcr",NOPROMPTCR, + "autoresume",AUTORESUME, + "listtypes",LISTTYPES, + "menucomplete",MENUCOMPLETE, + "zle",USEZLE, + "allexport",ALLEXPORT, + "errexit",ERREXIT, + "norcs",NORCS, + "histignorespace",HISTIGNORESPACE, + "histignoredups",HISTIGNOREDUPS, + "interactive",INTERACTIVE, + "histlit",HISTLIT, + "interactivecomments",INTERACTIVECOMMENTS, + "login",LOGINSHELL, + "monitor",MONITOR, + "noexec",NOEXEC, + "shinstdin",SHINSTDIN, + "nounset",NOUNSET, + "verbose",VERBOSE, + "chaselinks",CHASELINKS, + "xtrace",XTRACE, + "shwordsplit",SHWORDSPLIT, + "menucompletebeep",MENUCOMPLETEBEEP, + "histnostore",HISTNOSTORE, + "extendedglob",EXTENDEDGLOB, + "globcomplete",GLOBCOMPLETE, + "cshjunkiequotes",CSHJUNKIEQUOTES, + "pushdminus",PUSHDMINUS, + "cshjunkieloops",CSHJUNKIELOOPS, + "rcquotes",RCQUOTES, + "noshortloops",NOSHORTLOOPS, + "lastmenu",LASTMENU, + "automenu",AUTOMENU, + "histverify",HISTVERIFY, + "nolistbeep",NOLISTBEEP, + "nohup",NOHUP, + "noequals",NOEQUALS, + "kshoptionprint",KSHOPTIONPRINT, + "cshnullglob",CSHNULLGLOB, + "hashcmds",HASHCMDS, + "hashdirs",HASHDIRS, + "numericglobsort",NUMERICGLOBSORT, + "hashlistall",HASHLISTALL, + "overstrike",OVERSTRIKE, + "nohistbeep",NOHISTBEEP, + "pushdignoredups",PUSHDIGNOREDUPS, + "autoremoveslash",AUTOREMOVESLASH, + NULL,0 +}; +#endif + +#define ALSTAT_MORE 1 /* last alias ended with ' ' */ +#define ALSTAT_JUNK 2 /* don't put word in history List */ + +#undef isset +#define isset(X) (opts[X]) +#define unset(X) (!opts[X]) +#define interact (isset(INTERACTIVE)) +#define jobbing (isset(MONITOR)) +#define nointr() signal(SIGINT,SIG_IGN) +#define islogin (isset(LOGINSHELL)) + +#ifndef _IBMR2 +#undef WIFSTOPPED +#undef WIFSIGNALED +#undef WIFEXITED +#undef WEXITSTATUS +#undef WTERMSIG +#undef WSTOPSIG +#undef WCOREDUMPED + +#define WIFSTOPPED(X) (((X)&0377)==0177) +#define WIFSIGNALED(X) (((X)&0377)!=0&&((X)&0377)!=0177) +#define WIFEXITED(X) (((X)&0377)==0) +#define WEXITSTATUS(X) (((X)>>8)&0377) +#define WTERMSIG(X) ((X)&0177) +#define WSTOPSIG(X) (((X)>>8)&0377) +#endif +#define WCOREDUMPED(X) ((X)&0200) + +#ifndef S_ISBLK +#define _IFMT 0170000 +#define _IFDIR 0040000 +#define _IFCHR 0020000 +#define _IFBLK 0060000 +#define _IFREG 0100000 +#define _IFIFO 0010000 +#define S_ISBLK(m) (((m)&_IFMT) == _IFBLK) +#define S_ISCHR(m) (((m)&_IFMT) == _IFCHR) +#define S_ISDIR(m) (((m)&_IFMT) == _IFDIR) +#define S_ISFIFO(m) (((m)&_IFMT) == _IFIFO) +#define S_ISREG(m) (((m)&_IFMT) == _IFREG) +#endif + +#ifndef S_ISSOCK +#ifndef _IFMT +#define _IFMT 0170000 +#endif +#define _IFLNK 0120000 +#define _IFSOCK 0140000 +#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) +#define S_ISSOCK(m) (((m)&_IFMT) == _IFSOCK) +#endif + +#if S_IFIFO == S_IFSOCK +#undef S_IFIFO +#endif + +#ifndef S_IFIFO +#define NO_FIFOS +#endif + +/* buffered shell input for non-interactive shells */ + +EXTERN FILE *bshin; + +/* NULL-terminated arrays containing path, cdpath, etc. */ + +EXTERN char **path,**cdpath,**fpath,**watch,**mailpath; +EXTERN char **manpath,**tildedirs,**fignore; +EXTERN char **hosts; + +/* named directories */ + +EXTERN char **userdirs,**usernames; + +/* size of userdirs[], # of userdirs */ + +EXTERN int userdirsz,userdirct; + +EXTERN char *mailfile; + +EXTERN char *yytext; + +/* error/break flag */ + +EXTERN int errflag; + +EXTERN char *tokstr; +EXTERN int tok, tokfd; + +/* lexical analyzer error flag */ + +EXTERN int lexstop; + +/* suppress error messages */ + +EXTERN int noerrs; + +/* current history event number */ + +EXTERN int curhist; + +/* if != 0, this is the first line of the command */ + +EXTERN int isfirstln; + +/* if != 0, this is the first char of the command (not including + white space */ + +EXTERN int isfirstch; + +/* number of history entries */ + +EXTERN int histentct; + +/* array of history entries */ + +EXTERN Histent histentarr; + +/* capacity of history lists */ + +EXTERN int histsiz,lithistsiz; + +/* if = 1, we have performed history substitution on the current line + if = 2, we have used the 'p' modifier */ + +EXTERN int histdone; + +/* default event (usually curhist-1, that is, "!!") */ + +EXTERN int defev; + +/* != 0 if we are about to read a command word */ + +EXTERN int incmdpos; + +/* != 0 if we are in the middle of a [[ ... ]] */ + +EXTERN int incond; + +/* != 0 if we are after a redirection (for ctxtlex only) */ + +EXTERN int inredir; + +/* != 0 if we are about to read a case pattern */ + +EXTERN int incasepat; + +/* != 0 if we just read FUNCTION */ + +EXTERN int infunc; + +/* != 0 if we just read a newline */ + +EXTERN int isnewlin; + +/* the lists of history events */ + +EXTERN Lklist histlist,lithistlist; + +/* the directory stack */ + +EXTERN Lklist dirstack; + +/* the zle buffer stack */ + +EXTERN Lklist bufstack; + +/* the input queue (stack?) + + inbuf = start of buffer + inbufptr = location in buffer (= inbuf for a FULL buffer) + (= inbuf+inbufsz for an EMPTY buffer) + inbufct = # of chars in buffer (inbufptr+inbufct == inbuf+inbufsz) + inbufsz = max size of buffer +*/ + +EXTERN char *inbuf,*inbufptr; +EXTERN int inbufct,inbufsz; + +EXTERN char *ifs; /* $IFS */ + +EXTERN char *oldpwd; /* $OLDPWD */ + +EXTERN char *underscore; /* $_ */ + +/* != 0 if this is a subshell */ + +EXTERN int subsh; + +/* # of break levels */ + +EXTERN int breaks; + +/* != 0 if we have a return pending */ + +EXTERN int retflag; + +/* how far we've hashed the PATH so far */ + +EXTERN char **pathchecked; + +/* # of nested loops we are in */ + +EXTERN int loops; + +/* # of continue levels */ + +EXTERN int contflag; + +/* the job we are working on */ + +EXTERN int thisjob; + +/* the current job (+) */ + +EXTERN int curjob; + +/* the previous job (-) */ + +EXTERN int prevjob; + +/* hash table containing the aliases and reserved words */ + +EXTERN Hashtab aliastab; + +/* hash table containing the parameters */ + +EXTERN Hashtab paramtab; + +/* hash table containing the builtins/shfuncs/hashed commands */ + +EXTERN Hashtab cmdnamtab; + +/* hash table containing the zle multi-character bindings */ + +EXTERN Hashtab xbindtab; + +/* hash table for completion info for commands */ + +EXTERN Hashtab compctltab; + +/* default completion infos */ + +EXTERN struct compctl cc_compos, cc_default; + +/* the job table */ + +EXTERN struct job jobtab[MAXJOB]; + +/* shell timings */ + +#ifndef HAS_RUSAGE +EXTERN struct tms shtms; +#endif + +/* the list of sched jobs pending */ + +EXTERN struct schedcmd *schedcmds; + +/* the last l for s/l/r/ history substitution */ + +EXTERN char *hsubl; + +/* the last r for s/l/r/ history substitution */ + +EXTERN char *hsubr; + +EXTERN char *username; /* $USERNAME */ +EXTERN char *logname; /* $LOGNAME */ +EXTERN long lastval; /* $? */ +EXTERN long baud; /* $BAUD */ +EXTERN long columns; /* $COLUMNS */ +EXTERN long lines; /* $LINES */ +EXTERN long reporttime; /* $REPORTTIME */ + +/* input fd from the coprocess */ + +EXTERN int coprocin; + +/* output fd from the coprocess */ + +EXTERN int coprocout; + +EXTERN long mailcheck; /* $MAILCHECK */ +EXTERN long logcheck; /* $LOGCHECK */ + +/* the last time we checked mail */ + +EXTERN time_t lastmailcheck; + +/* the last time we checked the people in the WATCH variable */ + +EXTERN time_t lastwatch; + +/* the last time we did the periodic() shell function */ + +EXTERN time_t lastperiod; + +/* $SECONDS = time(NULL) - shtimer */ + +EXTERN time_t shtimer; + +EXTERN long mypid; /* $$ */ +EXTERN long lastpid; /* $! */ +EXTERN long ppid; /* $PPID */ + +/* the process group of the shell */ + +EXTERN long mypgrp; + +EXTERN char *pwd; /* $PWD */ +EXTERN char *optarg; /* $OPTARG */ +EXTERN long zoptind; /* $OPTIND */ +EXTERN char *prompt; /* $PROMPT */ +EXTERN char *rprompt; /* $RPROMPT */ +EXTERN char *prompt2; /* etc. */ +EXTERN char *prompt3; +EXTERN char *prompt4; +EXTERN char *sprompt; +EXTERN char *timefmt; +EXTERN char *watchfmt; +EXTERN char *wordchars; +EXTERN char *fceditparam; +EXTERN char *tmpprefix; +EXTERN char *rstring, *Rstring; +EXTERN char *postedit; + +EXTERN char *argzero; /* $0 */ + +EXTERN char *hackzero; + +/* the hostname */ + +EXTERN char *hostnam; + +EXTERN char *home; /* $HOME */ +EXTERN char **pparams; /* $argv */ + +/* the default command for null commands */ + +EXTERN char *nullcmd; +EXTERN char *readnullcmd; + +/* the List of local variables we have to destroy */ + +EXTERN Lklist locallist; + +/* the shell input fd */ + +EXTERN int SHIN; + +/* the shell tty fd */ + +EXTERN int SHTTY; + +/* the stack of aliases we are expanding */ + +EXTERN struct alias *alstack[MAXAL]; + +/* the alias stack pointer; also, the number of aliases currently + being expanded */ + +EXTERN int alstackind; + +/* != 0 means we are reading input from a string */ + +EXTERN int strin; + +/* period between periodic() commands, in seconds */ + +EXTERN long period; + +/* != 0 means history substitution is turned off */ + +EXTERN int stophist; + +EXTERN int lithist; + +/* this line began with a space, so junk it if HISTIGNORESPACE is on */ + +EXTERN int spaceflag; + +/* don't do spelling correction */ + +EXTERN int nocorrect; + +/* != 0 means we have removed the current event from the history List */ + +EXTERN int histremmed; + +/* the options; e.g. if opts['a'] == OPT_SET, -a is turned on */ + +EXTERN int opts[128]; + +EXTERN long lineno; /* LINENO */ +EXTERN long listmax; /* LISTMAX */ +EXTERN long savehist; /* SAVEHIST */ +EXTERN long shlvl; /* SHLVL */ +EXTERN long tmout; /* TMOUT */ +EXTERN long dirstacksize; /* DIRSTACKSIZE */ + +/* != 0 means we have called execlist() and then intend to exit(), + so don't fork if not necessary */ + +EXTERN int exiting; + +EXTERN int lastbase; /* last input base we used */ + +/* the limits for child processes */ + +#ifdef RLIM_INFINITY +EXTERN struct rlimit limits[RLIM_NLIMITS]; +#endif + +/* the current word in the history List */ + +EXTERN char *hlastw; + +/* pointer into the history line */ + +EXTERN char *hptr; + +/* the current history line */ + +EXTERN char *hline; + +/* the termcap buffer */ + +EXTERN char termbuf[1024]; + +/* $TERM */ + +EXTERN char *term; + +/* != 0 if this $TERM setup is usable */ + +EXTERN int termok; + +/* flag for CSHNULLGLOB */ + +EXTERN int badcshglob; + +/* max size of hline */ + +EXTERN int hlinesz; + +/* the alias expansion status - if == ALSTAT_MORE, we just finished + expanding an alias ending with a space */ + +EXTERN int alstat; + +/* we have printed a 'you have stopped (running) jobs.' message */ + +EXTERN int stopmsg; + +/* the default tty state */ + +EXTERN struct ttyinfo shttyinfo; + +/* $TTY */ + +EXTERN char *ttystrname; + +/* 1 if ttyctl -f has been executed */ + +EXTERN int ttyfrozen; + +/* list of memory heaps */ + +EXTERN Lklist heaplist; + +/* != 0 if we are allocating in the heaplist */ + +EXTERN int useheap; + +#include "signals.h" + +#ifdef GLOBALS + +/* signal names */ +char **sigptr = sigs; + +/* tokens */ +char *ztokens = "#$^*()$=|{}[]`<>?~`,"; + +#else +extern char *ztokens,**sigptr; +#endif + +#define SIGERR (SIGCOUNT+1) +#define SIGDEBUG (SIGCOUNT+2) +#define VSIGCOUNT (SIGCOUNT+3) +#define SIGEXIT 0 + +/* signals that are trapped = 1, signals ignored =2 */ + +EXTERN int sigtrapped[VSIGCOUNT]; + +/* trap functions for each signal */ + +EXTERN List sigfuncs[VSIGCOUNT]; + +/* $HISTCHARS */ + +EXTERN char bangchar,hatchar,hashchar; + +EXTERN int eofseen; + +/* we are parsing a line sent to use by the editor */ + +EXTERN int zleparse; + +EXTERN int wordbeg; + +EXTERN int parbegin; + +/* 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 TC_COUNT 17 + +/* lengths of each string */ + +EXTERN int tclen[TC_COUNT]; + +EXTERN char *tcstr[TC_COUNT]; + +#ifdef GLOBALS + +/* names of the strings we want */ + +char *tccapnams[TC_COUNT] = { + "cl","le","LE","nd","RI","up","UP","do", + "DO","dc","DC","ic","IC","cd","ce","al","dl" + }; + +#else +extern char *tccapnams[TC_COUNT]; +#endif + +#define tccan(X) (!!tclen[X]) + +#define HISTFLAG_DONE 1 +#define HISTFLAG_NOEXEC 2 +#define HISTFLAG_RECALL 4 + +#include "ztype.h" +#include "funcs.h" + +#ifdef HAS_SETPGID +#define setpgrp setpgid +#endif + +#define _INCLUDE_POSIX_SOURCE +#define _INCLUDE_XOPEN_SOURCE +#define _INCLUDE_HPUX_SOURCE + +#ifdef SV_BSDSIG +#define SV_INTERRUPT SV_BSDSIG +#endif + +#ifdef HAS_SIGRELSE +#define blockchld() sighold(SIGCHLD) +#define unblockchld() sigrelse(SIGCHLD) +#define chldsuspend() sigpause(SIGCHLD) +#else +#define blockchld() sigblock(sigmask(SIGCHLD)) +#define unblockchld() sigsetmask(0) +#define chldsuspend() sigpause(0) +#endif diff --git a/usr/othersrc/public/zsh-2.2/src/ztype.h b/usr/othersrc/public/zsh-2.2/src/ztype.h new file mode 100644 index 0000000000..8acbdc2f09 --- /dev/null +++ b/usr/othersrc/public/zsh-2.2/src/ztype.h @@ -0,0 +1,48 @@ +/* + * + * ztype.h - character classification macros + * + * This file is part of zsh, the Z shell. + * + * This software is Copyright 1992 by Paul Falstad + * + * Permission is hereby granted to copy, reproduce, redistribute or otherwise + * use this software as long as: there is no monetary profit gained + * specifically from the use or reproduction of this software, it is not + * sold, rented, traded or otherwise marketed, and this copyright notice is + * included prominently in any copy made. + * + * The author make no claims as to the fitness or correctness of this software + * for any use whatsoever, and it is provided as is. Any use of this software + * is at the user's own risk. + * + */ + +#define IDIGIT 1 +#define IALNUM 2 +#define IBLANK 4 +#define INBLANK 8 +#define ITOK 16 +#define ISEP 32 +#define IALPHA 64 +#define IIDENT 128 +#define IUSER 256 +#define ICNTRL 512 +#define IWORD 1024 +#define ISPECIAL 2048 +#define _icom(X,Y) (typtab[(int) (unsigned char) (X)] & Y) +#define idigit(X) _icom(X,IDIGIT) +#define ialnum(X) _icom(X,IALNUM) +#define iblank(X) _icom(X,IBLANK) /* blank, not including \n */ +#define inblank(X) _icom(X,INBLANK) /* blank or \n */ +#define itok(X) _icom(X,ITOK) +#define isep(X) _icom(X,ISEP) +#define ialpha(X) _icom(X,IALPHA) +#define iident(X) _icom(X,IIDENT) +#define iuser(X) _icom(X,IUSER) /* username char */ +#define icntrl(X) _icom(X,ICNTRL) +#define iword(X) _icom(X,IWORD) +#define ispecial(X) _icom(X,ISPECIAL) + +EXTERN short int typtab[256]; + -- 2.20.1