pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
-bash(1),
-ksh(1),
-cat(1),
-cd(1),
-chmod(1),
-cut(1),
-echo(1),
-emacs(1),
-env(1),
-gmacs(1),
-newgrp(1),
-stty(1),
-test(1),
-umask(1),
-vi(1),
-dup(2),
-exec(2),
-fork(2),
-ioctl(2),
-lseek(2),
-paste(1),
-pipe(2),
-signal(2),
-umask(2),
-ulimit(2),
-wait(2),
-rand(3),
-a.out(5),
-profile(5),
-environ(7),
-xtetris(6).
-.SH AUTHOR
-Paul Falstad <pfalstad@phoenix.princeton.edu>
-.PP
-The command line editor is a hacked-up version
-of the GNU readline library,
-written by Brian Fox (<bfox@ai.MIT.Edu>) of the Free
-Software Foundation. This shell is therefore
-under the GNU public license. I eventually plan
-to write my own command line editor to make everything
-my own code, but \fBzsh\fP will probably still be under
-the GPL, or perhaps something less restrictive.
-.SH CAVEATS
-.PP
-Using
-.B fc
-built-in command within a compound command will cause the whole
-command to disappear from the history file.
-.PP
-Shell functions are put in the function table when their declarations
-are parsed, not when they are executed. Thus function declarations
-inside \fBif\fP clauses, for example, will not work as expected.
-(This is a bug, not a caveat.)
-.PP
-The command line editor gets confused if you have termcap sequences
-(like %S) in your prompt.
-.PP
-The main shell does not get along with the command line editor.
-One of them will have to go.
-.PP
-Use of this shell is reserved for faculty, staff,
-graduate students,
-and special guests
-of the Princeton University
-Computer Science department.
End of zsh.1
echo COPYING 1>&2
sed 's/^-//' >COPYING <<'End of COPYING'
-
- GNU GENERAL PUBLIC LICENSE
- Version 1, February 1989
-
- Copyright (C) 1989 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The license agreements of most software companies try to keep users
-at the mercy of those companies. By contrast, our General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. The
-General Public License applies to the Free Software Foundation's
-software and to any other program whose authors commit to using it.
-You can use it for your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Specifically, the General Public License is designed to make
-sure that you have the freedom to give away or sell copies of free
-software, that you receive source code or can get it if you want it,
-that you can change the software or use pieces of it in new free
-programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of a such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must tell them their rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any program or other work which
-contains a notice placed by the copyright holder saying it may be
-distributed under the terms of this General Public License. The
-"Program", below, refers to any such program or work, and a "work based
-on the Program" means either the Program or any work containing the
-Program or a portion of it, either verbatim or with modifications. Each
-licensee is addressed as "you".
-
- 1. You may copy and distribute verbatim copies of the Program's source
-code as you receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice and
-disclaimer of warranty; keep intact all the notices that refer to this
-General Public License and to the absence of any warranty; and give any
-other recipients of the Program a copy of this General Public License
-along with the Program. You may charge a fee for the physical act of
-transferring a copy.
-
- 2. You may modify your copy or copies of the Program or any portion of
-it, and copy and distribute such modifications under the terms of Paragraph
-1 above, provided that you also do the following:
-
- a) cause the modified files to carry prominent notices stating that
- you changed the files and the date of any change; and
-
- b) cause the whole of any work that you distribute or publish, that
- in whole or in part contains the Program or any part thereof, either
- with or without modifications, to be licensed at no charge to all
- third parties under the terms of this General Public License (except
- that you may choose to grant warranty protection to some or all
- third parties, at your option).
-
- c) If the modified program normally reads commands interactively when
- run, you must cause it, when started running for such interactive use
- in the simplest and most usual way, to print or display an
- announcement including an appropriate copyright notice and a notice
- that there is no warranty (or else, saying that you provide a
- warranty) and that users may redistribute the program under these
- conditions, and telling the user how to view a copy of this General
- Public License.
-
- d) You may charge a fee for the physical act of transferring a
- copy, and you may at your option offer warranty protection in
- exchange for a fee.
-
-Mere aggregation of another independent work with the Program (or its
-derivative) on a volume of a storage or distribution medium does not bring
-the other work under the scope of these terms.
-
- 3. You may copy and distribute the Program (or a portion or derivative of
-it, under Paragraph 2) in object code or executable form under the terms of
-Paragraphs 1 and 2 above provided that you also do one of the following:
-
- a) accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- b) accompany it with a written offer, valid for at least three
- years, to give any third party free (except for a nominal charge
- for the cost of distribution) a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- c) accompany it with the information you received as to where the
- corresponding source code may be obtained. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form alone.)
-
-Source code for a work means the preferred form of the work for making
-modifications to it. For an executable file, complete source code means
-all the source code for all modules it contains; but, as a special
-exception, it need not include source code for modules which are standard
-libraries that accompany the operating system on which the executable
-file runs, or for standard header files or definitions files that
-accompany that operating system.
-
- 4. You may not copy, modify, sublicense, distribute or transfer the
-Program except as expressly provided under this General Public License.
-Any attempt otherwise to copy, modify, sublicense, distribute or transfer
-the Program is void, and will automatically terminate your rights to use
-the Program under this License. However, parties who have received
-copies, or rights to use copies, from you under this General Public
-License will not have their licenses terminated so long as such parties
-remain in full compliance.
-
- 5. By copying, distributing or modifying the Program (or any work based
-on the Program) you indicate your acceptance of this license to do so,
-and all its terms and conditions.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the original
-licensor to copy, distribute or modify the Program subject to these
-terms and conditions. You may not impose any further restrictions on the
-recipients' exercise of the rights granted herein.
-
- 7. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of the license which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-the license, you may choose any version ever published by the Free Software
-Foundation.
-
- 8. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to humanity, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
- To do so, attach the following notices to the program. It is safest to
-attach them to the start of each source file to most effectively convey
-the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19xx name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the
-appropriate parts of the General Public License. Of course, the
-commands you use may be called something other than `show w' and `show
-c'; they could even be mouse-clicks or menu items--whatever suits your
-program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- program `Gnomovision' (a program to direct compilers to make passes
- at assemblers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-That's all there is to it!
End of COPYING
echo README 1>&2
sed 's/^-//' >README <<'End of README'
-Read "INSTALL" for information on getting this shell running.
-
-zsh is free software. See the file COPYING for copying permission.
-
- This shell was "developed" by me, Paul Falstad, a sophomore at Princeton
-University. I borrowed _heavily_ from ksh, bash, tcsh, sh, and csh, as
-well as adding a few (IMHO) useful features. zsh was at first intended
-to be a subset of csh for the Commodore Amiga, but the project sort of
-ballooned; now I want it to be a cross between ksh and tcsh. It should
-be a powerful "command and programming language" that is well-designed
-and logical (like ksh), but it should also be built for humans (like
-tcsh), with all the neat features like spell checking, login/logout
-watching and termcap support that are probably too weird to make it into
-an AT&T product. This version of the shell has fallen far short of that
-goal; I just wanted to release _something_, because this is obviously
-going to be an extremely long project.
-
- This is version v1.0 of zsh. I incorporated the GNU "readline"
-editor, written by Brian Fox, into the shell, just to make my life
-temporarily easier. I made lots of changes to it, so if there are any
-bugs in the editor, they're probably my fault. readline will not be a
-part of the next version of zsh.
-
- If anyone has any questions, suggestions, comments, bugs, flames, or
-any other mail of any kind, send it to pfalstad@phoenix.princeton.edu.
-Thanks to Kartik Subbarao, Daniel Bernstein ("Yay. So sell it."),
-Kennedy Lemke, Chet Ramey (for the bash man page, and for putting features
-in the man page that weren't in our version of bash), Brian Fox (for
-helping me put off a lot of work, and for writing bash), Richard M. Stallman
-(for gdb and gcc; not for emacs though ;-) ) and many others.
-
End of README
echo INSTALL 1>&2
sed 's/^-//' >INSTALL <<'End of INSTALL'
-I was not able to port zsh to many platforms because I don't have
-accounts on many platforms. It shouldn't be too much trouble if you
-manage to decipher my code. I have tested zsh on SunOS 4.1, SunOS 4.0.3,
-4.3BSD UNIX.
-
-You need to edit the files config.h, config.local.h, makefile, and
-readline/Makefile. The comments should make clear what you have to do.
-Note that the files in the readline directory have been greatly
-modified, so you can't just copy over your changes from bash if you
-have it installed.
-
-Once you have done that, you might be able to do a make without any
-problem. If you have trouble, and can't get zsh to work, send me mail,
-and I'll try to help. If anyone manages to get zsh ported to some other
-platform, please mail me so I can tell other people about your changes
-and incorporate them into the next version.
-
End of INSTALL
echo makefile 1>&2
sed 's/^-//' >makefile <<'End of makefile'
-#! /bin/make -f
-#
-# makefile for zsh
-#
-# This file is part of zsh, the Z shell.
-#
-# zsh is free software; no one can prevent you from reading the source
-# code, or giving it to someone else.
-# This file is copyrighted under the GNU General Public License, which
-# can be found in the file called COPYING.
-#
-# Copyright (C) 1990 Paul Falstad
-#
-# zsh is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY. No author or distributor accepts
-# responsibility to anyone for the consequences of using it or for
-# whether it serves any particular purpose or works at all, unless he
-# says so in writing. Refer to the GNU General Public License
-# for full details.
-#
-# Everyone is granted permission to copy, modify and redistribute
-# zsh, but only under the conditions described in the GNU General Public
-# License. A copy of this license is supposed to have been given to you
-# along with zsh so you can know your rights and responsibilities.
-# It should be in a file named COPYING.
-#
-# Among other things, the copyright notice and this notice must be
-# preserved on all copies.
-#
-OBJS=hist.o glob.o table.o subst.o builtin.o loop.o vars.o\
-parse.o lex.o init.o jobs.o exec.o zhistory.o utils.o math.o test.o
-READLINE=readline/funmap.o readline/keymaps.o readline/readline.o
-BINDIR=/usr/local/bin
-MANDIR=/usr/local/man/man1
-CFLAGS=-O -fstrength-reduce -fomit-frame-pointer -finline-functions \
- -fsigned-char -fdelayed-branch
-CC=gcc
-ZSHPATH=zsh
-THINGS_TO_TAR=zsh.1 COPYING README INSTALL makefile sample.zshrc \
-sample.zlogin sample.zshrc.mine sample.zlogin.mine \
-alias.pro builtin.c builtin.pro config.h config.local.h \
-exec.c exec.pro funcs.h glob.c glob.pro hist.c hist.pro init.c \
-init.pro jobs.c jobs.pro lex.c lex.pro loop.c loop.pro math.c \
-math.pro parse.c parse.pro subst.c subst.pro table.c \
-table.pro test.c test.pro utils.c utils.pro vars.c vars.pro zhistory.c \
-readline/chardefs.h readline/emacs_keymap.c \
-readline/funmap.c readline/history.h readline/keymaps.c \
-readline/keymaps.h readline/readline.c readline/readline.h \
-readline/vi_keymap.c readline/vi_mode.c readline/Makefile \
-zsh.h proto
-
-.c.o:
- $(CC) $(CFLAGS) -c -o $*.o $<
-
-$(ZSHPATH): $(OBJS) $(READLINE)
- $(CC) -o $(ZSHPATH) $(OBJS) $(READLINE) -s -ltermcap
-
-$(OBJS): config.h
-
-zhistory.o: readline/history.h
-
-$(READLINE):
- cd readline;make
-
-clean:
- rm -f *.o zsh core readline/*.o
-
-install: zsh
- install -s -m 755 zsh $(BINDIR)
- install -m 444 zsh.1 $(MANDIR)
-
-tar: zsh.tar.Z
-
-zsh.tar: $(THINGS_TO_TAR)
- tar -cf zsh.tar $(THINGS_TO_TAR)
-
-zsh.tar.Z: zsh.tar
- compress -f zsh.tar
-
-shar: $(THINGS_TO_TAR)
- bundle $(THINGS_TO_TAR) > zsh.shar
-
End of makefile
echo sample.zshrc 1>&2
sed 's/^-//' >sample.zshrc <<'End of sample.zshrc'
-setenv() { export $1=$2 }
-
-umask 022
-
-PATH=$HOME/scr:$HOME/bin/$HOSTTYPE:/usr/local/bin:/usr/ucb:\
-/usr/bin:/bin:/usr/local/bin/X11:/usr/etc:/etc
-CDPATH=$HOME:/usr:/
-export MANPATH=/usr/man:/usr/local/man
-
-HISTSIZE=50
-setopt ignoreeof
-
-PROMPT='%n@%m [%h] %# '
-
-alias a alias
-
-a vi. 'vi ~/.cshrc'
-a s. '. ~/.cshrc'
-a more. 'more ~/.cshrc'
-
-chpwd() { pwd; ls -F }
-lsl() { ls -algF $* | more }
-
-a back cd -
-a h history
-a cls /usr/ucb/clear
-a type cat
-a copy cp
-a move mv
-a del rm
-a lo exit
-a lsa 'ls -aF'
-a dir 'ls -l'
-a ll 'ls -F'
-
End of sample.zshrc
echo sample.zlogin 1>&2
sed 's/^-//' >sample.zlogin <<'End of sample.zlogin'
-eval $(tset -Q -s '?xterm')
-stty dec crt kill ^U dsusp ^X
-msgs -q
-date
-biff y
-
-WATCH=$(echo $(<~/.friends) | tr ' ' :)
-MAIL=/usr/spool/mail/$USERNAME
-export DISPLAY=$(hostname):0.0
-
-limit coredumpsize 0
-/usr/games/fortune
-uptime
End of sample.zlogin
echo sample.zshrc.mine 1>&2
sed 's/^-//' >sample.zshrc.mine <<'End of sample.zshrc.mine'
-#
-# my rc file for zsh
-#
-PATH=~/scr:~/bin/$HOSTTYPE:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:\
-/u/maruchck/scr:/u/cs320/bin:/u/maruchck/bin:\
-/usr/princeton/bin/X11:/usr/etc:/etc
-CDPATH=~:~/src/cs320:~/src
-umask 022
-alias a alias
-a pd pushd
-a pop popd
-limit core 0
-a c cp
-a grep egrep
-a ps sps
-a j jobs
-a hide 'ARGV0=$(randline ~/pub/strings) '
-a rn hide /usr/princeton/bin/rn.4.1
-a v mv
-a t cat
-a where hostname'; echo >/dev/null'
-a l ls -AF
-a m make
-a mm hide less
-a talk hide talk
-a h history
-a a.out ./a.out
-a more less
-a strings strings -
-a lock lock -p
-a nw 'l -ltr | tail'
-a -a 'M' \| less
-a -a 'GF' \| fgrep -f ~/.friends
-a -a 'sub' subbarao
-a -a 'mjm' maruchck
-a -a 'paswd' '<(ypcat passwd)'
-a -a 'cex' '/u/pup/centrex'
-a rable ls -AFltrd '*(R)'
-a nrable ls -AFltrd '*(^R)'
-a ';' vi
-a 0 vi
-a '<<' more
-mostglob egrep sed
-noglob find
-PROMPT='Z %h %M:%~ '
-FCEDIT=vi
-LESSTERM=$(echo $TERMCAP | sed s/:ti=[^:]*:te=[^:]*:/:ti=:te=:/)
-a less TERMCAP='"$LESSTERM"' /usr/princeton/bin/less
-zsh=~/src/zsh
-a k9 kill -9
-cx() { chmod +x $* }
-acx() { chmod 755 $* }
-mere() { nroff -man -Tman $1 | less -s }
-
-[ `tty` = /dev/console ] || {
- PERIOD=40
- periodic() {
- echo checking news... # check news every 40 minutes
- rn -c
- }
-}
-
-randline() {
- integer z;
- z=$(wc -l <$1)
- sed -n $[RANDOM%z+1]p $1
- unset z
-}
-
-eval "proto () { $(grep -v '^#' ~/scr/proto) }"
-
-snoop() {
- (( $# )) || set `users`
- fgrep -i -f </u/pup/st{udents,aff} <(
- for i
- do
- ypmatch $i passwd
- done | cut -d: -f5 | cut -d, -f1 |
- awk '{ printf "%s,%s\n",$NF,substr($1,1,1) }')
-}
-
-MAIL=/usr/spool/mail/pfalstad
-MAILCHECK=30
-HISTSIZE=600
-setopt notify globdots autolist correct dextract pushdtohome cdablevars
-unsetopt bgnice
-WATCH=$(echo $(<~/.friends) | tr ' ' :)
-WATCHFMT='%n %a %l from %m at %t.'
-LOGCHECK=0
-
-[ -t ] && {
- (cd ; hostname >! .where)
-}
-
-export MANPATH=/usr/man:/usr/princeton/man:/u/cad/man
-
-setenv() { export $1=$2 }
-
End of sample.zshrc.mine
echo sample.zlogin.mine 1>&2
sed 's/^-//' >sample.zlogin.mine <<'End of sample.zlogin.mine'
-#
-# my login file for zsh
-#
-cd
-ls -l /etc/motd
-stty dec new cr0
-eval $(tset -s -Q '?xterm')
-stty -tabs
-umask 022
-export MAIL=/usr/spool/mail/$USER
-MAILCHECK=60
-# biff y
-msgs -fp
-uptime
-/usr/games/fortune
-log
-echo Thought for the day: $(randline ~/pub/commands)
-from 2>/dev/null
-cat .todo
-cat '. '
-echo last login $(date) on $(hostname) >! .' '
End of sample.zlogin.mine
echo alias.pro 1>&2
sed 's/^-//' >alias.pro <<'End of alias.pro'
-char *dynread(char stop);
-int filesub(void **namptr);
-char *gethome(char *user,int len);
-char *completehome(char *user,int len);
-char *getsparmval(char *s,int len);
-void setparml(char *s,int len,char *v);
-void parmsub(table list);
-void parminsall(table l,Node *nn,char **aptr,char **bptr);
-void comminsall(table l,Node *nn,char **aptr,char **bptr);
-void parmsuber(void **aptr,char **bptr);
-void modify(void **str,char **ptr);
-void tabmodify(table tab,char **ptr);
-int napply(int (*func)(void **),table list);
-int napplysplit(int (*func)(void **),table list);
-void split(Node node,table list);
-char *dstackent(int val);
-void doshfuncs(comm comm);
-void execshfunc(comm comm);
-struct anode *mkanode(char *txt,int cmflag);
-char *docompsubs(char *str,int *i);
-void docmdsubs(char **str);
-void dovarsubs(char **str);
End of alias.pro
echo builtin.c 1>&2
sed 's/^-//' >builtin.c <<'End of builtin.c'
-/*
-
- builtin.c - handles builtin commands
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <sys/signal.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
-#include <utmp.h>
-#define MAXPATHLEN 1024
-
-int echo(comm comm)
-{
-table list;
-char *str;
-int nline = 1;
-
- list = comm->args;
- if (full(list))
- if (!strcmp("--",list->first->dat))
- free(getnode(list));
- else if (!strcmp("-n",list->first->dat))
- {
- free(getnode(list));
- nline = 0;
- }
- if (str = getnode(list))
- {
- printf("%s",str);
- free(str);
- while (str = getnode(list))
- {
- printf(" %s",str);
- free(str);
- }
- }
- if (nline)
- printf("\n");
- return 0;
-}
-
-/* print the directory stack */
-
-void pdstack(void)
-{
-Node node;
-
- printdir(cwd);
- for (node = dirstack->first; node; node = node->next)
- {
- putchar(' ');
- printdir(node->dat);
- }
- putchar('\n');
-}
-
-/* exit */
-
-int zexit(comm comm)
-{
- if (interact)
- if (!stopmsg)
- {
- checkjobs();
- if (stopmsg)
- {
- stopmsg = 2;
- return 1;
- }
- }
- else
- killrunjobs();
- if (islogin && unset(NORCS))
- sourcehome(".zlogout");
- if (comm && full(comm->args))
- lastval = atoi(getnode(comm->args));
- if (sigtrapped[SIGEXIT])
- dotrap(SIGEXIT);
- exit(lastval); return 0;
-}
-
-/* return */
-
-int zreturn(comm comm)
-{
- if (full(comm->args))
- lastval = atoi(getnode(comm->args));
- retflag = 1;
- return lastval;
-}
-
-int logout(comm comm)
-{
- if (!islogin)
- {
- zerrnam("logout","not login shell");
- return 1;
- }
- return zexit(comm);
-}
-
-int Unset(comm comm)
-{
-table list = comm->args;
-char *s;
-
- while (full(list))
- {
- s = getnode(list);
- unsetparm(s);
- free(s);
- }
- return 0;
-}
-
-int set(comm comm)
-{
-char *s,*t;
-
- if (!full(comm->args))
- {
- char **p = environ;
-
- while (*p)
- puts(*p++);
- listhtable(parmhtab,(void (*)(char *,char *)) pparm);
- return 0;
- }
- s = getnode(comm->args);
- t = getnode(pparms);
- freetable(pparms,freestr);
- pparms = newtable();
- addnode(pparms,t);
- while (s)
- {
- addnode(pparms,s);
- s = getnode(comm->args);
- }
- return 0;
-}
-
-struct option {
- char *name;
- char id;
- };
-
-static struct option optns[] = {
- "clobber",'1',
- "nobadpattern",'2',
- "nonomatch",'3',
- "globdots",'4',
- "notify",'5',
- "allexport",'a',
- "errexit",'e',
- "bgnice",'6',
- "ignoreeof",'7',
- "keyword",'k',
- "markdirs",'8',
- "monitor",'m',
- "noexec",'n',
- "noglob",'F',
- "norcs",'f',
- "shinstdin",'s',
- "nounset",'u',
- "verbose",'v',
- "xtrace",'x',
- "interactive",'i',
- "autolist",'9',
- "correct",'0',
- "dextract",'A',
- "nobeep",'B',
- "printexitvalue",'C',
- "pushdtohome",'D',
- "pushdsilent",'E',
- "nullglob",'G',
- "rmstarsilent",'H',
- "ignorebraces",'I',
- "cdablevars",'J',
- "nobanghist",'K',
- NULL,0
-};
-
-int setopt(comm comm)
-{
- return csetopt(comm,0);
-}
-
-int unsetopt(comm comm)
-{
- return csetopt(comm,1);
-}
-
-/* common code for setopt and unsetopt */
-
-int csetopt(comm comm,int isun)
-{
-char *s,*os,*cmd;
-int flag;
-struct option *opp;
-
- cmd = (isun) ? "unsetopt" : "setopt";
- if (!full(comm->args))
- {
- if (isun)
- return 0;
- for (opp = optns; opp->name; opp++)
- if (opts[opp->id] == OPT_SET)
- puts(opp->name);
- return 0;
- }
- while ((os = s = getnode(comm->args)) && ((flag = *s == '-') || *s == '+'))
- {
- while (*++s)
- if (*s == INTERACTIVE || *s == MONITOR)
- zerrnam(cmd,"can't change that option");
- else if (opts[*s & 0x7f] != OPT_INVALID)
- opts[*s & 0x7f] = (flag^isun) ? OPT_SET : OPT_UNSET;
- else
- zerrnam(cmd,"illegal option: %c",*s);
- free(os);
- }
- if (!s)
- return 0;
- while (s)
- {
- for (opp = optns; opp->name; opp++)
- if (!strcmp(opp->name,s))
- break;
- if (opp->name)
- {
- if (opp->id == INTERACTIVE || opp->id == MONITOR)
- zerrnam(cmd,"can't change that option");
- else
- opts[opp->id] = (isun) ? OPT_UNSET : OPT_SET;
- }
- else
- {
- zerrnam(cmd,"no such option: %s",s);
- free(s);
- return 1;
- }
- free(s);
- s = getnode(comm->args);
- }
- return 0;
-}
-
-/* print a positional parameter */
-
-void pparm(char *s,struct pmnode *t)
-{
- if (s && t)
- if (t->isint)
- printf("%s=%ld\n",s,t->u.val);
- else
- {
- printf("%s=",s);
- niceprint(t->u.str);
- putchar('\n');
- }
-}
-
-int dirs(comm comm)
-{
- if (comm->args->first)
- {
- if (dirstack)
- freetable(dirstack,freestr);
- dirstack = comm->args;
- comm->args = NULL;
- }
- else
- pdstack();
- return 0;
-}
-
-/* call func once for each entry in a hash table */
-
-void listhtable(htable ht,void (*func)(char *,char *))
-{
-int t0;
-struct hnode *hn;
-
- for (t0 = ht->hsize-1; t0 >= 0; t0--)
- for (hn = ht->nodes[t0]; hn; hn = hn->hchain)
- func(hn->nam,hn->dat);
-}
-
-/* print an alias (used with listhtable) */
-
-void palias(char *s,struct anode *t)
-{
- if (t && t->cmd >= 0)
- {
- printf((t->cmd) ? "alias %-13s " : "alias -a %-10s ",s);
- niceprint(t->text);
- putchar('\n');
- }
-}
-
-/* print a shell function (used with listhtable) */
-
-void pshfunc(char *s,list l)
-{
-char *t;
-
- t = getltext(l);
- untokenize(t);
- printf("%s() {\n%s\n}\n",s,t);
- free(t);
-}
-
-void niceprint(char *s)
-{
- niceprintf(s,stdout);
-}
-
-void niceprintf(char *s,FILE *f)
-{
- for (; *s; s++)
- {
- if (*s >= 32 && *s <= 126)
- fputc(*s,f);
- else if (*s == '\n')
- {
- putc('\\',f);
- putc('n',f);
- }
- else
- {
- putc('^',f);
- fputc(*s | 0x40,f);
- }
- }
-}
-
-/* build a command line from a linked list */
-
-char *buildline(table t)
-{
-char *str = strdup(""),*s,*os;
-
- while (s = getnode(t))
- {
- os = str;
- str = (*os) ? tricat(os," ",s) : strdup(s);
- free(s);
- free(os);
- }
- return str;
-}
-
-int Alias(comm comm)
-{
-char *s1,*s2;
-int anyflag = 0;
-
- if (!(s1 = getnode(comm->args)))
- {
- listhtable(alhtab,(void (*)(char *,char *)) palias);
- return 0;
- }
- if (!strcmp(s1,"-a"))
- {
- anyflag = 1;
- free(s1);
- if (!(s1 = getnode(comm->args)))
- {
- zerrnam("alias","alias -a requires 2 arguments");
- return 1;
- }
- }
- if (!comm->args->first)
- {
- palias(s1,gethnode(s1,alhtab));
- free(s1);
- return 0;
- }
- s2 = buildline(comm->args);
- addhnode(s1,mkanode(s2,!anyflag),alhtab,freeanode);
- return 0;
-}
-
-int cd(comm comm)
-{
- if (!full(comm->args))
- return chcd("cd",strdup(getparm("HOME")));
- if (comm->args->first->next)
- {
- char *s,*t,*u,*v;
- int sl,tl;
-
- if (comm->args->first->next->next)
- {
- zerrnam("cd","too many arguments");
- return 1;
- }
- s = getnode(comm->args);
- t = getnode(comm->args);
- if (!(u = (char *) strstr(cwd,s)))
- {
- zerrnam("cd","string not in pwd: %s",s);
- return 1;
- }
- sl = strlen(s);
- tl = strlen(t);
- v = zalloc((u-cwd)+tl+strlen(u+sl)+1);
- strncpy(v,cwd,u-cwd);
- strcpy(v+(u-cwd),t);
- strcat(v,u+sl);
- free(s);
- free(t);
- return chcd("cd",v);
- }
- return chcd("cd",getnode(comm->args));
-}
-
-int dot(comm comm)
-{
-char *s;
-
- if (!full(comm->args))
- return 1;
- s = getnode(comm->args);
- if (source(s))
- {
- zerrnam(".","%e: %s",errno,s);
- free(s);
- return 1;
- }
- free(s);
- return 0;
-}
-
-int Umask(comm comm)
-{
-char *s,*t;
-int t0;
-
- if (!full(comm->args))
- {
- t0 = umask(0);
- umask(t0);
- printf("%03o\n",t0);
- return 0;
- }
- s = getnode(comm->args);
- t0 = strtol(s,&t,8);
- if (*t)
- {
- zerrnam("umask","bad umask");
- free(s);
- return 1;
- }
- umask(t0);
- free(s);
- return 0;
-}
-
-int which(comm comm)
-{
-struct chnode *chn;
-struct anode *a;
-char *str = getnode(comm->args),*cnam;
-
- if (!str)
- {
- zerrnam("which","argument required");
- return 1;
- }
- if ((a = gethnode(str,alhtab)) && a->cmd)
- {
- if (a->cmd < 0)
- printf("%s: shell reserved word\n",str);
- else
- printf("%s: aliased to %s\n",str,a->text);
- free(str);
- return 0;
- }
- if (gethnode(str,shfunchtab))
- printf("%s: shell function\n",str);
- else if (chn = gethnode(str,chtab))
- {
- if (chn->type != BUILTIN)
- puts(chn->u.nam);
- else
- printf("%s: shell built-in command\n",str);
- }
- else if (!(cnam = findcmd(str)))
- {
- zerr("command not found: %s",str);
- free(str);
- return 1;
- }
- else
- puts(cnam);
- free(str);
- return 0;
-}
-
-int popd(comm comm)
-{
-int val = 0;
-char *s;
-Node node;
-
- if (comm->args->first && *(s = comm->args->first->dat) == '+')
- val = atoi(s+1);
- if (val--)
- {
- if (val < 0)
- node = dirstack->last;
- else
- for (node = dirstack->first; val && node; node = node->next,
- val--);
- free(remnode(dirstack,node));
- if (unset(PUSHDSILENT))
- pdstack();
- return 0;
- }
- else
- {
- if (!full(dirstack))
- {
- zerrnam("popd","dir stack empty");
- return 1;
- }
- val = chcd("popd",getnode(dirstack));
- if (unset(PUSHDSILENT))
- pdstack();
- return val;
- }
-}
-
-int pushd(comm comm)
-{
-char *s;
-int num;
-
- if (comm->args->first)
- {
- s = getnode(comm->args);
-
- if (*s == '+')
- {
- if (!(num = atoi(s+1)))
- {
- free(s);
- return 0;
- }
- free(s);
- if (isset(DEXTRACT))
- {
- Node n = dirstack->first;
-
- insnode(dirstack,(Node) dirstack,strdup(cwd));
- while (--num && n)
- n = n->next;
- if (!n)
- {
- zerrnam("pushd","not that many dir stack entries");
- return 1;
- }
- insnode(dirstack,(Node) dirstack,remnode(dirstack,n));
- }
- else
- {
- addnode(dirstack,strdup(cwd));
- while(--num)
- addnode(dirstack,getnode(dirstack));
- }
- num = chcd("pushd",getnode(dirstack));
- if (unset(PUSHDSILENT))
- pdstack();
- return num;
- }
- pushnode(dirstack,strdup(cwd));
- num = chcd("pushd",s);
- if (num)
- free(getnode(dirstack));
- else if (unset(PUSHDSILENT))
- pdstack();
- return num;
- }
- else
- {
- char *s;
-
- if (isset(PUSHDTOHOME))
- s = strdup(getparm("HOME"));
- else
- s = getnode(dirstack);
- if (!s)
- {
- zerrnam("pushd","dir stack empty");
- return 1;
- }
- pushnode(dirstack,strdup(cwd));
- num = chcd("pushd",s);
- if (num)
- free(getnode(dirstack));
- else if (unset(PUSHDSILENT))
- pdstack();
- return num;
- }
-}
-
-/* common code for pushd, popd, cd */
-
-int chcd(char *cnam,char *cd)
-{
-char *s,*t;
-char buf[MAXPATHLEN],*new = cd;
-int t0,val,esav,pnew = 0;
-
- if (cd[0] == '-' && !cd[1])
- {
- free(cd);
- cd = getparm("OLDPWD");
- cd = strdup((cd) ? cd : ".");
- }
- if (*cd == '/')
- {
- val = chdir(new = cd);
- esav = errno;
- }
- else
- for (t0 = 0; t0 != cdpathct; t0++)
- {
- sprintf(buf,"%s/%s",cdpath[t0],cd);
- if ((val = chdir(new = buf)) != -1)
- {
- if (t0)
- pnew = 1;
- break;
- }
- if (t0 && errno != ENOENT && errno != ENOTDIR)
- zerrnam(cnam,"warning: %e: %s",errno,buf);
- if (!t0)
- esav = errno;
- }
- if (val == -1 && errno == ENOENT)
- {
- t = strdup(cd);
- if (isset(CDABLEVARS) && (s = getparm(t)) && *s == '/')
- if (chdir(new = s) != -1)
- {
- val = 0;
- pnew = 1;
- goto goneto;
- }
- free(t);
- zerrnam(cnam,"%e: %s",esav,cd);
- free(cd);
- return 1;
- }
-goneto:
- if (val == -1)
- {
- zerrnam(cnam,"%e: %s",esav,cd);
- free(cd);
- return 1;
- }
- else
- {
- list l;
-
- if (cwd)
- setparm(strdup("OLDPWD"),cwd,0,0);
- cwd = findcwd(new);
- setparm(strdup("PWD"),strdup(cwd),0,0);
- if (pnew)
- {
- printdir(cwd);
- putchar('\n');
- }
- if (l = gethnode("chpwd",shfunchtab))
- newrunlist(l);
- }
- return 0;
-}
-
-int shift(comm comm)
-{
-char *s;
-int sh = 1;
-
- if (comm->args->first && (s = comm->args->first->dat))
- sh = atoi(s);
- while (sh-- && pparms->first->next)
- remnode(pparms,pparms->first->next);
- return 0;
-}
-
-int unhash(comm comm)
-{
-char *s;
-
- if (!(s = getnode(comm->args)))
- {
- zerrnam("unhash","argument required");
- return 1;
- }
- while (s)
- {
- if (!gethnode(s,chtab))
- {
- zerrnam("unhash","not in command table: %s",s);
- return 1;
- }
- free(remhnode(s,chtab));
- free(s);
- s = getnode(comm->args);
- }
- return 0;
-}
-
-int rehash(comm comm)
-{
- parsepath();
- return 0;
-}
-
-int hash(comm comm)
-{
-char *s,*t;
-struct chnode *chn;
-
- if (!(s = getnode(comm->args)) || !(t = getnode(comm->args)))
- {
- zerrnam("hash","not enough arguments");
- if (s)
- free(s);
- return 1;
- }
- chn = alloc(sizeof(struct chnode));
- chn->type = EXCMD_PREDOT;
- chn->globstat = GLOB;
- chn->u.nam = t;
- addhnode(s,chn,chtab,freechnode);
- return 0;
-}
-
-int Break(comm comm)
-{
-char *s;
-
- if (!loops)
- {
- zerrnam("break","not in loop");
- return 1;
- }
- if (!(s = getnode(comm->args)))
- breaks = 1;
- else if (atoi(s))
- {
- breaks = atoi(s);
- free(s);
- }
- else
- {
- zerrnam("break","numeric argument required");
- free(s);
- return 1;
- }
- return 0;
-}
-
-int colon(comm comm)
-{
- return 0;
-}
-
-int Glob(comm comm)
-{
-struct chnode *chn;
-char *s;
-
- while (s = getnode(comm->args))
- {
- chn = gethnode(s,chtab);
- free(s);
- if (chn)
- chn->globstat = GLOB;
- }
- return 0;
-}
-
-int noglob(comm comm)
-{
-struct chnode *chn;
-char *s;
-
- while (s = getnode(comm->args))
- {
- chn = gethnode(s,chtab);
- free(s);
- if (chn)
- chn->globstat = NOGLOB;
- }
- return 0;
-}
-
-int mostglob(comm comm)
-{
-struct chnode *chn;
-char *s;
-
- while (s = getnode(comm->args))
- {
- chn = gethnode(s,chtab);
- free(s);
- if (chn)
- chn->globstat = MOSTGLOB;
- }
- return 0;
-}
-
-int unfunction(comm comm)
-{
-char *s1;
-list l;
-
- while (s1 = getnode(comm->args))
- {
- unsettrap(s1);
- if (l = remhnode(s1,shfunchtab))
- freelist(l);
- free(s1);
- }
- return 0;
-}
-
-int unalias(comm comm)
-{
-char *s1;
-struct anode *an;
-
- while (s1 = getnode(comm->args))
- {
- if (an = remhnode(s1,alhtab))
- freeanode(an);
- free(s1);
- }
- return 0;
-}
-
-/* != 0 if s is a prefix of t */
-
-int prefix(char *s,char *t)
-{
- while (*s && *t && *s == *t) s++,t++;
- return (!*s);
-}
-
-/* convert %%, %1, %foo, %?bar? to a job number */
-
-int getjob(char *s,char *prog)
-{
-int t0,retval;
-char *os = s;
-
- if (*s++ != '%')
- {
- zerrnam(prog,"bad job specifier");
- retval = -1; goto done;
- }
- if (*s == '%' || *s == '+' || !*s)
- {
- if (topjob == -1)
- {
- zerrnam(prog,"no current job");
- retval = -1; goto done;
- }
- retval = topjob; goto done;
- }
- if (*s == '-')
- {
- if (prevjob == -1)
- {
- zerrnam(prog,"no previous job");
- retval = -1; goto done;
- }
- retval = prevjob; goto done;
- }
- if (isdigit(*s))
- {
- t0 = atoi(s);
- if (t0 && t0 < MAXJOB && jobtab[t0].stat && t0 != curjob)
- { retval = t0; goto done; }
- zerrnam(prog,"no such job");
- retval = -1; goto done;
- }
- if (*s == '?')
- {
- struct procnode *pn;
-
- for (t0 = 0; t0 != MAXJOB; t0++)
- if (jobtab[t0].stat && t0 != curjob)
- for (pn = jobtab[t0].procs; pn; pn = pn->next)
- if (strstr(pn->text,s+1))
- { retval = t0; goto done; }
- zerrnam(prog,"job not found: %s",s);
- retval = -1; goto done;
- }
- for (t0 = 0; t0 != MAXJOB; t0++)
- if (jobtab[t0].stat && jobtab[t0].procs && t0 != curjob &&
- prefix(s,jobtab[t0].procs->text))
- { retval = t0; goto done; }
- zerrnam(prog,"job not found: %s",s);
- retval = -1;
-done:
- free(os);
- return retval;
-}
-
-int fg(comm comm)
-{
-char *s1;
-int ocj = curjob,job;
-
- scanjobs();
- if (!jobbing)
- {
- zerr("no job control in this shell.");
- return 1;
- }
- if (s1 = getnode(comm->args))
- job = getjob(s1,"fg");
- else
- {
- if (topjob == -1 || topjob == curjob)
- {
- zerrnam("fg","no current job");
- return 1;
- }
- job = topjob;
- }
- if (job == -1)
- return 1;
- makerunning(jobtab+job);
- if (topjob == job)
- {
- topjob = prevjob;
- prevjob = job;
- }
- if (prevjob == job)
- setprevjob();
- printjob(jobtab+job,-1);
- curjob = job;
- if (strcmp(jobtab[job].cwd,cwd))
- {
- printf("(pwd: ");
- printdir(jobtab[job].cwd);
- printf(")\n");
- }
- settyinfo(&jobtab[job].ttyinfo);
- attachtty(jobtab[job].gleader);
- killpg(jobtab[job].gleader,SIGCONT);
- waitjobs();
- curjob = ocj;
- return 0;
-}
-
-int bg(comm comm)
-{
-char *s1;
-int job,stopped;
-
- scanjobs();
- if (!jobbing)
- {
- zerr("no job control in this shell.");
- return 1;
- }
- if (s1 = getnode(comm->args))
- job = getjob(s1,"bg");
- else
- {
- if (topjob == -1 || topjob == curjob)
- {
- zerrnam("bg","no current job");
- return 1;
- }
- job = topjob;
- }
- if (job == -1)
- return 1;
- if (!(jobtab[job].stat & STAT_STOPPED))
- {
- zerrnam("bg","job already in background");
- return 1;
- }
- stopped = jobtab[job].stat & STAT_STOPPED;
- if (stopped)
- makerunning(jobtab+job);
- if (topjob == job)
- {
- topjob = prevjob;
- prevjob = -1;
- }
- if (prevjob == job)
- prevjob = -1;
- if (prevjob == -1)
- setprevjob();
- if (topjob == -1)
- {
- topjob = prevjob;
- setprevjob();
- }
- printjob(jobtab+job,(stopped) ? -1 : 0);
- if (stopped)
- killpg(jobtab[job].gleader,SIGCONT);
- return 0;
-}
-
-int jobs(comm comm)
-{
-int job,lng = 0;
-
- if (full(comm->args))
- {
- if (comm->args->first->next || (strcmp(comm->args->first->dat,"-l")
- && strcmp(comm->args->first->dat,"-p")))
- {
- zerrnam("jobs","usage: jobs [ -lp ]");
- return 1;
- }
- lng = (strcmp(comm->args->first->dat,"-l")) ? 2 : 1;
- }
- for (job = 0; job != MAXJOB; job++)
- if (job != curjob && jobtab[job].stat)
- printjob(job+jobtab,lng);
- stopmsg = 2;
- return 0;
-}
-
-int Kill(comm comm)
-{
-int sig = SIGTERM;
-char *s;
-
- s = getnode(comm->args);
- if (s && *s == '-')
- {
- if (isdigit(s[1]))
- sig = atoi(s+1);
- else
- {
- if (s[1] == 'l' && s[2] == '\0')
- {
- printf("%s",sigs[0]);
- for (sig = 1; sig != SIGCOUNT; sig++)
- printf(" %s",sigs[sig]);
- putchar('\n');
- return 0;
- }
- for (sig = 0; sig != SIGCOUNT; sig++)
- if (!strcmp(sigs[sig],s+1))
- break;
- if (sig == SIGCOUNT)
- {
- zerrnam("kill","unknown signal: SIG%s",s+1);
- zerrnam("kill","type kill -l for a list of signals");
- return 1;
- }
- }
- s = getnode(comm->args);
- }
- while (s)
- {
- if (*s == '%')
- {
- int job = getjob(s,"kill");
-
- if (killjb(jobtab+job,sig) == -1)
- {
- zerrnam("kill","kill failed: %e",errno);
- return 1;
- }
- if (jobtab[job].stat & STAT_STOPPED && sig == SIGCONT)
- jobtab[job].stat &= ~STAT_STOPPED;
- if (sig != SIGKILL)
- killpg(jobtab[job].gleader,SIGCONT);
- }
- else
- if (kill(atoi(s),sig) == -1)
- {
- zerrnam("kill","kill failed: %e");
- return 1;
- }
- s = getnode(comm->args);
- }
- return 0;
-}
-
-int export(comm comm)
-{
-char *s,*t;
-struct pmnode *pm;
-
- while (s = getnode(comm->args))
- {
- if (t = strchr(s,'='))
- {
- *t = '\0';
- if (pm = gethnode(s,parmhtab))
- freepm(remhnode(s,parmhtab));
- *t = '=';
- putenv(s);
- }
- else
- {
- if (!(pm = gethnode(s,parmhtab)))
- {
- if (!getenv(s))
- {
- zerrnam("export","parameter not set: %s",s);
- free(s);
- return 1;
- }
- }
- else if (pm->isint)
- {
- zerrnam("export","can't export integer parameters");
- free(s);
- return 1;
- }
- else
- {
- t = tricat(s,"=",pm->u.str);
- putenv(t);
- free(remhnode(s,parmhtab));
- }
- }
- }
- return 0;
-}
-
-int integer(comm comm)
-{
-char *s,*t;
-struct pmnode *uu;
-
- while (s = getnode(comm->args))
- {
- if (t = strchr(s,'='))
- {
- *t = '\0';
- setparm(s,t+1,0,1);
- *t = '=';
- }
- else
- {
- uu = gethnode(s,parmhtab);
- if (uu)
- {
- if (!uu->isint)
- {
- uu->isint = 1;
- uu->u.val = matheval(uu->u.str);
- }
- }
- else
- setiparm(s,0,1);
- }
- }
- return 0;
-}
-
-static char *recs[] = {
- "cputime","filesize","datasize","stacksize","coredumpsize",
- "resident","descriptors"
- };
-
-int limit(comm comm)
-{
-char *s;
-int hard = 0,t0,lim;
-long val;
-
- if (!(s = getnode(comm->args)))
- {
- showlimits(0,-1);
- return 0;
- }
- if (!strcmp(s,"-s"))
- {
- if (full(comm->args))
- zerr("limit","arguments after -s ignored");
- for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- if (setrlimit(t0,limits+t0) < 0)
- zerr("limit","setrlimit failed: %e",errno);
- return 0;
- }
- if (!strcmp(s,"-h"))
- {
- hard = 1;
- free(s);
- if (!(s = getnode(comm->args)))
- {
- showlimits(1,-1);
- return 0;
- }
- }
- while (s)
- {
- 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);
- free(s);
- return 1;
- }
- free(s);
- if (!(s = getnode(comm->args)))
- {
- showlimits(hard,lim);
- return 0;
- }
- if (!lim)
- {
- char *ss = s;
-
- val = strtol(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+strtol(s+1,&s,10);
- else
- {
- zerrnam("limit","unknown scaling factor: %s",s);
- free(ss);
- return 1;
- }
- }
-#ifdef RLIMIT_NOFILE
- else if (lim == RLIMIT_NOFILE)
- val = strtol(s,&s,10);
-#endif
- else
- {
- char *ss = s;
-
- val = strtol(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);
- free(ss);
- return 1;
- }
- free(ss);
- }
- if (hard)
- if (val > limits[lim].rlim_max && geteuid())
- {
- zerrnam("limit","can't raise hard limits");
- 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");
- return 1;
- }
- else
- limits[lim].rlim_cur = val;
- s = getnode(comm->args);
- }
- return 0;
-}
-
-int unlimit(comm comm)
-{
-char *s = getnode(comm->args);
-int hard = 0,t0,lim;
-
- if (s && !strcmp(s,"-h"))
- {
- hard = 1;
- if (geteuid())
- {
- zerrnam("unlimit","can't remove hard limits");
- return 1;
- }
- free(s);
- s = getnode(comm->args);
- }
- if (!s)
- {
- 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;
- }
- while (s)
- {
- 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("unlimit",
- (lim == -2) ? "ambiguous resource specification: %s"
- : "no such resource: %s",s);
- free(s);
- return 1;
- }
- free(s);
- if (hard)
- limits[lim].rlim_max = RLIM_INFINITY;
- else
- limits[lim].rlim_cur = limits[lim].rlim_max;
- s = getnode(comm->args);
- }
- return 0;
-}
-
-void showlimits(int hard,int lim)
-{
-int t0;
-long val;
-
- 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);
- }
-}
-
-int sched(comm comm)
-{
-char *s = getnode(comm->args);
-time_t t;
-long h,m;
-struct tm *tm;
-struct schnode *sch,*sch2,*schl;
-int t0;
-
- if (s && *s == '-')
- {
- t0 = atoi(s+1);
-
- if (!t0)
- {
- zerrnam("sched","usage for delete: sched -<item#>.");
- return 1;
- }
- for (schl = (struct schnode *) &scheds, sch = scheds, t0--;
- sch && t0; sch = (schl = sch)->next, t0--);
- if (!sch)
- {
- zerrnam("sched","not that many entries");
- return 1;
- }
- schl->next = sch->next;
- free(sch->cmd);
- free(sch);
- return 0;
- }
- if (s && !full(comm->args))
- {
- zerrnam("sched","not enough arguments");
- return 1;
- }
- if (!s)
- {
- char tbuf[40];
-
- for (t0 = 1, sch = scheds; sch; sch = sch->next,t0++)
- {
- t = sch->time;
- tm = localtime(&t);
- strftime(tbuf,20,"%a %b %e %k:%M:%S",tm);
- printf("%3d %s %s\n",t0,tbuf,sch->cmd);
- }
- return 0;
- }
- if (*s == '+')
- {
- h = strtol(s+1,&s,10);
- if (*s != ':')
- {
- zerrnam("sched","bad time specifier");
- return 1;
- }
- m = strtol(s+1,&s,10);
- if (*s)
- {
- zerrnam("sched","bad time specifier");
- return 1;
- }
- t = time(NULL)+h*3600+m*60;
- }
- else
- {
- h = strtol(s,&s,10);
- if (*s != ':')
- {
- zerrnam("sched","bad time specifier");
- return 1;
- }
- m = strtol(s+1,&s,10);
- if (*s && *s != 'a' && *s != 'p')
- {
- zerrnam("sched","bad time specifier");
- 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 = alloc(sizeof(struct schnode));
- sch->time = t;
- sch->cmd = buildline(comm->args);
- sch->next = NULL;
- for (sch2 = (struct schnode *) &scheds; sch2->next; sch2 = sch2->next);
- sch2->next = sch;
- return 0;
-}
-
-int eval(comm comm)
-{
-char *s = buildline(comm->args);
-list list;
-
- hungets(s);
- strinbeg();
- if (!(list = parlist(1)))
- {
- hflush();
- strinend();
- return 1;
- }
- strinend();
- runlist(list);
- return lastval;
-}
-
-int Brk(comm comm)
-{
- printf("%lx\n",(long) sbrk(0));
- return 0;
-}
-
-static struct utmp *wtab;
-static int wtabsz;
-
-int log(comm comm)
-{
- if (!getparm("WATCH"))
- return 1;
- if (wtab)
- free(wtab);
- wtab = (struct utmp *) zalloc(1);
- wtabsz = 0;
- watch();
- return 0;
-}
-
-int let(comm comm)
-{
-char *str;
-long val;
-
- while (str = getnode(comm->args))
- val = matheval(str);
- return !val;
-}
-
-int Read(comm comm)
-{
-char *str,*pmpt;
-int r = 0,bsiz,c,gotnl = 0;
-char *buf,*bptr;
-char cc;
-
- str = getnode(comm->args);
- if (str && !strcmp(str,"-r"))
- {
- r = 1;
- str = getnode(comm->args);
- }
- if (!str)
- str = strdup("REPLY");
- if (interact)
- {
- for (pmpt = str; *pmpt && *pmpt != '?'; pmpt++);
- if (*pmpt++)
- {
- write(2,pmpt,strlen(pmpt));
- *pmpt = '\0';
- }
- }
- while (full(comm->args))
- {
- buf = bptr = zalloc(bsiz = 64);
- FOREVER
- {
- if (gotnl)
- break;
- if (read(0,&cc,1) == 1)
- c = cc;
- else
- c = EOF;
- if (c == EOF || znspace(c))
- break;
- *bptr++ = c;
- if (bptr == buf+bsiz)
- {
- buf = realloc(buf,bsiz *= 2);
- bptr = buf+(bsiz/2);
- }
- }
- if (c == EOF)
- return 1;
- if (c == '\n')
- gotnl = 1;
- *bptr = '\0';
- setparm(str,buf,0,0);
- str = getnode(comm->args);
- }
- buf = bptr = zalloc(bsiz = 64);
- if (!gotnl)
- FOREVER
- {
- if (read(0,&cc,1) == 1)
- c = cc;
- else
- c = EOF;
- if (c == EOF || c == '\n')
- break;
- *bptr++ = c;
- if (bptr == buf+bsiz)
- {
- buf = realloc(buf,bsiz *= 2);
- bptr = buf+(bsiz/2);
- }
- *bptr = '\0';
- }
- if (c == EOF)
- return 1;
- setparm(str,buf,0,0);
- return 0;
-}
-
-int fc(comm comm)
-{
-char *ename = getparm("FCEDIT"),*str,*s;
-int n = 0,l = 0,r = 0,first = -1,last = -1,retval;
-table subs = NULL;
-
- if (!interact)
- {
- zerrnam("fc","not interactive shell");
- return 1;
- }
- remhist();
- if (!ename)
- ename = DEFFCEDIT;
- str = getnode(comm->args);
- for (; str && *str == '-' && str[1] && !isdigit(str[1]);
- str = getnode(comm->args))
- while (str[1])
- switch(*++str)
- {
- case 'e':
- if (str[1])
- {
- zerrnam("fc","editor name expected after -e");
- return 1;
- }
- ename = getnode(comm->args);
- if (!ename)
- {
- zerrnam("fc","editor name expected after -e");
- return 1;
- }
- break;
- case 'n':
- n = 1;
- break;
- case 'l':
- l = 1;
- break;
- case 'r':
- r = 1;
- break;
- default:
- zerrnam("fc","bad option: %c",*str);
- return 1;
- }
- subs = newtable();
- while (str)
- {
- for (s = str; *s && *s != '='; s++);
- if (!*s)
- break;
- *s++ = '\0';
- addnode(subs,str);
- addnode(subs,s);
- str = getnode(comm->args);
- }
- if (str)
- {
- first = fcgetcomm(str);
- if (first == -1)
- {
- freetable(subs,freestr);
- return 1;
- }
- str = getnode(comm->args);
- }
- if (str)
- {
- last = fcgetcomm(str);
- if (last == -1)
- {
- freetable(subs,freestr);
- return 1;
- }
- if (full(comm->args))
- {
- zerrnam("fc","too many arguments");
- freetable(subs,freestr);
- return 1;
- }
- }
- if (first == -1)
- {
- first = (l) ? cev-16 : cev;
- if (last == -1)
- last = cev;
- }
- if (first < tfev)
- first = tfev;
- if (last == -1)
- last = first;
- if (l)
- retval = fclist(stdout,!n,r,first,last,subs);
- else
- {
- FILE *out;
- char *fn = gettemp();
-
- out = fopen(fn,"w");
- if (!out)
- zerrnam("fc","can't open temp file: %e",errno);
- else
- {
- retval = 1;
- if (!fclist(out,0,r,first,last,subs))
- if (fcedit(ename,fn))
- if (stuff(fn))
- zerrnam("fc","%e: %s",errno,s);
- else
- retval = 0;
- }
- unlink(fn);
- free(fn);
- }
- freetable(subs,freestr);
- return retval;
-}
-
-/* get the history event associated with s */
-
-int fcgetcomm(char *s)
-{
-int cmd;
-
- if (cmd = atoi(s))
- {
- if (cmd < 0)
- cmd = cev+cmd+1;
- return cmd;
- }
- cmd = hcomsearch(s);
- if (cmd == -1)
- zerrnam("fc","event not found: %s",s);
- return cmd;
-}
-
-/* list a series of history events to a file */
-
-int fclist(FILE *f,int n,int r,int first,int last,table subs)
-{
-int done = 0,ct;
-Node node;
-char *s;
-
- if (!subs->first)
- done = 1;
- last -= first;
- first -= tfev;
- if (r)
- first += last;
- for (node = histlist->first,ct = first; ct && node;
- node = node->next, ct--);
- first += tfev;
- while (last-- >= 0)
- {
- if (!node)
- {
- zerrnam("fc","no such event: %d",first);
- return 1;
- }
- s = makehlist(node->dat,0);
- done |= fcsubs(&s,subs);
- if (n)
- fprintf(f,"%5d ",first);
- if (f == stdout)
- {
- niceprintf(s,f);
- putc('\n',f);
- }
- else
- fprintf(f,"%s\n",s);
- node = (r) ? node->last : node->next;
- (r) ? first-- : first++;
- }
- if (f != stdout)
- fclose(f);
- if (!done)
- {
- zerrnam("fc","no substitutions performed");
- return 1;
- }
- return 0;
-}
-
-/* perform old=new substituion */
-
-int fcsubs(char **sp,table tab)
-{
-Node n;
-char *s1,*s2,*s3,*s4,*s = *sp,*s5;
-int subbed = 0;
-
- for (n = tab->first; n; )
- {
- s1 = n->dat;
- n = n->next;
- s2 = n->dat;
- n = n->next;
- s5 = s;
- while (s3 = (char *) strstr(s5,s1))
- {
- s4 = zalloc(1+(s3-s)+strlen(s2)+strlen(s3+strlen(s1)));
- strncpy(s4,s,s3-s);
- s4[s3-s] = '\0';
- strcat(s4,s2);
- s5 = s4+strlen(s4);
- strcat(s4,s3+strlen(s1));
- free(s);
- s = s4;
- subbed = 1;
- }
- }
- *sp = s;
- return subbed;
-}
-
-int fcedit(char *ename,char *fn)
-{
- if (!strcmp(ename,"-"))
- return 1;
- return !zyztem(ename,fn);
-}
-
-int disown(comm comm)
-{
-char *str;
-int t0;
-static struct jobnode zero;
-
- while (str = getnode(comm->args))
- {
- t0 = getjob(str,"disown");
- if (t0 == -1)
- return 1;
- jobtab[t0] = zero;
- }
- return 0;
-}
-
-int function(comm comm)
-{
- if (full(comm->args))
- {
- zerrnam("function","too many arguments");
- return 1;
- }
- listhtable(shfunchtab,(void (*)(char *,char *)) pshfunc);
- return 0;
-}
-
-int (*funcs[])(comm) = {
- echo,zexit,logout,Unset,dirs,
- Alias,cd,which,popd,
- dot,pushd,shift,unhash,Break,
- colon,Glob,noglob,mostglob,unalias,
- fg,bg,jobs,Kill,export,
- Umask,cd,limit,unlimit,eval,
- unfunction,set,Brk,log,builtin,
- sched,let,fc,
- rehash,hash,disown,test,Read,
- integer,setopt,unsetopt,zreturn,function,
- test,
- NULL
- };
-char *funcnams[] = {
- "echo","exit","logout","unset","dirs",
- "alias","cd","which","popd",
- ".","pushd","shift","unhash","break",
- ":","glob","noglob","mostglob","unalias",
- "fg","bg","jobs","kill","export",
- "umask","chdir","limit","unlimit","eval",
- "unfunction","set","brk","log","builtin",
- "sched","let","fc",
- "rehash","hash","disown","test","read",
- "integer","setopt","unsetopt","return","function",
- "["
- };
-
-int builtin(comm comm)
-{
-char *s;
-int t0;
-
- s = getnode(comm->args);
- if (!s)
- {
- zerrnam("builtin","not enough arguments");
- return 1;
- }
- for (t0 = 0; funcs[t0]; t0++)
- if (!strcmp(funcnams[t0],s))
- break;
- if (!funcs[t0])
- {
- zerrnam("builtin","no such builtin: %s",s);
- return 1;
- }
- return (funcs[t0])(comm);
-}
-
-/* add builtins to the command hash table */
-
-void addintern(htable ht)
-{
-int (**ptr)(comm);
-struct chnode *ch;
-char **nam;
-
- for (ptr = funcs, nam = funcnams; *ptr; ptr++,nam++)
- {
- ch = alloc(sizeof(struct chnode));
- ch->type = BUILTIN;
- ch->u.func = *ptr;
- addhnode(strdup(*nam),ch,ht,freechnode);
- }
-}
-
-/* get the time of login/logout for WATCH */
-
-static time_t getlogtime(struct utmp *u,int inout)
-{
-FILE *in;
-struct utmp uu;
-int first = 1;
-
- 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);
- }
- }
- 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 */
-
-static void watchlog2(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':
- printf("%.*s",5,u->ut_line+3);
- break;
- case 'm':
- for (p = u->ut_host,i = 16; i && *p;i--,p++)
- {
- if (*p == '.' && !isdigit(p[1]))
- break;
- putchar(*p);
- }
- break;
- case 'M':
- printf("%.*s",16,u->ut_host);
- break;
- case 't':
- case '@':
- timet = getlogtime(u,inout);
- tm = localtime(&timet);
- strftime(buf,40,"%l:%M%p",tm);
- printf("%s",(*buf == ' ') ? buf+1 : buf);
- break;
- case 'T':
- timet = getlogtime(u,inout);
- tm = localtime(&timet);
- strftime(buf,40,"%k:%M",tm);
- printf("%s",buf);
- break;
- case 'w':
- timet = getlogtime(u,inout);
- tm = localtime(&timet);
- strftime(buf,40,"%a %e",tm);
- printf("%s",buf);
- break;
- case 'W':
- timet = getlogtime(u,inout);
- tm = localtime(&timet);
- strftime(buf,40,"%m/%d/%y",tm);
- printf("%s",buf);
- break;
- case 'D':
- timet = getlogtime(u,inout);
- tm = localtime(&timet);
- strftime(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 */
-
-static void watchlog(int inout,struct utmp *u,char *w,char *fmt)
-{
-char *v;
-
- if (!strcmp(w,"all"))
- {
- watchlog2(inout,u,fmt);
- return;
- }
- for(;;)
- if (v = strchr(w,':'))
- {
- if (!strncmp(u->ut_name,w,v-w))
- watchlog2(inout,u,fmt);
- w = v+1;
- }
- else
- {
- if (!strncmp(u->ut_name,w,8))
- watchlog2(inout,u,fmt);
- break;
- }
-}
-
-/* compare 2 utmp entries */
-
-static int ucmp(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(void)
-{
-struct utmp *uptr;
-int wtabmax = 32;
-FILE *in;
-
- wtabsz = 0;
- uptr = wtab = (struct utmp *) zalloc(wtabmax*sizeof(struct utmp));
- in = fopen(UTMP_FILE,"r");
- while (fread(uptr,sizeof(struct utmp),1,in))
- if (uptr->ut_host[0])
- {
- uptr++;
- if (++wtabsz == wtabmax)
- uptr = (wtab = (struct utmp *) realloc(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 watch(void)
-{
-char *s = getparm("WATCH");
-char *fmt = getparm("WATCHFMT");
-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));
- in = fopen(UTMP_FILE,"r");
- while (fread(uptr,sizeof *uptr,1,in))
- if (uptr->ut_host[0])
- {
- uptr++;
- if (++utabsz == utabmax)
- uptr = (utab = (struct utmp *) realloc(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);
-}
-
End of builtin.c
echo builtin.pro 1>&2
sed 's/^-//' >builtin.pro <<'End of builtin.pro'
-int echo(comm comm);
-void pdstack(void);
-int zexit(comm comm);
-int zreturn(comm comm);
-int logout(comm comm);
-int Unset(comm comm);
-int set(comm comm);
-int setopt(comm comm);
-int unsetopt(comm comm);
-int csetopt(comm comm,int isun);
-void pparm(char *s,struct pmnode *t);
-int dirs(comm comm);
-void listhtable(htable ht,void (*func)(char *,char *));
-void palias(char *s,struct anode *t);
-void pshfunc(char *s,list l);
-void niceprint(char *s);
-void niceprintf(char *s,FILE *f);
-char *buildline(table t);
-int Alias(comm comm);
-int cd(comm comm);
-int dot(comm comm);
-int Umask(comm comm);
-int which(comm comm);
-int popd(comm comm);
-int pushd(comm comm);
-int chcd(char *cnam,char *cd);
-int shift(comm comm);
-int unhash(comm comm);
-int rehash(comm comm);
-int hash(comm comm);
-int Break(comm comm);
-int colon(comm comm);
-int Glob(comm comm);
-int noglob(comm comm);
-int mostglob(comm comm);
-int unfunction(comm comm);
-int unalias(comm comm);
-int prefix(char *s,char *t);
-int getjob(char *s,char *prog);
-int fg(comm comm);
-int bg(comm comm);
-int jobs(comm comm);
-int Kill(comm comm);
-int export(comm comm);
-int integer(comm comm);
-int limit(comm comm);
-int unlimit(comm comm);
-void showlimits(int hard,int lim);
-int sched(comm comm);
-int eval(comm comm);
-int Brk(comm comm);
-int log(comm comm);
-int let(comm comm);
-int Read(comm comm);
-int fc(comm comm);
-int fcgetcomm(char *s);
-int fclist(FILE *f,int n,int r,int first,int last,table subs);
-int fcsubs(char **sp,table tab);
-int fcedit(char *ename,char *fn);
-int disown(comm comm);
-int function(comm comm);
-int builtin(comm comm);
-void addintern(htable ht);
-void readwtab(void);
-void watch(void);
End of builtin.pro
echo config.h 1>&2
sed 's/^-//' >config.h <<'End of config.h'
-/*
-
- config.h - configuration file
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-/* define this if you have WAITPID */
-
-#define WAITPID
-
-/* define if the return type of signal handlers is int */
-
-/* #define INTHANDTYPE */
-
-/* the return type of handlers */
-
-#define HANDTYPE void
-
-/* define this if you have putenv */
-
-#define PUTENV
-
-/* define this if you have strstr */
-
-#define STRSTR
-
-/* define this if you have strftime */
-
-/* #define STRFTIME */
-
-/* define if you have struct termios, else struct sgttyb */
-
-#define TERMIOS
-
-#include "config.local.h"
-
End of config.h
echo config.local.h 1>&2
sed 's/^-//' >config.local.h <<'End of config.local.h'
-/*
-
- config.local.h - local machine configuration file
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-/* a string corresponding to the host type */
-
-#define HOSTTYP "sun4"
-
-/* define if you prefer "suspended" to "stopped" */
-
-#define USE_SUSPENDED
-
-/* the path of zsh in the file system */
-
-#define MYSELF "/usr/princeton/bin/zsh"
-
-/* the default editor for the fc builtin */
-
-#define DEFFCEDIT "/usr/ucb/vi"
-
-/* the file to source whenever zsh is run; if undefined, don't source
- anything */
-
-#define GLOBALZSHRC "/etc/zshrc"
-
-/* the file to source whenever zsh is run as a login shell; if
- undefined, don't source anything */
-
-#define GLOBALZLOGIN "/etc/zlogin"
-
-/* the default HISTSIZE */
-
-#define DEFAULT_HISTSIZE 128
-
-/* the path of utmp */
-
-#define UTMP_FILE "/etc/utmp"
-
-/* the path of wtmp */
-
-#define WTMP_FILE "/var/adm/wtmp"
-
-/* define if you have problems with job control or tty modes.
- gcc-cpp does not seem to handle ioctls correctly. */
-
-/*#define BUGGY_GCC*/
-
-/* define if you like interactive comments */
-
-/*#define INTERACTIVE_COMMENTS*/
-
-/* define if you want warnings about nonexistent path components */
-
-#define PATH_WARNINGS
-
End of config.local.h
echo exec.c 1>&2
sed 's/^-//' >exec.c <<'End of exec.c'
-/*
-
- exec.c - command execution
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <sys/errno.h>
-#include <sys/dir.h>
-
-#define execerr() { if (forked) exit(1); freecmd(comm); \
- closemnodes(mfds); errflag = 1; return; }
-#define magicerr() { if (magic) putc('\n',stderr); errflag = 1; }
-
-/* execute a string */
-
-void execstring(char *s)
-{
-list l;
-
- hungets(strdup("\n"));
- hungets(s);
- strinbeg();
- if (!(l = parlist(1)))
- {
- strinend();
- hflush();
- return;
- }
- if (peek != EOF && peek != EMPTY)
- {
- strinend();
- hflush();
- return;
- }
- strinend();
- execlist(l);
-}
-
-/* duplicate a list and run it */
-
-void newrunlist(list l)
-{
-list a = duplist(l); runlist(a);
-}
-
-/* fork and set limits */
-
-int phork(void)
-{
-int pid = fork(),t0;
-
- if (pid == -1)
- {
- zerr("fork failed: %e",errno);
- return -1;
- }
- if (!pid)
- for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- setrlimit(t0,limits+t0);
- return pid;
-}
-
-/* execute a current shell command */
-
-void execcursh(comm comm)
-{
- runlist(comm->left);
- comm->left = NULL;
-}
-
-/* execve an external command */
-
-void execute(char *arg0,table args)
-{
-char **argv;
-char *z,*s,buf[MAXPATHLEN],buf2[MAXPATHLEN];
-struct chnode *cn;
-int t0,tl,ee = 0;
-
-#define zexecve(X,Y,Z) {execve(z=(X),Y,Z);\
- if(errno!=ENOENT){ee = errno;strcpy(buf2,buf);}}
-
- cn = gethnode(arg0,chtab);
- if (s = getenv("STTY"))
- zyztem("stty",s);
- if (z = getenv("ARGV0"))
- z = strdup(z);
- else
- z = arg0;
- argv = makecline(z,args);
- fixsigs();
- if (cn)
- {
- if (cn->type == EXCMD_POSTDOT)
- {zexecve(arg0,argv,environ);}
- {zexecve(cn->u.nam,argv,environ);}
- }
- for (s = arg0; *s; s++)
- if (*s == '/')
- {
- execve(arg0,argv,environ);
- zerr("%e: %s",errno,arg0);
- _exit(1);
- }
- for (t0 = pathct; t0; t0--,path++)
- if (**path == '.')
- {zexecve(arg0,argv,environ);}
- else
- {
- tl = strlen(*path);
- strcpy(buf,*path);
- buf[tl] = '/';
- if (strlen(arg0)+strlen(buf)+1 >= MAXPATHLEN)
- {
- zerr("command too long: %s",arg0);
- _exit(1);
- }
- strcpy(buf+tl+1,arg0);
- {zexecve(buf,argv,environ);}
- }
- if (ee)
- {
- z = buf2;
- errno = ee;
- goto errs;
- }
- zerr("command not found: %s",arg0);
- _exit(1);
-errs:
- zerr("%e: %s",errno,z);
- _exit(1);
-}
-
-#define try(X) { if (!access(X,X_OK)) return strdup(X); }
-
-/* get the pathname of a command */
-
-char *findcmd(char *arg0)
-{
-char *s,buf[MAXPATHLEN];
-int t0,tl;
-struct chnode *cn = gethnode(arg0,chtab);
-char **pp = path;
-
- if (cn)
- {
- if (cn->type == EXCMD_POSTDOT)
- {
- strcpy(buf,"./");
- strcat(buf,arg0);
- try(buf);
- }
- try(cn->u.nam);
- }
- for (s = arg0; *s; s++)
- if (*s == '/')
- {
- try(arg0);
- goto failed;
- }
- for (t0 = pathct; t0; t0--,pp++)
- if (**pp == '.')
- {
- strcpy(buf,"./");
- strcat(buf,arg0);
- try(buf);
- }
- else
- {
- tl = strlen(*pp);
- strcpy(buf,*pp);
- buf[tl] = '/';
- strcpy(buf+tl+1,arg0);
- try(buf);
- }
-failed:
- return NULL;
-}
-
-void execlist(list list)
-{
- execlist1(list);
- freelist(list);
-}
-
-void execlist1(list list)
-{
- if (breaks)
- return;
- 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)
- execlist1(list->right);
- break;
- }
-}
-
-void execlist2(list2 list,int type,int last1)
-{
- switch(list->type)
- {
- case END:
- execpline(list,type,last1);
- break;
- case ORNEXT:
- if (!execpline(list,SYNC,0))
- execlist2(list->right,type,last1);
- break;
- case ANDNEXT:
- if (execpline(list,SYNC,0))
- execlist2(list->right,type,last1);
- break;
- }
-}
-
-int execpline(list2 l,int how,int last1)
-{
-int ipipe[2] = {0,0},opipe[2] = {0,0};
-
- sigblock(sigmask(SIGCHLD));
- curjob = getfreejob();
- initjob(l->flags);
- if (l->flags & PFLAG_COPROC)
- {
- how = ASYNC;
- mpipe(ipipe);
- mpipe(opipe);
- if (spin)
- {
- close(spin);
- close(spout);
- }
- spin = ipipe[0];
- spout = opipe[1];
- }
- execpline2(l->left,how,opipe[0],ipipe[1],last1);
- if (how == ASYNC)
- {
- spawnjob();
- sigsetmask(0);
- return 1;
- }
- else
- {
- waitjobs();
- sigsetmask(0);
- if (l->flags & PFLAG_NOT)
- lastval = !lastval;
- return !lastval;
- }
-}
-
-void execpline2(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)
- {
- execcomm(pline->left,input,output,how==ASYNC,last1);
- pline->left = NULL;
- }
- else
- {
- mpipe(pipes);
-
- /* if we are doing "foo | bar" where foo is a current
- shell command, do foo in the current shell and do
- the rest of the pipeline in a subshell. */
-
- if (pline->left->type >= CURSH && how == SYNC)
- {
- if (!(pid = fork()))
- {
---cut here---cut here---cut here---pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
- case 'M':
- stradd(&bp,hostM);
- break;
- case 'm':
- stradd(&bp,hostm);
- break;
- case 'S':
- if (tgetstr("so",&bp))
- bp--;
- break;
- case 's':
- if (tgetstr("se",&bp))
- bp--;
- break;
- case 'B':
- if (tgetstr("md",&bp))
- bp--;
- break;
- case 'b':
- if (tgetstr("me",&bp))
- bp--;
- break;
- case 'U':
- if (tgetstr("us",&bp))
- bp--;
- break;
- case 'u':
- if (tgetstr("ue",&bp))
- bp--;
- break;
- case 't':
- case '@':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%l:%M%p",tm);
- if (*bp == ' ')
- chuck(bp);
- bp += strlen(bp);
- break;
- case 'T':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%k:%M",tm);
- bp += strlen(bp);
- break;
- case '*':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%k:%M:%S",tm);
- bp += strlen(bp);
- break;
- case 'n':
- stradd(&bp,username);
- break;
- case 'w':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%a %e",tm);
- bp += strlen(bp);
- break;
- case 'W':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%m/%d/%y",tm);
- bp += strlen(bp);
- break;
- case 'D':
- timet = time(NULL);
- tm = localtime(&timet);
- strftime(bp,16,"%y-%m-%d",tm);
- bp += strlen(bp);
- break;
- case 'l':
- if (ss = ttyname(SHTTY))
- stradd(&bp,ss+8);
- else
- stradd(&bp,"(none)");
- break;
- case '%':
- *bp++ = '%';
- break;
- case '#':
- *bp++ = (geteuid()) ? '%' : '#';
- break;
- default:
- *bp++ = '%';
- *bp++ = *fm;
- break;
- }
- else
- *bp++ = *fm;
- }
- *bp = '\0';
- return buf;
-}
-
-void herrflush(void)
-{
- if (strin)
- hflush();
- else while (lastc != '\n' && lastc != HERR)
- hgetch();
- if (magic)
- putc('\n',stderr);
-}
-
-/* read an arbitrary amount of data into a buffer until stop is found */
-
-char *hdynread(char stop)
-{
-int bsiz = 256,ct = 0,c;
-char *buf = zalloc(bsiz),*ptr;
-
- ptr = buf;
- while ((c = hgetch()) != stop && c != '\n')
- {
- 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");
- errflag = 1;
- free(buf);
- return NULL;
- }
- return buf;
-}
-
-char *hdynread2(char stop)
-{
-int bsiz = 256,ct = 0,c;
-char *buf = zalloc(bsiz),*ptr;
-
- ptr = buf;
- while ((c = hgetch()) != stop && c != '\n')
- {
- if (c == '\n')
- {
- hungetch(c);
- break;
- }
- if (c == '\\')
- if ((c = hgetch()) == '&')
- c = '&';
- *ptr++ = c;
- if (++ct == bsiz)
- {
- buf = realloc(buf,bsiz *= 2);
- ptr = buf+ct;
- }
- }
- *ptr = 0;
- if (c == '\n')
- hungetch('\n');
- return buf;
-}
-
-/* set cbreak mode, or the equivalent */
-
-void setcbreak(void)
-{
-struct ttyinfo ti;
-
- ti = shttyinfo;
-#ifdef TERMIOS
- ti.termios.c_lflag &= ~ICANON;
- ti.termios.c_cc[VMIN] = 1;
- ti.termios.c_cc[VTIME] = 0;
-#else
- ti.sgttyb.sg_flags |= CBREAK;
-#endif
- settyinfo(&ti);
-}
-
-int getlineleng(void)
-{
-int z;
-
- z = shttyinfo.winsize.ws_col;
- return (z) ? z : 80;
-}
-
-void unsetcbreak(void)
-{
- settyinfo(&shttyinfo);
-}
-
-/* give the tty to some process */
-
-void attachtty(long pgrp)
-{
-static int ep = 0;
-
- if (jobbing)
-#ifdef BUGGY_GCC
- if (SHTTY != -1 && ioctl(SHTTY,(0x80000000|((sizeof(int)&0xff)<<16)|
- ('t'<<8)|118),&pgrp) == -1 && !ep)
-#else
- if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&pgrp) == -1 && !ep)
-#endif
- {
- zerr("can't set tty pgrp: %e",errno);
- opts[MONITOR] = OPT_UNSET;
- ep =1;
- }
-}
-
End of hist.c
echo hist.pro 1>&2
sed 's/^-//' >hist.pro <<'End of hist.pro'
-void hwaddc(int c);
-int hgetc(void);
-void strinbeg(void);
-void strinend(void);
-int stuff(char *fn);
-int hgetch(void);
-void hungetch(int c);
-void hungetc(int c);
-void hflush(void);
-void hungets(char *str);
-void hbegin(void);
-void inittty(void);
-int hend(void);
-void remhist(void);
-void hwbegin(void);
-char *hwadd(void);
-int getargspec(int argc,int marg);
-int hconsearch(char *str,int *marg);
-int hcomsearch(char *str);
-int apply1(int gflag,int (*func)(void **),table list);
-int remtpath(void **junkptr);
-int remtext(void **junkptr);
-int rembutext(void **junkptr);
-int remlpaths(void **junkptr);
-int subst(int gbal,table slist,char *ptr1,char *ptr2);
-int subststr(void **strptr,char *in,char *out,int gbal);
-char *convamps(char *out,char *in);
-char *makehlist(table tab,int freeit);
-table quietgetevent(int ev);
-table getevent(int ev);
-int getargc(table tab);
-table getargs(table elist,int arg1,int arg2);
-int quote(void **tr);
-int quotebreak(void **tr);
-void stradd(char **p,char *d);
-char *putprompt(char *fm);
-void herrflush(void);
-char *hdynread(char stop);
-char *hdynread2(char stop);
-void setcbreak(void);
-int getlineleng(void);
-void unsetcbreak(void);
-void attachtty(long pgrp);
End of hist.pro
echo init.c 1>&2
sed 's/^-//' >init.c <<'End of init.c'
-/*
-
- init.c - initialization, main loop
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <pwd.h>
-
-void main(int argc, char **argv)
-{
-int notect = 0;
-
- setflags();
- parseargs(argv);
- setmoreflags();
- setupvals();
- initialize();
- runscripts();
- FOREVER
- {
- do
- loop();
- while (peek != EOF);
- if (!(isset(IGNOREEOF) && interact))
- {
- if (interact)
- fputs(islogin ? "logout\n" : "exit\n",stderr);
- zexit(NULL);
- continue;
- }
- zerrnam("\nzsh",(!islogin) ? "use 'exit' to exit."
- : "use 'logout' to logout.");
- notect++;
- if (notect == 10)
- zexit(NULL);
- }
-}
-
-/* keep executing lists until EOF found */
-
-void loop(void)
-{
-list list;
-
- FOREVER
- {
- peek = EMPTY;
- if (interact)
- preprompt();
- hbegin(); /* init history mech */
- intr(); /* interrupts on */
- ainit(); /* init alias mech */
- if (!(list = parlist1(0)))
- { /* if we couldn't parse a list */
- hend();
- if (!errflag)
- if (peek == OUTPAR)
- {
- errflag = 1;
- zerr("mismatched parenthesis");
- }
- else if (peek == OUTBRACE)
- {
- errflag = 1;
- zerr("mismatched brace");
- }
- else if (peek != EOF && peek != EMPTY && peek != NEWLIN)
- {
- errflag = 1;
- zerr("semicolon or newline expected");
- }
- if (peek == EOF && !errflag)
- return;
- continue;
- }
- if (peek != EMPTY && peek != EOF)
- {
- if (peek == OUTPAR)
- zerr("mismatched parenthesis");
- else if (peek == OUTBRACE)
- zerr("mismatched brace");
- else
- zerr("semicolon or newline expected");
- hend();
- errflag = 1;
- }
- else if (hend())
- {
- if (stopmsg) /* unset 'you have stopped jobs' flag */
- stopmsg--;
- execlist(list);
- }
- if (ferror(stderr))
- {
- zerr("write error");
- clearerr(stderr);
- }
- if (subsh) /* how'd we get this far in a subshell? */
- exit(lastval);
- if ((!interact && errflag) || retflag)
- return;
- if ((opts['t'] == OPT_SET) || (lastval && opts[ERREXIT] == OPT_SET))
- {
- if (sigtrapped[SIGEXIT])
- dotrap(SIGEXIT);
- exit(lastval);
- }
- }
-}
-
-void setflags(void)
-{
-int c;
-
- for (c = 0; c != 128; c++)
- opts[c] = OPT_INVALID;
- opts['a'] = opts['e'] = opts['f'] = opts['h'] = opts['k'] = opts['n'] =
- opts['s'] = opts['t'] = opts['u'] = opts['v'] = opts['x'] =
- opts['c'] = OPT_UNSET;
- opts['i'] = (isatty(0)) ? OPT_SET : OPT_UNSET;
- for (c = '0'; c <= '9'; c++)
- opts[c] = OPT_UNSET;
- for (c = 'A'; c <= 'K'; c++)
- opts[c] = OPT_UNSET;
- opts[BGNICE] = opts[NOTIFY] = OPT_SET;
-}
-
-static char *cmd;
-
-void parseargs(char **argv)
-{
-char *argv0 = *argv;
-int bk = 0;
-
- islogin = **(argv++) == '-';
- SHIN = 0;
- while (!bk && *argv && **argv == '-')
- {
- while (*++*argv)
- {
- if (opts[**argv] == OPT_INVALID)
- {
- zerr("bad option: -%c",**argv);
- exit(1);
- }
- opts[**argv] = OPT_SET;
- if (bk = **argv == 'b')
- break;
- if (**argv == 'c') /* -c command */
- {
- argv++;
- if (!*argv)
- {
- zerr("string expected after -c");
- exit(1);
- }
- cmd = strdup(*argv);
- opts[INTERACTIVE] = OPT_UNSET;
- break;
- }
- }
- argv++;
- }
- pparms = newtable();
- if (*argv)
- {
- if (opts[SHINSTDIN] == OPT_UNSET)
- {
- SHIN = movefd(open(argv0 = *argv,O_RDONLY));
- if (SHIN == -1)
- {
- zerr("can't open input file: %s",*argv);
- exit(1);
- }
- opts[INTERACTIVE] = OPT_UNSET;
- argv++;
- }
- addnode(pparms,argv0); /* assign positional parameters */
- while (*argv)
- addnode(pparms,strdup(*argv++));
- }
- else
- {
- addnode(pparms,strdup(argv0));
- opts[SHINSTDIN] = OPT_SET;
- }
-}
-
-void setmoreflags(void)
-{
- setlinebuf(stderr);
- setlinebuf(stdout);
- subsh = 0;
- 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
- gettyinfo(&shttyinfo); /* get tty state */
- if ((shpgrp = getpgrp(0)) <= 0)
- opts[MONITOR] = OPT_UNSET;
- }
- else
- SHTTY = -1;
-}
-
-void setupvals(void)
-{
-struct passwd *pwd;
-char *ptr;
-
- shtimer = time(NULL); /* init $SECONDS */
- /* build various hash tables; argument to newhtable is table size */
- alhtab = newhtable(37);
- parmhtab = newhtable(17);
- shfunchtab = newhtable(17);
- if (interact)
- {
- if (!getparm("PROMPT"))
- setparm(strdup("PROMPT"),strdup("%M%# "),0,0);
- if (!getparm("PROMPT2"))
- setparm(strdup("PROMPT2"),strdup("> "),0,0);
- if (!getparm("PROMPT3"))
- setparm(strdup("PROMPT3"),strdup("?# "),0,0);
- }
- if (!getparm("PATH"))
- setparm(strdup("PATH"),strdup("/bin:/usr/bin:/usr/ucb"),1,0);
- setparm(strdup("VERSION"),strdup(VERSIONSTR),1,0);
- home = xsymlink(getparm("HOME"));
- setparm(strdup("HOME"),strdup(home),0,0);
- setiparm(strdup("UID"),getuid(),1);
- setiparm(strdup("EUID"),geteuid(),1);
- setiparm(strdup("PPID"),getppid(),1);
- lineno = 0;
- pwd = getpwuid(getuid());
- setparm(strdup("USERNAME"),strdup(pwd->pw_name),0,0);
- username = strdup(pwd->pw_name);
- setparm(strdup("HOSTTYPE"),strdup(HOSTTYP),0,0);
- cwd = zgetwd();
- setparm(strdup("PWD"),strdup(cwd),0,0);
- if (!getparm("IFS"))
- {
- ifs = strdup(" \t\n");
- setparm(strdup("IFS"),strdup(ifs),0,0);
- }
- hostM = alloc(512); /* get hostname, with and without .podunk.edu */
- hostm = hostM+256;
- gethostname(hostm,256);
- gethostname(hostM,256);
- procnum = getpid();
- for (ptr = hostM; *ptr && *ptr != '.'; ptr++);
- *ptr = '\0';
-}
-
-void initialize(void)
-{
-int t0;
-
- breaks = loops = incmd = 0;
- lastmailcheck = 0;
- lastmailval = -1;
- tfev = 1;
- tevs = DEFAULT_HISTSIZE;
- histlist = newtable();
- dirstack = newtable();
- ungots = ungotptr = NULL;
- signal(SIGQUIT,SIG_IGN);
- for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- getrlimit(t0,limits+t0);
- last = rast = NULL;
- proclast = 0;
- if (!interact || SHTTY == -1)
- bshin = fdopen(SHIN,"r");
- signal(SIGCHLD,handler);
- addreswords();
- addhnode(strdup("false"),mkanode(strdup("let 0"),1),alhtab,NULL);
- addhnode(strdup("history"),mkanode(strdup("fc -l"),1),alhtab,NULL);
- addhnode(strdup("nohup"),mkanode(strdup("nohup "),1),alhtab,NULL);
- addhnode(strdup("r"),mkanode(strdup("fc -e -"),1),alhtab,NULL);
- addhnode(strdup("true"),mkanode(strdup(":"),1),alhtab,NULL);
- addhnode(strdup("pwd"),mkanode(strdup("echo $PWD"),1),alhtab,NULL);
- parsepath();
- parsecdpath();
- if (jobbing)
- {
- signal(SIGTTOU,SIG_IGN);
- signal(SIGTSTP,SIG_IGN);
- signal(SIGTTIN,SIG_IGN);
- signal(SIGPIPE,SIG_IGN);
- attachtty(shpgrp);
- }
- if (interact)
- {
- signal(SIGTERM,SIG_IGN);
- intr();
- }
-}
-
-void addreswords(void)
-{
-char *reswds[] = {
- "do", "done", "esac", "then", "elif", "else", "fi", "for", "case",
- "if", "while", "function", "repeat", "time", "until", "exec", "command",
- "select", "coproc", NULL
- };
-int t0;
-
- for (t0 = 0; reswds[t0]; t0++)
- addhnode(strdup(reswds[t0]),mkanode(NULL,-1-t0),alhtab,NULL);
-}
-
-void runscripts(void)
-{
- if (interact)
- checkfirstmail();
- if (opts[NORCS] == OPT_UNSET)
- {
-#ifdef GLOBALZSHRC
- source(GLOBALZSHRC);
-#endif
- sourcehome(".zshrc");
- if (islogin)
- {
-#ifdef GLOBALZLOGIN
- source(GLOBALZLOGIN);
-#endif
- sourcehome(".zlogin");
- }
- }
- if (opts['c'] == OPT_SET)
- {
- close(SHIN);
- SHIN = movefd(open("/dev/null",O_RDONLY));
- hungets(cmd);
- strinbeg();
- }
-}
-
-void ainit(void)
-{
- alix = 0; /* reset alias stack */
- alstat = 0;
- firstln = 1;
-}
End of init.c
echo init.pro 1>&2
sed 's/^-//' >init.pro <<'End of init.pro'
-void main(int argc, char **argv);
-void loop(void);
-void setflags(void);
-void parseargs(char **argv);
-void setmoreflags(void);
-void setupvals(void);
-void initialize(void);
-void addreswords(void);
-void runscripts(void);
-void ainit(void);
End of init.pro
echo jobs.c 1>&2
sed 's/^-//' >jobs.c <<'End of jobs.c'
-/*
-
- jobs.c - job control
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <sys/errno.h>
-
-#define WCOREDUMPED(x) ((x)&0x80)
-
-/* != 0 means the handler is active */
-
-static int handling = 0;
-
-/* != 0 means the shell is waiting for a job to complete */
-
-static int waiting = 0;
-
-/* != 0 means readline is active */
-
-extern int rl_active;
-
-/* != 0 means readline is waiting for a keypress */
-
-extern int rl_waiting;
-
-#ifdef INTHANDTYPE
-#define RETURN return 0
-#else
-#define RETURN return
-#endif
-
-/* the signal handler */
-
-HANDTYPE handler(int sig,int code)
-{
-long pid;
-int statusp;
-struct jobnode *jn;
-struct procnode *pn;
-struct rusage ru;
-
- if (sig == SIGINT)
- {
- if (sigtrapped[SIGINT])
- dotrap(SIGINT);
- else
- errflag = 1;
- RETURN;
- }
- if (sig != SIGCHLD)
- {
- dotrap(sig);
- RETURN;
- }
- for (;;)
- {
- pid = wait3(&statusp,WNOHANG|WUNTRACED,&ru);
- if (pid == -1)
- {
- if (errno != ECHILD)
- zerr("%e",errno);
- RETURN;
- }
- if (!pid)
- RETURN;
- findproc(pid,&jn,&pn); /* find the procnode of this pid */
- if (jn)
- {
- pn->statusp = statusp;
- handling = 1;
- pn->ru_utime = ru.ru_utime;
- pn->ru_stime = ru.ru_stime;
- pn->endtime = time(NULL);
- updatestatus(jn);
- handling = 0;
- }
- else if (WIFSTOPPED(SP(statusp)))
- kill(pid,SIGKILL); /* kill stopped untraced children */
- }
- if (rl_active)
- rl_prep_terminal();
- RETURN;
-}
-
-/* change job table entry from stopped to running */
-
-void makerunning(struct jobnode *jn)
-{
-struct procnode *pn;
-
- jn->stat &= ~STAT_STOPPED;
- for (pn = jn->procs; pn; pn = pn->next)
- if (WIFSTOPPED(SP(pn->statusp)))
- pn->statusp = SP_RUNNING;
-}
-
-/* update status of job, possibly printing it */
-
-void updatestatus(struct jobnode *jn)
-{
-struct procnode *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(SP(pn->statusp)))
- alldone = 0;
- if (WIFSTOPPED(SP(pn->statusp)))
- somestopped = 1;
- if (!pn->next && jn)
- val = (WIFSIGNALED(SP(pn->statusp))) ?
- 0200 | WTERMSIG(SP(pn->statusp)) : WEXITSTATUS(SP(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)
- gettyinfo(&jn->ttyinfo);
- if (job == curjob)
- {
- if (!val)
- gettyinfo(&shttyinfo);
- else
- settyinfo(&shttyinfo);
- lastval = val;
- }
- if (jn->stat & STAT_STOPPED)
- {
- prevjob = topjob;
- topjob = job;
- }
- if ((isset(NOTIFY) || job == curjob) && jn->stat & STAT_LOCKED)
- printjob(jn,0);
- if (sigtrapped[SIGCHLD] && job != curjob)
- dotrap(SIGCHLD);
-}
-
-/* find procnode and jobnode associated with pid */
-
-void findproc(int pid,struct jobnode **jptr,struct procnode **pptr)
-{
-struct procnode *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;
-}
-
-static char *sigmsg[32] = {
- "done","hangup","interrupt","quit",
- "illegal instruction","trace trap","IOT instruction","EMT instruction",
- "floating exception","killed","bus error","segmentation fault",
- "bad system call","broken pipe","SIGALRM","terminated",
-#ifdef USE_SUSPENDED
- "SIGURG","suspended (signal)","suspended","continued",
- "SIGCHLD","suspended (tty input)","suspended (tty output)","SIGIO",
-#else
- "SIGURG","stopped (signal)","stopped","continued",
- "SIGCHLD","stopped (tty input)","stopped (tty output)","SIGIO",
-#endif
- "CPU time limit exceeded","file size limit exceeded","SIGVTALRM","SIGPROF",
- "window changed","resource lost","SIGUSR1","SIGUSR2"
- };
-
-/* lng = 0 means jobs
- lng = 1 means jobs -l
- lng = 2 means jobs -p
-*/
-
-void printjob(struct jobnode *jn,int lng)
-{
-int job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0;
-int conted = 0,lineleng = getlineleng(),doputnl = 0;
-struct procnode *pn;
-extern void rl_on_new_line(void);
-
- 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(SP(pn->statusp)))
- {
- sig = WTERMSIG(SP(pn->statusp));
- llen = strlen(sigmsg[sig]);
- if (WCOREDUMPED(pn->statusp))
- llen += 14;
- if (llen > len)
- len = llen;
- if (sig != SIGINT && sig != SIGPIPE)
- sflag = 1;
- if (sig == SIGINT && job == curjob && interact)
- doputnl = 1;
- }
- else if (WIFSTOPPED(SP(pn->statusp)))
- {
- sig = WSTOPSIG(SP(pn->statusp));
- if (strlen(sigmsg[sig]) > len)
- len = strlen(sigmsg[sig]);
- }
- else if (isset(PRINTEXITVALUE) && WEXITSTATUS(SP(pn->statusp)))
- sflag = 1;
- }
- if (doputnl)
- putc('\n',stderr);
-
- /* print if necessary */
-
- if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
- job != curjob))
- {
- int len2,fline = 1;
- struct procnode *qn;
-
- if (handling && (!waiting || jn->stat & STAT_STOPPED))
- putc('\n',stderr);
- for (pn = jn->procs; pn;)
- {
- len2 = ((job == curjob) ? 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 != curjob)
- if (fline)
- fprintf(stderr,"[%d] %c ",jn-jobtab,(job == topjob) ? '+' :
- (job == prevjob) ? '-' : ' ');
- else
- fprintf(stderr,(job > 9) ? " " : " ");
- else
- fprintf(stderr,"zsh: ");
- if (lng)
- if (lng == 1)
- fprintf(stderr,"%d ",pn->pid);
- else
- {
- fprintf(stderr,"%d ",jn->gleader);
- lng = 0;
- }
- 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(SP(pn->statusp)))
- if (WEXITSTATUS(SP(pn->statusp)))
- fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(SP(pn->statusp)),
- len-9+2,"");
- else
- fprintf(stderr,"done%*s",len-4+2,"");
- else if (WIFSTOPPED(SP(pn->statusp)))
- fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(SP(pn->statusp))]);
- else if (WCOREDUMPED(pn->statusp))
- fprintf(stderr,"%s (core dumped)%*s",
- sigmsg[WTERMSIG(SP(pn->statusp))],
- len-14+2-strlen(sigmsg[WTERMSIG(SP(pn->statusp))]),"");
- else
- fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(SP(pn->statusp))]);
- for (; pn != qn; pn = pn->next)
- fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
- putc('\n',stderr);
- fline = 0;
- }
- printed = 1;
- }
-
- /* print "(pwd now: foo)" messages */
-
- if (interact && job==curjob && strcmp(jn->cwd,cwd))
- {
- printf("(pwd now: ");
- printdir(cwd);
- printf(")\n");
- fflush(stdout);
- }
-
- /* delete job if done */
-
- if (jn->stat & STAT_DONE)
- {
- static struct jobnode zero;
- struct procnode *nx;
- char *s;
-
- if (jn->stat & STAT_TIMED)
- {
- dumptime(jn);
- printed = 1;
- }
- for (pn = jn->procs; pn; pn = nx)
- {
- nx = pn->next;
- if (pn->text)
- free(pn->text);
- free(pn);
- }
- free(jn->cwd);
- if (jn->filelist)
- {
- while (s = getnode(jn->filelist))
- {
- unlink(s);
- free(s);
- }
- free(jn->filelist);
- }
- *jn = zero;
- if (job == topjob)
- {
- topjob = prevjob;
- prevjob = job;
- }
- if (job == prevjob)
- setprevjob();
- }
- else
- jn->stat &= ~STAT_CHANGED;
- if (printed && rl_active)
- {
- rl_on_new_line();
- if (rl_waiting)
- rl_redisplay();
- }
-}
-
-/* set the previous job to something reasonable */
-
-void setprevjob(void)
-{
-int t0;
-
- for (t0 = MAXJOB-1; t0; t0--)
- if (jobtab[t0].stat && jobtab[t0].stat & STAT_STOPPED &&
- t0 != topjob && t0 != curjob)
- break;
- if (!t0)
- for (t0 = MAXJOB-1; t0; t0--)
- if (jobtab[t0].stat && t0 != topjob && t0 != curjob)
- break;
- prevjob = (t0) ? t0 : -1;
-}
-
-/* initialize a job table entry */
-
-void initjob(int flags)
-{
- jobtab[curjob].cwd = strdup(cwd);
- jobtab[curjob].stat = (flags & PFLAG_TIMED) | STAT_INUSE;
- jobtab[curjob].ttyinfo = shttyinfo;
- jobtab[curjob].gleader = 0;
-}
-
-/* add a process to the current job */
-
-struct procnode *addproc(long pid,char *text)
-{
-struct procnode *procnode;
-
- if (!jobtab[curjob].gleader)
- jobtab[curjob].gleader = proclast = pid;
- proclast = pid;
- procnode = alloc(sizeof(struct procnode));
- procnode->pid = pid;
- procnode->text = text;
- procnode->next = NULL;
- procnode->statusp = SP_RUNNING;
- procnode->bgtime = time(NULL);
- if (jobtab[curjob].procs)
- {
- struct procnode *n;
-
- for (n = jobtab[curjob].procs; n->next && !n->next->lastfg; n = n->next);
- procnode->next = n->next;
- n->next = procnode;
- }
- else
- jobtab[curjob].procs = procnode;
- return procnode;
-}
-
-/* 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(void)
-{
-struct jobnode *jn;
-
- if (!exiting)
- return 0;
- for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
- if (jn->stat && jn->filelist)
- return 0;
- return 1;
-}
-
-/* wait for a SIGCHLD, wait for the handler to execute, and return */
-
-void chldsuspend(void)
-{
-struct sigvec vec = { handler,sigmask(SIGCHLD),SV_INTERRUPT };
-
- sigvec(SIGCHLD,&vec,NULL);
- sigpause(0);
- signal(SIGCHLD,handler);
-}
-
-/* wait for the current job to finish */
-
-void waitjobs(void)
-{
-static struct jobnode zero;
-struct jobnode *jn;
-
- if (jobtab[curjob].procs) /* if any forks were done */
- {
- jobtab[curjob].stat |= STAT_LOCKED;
- waiting = 1;
- if (jobtab[curjob].stat & STAT_CHANGED)
- printjob(jobtab+curjob,0);
- while (jobtab[curjob].stat &&
- !(jobtab[curjob].stat & (STAT_DONE|STAT_STOPPED)))
- chldsuspend();
- waiting = 0;
- }
- else /* else do what printjob() usually does */
- {
- char *s;
-
- jn = jobtab+curjob;
- free(jn->cwd);
- if (jn->filelist)
- {
- while (s = getnode(jn->filelist))
- {
- unlink(s);
- free(s);
- }
- free(jn->filelist);
- }
- *jn = zero;
- }
- curjob = -1;
-}
-
-/* clear jobtab when entering subshells */
-
-void clearjobtab(void)
-{
-static struct jobnode zero;
-int t0;
-
- for (t0 = 1; t0 != MAXJOB; t0++)
- jobtab[curjob] = zero;
-}
-
-/* get a free entry in the job table to use */
-
-int getfreejob(void)
-{
-int mask,t0;
-
- FOREVER
- {
- mask = sigblock(sigmask(SIGCHLD));
- for (t0 = 1; t0 != MAXJOB; t0++)
- if (!jobtab[t0].stat)
- {
- sigsetmask(mask);
- jobtab[t0].stat |= STAT_INUSE;
- return t0;
- }
- sigsetmask(mask);
- sleep(1);
- }
-}
-
-/* print pids for & */
-
-void spawnjob(void)
-{
-struct procnode *pn;
-
- if (!subsh)
- {
- if (topjob == -1 || !(jobtab[topjob].stat & STAT_STOPPED))
- {
- topjob = curjob;
- setprevjob();
- }
- else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
- prevjob = curjob;
- if (interact && jobbing)
- {
- fprintf(stderr,"[%d]",curjob);
- for (pn = jobtab[curjob].procs; pn; pn = pn->next)
- fprintf(stderr," %d",pn->pid);
- fprintf(stderr,"\n");
- }
- }
- jobtab[curjob].stat |= STAT_LOCKED;
- curjob = -1;
-}
-
-void fixsigs(void)
-{
- sigsetmask(0);
-}
-
-/* timing */
-
-static void addtimeval(struct timeval *s,struct timeval *t)
-{
- s->tv_sec += t->tv_sec+(s->tv_usec+t->tv_usec)/1000000;
- s->tv_usec = (s->tv_usec+t->tv_usec)%1000000;
-}
-
-static void printtime(time_t real,struct timeval *u,struct timeval *s,char *desc)
-{
- if (!desc)
- desc = "";
- fprintf(stderr,"real: %lds user: %ld.%03lds sys: %ld.%03lds\n",
- real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000);
-}
-
-static void printheader(void)
-{
- fprintf(stderr," real user system\n");
-}
-
-static void printtimes(time_t real,struct timeval *u,struct timeval *s,char *desc)
-{
- if (!desc)
- desc = "";
- fprintf(stderr,"% 8lds % 4d.%03lds % 4d.%03lds %s\n",
- real,u->tv_sec,u->tv_usec/1000,s->tv_sec,s->tv_usec/1000,desc);
-}
-
-void dumptime(struct jobnode *jn)
-{
-struct procnode *pn = jn->procs;
-struct timeval utot = { 0,0 },stot = { 0,0 };
-time_t maxend,minbeg;
-
- if (!jn->procs)
- return;
- if (!jn->procs->next)
- printtime(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text);
- else
- {
- maxend = jn->procs->endtime;
- minbeg = jn->procs->bgtime;
- printheader();
- for (pn = jn->procs; pn; pn = pn->next)
- {
- printtimes(pn->endtime-pn->bgtime,&pn->ru_utime,&pn->ru_stime,pn->text);
- addtimeval(&utot,&pn->ru_utime);
- addtimeval(&stot,&pn->ru_stime);
- if (pn->endtime > maxend)
- maxend = pn->endtime;
- if (pn->bgtime < minbeg)
- minbeg = pn->bgtime;
- }
- printtimes(maxend-minbeg,&utot,&stot,"total");
- }
-}
-
-/* SIGHUP any jobs left running */
-
-void killrunjobs(void)
-{
-int t0,killed = 0;
-
- for (t0 = 1; t0 != MAXJOB; t0++)
- if (t0 != curjob && jobtab[t0].stat &&
- !(jobtab[t0].stat & STAT_STOPPED))
- {
- killpg(jobtab[t0].gleader,SIGHUP);
- killed++;
- }
- if (killed)
- zerr("warning: %d jobs SIGHUPed",killed);
-}
-
-/* check to see if user has jobs running/stopped */
-
-void checkjobs(void)
-{
-int t0;
-
- for (t0 = 1; t0 != MAXJOB; t0++)
- if (t0 != curjob && jobtab[t0].stat)
- break;
- if (t0 != MAXJOB)
- {
- if (jobtab[t0].stat & STAT_STOPPED)
- {
-#ifdef USE_SUSPENDED
- zerr("you have suspended jobs.");
-#else
- zerr("you have stopped jobs.");
-#endif
- }
- else
- zerr("you have running jobs.");
- stopmsg = 1;
- }
-}
-
-/* send a signal to a job (simply involves killpg if monitoring is on) */
-
-int killjb(struct jobnode *jn,int sig)
-{
-struct procnode *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;
-}
-
End of jobs.c
echo jobs.pro 1>&2
sed 's/^-//' >jobs.pro <<'End of jobs.pro'
-HANDTYPE handler(int sig,int code);
-void makerunning(struct jobnode *jn);
-void updatestatus(struct jobnode *jn);
-void findproc(int pid,struct jobnode **jptr,struct procnode **pptr);
-void printjob(struct jobnode *jn,int lng);
-void setprevjob(void);
-void initjob(int flags);
-struct procnode *addproc(long pid,char *text);
-int execok(void);
-void chldsuspend(void);
-void waitjobs(void);
-void clearjobtab(void);
-int getfreejob(void);
-void spawnjob(void);
-void fixsigs(void);
-void dumptime(struct jobnode *jn);
-void killrunjobs(void);
-void checkjobs(void);
-int killjb(struct jobnode *jn,int sig);
End of jobs.pro
echo lex.c 1>&2
sed 's/^-//' >lex.c <<'End of lex.c'
-/*
-
- lex.c - lexical analysis
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-
-/* match the current token and get another
- (actually just get another) */
-
-void matchit(void)
-{
- do
- gettok();
- while (exalias());
-}
-
-int len = 0,bsiz = 256;
-char *bptr;
-
-/* add a char to the string buffer */
-
-void add(int c)
-{
- *bptr++ = c;
- if (bsiz == ++len)
- bptr = len+(tstr = realloc(tstr,bsiz *= 2));
-}
-
-/* get a token */
-
-void gettok(void)
-{
-int bct = 0,pct = 0;
-int c,d,intpos = 1;
-static int dbparens = 0;
-
-beginning:
- hlastw = NULL;
- tstr = NULL;
- while (zspace(c = hgetc()) || c == '\t' || c == ' ');
- firstln = 0;
- hwbegin();
- hwaddc(c);
- if (dbparens) /* handle ((...)) */
- {
- int pct = 2;
-
- peek = STRING;
- len = dbparens = 0;
- bptr = tstr = zalloc(bsiz = 256);
- for (;;)
- {
- if (c == '(')
- pct++;
- else if (c == ')')
- pct--;
- else if (c == '\n')
- {
- zerr("parse error: )) expected");
- peek = HERR;
- free(tstr);
- return;
- }
- else if (c == '$')
- c = Qstring;
- if (pct >= 2)
- add(c);
- if (pct)
- c = hgetc();
- else
- break;
- }
- *bptr = '\0';
- return;
- }
- peekfd = -1;
- if (isdigit(c)) /* handle 1< foo */
- {
- d = hgetc();
- hungetc(d);
- if (d == '>' || d == '<')
- {
- peekfd = c-'0';
- c = hgetc();
- }
- }
-
- /* chars in initial position in word */
-
- switch (c)
- {
- case '\\':
- d = hgetc();
- if (d == '\n')
- goto beginning;
- hungetc(d);
- break;
- case EOF:
- peek = EOF;
- return;
- case HERR:
- peek = HERR;
- return;
- case '\n':
- peek = NEWLIN;
- return;
- case ';':
- d = hgetc();
- if (d != ';')
- {
- hungetc(d);
- peek = SEMI;
- }
- else
- peek = DSEMI;
- return;
- case '!':
- if (!incmd)
- {
- peek = BANG;
- return;
- }
- break;
- case '&':
- d = hgetc();
- if (d != '&')
- {
- hungetc(d);
- peek = AMPER;
- }
- else
- peek = DAMPER;
- return;
- case '|':
- d = hgetc();
- if (d == '|')
- peek = DBAR;
- else if (d == '&')
- peek = BARAMP;
- else
- {
- hungetc(d);
- peek = BAR;
- }
- return;
- case '(':
- if (incmd)
- break;
- d = hgetc();
- if (d == '(')
- {
- peek = STRING;
- tstr = strdup("let");
- dbparens = 1;
- return;
- }
- hungetc(d);
- peek = INPAR;
- return;
- case ')':
- peek = OUTPAR;
- return;
- case '{':
- if (incmd)
- break;
- peek = INBRACE;
- return;
- case '}':
- peek = OUTBRACE;
- return;
- case '<':
- d = hgetc();
- if (incmd && d == '(')
- {
- hungetc(d);
- break;
- }
- else if (d == '<')
- {
- int e = hgetc();
-
- hungetc(e);
- if (e == '(')
- {
- hungetc(d);
- peek = INANG;
- }
- else
- peek = DINANG;
- }
- else if (d == '&')
- peek = INANGAMP;
- else
- {
- peek = INANG;
- hungetc(d);
- }
- return;
- case '>':
- 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;
- }
- }
- else
- {
- hungetc(d);
- peek = OUTANG;
- }
- return;
- case '#':
-#ifndef INTERACTIVE_COMMENTS
- if (interact)
- break;
-#endif
- while ((c = hgetch()) != '\n' && !istok(c) && c != EOF);
- if (c == '\n')
- peek = NEWLIN;
- else
- errflag = 1;
- return;
- }
-
- /* we've started a string, now get the rest of it, performing
- tokenization */
-
- peek = STRING;
- len = 0;
- bptr = tstr = zalloc(bsiz = 256);
- for(;;)
- {
- if (c == ';' || c == '&' || c == EOF ||
- c == HERR || c == '\03' || c == '\n' ||
- c == ' ' || c == '\t' || znspace(c))
- break;
- if (c == '#')
- c = Pound;
- else if (c == ')')
- {
- if (!pct)
- break;
- pct--;
- c = Outpar;
- }
- else if (c == ',')
- c = Comma;
- else if (c == '|')
- {
- if (!pct)
- break;
- c = Bar;
- }
- else if (c == '$')
- {
- d = hgetc();
-
- c = String;
- if (d == '[')
- {
- add(String);
- add(Inbrack);
- while ((c = hgetc()) != ']' && !istok(c) && c != EOF)
- add(c);
- c = Outbrack;
- }
- else if (d == '(')
- {
- add(String);
- skipcomm();
- c = Outpar;
- }
- else
- hungetc(d);
- }
- else if (c == '^')
- c = Hat;
- else if (c == '[')
- c = Inbrack;
- else if (c == ']')
- c = Outbrack;
- else if (c == '*')
- c = Star;
- else if (intpos && c == '~')
- c = Tilde;
- else if (c == '?')
- c = Quest;
- else if (c == '(')
- {
- int d = hgetc();
-
- hungetc(d);
- if (!incmd)
- break;
-#if 0
- if (d != ')' && intpos)
- {
- add(Inang);
- skipcomm();
- c = Outpar;
- }
- else
-#endif
- {
- pct++;
- c = Inpar;
- }
- }
- else if (c == '{')
- {
- c = Inbrace;
- bct++;
- }
- else if (c == '}')
- {
- if (!bct)
- break;
- c = Outbrace;
- bct--;
- }
- else if (c == '>')
- {
- d = hgetc();
- if (d != '(')
- {
- hungetc(d);
- break;
- }
- add(Outang);
- skipcomm();
- c = Outpar;
- }
- else if (c == '<')
- {
- d = hgetc();
- if (!(isdigit(d) || d == '-' || d == '>' || d == '(' || d == ')'))
- {
- hungetc(d);
- break;
- }
- c = Inang;
- if (d == '(')
- {
- add(c);
- skipcomm();
- c = Outpar;
- }
- else if (d == ')')
- hungetc(d);
- else
- {
- add(c);
- c = d;
- while (c != '>' && !istok(c) && c != EOF)
- add(c),c = hgetc();
- if (c == EOF)
- {
- errflag = 1;
- peek = EOF;
- return;
- }
- c = Outang;
- }
- }
- else if (c == '=')
- {
- if (intpos)
- {
- d = hgetc();
- if (d != '(')
- {
- hungetc(d);
- c = Equals;
- }
- else
- {
- add(Equals);
- skipcomm();
- c = Outpar;
- }
- }
- else if (peek != ENVSTRING)
- {
- peek = ENVSTRING;
- intpos = 2;
- }
- }
- else if (c == '\\')
- {
- c = hgetc();
-
- if (c == '\n')
- {
- c = hgetc();
- continue;
- }
- add(c);
- c = hgetc();
- continue;
- }
- else if (c == '\'')
- {
- add(Nularg);
-
- /* we add the Nularg to prevent this:
-
- echo $PA'TH'
-
- from printing the path. */
-
- while ((c = hgetc()) != '\'' && !istok(c) && c != EOF)
- add(c);
- if (c == EOF)
- {
- errflag = 1;
- peek = EOF;
- return;
- }
- c = Nularg;
- }
- else if (c == HQUOT)
- {
- add(Nularg);
- while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF)
- add(c);
- if (c == EOF)
- {
- errflag = 1;
- peek = EOF;
- return;
- }
- c = Nularg;
- }
- else if (c == '\"')
- {
- add(Nularg);
- while ((c = hgetc()) != '\"' && !istok(c) && c != EOF)
- if (c == '\\')
- {
- c = hgetc();
- if (c != '\n')
- {
- if (c != '$' && c != '\\' && c != '\"' && c != '`')
- add('\\');
- add(c);
- }
- }
- else
- {
- if (c == '$')
- {
- int d = hgetc();
-
- if (d == '(')
- {
- add(Qstring);
- skipcomm();
- c = Outpar;
- }
- else if (d == '[')
- {
- add(String);
- add(Inbrack);
- while ((c = hgetc()) != ']' && c != EOF)
- add(c);
- c = Outbrack;
- }
- else
- {
- c = Qstring;
- hungetc(d);
- }
- }
- else if (c == '`')
- c = Qtick;
- add(c);
- }
- if (c == EOF)
- {
- errflag = 1;
- peek = EOF;
- return;
- }
- c = Nularg;
- }
- else if (c == '`')
- {
- add(Tick);
- while ((c = hgetc()) != '`' && !istok(c) && c != EOF)
- if (c == '\\')
- {
- c = hgetc();
- if (c != '\n')
- {
- if (c != '`' && c != '\\' && c != '$')
- add('\\');
- add(c);
- }
- }
- else
- {
- if (c == '$')
- c = String;
- add(c);
- }
- if (c == EOF)
- {
- errflag = 1;
- peek = EOF;
- return;
- }
- c = Tick;
- }
- add(c);
- c = hgetc();
- if (intpos)
- intpos--;
- }
- if (c == HERR)
- {
- free(tstr);
- peek = HERR;
- return;
- }
- hungetc(c);
- *bptr = '\0';
-}
-
-/* expand aliases, perhaps */
-
-int exalias(void)
-{
-struct anode *an;
-char *s;
-
- s = hwadd();
- if (alix != MAXAL && (an = gethnode(s,alhtab)) && !an->inuse &&
- !(an->cmd && incmd && alstat != ALSTAT_MORE))
- {
- if (an->cmd < 0)
- {
- peek = DO-an->cmd-1;
- return 0;
- }
- an->inuse = 1;
- hungets(strdup(ALPOPS));
- hungets(strdup((alstack[alix++] = an)->text));
- alstat = 0;
- if (tstr)
- free(tstr);
- return 1;
- }
- return 0;
-}
-
-/* != 0 if c is not a newline, but in IFS */
-
-int zspace(int c)
-{
- if (c == '\n')
- return 0;
- return znspace(c);
-}
-
-/* != 0 if c is in IFS */
-
-int znspace(int c)
-{
-char *ptr = ifs;
-
- while (*ptr)
- if (*ptr++ == c)
- return 1;
- return 0;
-}
-
-/* skip (...) */
-
-void skipcomm(void)
-{
-int pct = 1,c;
-
- c = Inpar;
- do
- {
- add(c);
-reget:
- c = hgetc();
- if (istok(c) || c == EOF)
- break;
- else if (c == '(') pct++;
- else if (c == ')') pct--;
- else if (c == '\\')
- {
- add(c);
- c = hgetc();
- }
- else if (c == '\'')
- {
- add(c);
- while ((c = hgetc()) != '\'' && !istok(c) && c != EOF)
- add(c);
- }
- else if (c == HQUOT)
- {
- while ((c = hgetc()) != HQUOT && !istok(c) && c != EOF)
- add(c);
- goto reget;
- }
- else if (c == '\"')
- {
- add(c);
- while ((c = hgetc()) != '\"' && !istok(c) && c != EOF)
- if (c == '\\')
- {
- add(c);
- add(hgetc());
- }
- else add(c);
- }
- else if (c == '`')
- {
- add(c);
- while ((c = hgetc()) != '`' && c != HERR && c != EOF)
- if (c == '\\') add(c), add(hgetc());
- else add(c);
- }
- }
- while(pct);
-}
-
End of lex.c
echo lex.pro 1>&2
sed 's/^-//' >lex.pro <<'End of lex.pro'
-void matchit(void);
-void add(int c);
-void gettok(void);
-int exalias(void);
-int zspace(int c);
-int znspace(int c);
-void skipcomm(void);
End of lex.pro
echo loop.c 1>&2
sed 's/^-//' >loop.c <<'End of loop.c'
-/*
-
- loop.c - parsing and executing loop constructs
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-
-/* parse a for/select loop */
-
-int parfor(comm comm,int isfor)
-{
-struct fornode *node = alloc(sizeof(struct fornode));
-char *comnam = (isfor) ? "for" : "select";
-
- comm->type = (isfor) ? CFOR : CSELECT;
- comm->info = node;
- if (peek != STRING)
- {
- zerr("parse error in %s: identifier expected",comnam);
- errflag = 1;
- return 0;
- }
- node->name = tstr;
- matchit();
- node->list = NULL;
- node->inflag = 0;
- if (peek == STRING && !strcmp("in",tstr))
- {
- node->inflag = 1;
- free(tstr);
- matchit();
- while (peek == STRING)
- {
- addnode(comm->args,tstr);
- matchit();
- }
- }
- if (peek != NEWLIN && peek != SEMI)
- {
- zerr("parse error: bad token in '%s' list",comnam);
- freecmd(comm);
- return 1;
- }
- incmd = 0;
- matchit();
- while (peek == NEWLIN)
- matchit();
- if (peek != DO)
- {
- zerr("parse error: 'do' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- if (!(node->list = parlist(1)))
- {
- freecmd(comm);
- return 1;
- }
- if (peek != DONE)
- {
- zerr("parse error: 'done' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- return 0;
-}
-
-int parcase(comm comm)
-{
-struct casenode *node = alloc(sizeof(struct casenode)),*last = NULL;
-char *tok; /* add FREES to this function */
-
- comm->type = CCASE;
- comm->info = node;
- if (peek != STRING)
- {
- zerr("parse error in case: identifier expected");
- errflag = 1;
- return 0;
- }
- addnode(comm->args,tstr);
- matchit();
- if (peek != STRING || strcmp(tstr,"in"))
- {
- zerr("parse error in case: `in' expected");
- errflag = 1;
- return 0;
- }
- while (tok = getcasepat())
- {
- node = alloc(sizeof(struct casenode));
- node->pat = tok;
- if (last)
- last->next = node;
- else
- comm->info = node;
- (last = node)->list = parlist(1);
- if (peek != DSEMI)
- {
- zerr("parse error: ;; expected");
- return 1;
- }
- }
- if (!last)
- {
- zerr("null case construct");
- return 1;
- }
- return 0;
-}
-
-/* get a case pattern: foo) */
-
-char *getcasepat(void)
-{
-int c,bsiz = 256,ct = 0,pct = 0,qt = 0;
-char *buf = zalloc(bsiz),*ptr,*s;
-
- peek = EMPTY;
- while (znspace(c = hgetc()))
- {
- if (c == '\n')
- {
- hwbegin();
- hwaddc('\n');
- hwadd();
- }
- }
- ptr = buf;
- hwbegin();
- hwaddc(c);
- while (c != ')' || pct)
- {
- for (s = tokens; *s; s++)
- if (*s == c)
- {
- c = (s-tokens)+Pound;
- break;
- }
- if (qt)
- {
- if (c == '\'')
- {
- qt = 0;
- c = hgetc();
- continue;
- }
- if (c == EOF)
- {
- qt = 0;
- continue;
- }
- }
- else
- {
- if (c == '\\')
- c = hgetc();
- if (c == '\'')
- {
- qt = 1;
- c = hgetc();
- continue;
- }
- if (c == Inpar)
- pct++;
- if (c == Outpar)
- pct--;
- if (ct == 4 && (znspace(c)||c ==';'||c=='&') && !strncmp(buf,"esac",4))
- {
- hungetc(c);
- hwadd();
- free(buf);
- matchit();
- return NULL;
- }
- if (c == '\n' || c == EOF)
- {
- free(buf);
- zerr("parse error: 'esac' expected");
- return NULL;
- }
- }
- if (c == HERR)
- {
- free(buf);
- return NULL;
- }
- *ptr++ = c;
- if (++ct == bsiz)
- {
- ptr = zalloc(bsiz *= 2);
- memcpy(ptr,buf,ct);
- free(buf);
- buf = ptr;
- ptr = buf+ct;
- }
- c = hgetc();
- }
- *ptr = 0;
- hwadd();
- return buf;
-}
-
-int parif(comm comm)
-{
-struct ifnode *node = alloc(sizeof(struct ifnode));
-
- comm->type = CIF;
- comm->info = node;
-do_then:
- node->next = NULL;
- if (!(node->ifl = parlist(1)))
- {
- freecmd(comm);
- return 1;
- }
- if (peek != THEN)
- {
- zerr("parse error: 'then' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- if (!(node->thenl = parlist(1)))
- {
- freecmd(comm);
- return 1;
- }
- if (peek == ELIF)
- {
- matchit();
- node = node->next = alloc(sizeof(struct ifnode));
- goto do_then;
- }
- else if (peek == ELSE)
- {
- matchit();
- node = node->next = alloc(sizeof(struct ifnode));
- node->next = NULL;
- node->ifl = NULL;
- if (!(node->thenl = parlist(1)))
- {
- freecmd(comm);
- return 1;
- }
- }
- if (peek != FI)
- {
- zerr("parse error: 'fi' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- return 0;
-}
-
-/* parse while or until */
-
-int parwhile(comm comm,int cond)
-{
-struct whilenode *node = alloc(sizeof (struct whilenode));
-
- comm->type = CWHILE;
- comm->info = node;
- node->cond = cond;
- node->loop = node->cont = NULL;
- if (!(node->cont = parlist(1)))
- {
- freecmd(comm);
- return NULL;
- }
- if (peek != DO)
- {
- zerr("parse error: 'do' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- node->loop = parlist(1);
- if (peek != DONE)
- {
- zerr("parse error: 'done' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- return 0;
-}
-
-int parrepeat(comm comm)
-{
-struct repeatnode *node = alloc(sizeof (struct repeatnode));
-
- comm->type = CREPEAT;
- comm->info = node;
- node->list = NULL;
- if (peek != STRING || !isdigit(*tstr))
- {
- zerr("parse error: number expected");
- freecmd(comm);
- return 1;
- }
- node->count = atoi(tstr);
- free(tstr);
- incmd = 0;
- do
- matchit();
- while (peek == NEWLIN);
- if (peek != DO)
- {
- zerr("parse error: 'do' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- node->list = parlist(1);
- if (peek != DONE)
- {
- zerr("parse error: 'done' expected");
- freecmd(comm);
- return 1;
- }
- matchit();
- return 0;
-}
-
-void execfor(comm comm)
-{
-list list;
-struct fornode *node;
-char *str;
-table args;
-int cj = curjob;
-
- loops++;
- exiting = 0;
- node = comm->info;
- args = comm->args;
- if (!node->inflag)
- {
- args = duptable(pparms,dupstr);
- freestr(getnode(args));
- }
- while (str = getnode(args))
- {
- setparm(strdup(node->name),str,0,0);
- list = duplist(node->list);
- execlist(list);
- if (breaks)
- {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- }
- curjob = cj;
-}
-
-void execselect(comm comm)
-{
-list list;
-struct fornode *node;
-char *str,*s;
-table args;
-Node n;
-int cj = curjob,t0;
-
- loops++;
- node = comm->info;
- args = comm->args;
- exiting = 0;
- for (;;)
- {
- do
- {
- for (t0 = 1,n = args->first; n; n=n->next,t0++)
- fprintf(stderr,"%d %s\n",t0,n->dat);
- if (interact && SHTTY != -1)
- {
- inittty();
- str = readline(putprompt("PROMPT3"));
- }
- else
- str = fgets(zalloc(256),256,bshin);
- if (!str || errflag)
- {
- fprintf(stderr,"\n");
- goto done;
- }
- if (s = strchr(str,'\n'))
- *s = '\0';
- }
- while (!*str);
- setparm(strdup("REPLY"),str,0,0);
- t0 = atoi(str);
- if (!t0)
- str = "";
- else
- {
- for (t0--,n = args->first; n && t0; n=n->next,t0--);
- if (n)
- str = n->dat;
- else
- str = "";
- }
- setparm(strdup(node->name),strdup(str),0,0);
- list = duplist(node->list);
- execlist(list);
- if (breaks)
- {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (errflag)
- break;
- }
-done:
- curjob = cj;
-}
-
-void execwhile(comm comm)
-{
-list list;
-struct whilenode *node;
-int cj = curjob;
-
- loops++;
- node = comm->info;
- exiting = 0;
- FOREVER
- {
- list = duplist(node->cont);
- execlist(list);
- if (!((lastval == 0) ^ node->cond))
- break;
- if (breaks)
- {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- list = duplist(node->loop);
- execlist(list);
- }
- curjob = cj;
-}
-
-void execrepeat(comm comm)
-{
-list list;
-struct repeatnode *node;
-int cj = curjob;
-
- loops++;
- node = comm->info;
- exiting = 0;
- while (node->count--)
- {
- list = duplist(node->list);
- execlist(list);
- if (breaks)
- {
- breaks--;
- if (breaks || !contflag)
- break;
- contflag = 0;
- }
- if (lastval)
- break;
- }
- curjob = cj;
-}
-
-void execif(comm comm)
-{
-list list;
-struct ifnode *node;
-int cj = curjob;
-
- node = comm->info;
- exiting = 0;
- while (node)
- {
- if (node->ifl)
- {
- list = duplist(node->ifl);
- execlist(list);
- if (lastval)
- {
- node = node->next;
- continue;
- }
- }
- list = duplist(node->thenl);
- execlist(list);
- break;
- }
- curjob = cj;
-}
-
-void execcase(comm comm)
-{
-list list;
-struct casenode *node;
-char *word;
-table args;
-int cj = curjob;
-
- node = comm->info;
- args = comm->args;
- exiting = 0;
- if (!args->first || args->first->next)
- {
- zerr("bad case statement");
- errflag = 1;
- return;
- }
- word = args->first->dat;
- while (node)
- if (matchpat(word,node->pat))
- break;
- else
- node = node->next;
- if (node)
- {
- list = duplist(node->list);
- execlist(list);
- }
- curjob = cj;
-}
-
-list duplist(list xlist)
-{
-list nlist;
-
- if (!xlist)
- return NULL;
- nlist = alloc(sizeof(struct lnode));
- nlist->left = duplist2(xlist->left);
- nlist->right = duplist(xlist->right);
- nlist->type = xlist->type;
- return nlist;
-}
-
-void freelist(list xlist)
-{
- if (xlist)
- {
- freelist2(xlist->left);
- freelist(xlist->right);
- free(xlist);
- }
-}
-
-list2 duplist2(list2 x)
-{
-list2 y;
-
- if (!x)
- return NULL;
- y = alloc(sizeof(struct l2node));
- *y = *x;
- y->left = duppline(x->left);
- y->right = duplist2(x->right);
- return y;
-}
-
-void freelist2(list2 x)
-{
- if (x)
- {
- freepline(x->left);
- freelist2(x->right);
- free(x);
- }
-}
-
-pline duppline(pline xpline)
-{
-pline npline;
-
- if (!xpline)
- return NULL;
- npline = alloc(sizeof(struct pnode));
- npline->left = dupcomm(xpline->left);
- npline->right = duppline(xpline->right);
- npline->type = xpline->type;
- return npline;
-}
-
-void freepline(pline x)
-{
- if (x)
- {
- freecmd(x->left);
- freepline(x->right);
- free(x);
- }
-}
-
-comm dupcomm(comm xcomm)
-{
-comm ncomm;
-void *(*duprs[])(void *) = {dupfor,dupwhile,duprepeat,dupif,dupcase};
-int type;
-
- if (!xcomm)
- return NULL;
- ncomm = alloc(sizeof(struct cnode));
- ncomm->left = duplist(xcomm->left);
- ncomm->cmd = dupstr(xcomm->cmd);
- ncomm->args = duptable(xcomm->args,dupstr);
- ncomm->redir = duptable(xcomm->redir,dupfnode);
- ncomm->vars = (xcomm->vars) ? duptable(xcomm->vars,dupstr) : NULL;
- ncomm->type = type = xcomm->type;
- if (type >= CFOR && type <= CCASE)
- ncomm->info = (duprs[type-CFOR])(xcomm->info);
- return ncomm;
-}
-
-void freecmd(comm x)
-{
- if (x)
- {
- freelist(x->left);
- if (x->cmd)
- free(x->cmd);
- if (x->args)
- freetable(x->args,freestr);
- if (x->redir)
- freetable(x->redir,freeredir);
- if (x->vars)
- freetable(x->vars,freestr);
-/* if (x->info)
- freeinfo(x->info);*/
- free(x);
- }
-}
-
-void *dupstr(void *str)
-{
- if (!str)
- return NULL;
- return strdup(str);
-}
-
-void *dupfnode(void *i)
-{
-struct fnode *fn = i,*nfn = alloc(sizeof(struct fnode));
-
- if (!i)
- return NULL;
- *nfn = *fn;
- if (nfn->type < HEREDOC)
- nfn->u.name = strdup(fn->u.name);
- return nfn;
-}
-
-void *dupfor(void *i)
-{
-struct fornode *nnode,*node = i;
-
- nnode = alloc(sizeof(struct fornode));
- *nnode = *(struct fornode *) i;
- nnode->name = strdup(node->name);
- nnode->list = duplist(node->list);
- return nnode;
-}
-
-void *dupcase(void *i)
-{
-struct casenode *nnode,*node = i;
-
- if (!i)
- return NULL;
- nnode = alloc(sizeof(struct casenode));
- nnode->next = dupcase(node->next);
- nnode->list = duplist(node->list);
- nnode->pat = strdup(node->pat);
- return nnode;
-}
-
-void *dupif(void *i)
-{
-struct ifnode *nnode,*node = i;
-
- if (!i)
- return NULL;
- nnode = alloc(sizeof(struct ifnode));
- nnode->next = dupif(node->next);
- nnode->ifl = duplist(node->ifl);
- nnode->thenl = duplist(node->thenl);
- return nnode;
-}
-
-void *dupwhile(void *i)
-{
-struct whilenode *nnode,*node = i;
-
- if (!i)
- return NULL;
- nnode = alloc(sizeof(struct whilenode));
- nnode->cond = node->cond;
- nnode->cont = duplist(node->cont);
- nnode->loop = duplist(node->loop);
- return nnode;
-}
-
-void *duprepeat(void *i)
-{
-struct repeatnode *nnode,*node = i;
-
- if (!i)
- return NULL;
- nnode = alloc(sizeof(struct repeatnode));
- nnode->count = node->count;
- nnode->list = duplist(node->list);
- return nnode;
-}
-
-table duptable(table tab,void *(*func)(void *))
-{
-table ret;
-Node node;
-
- ret = newtable();
- for (node = tab->first; node; node = node->next)
- addnode(ret,func(node->dat));
- return ret;
-}
End of loop.c
echo loop.pro 1>&2
sed 's/^-//' >loop.pro <<'End of loop.pro'
-int parfor(comm comm,int isfor);
-int parcase(comm comm);
-char *getcasepat(void);
-int parif(comm comm);
-int parwhile(comm comm,int cond);
-int parrepeat(comm comm);
-void execfor(comm comm);
-void execselect(comm comm);
-void execwhile(comm comm);
-void execrepeat(comm comm);
-void execif(comm comm);
-void execcase(comm comm);
-list duplist(list xlist);
-void freelist(list xlist);
-list2 duplist2(list2 x);
-void freelist2(list2 x);
-pline duppline(pline xpline);
-void freepline(pline x);
-comm dupcomm(comm xcomm);
-void freecmd(comm x);
-void *dupstr(void *str);
-void *dupfnode(void *i);
-void *dupfor(void *i);
-void *dupcase(void *i);
-void *dupif(void *i);
-void *dupwhile(void *i);
-void *duprepeat(void *i);
-table duptable(table tab,void *(*func)(void *));
End of loop.pro
echo math.c 1>&2
sed 's/^-//' >math.c <<'End of math.c'
-/*
-
- math.c - evaluating arithmetic expressions
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-
-extern int errflag;
-extern char *setiparm(char *,long,int);
-extern long getiparm(char *);
-extern void zerr(char *,...);
-extern char *strdup(char *);
-
-char *ptr;
-
-typedef int LV;
-
-long yyval;
-LV yylval;
-
-/* nonzero means we are not evaluating, just parsing */
-
-int noeval = 0;
-
-/* != 0 means recognize unary plus, minus, etc.
- The parser was originally written in lex, hence the name. */
-
-int initial = 1;
-
-void mathparse(int);
-
-/* LR = left-to-right associativity
- RL = right-to-left associativity
- BOO = short-circuiting boolean */
-
-enum xtyp { LR,RL,BOO };
-
-enum xtok {
-INPAR, OUTPAR, NOT, COMP, POSTPLUS,
-POSTMINUS, UPLUS, UMINUS, AND, XOR,
-OR, MUL, DIV, MOD, PLUS,
-MINUS, SHLEFT, SHRIGHT, LES, LEQ,
-GRE, GEQ, DEQ, NEQ, DAND,
-DOR, DXOR, QUEST, COLON, EQ,
-PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ,
-ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ,
-DANDEQ, DOREQ, DXOREQ, COMMA, EOI,
-PREPLUS, PREMINUS, NUM, ID, TOKCOUNT
-};
-
-/* precedences */
-
-int prec[TOKCOUNT] = {
-1,200,2,2,2,
-2,2,2,3,4,
-5,6,6,6,7,
-7,8,8,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
-
-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,BOO,
-BOO,LR,RL,RL,RL,
-RL,RL,RL,RL,RL,
-RL,RL,RL,RL,RL,
-BOO,BOO,RL,RL,RL,
-RL,RL,LR,LR,
-};
-
-#define LVCOUNT 32
-
-/* table of lvalues (variables) */
-
-int lvc;
-char *lvals[LVCOUNT];
-
-int yylex(void)
-{
- for(;;)
- switch (*ptr++)
- {
- case '+':
- if (*ptr == '+' && (initial || !isalnum(*ptr)))
- {
- ptr++;
- return (initial) ? PREPLUS : POSTPLUS;
- }
- if (*ptr == '=') { initial = 1; ptr++; return PLUSEQ; }
- return (initial) ? UPLUS : PLUS;
- case '-':
- if (*ptr == '-' && (initial || !isalnum(*ptr)))
- {
- ptr++;
- return (initial) ? PREMINUS : POSTMINUS;
- }
- if (*ptr == '=') { initial = 1; ptr++; return MINUSEQ; }
- return (initial) ? UMINUS : MINUS;
- case '(': initial = 1; return INPAR;
- case ')': return OUTPAR;
- case '!': if (*ptr == '=')
- { initial = 1; ptr++; return NEQ; }
- return NOT;
- case '~': return COMP;
- case '&': initial = 1;
- if (*ptr == '&') { if (*++ptr == '=')
- { ptr++; return DANDEQ; } return DAND; }
- else if (*ptr == '=') { ptr++; return ANDEQ; } return AND;
- case '|': initial = 1;
- if (*ptr == '|') { if (*++ptr == '=')
- { ptr++; return DOREQ; } return DOR; }
- else if (*ptr == '=') { ptr++; return OREQ; } return OR;
- case '^': initial = 1;
- if (*ptr == '^') { if (*++ptr == '=')
- { ptr++; return DXOREQ; } return DXOR; }
- else if (*ptr == '=') { ptr++; return XOREQ; } return XOR;
- case '*': initial = 1;
- if (*ptr == '=') { ptr++; return MULEQ; } return MUL;
- case '/': initial = 1;
- if (*ptr == '=') { ptr++; return DIVEQ; } return DIV;
- case '%': initial = 1;
- if (*ptr == '=') { ptr++; return MODEQ; } return MOD;
- case '<': initial = 1; if (*ptr == '<')
- { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; }
- else if (*ptr == '=') { ptr++; return LEQ; } return LES;
- case '>': initial = 1; if (*ptr == '>')
- { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; }
- else if (*ptr == '=') { ptr++; return GEQ; } return GRE;
- case '=': initial = 1; if (*ptr == '=') { ptr++; return DEQ; }
- return EQ;
- case '?': initial = 1; return QUEST;
- case ':': initial = 1; return COLON;
- case ',': initial = 1; return COMMA;
- case '\0': initial = 1; ptr--; return EOI;
- case '[': initial = 0;
- { int base = strtol(ptr,&ptr,10);
- yyval = strtol(ptr+1,&ptr,base); return NUM; }
- case ' ': case '\t':
- break;
- default:
- if (isdigit(*--ptr))
- { initial = 0; yyval = strtol(ptr,&ptr,10); return NUM; }
- if (isalpha(*ptr) || *ptr == '$')
- {
- char *p,q;
-
- if (*ptr == '$')
- ptr++;
- p = ptr;
- if (lvc == LVCOUNT)
- {
- zerr("too many identifiers in expression");
- errflag = 1;
- return EOI;
- }
- initial = 0;
- while(isalpha(*++ptr));
- q = *ptr;
- *ptr = '\0';
- lvals[yylval = lvc++] = strdup(p);
- *ptr = q;
- return ID;
- }
- zerr("illegal character: %c",*ptr);
- errflag = 1;
- return EOI;
- }
-}
-
-/* the value stack */
-
-#define STACKSZ 1000
-int tok; /* last token */
-int sp = -1; /* stack pointer */
-struct value {
- LV lval;
- long val;
- } stack[STACKSZ];
-
-void push(long val,LV lval)
-{
- sp++;
- stack[sp].val = val;
- stack[sp].lval = lval;
-}
-
-long getvar(LV s)
-{
-long t;
-
- if (!(t = getiparm(lvals[s])))
- return 0;
- return t;
-}
-
-long setvar(LV s,long v)
-{
- if (s == -1)
- {
- zerr("lvalue required");
- errflag = 1;
- return 0;
- }
- if (noeval)
- return v;
- setiparm(strdup(lvals[s]),v,0);
- return v;
-}
-
-int notzero(int a)
-{
- if (a == 0)
- {
- errflag = 1;
- zerr("division by zero");
- 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(int what)
-{
-long a,b,c;
-LV lv;
-
- 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 SHRIGHT: pop2(); pushv(a>>b); break;
- case LES: pop2(); pushv(a<b); break;
- case LEQ: pop2(); pushv(a<=b); break;
- case GRE: pop2(); pushv(a>b); 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 SHRIGHTEQ: 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: fprintf(stderr,"whoops.\n"); exit(1);
- }
-}
-
-void bop(int tok)
-{
- switch (tok) {
- case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break;
- case DOR: case DOREQ: if (stack[sp].val) noeval++; break;
- };
-}
-
-long matheval(char *s)
-{
-int t0;
-
- for (t0 = 0; t0 != LVCOUNT; t0++)
- lvals[t0] = NULL;
- lvc = 0;
- ptr = s;
- sp = -1;
- mathparse(TOPPREC);
- if (!errflag && sp)
- zerr("arithmetic error: unbalanced stack");
- for (t0 = 0; t0 != lvc; t0++)
- free(lvals[t0]);
- return stack[0].val;
-}
-
-/* operator-precedence parse the string and execute */
-
-void mathparse(int pc)
-{
- if (errflag)
- return;
- tok = yylex();
- while (prec[tok] <= pc)
- {
- if (errflag)
- return;
- if (tok == NUM)
- push(yyval,-1);
- else if (tok == ID)
- push(getvar(yylval),yylval);
- else if (tok == INPAR)
- {
- mathparse(TOPPREC);
- if (tok != OUTPAR)
- exit(1);
- }
- else if (tok == 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 = tok,onoeval = noeval;
-
- if (type[otok] == BOO)
- bop(otok);
- mathparse(prec[otok]-(type[otok] != RL));
- noeval = onoeval;
- op(otok);
- continue;
- }
- tok = yylex();
- }
-}
-
End of math.c
echo math.pro 1>&2
sed 's/^-//' >math.pro <<'End of math.pro'
-INPAR, OUTPAR, NOT, COMP, POSTPLUS,;
-POSTMINUS, UPLUS, UMINUS, AND, XOR,;
-OR, MUL, DIV, MOD, PLUS,;
-MINUS, SHLEFT, SHRIGHT, LES, LEQ,;
-GRE, GEQ, DEQ, NEQ, DAND,;
-DOR, DXOR, QUEST, COLON, EQ,;
-PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ,;
-ANDEQ, XOREQ, OREQ, SHLEFTEQ, SHRIGHTEQ,;
-DANDEQ, DOREQ, DXOREQ, COMMA, EOI,;
-PREPLUS, PREMINUS, NUM, ID, 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,BOO,;
-BOO,LR,RL,RL,RL,;
-RL,RL,RL,RL,RL,;
-RL,RL,RL,RL,RL,;
-BOO,BOO,RL,RL,RL,;
-RL,RL,LR,LR,;
-int yylex(void);
-void push(long val,LV lval);
-long getvar(LV s);
-long setvar(LV s,long v);
-int notzero(int a);
-void op(int what);
-void bop(int tok);
-long matheval(char *s);
-void mathparse(int pc);
End of math.pro
echo parse.c 1>&2
sed 's/^-//' >parse.c <<'End of parse.c'
-/*
-
- parse.c - parsing
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-
-/* parse a list, but return : instead of NULL */
-
-list parlist(int nest)
-{
-list l1;
-list2 l2;
-pline p;
-comm c;
-
- if (l1 = parlist1(nest))
- return l1;
- if (errflag)
- return NULL;
- c = alloc(sizeof *c);
- c->cmd = strdup("");
- c->args = newtable();
- c->redir = newtable();
- c->type = SIMPLE;
- p = alloc(sizeof *p);
- p->left = c;
- p->type = END;
- l2 = alloc(sizeof *l2);
- l2->left = p;
- l2->type = END;
- l1 = alloc(sizeof *l1);
- l1->left = l2;
- l1->type = SYNC;
- return l1;
-}
-
-/* parse a list */
-
-list parlist1(int nest)
-{
-list l1 = (list) alloc(sizeof *l1);
-int isnl;
-
- incmd = 0;
- if (peek == EMPTY)
- matchit();
- if (nest)
- while (peek == NEWLIN || peek == SEMI)
- matchit();
- if (!(l1->left = parlist2()))
- {
- free(l1);
- return NULL;
- }
- l1->type = (peek == AMPER) ? ASYNC : SYNC;
- if ((isnl = peek == NEWLIN) || peek == SEMI || peek == AMPER)
- peek = EMPTY;
- if ((nest || !isnl) && peek == EMPTY)
- {
- if (!(l1->right = parlist1(nest)))
- {
- if (!errflag)
- {
- if (peek == NEWLIN)
- peek = EMPTY;
- return l1;
- }
- freelist2(l1->left);
- free(l1);
- return NULL;
- }
- }
- else
- l1->right = NULL;
- return l1;
-}
-
-/* parse a sublist */
-
-list2 parlist2(void)
---cut here---cut here---cut here---pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
-{
-list2 l2 = (list2) alloc(sizeof *l2);
-int iter = 0;
-
- for (;;)
- {
- if (peek == BANG)
- {
- l2->flags |= PFLAG_NOT;
- matchit();
- }
- else if (peek == TIME)
- {
- l2->flags |= PFLAG_TIMED;
- matchit();
- }
- else if (peek == COPROC)
- {
- l2->flags |= PFLAG_COPROC;
- matchit();
- }
- else
- break;
- iter = 1;
- }
- if (!(l2->left = parpline()))
- {
- free(l2);
- if (!errflag && iter)
- {
- zerr("parse error: pipeline expected");
- errflag = 1;
- }
- return NULL;
- }
- if (peek == DAMPER || peek == DBAR)
- {
- l2->type = (peek == DAMPER) ? ANDNEXT : ORNEXT;
- matchit();
- while (peek == NEWLIN)
- matchit();
- if (!(l2->right = parlist2()))
- {
- if (!errflag)
- {
- zerr("invalid null command");
- errflag = 1;
- }
- freepline(l2->left);
- free(l2);
- return NULL;
- }
- }
- else
- {
- l2->type = END;
- l2->right = NULL;
- }
- return l2;
-}
-
-/* parse a pipeline */
-
-pline parpline(void)
-{
-pline p = (pline) alloc(sizeof *p);
-
- if (!(p->left = parcmd()))
- {
- free(p);
- return NULL;
- }
- if (peek == HERR)
- {
- freecmd(p->left);
- free(p);
- return NULL;
- }
- if (peek == BAR || peek == BARAMP)
- {
- if (peek == BARAMP)
- {
- struct fnode *f;
-
- f = alloc(sizeof *f);
- f->type = MERGEOUT;
- f->fd1 = 2;
- f->u.fd2 = 1;
- addnode(p->left->redir,f);
- }
- matchit();
- while (peek == NEWLIN)
- matchit();
- p->type = PIPE;
- if (!(p->right = parpline()))
- {
- if (!errflag)
- {
- zerr("invalid null command");
- errflag = 1;
- }
- freecmd(p->left);
- free(p);
- return NULL;
- }
- }
- else
- {
- p->type = END;
- p->right = NULL;
- }
- return p;
-}
-
-/* parse a command */
-
-comm parcmd(void)
-{
-comm c = (comm) alloc(sizeof *c);
-list l;
-char *str;
-int flag,iter = 0;
-
- incmd = 0;
- c->left = NULL;
- c->cmd = NULL;
- c->args = newtable();
- c->redir = newtable();
- c->type = SIMPLE;
- c->vars = NULL;
- if (peek == EOF)
- return NULL;
-foo:
- switch (peek)
- {
- case HERR:
- return NULL;
- case ENVSTRING:
- if (!c->vars)
- c->vars = newtable(); /* FIX */
- for (str = tstr; *str != '='; str++);
- *str++ = '\0';
- addnode(c->vars,tstr);
- addnode(c->vars,strdup(str));
- matchit();
- goto foo;
- case FOR:
- incmd = 1;
- matchit();
- if (parfor(c,1))
- return NULL;
- break;
- case SELECT:
- incmd = 1;
- matchit();
- if (parfor(c,0))
- return NULL;
- break;
- case CASE:
- incmd = 1;
- matchit();
- if (parcase(c))
- return NULL;
- break;
- case IF:
- matchit();
- if (parif(c))
- return NULL;
- break;
- case WHILE:
- matchit();
- if (parwhile(c,0))
- return NULL;
- break;
- case UNTIL:
- matchit();
- if (parwhile(c,1))
- return NULL;
- break;
- case REPEAT:
- incmd = 1;
- matchit();
- if (parrepeat(c))
- return NULL;
- break;
- case INPAR:
- matchit();
- c->type = SUBSH;
- if (!(c->left = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTPAR)
- {
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- break;
- case INBRACE:
- matchit();
- c->type = CURSH;
- if (!(c->left = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- break;
- case FUNC:
- matchit();
- str = tstr;
- if (peek != STRING && peek != ENVSTRING)
- {
- c->cmd = strdup("function");
- incmd = 1;
- if (isredir())
- goto jump1;
- else
- goto jump2;
- }
- do
- matchit();
- while (peek == NEWLIN);
- if (peek != INBRACE)
- {
- freecmd(c);
- zerr("parse error: '{' expected");
- return NULL;
- }
- matchit();
- flag = peek == OUTBRACE;
- if (!(l = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freelist(l);
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- settrap(str,flag);
- addhnode(str,l,shfunchtab,freeshfunc);
- c->cmd = strdup("");
- c->type = SIMPLE;
- break;
- case EXEC:
- c->flags |= CFLAG_EXEC;
- matchit();
- iter = 1;
- goto foo;
- case COMMAND:
- c->flags |= CFLAG_COMMAND;
- matchit();
- iter = 1;
- goto foo;
- default:
-jump1:
- if (isredir())
- {
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- goto foo;
- }
- if (!(peek == STRING || peek == ENVSTRING))
- {
- if (full(c->redir))
- {
- c->cmd = strdup("cat");
- return c;
- }
- if (c->vars)
- {
- c->cmd = strdup("");
- return c;
- }
- free(c->args);
- free(c->redir);
- free(c);
- if (iter && !errflag)
- {
- errflag = 1;
- zerr("parse error: command expected");
- }
- return NULL;
- }
-jump2:
- while (peek == STRING || peek == ENVSTRING || isredir())
- if (isredir())
- {
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- }
- else
- {
- if (tstr[0] == Inpar && tstr[1] == Outpar && !tstr[2])
- {
- free(tstr);
- incmd = 0;
- matchit();
- if (full(c->args))
- {
- zerr("illegal function definition");
- freecmd(c);
- return NULL;
- }
- while (peek == NEWLIN)
- matchit();
- if (peek != INBRACE)
- {
- freecmd(c);
- zerr("parse error: '{' expected");
- return NULL;
- }
- matchit();
- flag = peek == OUTBRACE;
- if (!(l = parlist(1)))
- {
- freecmd(c);
- return NULL;
- }
- if (peek != OUTBRACE)
- {
- freelist(l);
- freecmd(c);
- zerr("parse error: '}' expected");
- return NULL;
- }
- matchit();
- settrap(c->cmd,flag);
- addhnode(c->cmd,l,shfunchtab,freeshfunc);
- c->cmd = strdup("");
- c->type = SIMPLE;
- incmd = 0;
- return c;
- }
- if (peek == ENVSTRING && (!incmd || opts[KEYWORD] == OPT_SET))
- {
- if (!c->vars)
- c->vars = newtable(); /* FIX */
- for (str = tstr; *str != '='; str++);
- *str++ = '\0';
- addnode(c->vars,tstr);
- addnode(c->vars,strdup(str));
- }
- else if (c->cmd)
- addnode(c->args,tstr);
- else
- {
- c->cmd = tstr;
- incmd = 1;
- }
- matchit();
- }
- break;
- }
- while (isredir())
- if (parredir(c))
- {
- freecmd(c);
- return NULL;
- }
- incmd = 0;
- if (peek == HERR)
- {
- freecmd(c);
- return NULL;
- }
- return c;
-}
-
-/* != 0 if peek is a redirection operator */
-
-int isredir(void)
-{
- return (peek >= OUTANG && peek <= DOUTANGAMPBANG);
-}
-
-/* get fd associated with str */
-
-int getfdstr(char *s)
-{
- if (s[1])
- return -1;
- if (isdigit(*s))
- return *s-'0';
- if (*s == 'p')
- return -2;
- return -1;
-}
-
-int parredir(comm c)
-{
-struct fnode *fn = (struct fnode *) alloc(sizeof *fn);
-int pk = peek,ic = incmd,mrg2 = 0;
-
- fn->type = peek-OUTANG+WRITE;
- if (peek == OUTANGAMP)
- fn->type = MERGEOUT;
- if (peekfd != -1)
- fn->fd1 = peekfd;
- else if (peek <= DOUTANGBANG || peek >= OUTANGAMP)
- fn->fd1 = 1;
- else
- fn->fd1 = 0;
- incmd = 1;
- matchit();
- incmd = ic;
- if (peek != STRING)
- {
- zerr("parse error: filename expected");
- return 1;
- }
-
- if ((*tstr == Inang || *tstr == Outang) && tstr[1] == Inpar)
- {
- if (fn->type == WRITE)
- fn->type = OUTPIPE;
- else if (fn->type == READ)
- fn->type = INPIPE;
- else
- {
- zerr("parse error: bad process redirection");
- return 1;
- }
- fn->u.name = tstr;
- }
- else if (fn->type == HEREDOC)
- fn->u.fd2 = gethere(tstr);
- else if (pk >= OUTANGAMP && getfdstr(tstr) == -1)
- {
- mrg2 = 1;
- fn->u.name = tstr;
- fn->type = pk-OUTANGAMP;
- }
- else if (pk > OUTANGAMPBANG)
- {
- zerr("parse error: filename expected");
- return 1;
- }
- else if (pk == OUTANGAMPBANG)
- {
- struct fnode *fe = alloc(sizeof *fe);
-
- fe->fd1 = fn->fd1;
- fe->type = CLOSE;
- addnode(c->redir,fe);
- fn->u.fd2 = getfdstr(tstr);
- if (fn->u.fd2 == -2)
- fn->u.fd2 = spout;
- fn->type = MERGEOUT;
- }
- else if (fn->type == MERGE || fn->type == MERGEOUT)
- {
- if (*tstr == '-')
- fn->type = CLOSE;
- else
- {
- fn->u.fd2 = getfdstr(tstr);
- if (fn->u.fd2 == -2)
- fn->u.fd2 = (pk == OUTANGAMP) ? spout : spin;
- }
- }
- else
- fn->u.name = tstr;
- addnode(c->redir,fn);
- if (mrg2)
- {
- struct fnode *fe = alloc(sizeof *fe);
-
- fe->fd1 = 2;
- fe->u.fd2 = fn->fd1;
- fe->type = MERGEOUT;
- addnode(c->redir,fe);
- }
- matchit();
- return 0;
-}
-
End of parse.c
echo parse.pro 1>&2
sed 's/^-//' >parse.pro <<'End of parse.pro'
-list parlist(int nest);
-list parlist1(int nest);
-list2 parlist2(void);
-pline parpline(void);
-comm parcmd(void);
-int isredir(void);
-int getfdstr(char *s);
-int parredir(comm c);
End of parse.pro
echo subst.c 1>&2
sed 's/^-//' >subst.c <<'End of subst.c'
-/*
-
- subst.c - various substitution
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <pwd.h>
-#define MAXPATHLEN 1024
-
-#define magicerr() { if (magic) putc('\n',stderr); }
-
-/* do substitutions before fork */
-
-void prefork(table list)
-{
-Node node = list->first;
-
- while (node)
- {
- char *str,*str3;
-
- str = str3 = node->dat;
- if (!magic && str[1] == Inpar && (*str == Inang ||
- *str == Outang || *str == Equals))
- {
- if (*str == Inang)
- node->dat = getoutproc(str+2); /* <(...) */
- else if (*str == Equals)
- node->dat = getoutputfile(str+2); /* =(...) */
- else
- node->dat = getinproc(str+2); /* >(...) */
- free(str);
- if (!node->dat)
- {
- zerr("parse error in process substitution");
- errflag = 1;
- return;
- }
- }
- else while (*str)
- {
- if (*str == String || *str == Qstring)
- if (str[1] != Inpar)
- if (str[1] == '*' || str[1] == Star)
- parminsall(list,&node,&str,&str3); /* $* */
- else if (str[1] == Inbrack)
- {
- arithsuber((void **) &str,&str3); /* $[...] */
- if (magic)
- magic = 2;
- node->dat = str3;
- }
- else
- {
- parmsuber(str,&str3); /* $foo */
- node->dat = str = str3;
- if (errflag)
- return;
- continue;
- }
- str++;
- if (errflag)
- return;
- }
- node = node->next;
- }
-}
-
-void postfork(table list,int globstat)
-{
-Node node = list->first;
-int glb = 1;
-
- if (isset(NOGLOBOPT) || globstat != GLOB)
- glb = 0;
- while (node)
- {
- char *str,*str3;
-
- str = str3 = node->dat;
- while (*str)
- {
- if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
- *str == Tick || *str == Qtick)
- comminsall(list,&node,&str,&str3); /* `...`,$(...) */
- str++;
- if (errflag)
- return;
- }
-
- /* now we remove the Nulargs tokens if this is not a null
- arguments. The lexical analyzer throws these in so that
- zsh will not look at this:
-
- $PA"TH"
-
- and expand it to $PATH. But after parameter substitution
- these are only a nuisance, so we remove them. */
-
- if (*(char *) node->dat)
- remnulargs(node->dat);
-
- if (unset(IGNOREBRACES))
- while (hasbraces(node->dat))
- xpandbraces(list,&node);
- filesub(&node->dat);
- if (errflag)
- return;
- if (glb)
- {
- if (haswilds(node->dat))
- glob(list,&node);
- if (errflag)
- return;
- }
- else if (globstat == MOSTGLOB && *(char *) node->dat != '-')
- glb = 1;
- node = node->next;
- }
-}
-
-/* strdup, but returns "Nularg" if this is a null string */
-
-void *nstrdup(void *s)
-{
-char *t = s,u[] = {Nularg,'\0'};
-
- if (!*t)
- return strdup(u);
- return strdup(t);
-}
-
-/* $* */
-
-void parminsall(table l,Node *nn,char **aptr,char **bptr)
-{
-char *str3 = *aptr,*str = *bptr;
-Node n = *nn,where = n->last;
-table pl;
-
- if (magic)
- magic = 2;
- *str3 = '\0';
- str3 += 2;
- remnode(l,n);
- pl = duptable(pparms,nstrdup);
- free(getnode(pl));
- if (pl->first) /* if $# > 1 */
- {
- char *ptr;
- Node tmp;
-
- ptr = pl->first->dat;
- pl->first->dat = dyncat(str,ptr);
- free(ptr);
- ptr = pl->last->dat;
- *bptr = pl->last->dat = dyncat(ptr,str3);
- *aptr = *bptr+strlen(str)+strlen(ptr)-1;
- free(ptr);
- tmp = where->next;
- where->next = pl->first;
- pl->last->next = tmp;
- pl->first->last = where;
- if (tmp)
- tmp->last = pl->last;
- else
- l->last = pl->last;
- *nn = pl->last;
- }
- else /* just remove the $* */
- {
- insnode(l,where,*bptr = dyncat(str,str3));
- *nn = where->next;
- *aptr = *bptr+strlen(str)-1;
- }
-}
-
-char *dynread(char 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(void **namptr)
-{
-char *str = *namptr,*cnam;
-
- if (*str == Tilde && str[1] != '=')
- {
- if (str[1] == '+')
- {
- char *foo = strdup(cwd),*t = str; /* ~+ */
-
- str+=2;
- modify((void **) &foo,&str);
- *namptr = dyncat(cwd,str);
- free(foo);
- free(t);
- return 1;
- }
- else if (str[1] == '-') /* ~- */
- {
- char *foo,*t = str;
-
- if (cnam = getparm("OLDPWD"))
- foo = cnam;
- else
- foo = cwd;
- str += 2;
- foo = strdup(foo);
- modify((void **) &foo,&str);
- *namptr = dyncat(foo,str);
- free(t);
- free(foo);
- return 1;
- }
- if (isalpha(str[1])) /* ~foo */
- {
- char *ptr,*home;
-
- for (ptr = ++str; *ptr && !istok(*ptr) && (isalnum(*ptr) || *ptr == '-'); ptr++)
- if (*ptr == '-')
- *ptr = '-';
- if (!(home = gethome(str,ptr-str)))
- {
- if (magic)
- home = completehome(str,ptr-str);
- if (!home)
- {
- magicerr();
- zerr("user not found: %l",ptr-str,str);
- errflag = 1;
- return 0;
- }
- }
- modify((void **) &home,&ptr);
- *namptr = dyncat(home,ptr);
- free(home);
- free(str-1);
- return 1;
- }
- else if (str[1] == '/') /* ~/foo */
- {
- *namptr = dyncat(home,str+1);
- free(str);
- return 1;
- }
- else if (!str[1]) /* ~ by itself */
- {
- free(str);
- *namptr = strdup(home);
- return 1;
- }
- }
- if (*str == Equals && !istok(str[1]) && (isalnum(str[1]) || str[1] == '-'))
- {
- char *ptr,*s,*ds;
- int val;
-
- untokenize(str);
- if (isalpha(str[1])) /* =foo */
- {
- struct chnode *chn;
- struct anode *t;
- char sav,*pp;
-
- for (pp = str+1; *pp && *pp != ':'; pp++);
- sav = *pp;
- *pp = '\0';
- if ((t = gethnode(str+1,alhtab)) && t->cmd)
- if (t->cmd >= 0)
- cnam = strdup(t->text);
- else
- {
- magicerr();
- zerr("%s: shell reserved word",str+1);
- errflag = 1;
- return 0;
- }
- else if (chn = gethnode(str+1,chtab))
- if (chn->type != BUILTIN)
- cnam = strdup(chn->u.nam);
- else
- {
- magicerr();
- zerr("%s: shell built-in command",str+1);
- errflag = 1;
- return 0;
- }
- else if (!(cnam = findcmd(str+1)))
- {
- magicerr();
- zerr("%s not found",str+1);
- errflag = 1;
- return 0;
- }
- *namptr = cnam;
- if ((*pp = sav) == ':')
- {
- modify(namptr,&pp);
- s = *namptr;
- *namptr = dyncat(*namptr,pp);
- free(s);
- }
- free(str);
- return 1;
- }
- if (str[1] == '-') /* =- */
- {
- val = -1;
- ptr = str+2;
- }
- else
- val = strtol(str+1,&ptr,10); /* =# */
- ds = dstackent(val);
- if (!ds)
- return 1;
- s = strdup(ds);
- modify((void **) &s,&ptr);
- *namptr = dyncat(s,ptr);
- free(s);
- free(str);
- return 1;
- }
- return 0;
-}
-
-/* get a user's directory */
-
-char *gethome(char *user,int len)
-{
-char sav,*str;
-struct passwd *pw;
-
- sav = user[len];
- user[len] = '\0';
- if (!(pw = getpwnam(user)))
- {
- user[len] = sav;
- return NULL;
- }
- str = xsymlink(pw->pw_dir);
- user[len] = sav;
- return str;
-}
-
-/* complete a user and try to get his home directory */
-
-char *completehome(char *user,int len)
-{
-FILE *in;
-char buf[MAXPATHLEN],*str;
-
- sprintf(buf,"%s/.zfriends",getparm("HOME"));
- if (!(in = fopen(buf,"r")))
- return NULL;
- while (fgetline(buf,MAXPATHLEN,in))
- if (!strncmp(user,buf,len))
- if (str = gethome(buf,strlen(buf)))
- {
- fclose(in);
- return str;
- }
- fclose(in);
- return NULL;
-}
-
-/* get the value of the parameter specified by the first len
- characters of s */
-
-char *getsparmval(char *s,int len)
-{
-char sav = s[len];
-char *val;
-char buf[50];
-int t0;
-
- if (len == 1 && (istok(*s) || !isalnum(*s)))
- switch(*s)
- {
- case Pound:
- case '#':
- sprintf(buf,"%d",ppcount());
- return strdup(buf);
- case '-':
- for (val = buf, t0 = ' '; t0 <= 'z'; t0++)
- if (opts[t0] == OPT_SET)
- *val++ = t0;
- *val = '\0';
- return strdup(buf);
- case '?':
- case Quest:
- sprintf(buf,"%d",lastval);
- return strdup(buf);
- case '$':
- case String:
- sprintf(buf,"%d",procnum);
- return strdup(buf);
- case '!':
- sprintf(buf,"%d",proclast);
- return strdup(buf);
- default:
- return NULL;
- }
- s[len] = '\0';
- if (isdigit(*s))
- {
- int num;
- Node node;
-
- num = atoi(s);
- s[len] = sav;
- for (node = pparms->first; node && num; num--,node = node->next);
- return (node) ? strdup(node->dat) : NULL;
- }
- val = getparm(s);
- s[len] = sav;
- return (val) ? strdup(val) : NULL;
-}
-
-/* set the parameter associated with the first len characters of s
- to v. */
-
-void setparml(char *s,int len,char *v)
-{
-char c;
-
- c = s[len];
- s[len] = 0;
- if (isdigit(*s))
- {
- int num;
- Node node;
-
- num = atoi(s);
- for (node = pparms->first; node && num; num--,node = node->next);
- if (node)
- {
- free(node->dat);
- node->dat = v;
- }
- else
- {
- while (num--)
- addnode(pparms,strdup(""));
- addnode(pparms,v);
- }
- }
- else
- setparm(strdup(s),v,0,0);
- s[len] = c;
-}
-
-/* `...`, $(...) */
-
-void comminsall(table l,Node *nn,char **aptr,char **bptr)
-{
-char *str3 = *aptr,*str = *bptr,*str2;
-Node n = *nn,where = n->last;
-table pl;
-int s31 = (*str3 == Qtick || *str3 == Qstring);
-
- if (magic) magic = 2;
- 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';
- }
- remnode(l,n);
- if (!(pl = getoutput(str2,s31)))
- {
- magicerr();
- zerr("parse error in command substitution");
- errflag = 1;
- return;
- }
- if (pl->first)
- {
- char *ptr;
- Node tmp;
-
- ptr = pl->first->dat;
- pl->first->dat = dyncat(str,ptr);
- free(ptr);
- ptr = pl->last->dat;
- *bptr = pl->last->dat = dyncat(ptr,str3);
- *aptr = *bptr+strlen(str)+strlen(ptr)-1;
- free(ptr);
- tmp = where->next;
- where->next = pl->first;
- pl->last->next = tmp;
- pl->first->last = where;
- if (tmp)
- tmp->last = pl->last;
- else
- l->last = pl->last;
- /* free(tmp); */
- *nn = pl->last;
- free(pl);
- }
- else
- {
- insnode(l,where,*bptr = dyncat(str,str3));
- *nn = where->next;
- *aptr = *bptr+strlen(str)-1;
- }
-}
-
-/* do simple parameter substitution */
-
-/*
- consider an argument like this:
-
- abcde${fgh:-ijk}lmnop
-
- aptr will point to the $.
- *bptr,ostr will point to the a.
- t will point to the f.
- u will point to the i.
- s will point to the l (eventually).
-*/
-
-void parmsuber(char *aptr,char **bptr)
-{
-char *s = aptr,*t,*u,*val,*ostr = *bptr;
-int brs; /* != 0 means ${...}, otherwise $... */
-int vlen; /* the length of the name of the parameter */
-int colf; /* != 0 means we found a colon after the name */
-int doub = 0; /* != 0 means we have %%, not %, or ##, not # */
-
- /* first, remove the $ so *bptr is pointing to a null-terminated
- string containing the stuff before the $. Then check for braces,
- and get the parameter name and value, if any. */
-
- *s++ = '\0';
- if (brs = (*s == '{' || *s == Inbrace))
- s++;
- t = s;
- if (istok(*s) || !isalnum(*s))
- {
- val = getsparmval(t,vlen = 1);
- if (!val)
- {
- *(char *) aptr = '$';
- if (brs)
- s[-1] = '{';
- return;
- }
- s++;
- }
- else
- {
- while (!istok(*s) && (isalnum(*s) || *s == '_'))
- s++;
- val = getsparmval(t,vlen = s-t);
- }
-
- /* val can still be NULL at this point. */
-
- 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 (*s == s[1])
- {
- s++;
- doub = 1;
- }
- u = ++s;
- if (brs)
- while (*s != '}' && *s != Outbrace)
- s++;
- else
- {
- while (*s++);
- s--;
- }
- *s = '\0';
- switch (u[-1])
- {
- case '-':
- if (!val || (colf && !*val))
- val = strdup(u);
- break;
- case '=':
- if (!val || (colf && !*val))
- setparml(t,vlen,val = strdup(u));
- break;
- case '?':
- case Quest:
- if (!val || (colf && !*val))
- {
- magicerr();
- zerr("%s",(*u) ? u : "parameter not set");
- if (!interact)
- exit(1);
- else
- errflag = 1;
- return;
- }
- break;
- case '+':
- if (!val || (colf && !*val))
- val = strdup("");
- else
- val = strdup(u);
- break;
- case '#':
- case Pound:
- if (!val)
- val = strdup("");
- getmatch(&val,u,doub);
- break;
- case '%':
- if (!val)
- val = strdup("");
- getmatch(&val,u,doub+2);
- break;
- }
- }
- else /* no ${...=...} or anything, but possible modifiers. */
- {
- if (!val)
- {
- if (isset(NOUNSET))
- {
- zerr("parameter not set: %l",vlen,t);
- errflag = 1;
- return;
- }
- val = strdup("");
- }
- if (colf)
- {
- s--;
- modify((void **) &val,&s); /* do modifiers */
- }
- if (brs)
- {
- if (*s != '}' && *s != Outbrace)
- {
- zerr("closing brace expected");
- errflag = 1;
- return;
- }
- s++;
- }
- }
- if (errflag)
- {
- free(ostr);
- return;
- }
- *bptr = zalloc((char *) aptr-(*bptr)+strlen(val)+strlen(s)+1);
- strcpy(*bptr,ostr);
- strcat(*bptr,val);
- strcat(*bptr,s);
- free(ostr);
- if (magic)
- magic = 2;
-}
-
-/* arithmetic substitution */
-
-void arithsuber(void **aptr,char **bptr)
-{
-char *s = *aptr,*t,buf[16];
-long v;
-
- *s = '\0';
- for (; *s != Outbrack; s++);
- *s++ = '\0';
- v = matheval(*aptr+2);
- sprintf(buf,"%ld",v);
- t = zalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
- strcpy(t,*bptr);
- strcat(t,buf);
- strcat(t,s);
- free(*bptr);
- *bptr = t;
-}
-
-void modify(void **str,char **ptr)
-{
-char *ptr1,*ptr2,*ptr3,del,*lptr;
-int gbal;
-
- while (**ptr == ':')
- {
- lptr = *ptr;
- (*ptr)++;
- gbal = 0;
-here:
- switch(*(*ptr)++)
- {
- case 'h':
- while (remtpath(str) && gbal);
- break;
- case 'r':
- while (remtext(str) && gbal);
- break;
- case 'e':
- while (rembutext(str) && gbal);
- break;
- case 't':
- while (remlpaths(str) && gbal);
- break;
- case 's':
- if (last)
- free(last);
- if (rast)
- free(rast);
- ptr1 = *ptr;
- del = *ptr1++;
- for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
- if (!*ptr2)
- {
- magicerr();
- zerr("bad subtitution");
- errflag = 1;
- return;
- }
- *ptr2++ = '\0';
- for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
- if (*ptr3)
- *ptr3++ = '\0';
- last = strdup(ptr1);
- rast = strdup(ptr2);
- *ptr = ptr3;
- case '&':
- if (last && rast)
- subststr(str,last,rast,gbal);
- break;
- case 'g':
- gbal = 1;
- goto here;
- default:
- *ptr = lptr;
- return;
- }
- }
-}
-
-/* get a directory stack entry */
-
-char *dstackent(int val)
-{
-Node node;
-
- if ((val < 0 && !dirstack->first) || !val--)
- return cwd;
- if (val < 0)
- node = dirstack->last;
- else
- for (node = dirstack->first; node && val; val--,node = node->next);
- if (!node)
- {
- magicerr();
- zerr("not enough dir stack entries.");
- errflag = 1;
- return NULL;
- }
- return node->dat;
-}
-
-void execshfunc(comm comm)
-{
-table tab,oldlocals;
-Node n;
-char *s;
-
- tab = pparms;
- oldlocals = locallist;
- locallist = newtable();
- for (n = tab->first; n; n = n->next);
- pparms = comm->args;
- runlist(comm->left);
- retflag = 0;
- comm->left = NULL;
- pparms = tab;
- while (s = getnode(locallist))
- {
- void *z = remhnode(s,parmhtab);
- if (z)
- freepm(z);
- }
- free(locallist);
- locallist = oldlocals;
-}
-
-/* make an alias hash table node */
-
-struct anode *mkanode(char *txt,int cmflag)
-{
-struct anode *ptr = (void *) alloc(sizeof(struct anode));
-
- ptr->text = txt;
- ptr->cmd = cmflag;
- ptr->inuse = 0;
- return ptr;
-}
-
-/* perform TAB substitution */
-
-char *docompsubs(char *str,int *i)
-{
-table fake,curt = curtab;
-char *s,*t;
-int ct = 0;
-
- for (s = str; *s; s++)
- for (t = tokens; *t; t++)
- if (*s == *t)
- {
- *s = (t-tokens)+Pound;
- break;
- }
- curtab = NULL;
- magic = 1;
- fake = newtable();
- addnode(fake,str);
- prefork(fake);
- if (!errflag)
- postfork(fake,GLOB);
- if (fake->first && fake->first->next)
- ct = 1;
- t = s = buildline(fake);
- free(fake);
- rl_prep_terminal();
- if (errflag)
- {
- rl_on_new_line();
- rl_redisplay();
- errflag = 0;
- magic = 0;
- curtab = curt;
- *i = 0;
- return NULL;
- }
- *i = (magic == 2) + ct;
- magic = 0;
- curtab = curt;
- untokenize(s);
- return s;
-}
-
-/* perform substitution on the command name */
-
-void docmdsubs(char **str)
-{
-table fake;
-char *s = strdup(*str);
-
- fake = newtable();
- addnode(fake,*str);
- prefork(fake);
- if (!errflag) postfork(fake,GLOB);
- if (errflag)
- {
- free(fake);
- free(s);
- return;
- }
- if (fake->first && fake->first->next)
- {
- zerr("%s: ambiguous",s);
- errflag = 1;
- free(fake);
- free(s);
- return;
- }
- *str = getnode(fake);
- free(s);
- free(fake);
-}
-
-/* perform substitution on the variables */
-
-void dovarsubs(char **str)
-{
-table fake;
-char *s;
-
- fake = newtable();
- addnode(fake,*str);
- prefork(fake);
- if (!errflag) postfork(fake,GLOB);
- if (errflag)
- return;
- s = buildline(fake);
- untokenize(s);
- *str = s;
- free(fake);
-}
-
End of subst.c
echo subst.pro 1>&2
sed 's/^-//' >subst.pro <<'End of subst.pro'
-void prefork(table list);
-void postfork(table list,int globstat);
-void *nstrdup(void *s);
-void parminsall(table l,Node *nn,char **aptr,char **bptr);
-char *dynread(char stop);
-int filesub(void **namptr);
-char *gethome(char *user,int len);
-char *completehome(char *user,int len);
-char *getsparmval(char *s,int len);
-void setparml(char *s,int len,char *v);
-void comminsall(table l,Node *nn,char **aptr,char **bptr);
-void parmsuber(char *aptr,char **bptr);
-void arithsuber(void **aptr,char **bptr);
-void modify(void **str,char **ptr);
-char *dstackent(int val);
-void execshfunc(comm comm);
-struct anode *mkanode(char *txt,int cmflag);
-char *docompsubs(char *str,int *i);
-void docmdsubs(char **str);
-void dovarsubs(char **str);
End of subst.pro
echo table.c 1>&2
sed 's/^-//' >table.c <<'End of table.c'
-/*
-
- table.c - linked list and hash table management
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-
-/* get an empty linked list header */
-
-table newtable()
-{
-table list;
-
- list = alloc(sizeof(*list));
- list->first = 0;
- list->last = (Node) list;
- return list;
-}
-
-/* get an empty hash table */
-
-htable newhtable(int size)
-{
-htable ret;
-
- ret = alloc(sizeof(struct xhtab));
- ret->hsize = size;
- ret->nodes = alloc(size*sizeof(struct hnode *));
- return ret;
-}
-
-/* Peter Weinberger's hash function */
-
-int hasher(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(char *nam,void *dat,htable ht,void (*freefunc)(void *))
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hp = ht->nodes[hval],*hn;
-
- for (; hp; hp = hp->hchain)
- if (!strcmp(hp->nam,nam))
- {
- freefunc(hp->dat);
- hp->dat = dat;
- free(nam);
- return;
- }
- hn = (void *) alloc(sizeof(struct hnode));
- hn->nam = nam;
- hn->dat = dat;
- hn->hchain = ht->nodes[hval];
- ht->nodes[hval] = hn;
- if (++ht->ct == ht->hsize*4)
- expandhtab(ht);
-}
-
-/* expand hash tables when they get too many entries */
-
-void expandhtab(htable ht)
-{
-struct hnode *hp,**arr,**ha,*hn;
-int osize = ht->hsize,nsize = osize*8;
-
- ht->hsize = nsize;
- arr = ht->nodes;
- ht->nodes = alloc(nsize*sizeof(struct hnode *));
- for (ha = arr; osize; osize--,ha++)
- for (hn = *ha; hn; )
- {
- addhnode(hn->nam,hn->dat,ht,NULL);
- hp = hn->hchain;
- free(hn);
- hn = hp;
- }
- free(arr);
-}
-
-/* get an entry in a hash table */
-
-void *gethnode(char *nam,htable ht)
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hn = ht->nodes[hval];
-
- for (; hn; hn = hn->hchain)
- if (!strcmp(hn->nam,nam))
- return hn->dat;
- return NULL;
-}
-
-void freehtab(htable ht,void (*freefunc)(void *))
-{
-int val;
-struct hnode *hn,**hptr = &ht->nodes[0],*next;
-
- for (val = ht->hsize; val; val--,hptr++)
- for (hn = *hptr; hn; )
- {
- next = hn->hchain;
- freefunc(hn);
- hn = next;
- }
-}
-
-/* remove a hash table entry and return a pointer to it */
-
-void *remhnode(char *nam,htable ht)
-{
-int hval = hasher(nam) % ht->hsize;
-struct hnode *hn = ht->nodes[hval],*hp;
-void *dat;
-
- if (!hn)
- return NULL;
- if (!strcmp(hn->nam,nam))
- {
- ht->nodes[hval] = hn->hchain;
- dat = hn->dat;
- free(hn->nam);
- free(hn);
- ht->ct--;
- return dat;
- }
- for (hp = hn, hn = hn->hchain; hn; hn = (hp = hn)->hchain)
- if (!strcmp(hn->nam,nam))
- {
- hp->hchain = hn->hchain;
- dat = hn->dat;
- free(hn->nam);
- free(hn);
- ht->ct--;
- return dat;
- }
- return NULL;
-}
-
-void *zalloc(int l)
-{
-void *z;
-
- if (!(z = malloc(l)))
- {
- zerr("fatal error: out of memory: restarting");
- execl(MYSELF,"zsh","-f",(void *) 0);
- exit(1);
- }
- return z;
-}
-
-void *alloc(int l)
-{
-void *z;
-
- if (!(z = calloc(l,1)))
- {
- zerr("fatal error: out of memory: restarting");
- execl(MYSELF,"zsh","-f",(void *) 0);
- exit(1);
- }
- return z;
-}
-
-/* add a node to the end of a linked list */
-
-void addnode(table list,void *str)
-{
- insnode(list,list->last,str);
-}
-
-/* insert a node in a linked list after 'last' */
-
-void insnode(table list,Node last,void *dat)
-{
-Node tmp;
-
- tmp = last->next;
- last->next = alloc(sizeof(*tmp));
- last->next->last = last;
- last->next->dat = dat;
- last->next->next = tmp;
- if (tmp)
- tmp->last = last->next;
- else
- list->last = last->next;
-}
-
-/* remove a node from a linked list */
-
-void *remnode(table list,Node nd)
-{
-void *dat;
-
- nd->last->next = nd->next;
- if (nd->next)
- nd->next->last = nd->last;
- else
- list->last = nd->last;
- free(nd);
- dat = nd->dat;
- return dat;
-}
-
-/* delete a character in a string */
-
-void chuck(char *str)
-{
- while (str[0] = str[1])
- str++;
-}
-
-/* get a node in a linked list */
-
-void *getnode(table list)
-{
-void *dat;
-Node node = list->first;
-
- if (!node)
- return NULL;
- dat = node->dat;
- list->first = node->next;
- if (node->next)
- node->next->last = (Node) list;
- else
- list->last = (Node) list;
- free(node);
- return dat;
-}
-
-/* != 0 if the linked list has at least one entry */
-
-int full(table list)
-{
- return list->first != NULL;
-}
-
-void freetable(table tab,void (*freefunc)(void *))
-{
-Node node = tab->first,next;
-
- while (node)
- {
- next = node->next;
- freefunc(node);
- node = next;
- }
- free(tab);
-}
-
-char *strdup(char *str)
-{
-char *ret = zalloc(strlen(str)+1);
-
- strcpy(ret,str);
- return ret;
-}
-
-#ifndef STRSTR
-const char *strstr(const char *s,const char *t)
-{
-const char *p1,*p2;
-
- for (; *s; s++)
- {
- for (p1 = s, p2 = t; *p2; p1++,p2++)
- if (*p1 != *p2)
- break;
- if (!*p2)
- return (char *) s;
- }
- return NULL;
-}
-#endif
-
End of table.c
echo table.pro 1>&2
sed 's/^-//' >table.pro <<'End of table.pro'
-table newtable();
-htable newhtable(int size);
-int hasher(char *s) /* copied from Programming in C++, p14 */;
-void addhnode(char *nam,void *dat,htable ht,void (*freefunc)(void *));
-void expandhtab(htable ht);
-void *gethnode(char *nam,htable ht);
-void freehtab(htable ht,void (*freefunc)(void *));
-void *remhnode(char *nam,htable ht);
-void *zalloc(int l);
-void *alloc(int l);
-void addnode(table list,void *str);
-void insnode(table list,Node last,void *dat);
-void *remnode(table list,Node nd);
-void chuck(char *str);
-void *getnode(table list);
-int full(table list);
-void freetable(table tab,void (*freefunc)(void *));
-char *strdup(char *str);
-/*const char *strstr(const char *s,const char *t); */
End of table.pro
echo test.c 1>&2
sed 's/^-//' >test.c <<'End of test.c'
-/*
-
- test.c - the test builtin
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-
-#ifndef F_OK
-#define F_OK 00
-#define R_OK 04
-#define W_OK 02
-#define X_OK 01
-#endif
-
-#include "test.pro"
-#include "table.pro"
-
-static char **arg;
-static int efg;
-
-void die(char *str)
-{
- if (!efg)
- zerrnam("test",str);
- efg = 1;
-}
-
-int test(comm comm)
-{
-Node n;
-int t0;
-char **av,**ap;
-
- for (n = comm->args->first, t0 = 0; n; n = n->next,t0++);
- ap = av = (char **) zalloc((sizeof(char *))*(t0+1));
- for (n = comm->args->first; n; n = n->next)
- *ap++ = n->dat;
- *ap = NULL;
- t0 = testmain(av);
- free(av);
- return t0;
-}
-
-int testmain(char **argv)
-{
-int ret,isbrack;
-
- efg = 0;
- arg = argv+1;
- ret = testexpr();
- if (efg)
- return 1;
- isbrack = !strcmp(*argv,"[");
- if (isbrack)
- {
- if (*arg && !strcmp(*arg,"]") && !arg[1])
- return !ret;
- }
- else
- if (!*arg)
- return !ret;
- die("bad test format");
- return 1;
-}
-
-int testexpr(void)
-{
-int ret = testexpr2(),ret2;
-
- if (*arg && !strcmp(*arg,"-o"))
- {
- arg++;
- ret2 = testexpr2();
- if (efg)
- return 0;
- ret = ret || ret2;
- }
- return ret;
-}
-
-int testexpr2(void)
-{
-int ret = testexpr3(),ret2;
-
- if (*arg && !strcmp(*arg,"-a"))
- {
- arg++;
- ret2 = testexpr2();
- if (efg)
- return 0;
- ret = ret && ret2;
- }
- return ret;
-}
-
-int testexpr3(void)
-{
- if (*arg && !strcmp(*arg,"!"))
- {
- arg++;
- return !testexpr3();
- }
- return testexpr4();
-}
-
-int testexpr4(void)
-{
-int ret,t0,t1;
-struct stat *st;
-char buf[16],*op;
-
- if (!*arg)
- {
- die("expression expected");
- return 0;
- }
- if (!strcmp(*arg,"("))
- {
- arg++;
- ret = testexpr();
- if (!*arg || strcmp(*arg,")"))
- {
- die("')' expected");
- return 0;
- }
- arg++;
- return ret;
- }
- if (**arg == '-' && !(*arg)[2])
- {
- switch((*arg++)[1])
- {
- case 'a': return(doaccess(F_OK));
- case 'b': return(S_ISBLK(dostat()));
- case 'c': return(S_ISCHR(dostat()));
- case 'd': return(S_ISDIR(dostat()));
- case 'f': return(S_ISREG(dostat()));
- case 'g': return(!!(dostat() & S_ISGID));
- case 'k': return(!!(dostat() & S_ISVTX));
- case 'L': return(S_ISLNK(dostat()));
- case 'p': return(S_ISFIFO(dostat()));
- case 'r': return(doaccess(R_OK));
- case 's': return((st = getstat()) && !!(st->st_size));
- case 'S': return(S_ISSOCK(dostat()));
- case 'u': return(!!(dostat() & S_ISUID));
- case 'w': return(doaccess(W_OK));
- case 'x': return(doaccess(X_OK));
- case 'O': return((st = getstat()) && st->st_uid == geteuid());
- case 'G': return((st = getstat()) && st->st_gid == getegid());
- case 't': {
- int t0 = 1;
-
- if (*arg && isdigit(**arg))
- t0 = atoi(*arg++);
- return isatty(t0);
- }
- case 'z':
- if (!*arg)
- {
- die("string expected");
- return 0;
- }
- return !strlen(*arg++);
- case 'n':
- if (!*arg)
- {
- die("string expected");
- return 0;
- }
- return !!strlen(*arg++);
- case 'l':
- sprintf(buf,"%d",strlen(*arg));
- *arg = buf;
- break;
- }
- }
- if (!arg[1] || !strcmp(arg[1],"-o") || !strcmp(arg[1],"-a") ||
- !strcmp(arg[1],"]") || !strcmp(arg[1],")"))
- return(!!strlen(*arg++));
- if (!arg[2])
- {
- die("bad expression");
- return 0;
- }
- if (!strcmp(arg[1],"-nt"))
- {
- time_t a;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- a = st->st_mtime;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return a > st->st_mtime;
- }
- if (!strcmp(arg[1],"-ot"))
- {
- time_t a;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- a = st->st_mtime;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return a < st->st_mtime;
- }
- if (!strcmp(arg[1],"-ef"))
- {
- dev_t d;
- ino_t i;
-
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- d = st->st_dev;
- i = st->st_ino;
- arg++;
- if (!(st = getstat()))
- {
- arg += 2;
- return 0;
- }
- return d == st->st_dev && i == st->st_ino;
- }
- if (!strcmp(arg[1],"~="))
- {
- arg += 3;
- return patmatch(arg[-3],arg[-1]);
- }
- if (!strcmp(arg[1],"="))
- {
- arg += 3;
- return !strcmp(arg[-3],arg[-1]);
- }
- if (!strcmp(arg[1],"!="))
- {
- arg += 3;
- return !!strcmp(arg[-3],arg[-1]);
- }
- t0 = atoi(arg[0]);
- op = arg[1];
- arg += 2;
- if (!strcmp(*arg,"-l"))
- {
- if (!arg[1])
- {
- die("string expected");
- return 0;
- }
- t1 = strlen(arg[1]);
- arg += 2;
- }
- else
- t1 = atoi(*arg++);
- if (!strcmp(op,"-eq"))
- return t0 == t1;
- if (!strcmp(op,"-ne"))
- return t0 != t1;
- if (!strcmp(op,"-lt"))
- return t0 < t1;
- if (!strcmp(op,"-le"))
- return t0 <= t1;
- if (!strcmp(op,"-gt"))
- return t0 > t1;
- if (!strcmp(op,"-ge"))
- return t0 >= t1;
- if (!efg)
- zerrnam("test","unrecognized operator: %s",op);
- efg = 1;
- return 0;
-}
-
-int doaccess(int c)
-{
- if (!*arg)
- {
- die("filename expected");
- return 0;
- }
- return !access(*arg++,c);
-}
-
-struct stat *getstat(void)
-{
-static struct stat st;
-
- if (!*arg)
- {
- die("filename expected");
- return NULL;
- }
- if (!strncmp(*arg,"/dev/fd/",8))
- {
- if (fstat(atoi((*arg++)+8),&st))
- return NULL;
- }
- else if (lstat(*arg++,&st))
- return NULL;
- return &st;
-}
-
-unsigned short dostat(void)
-{
-struct stat *st;
-
- if (!(st = getstat()))
- return 0;
- return st->st_mode;
-}
-
End of test.c
echo test.pro 1>&2
sed 's/^-//' >test.pro <<'End of test.pro'
-void die(char *str);
-int test(comm comm);
-int testmain(char **argv);
-int testexpr(void);
-int testexpr2(void);
-int testexpr3(void);
-int testexpr4(void);
-int doaccess(int c);
-struct stat *getstat(void);
-unsigned short dostat(void);
End of test.pro
echo utils.c 1>&2
sed 's/^-//' >utils.c <<'End of utils.c'
-/*
-
- utils.c - miscellaneous utilities
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include <pwd.h>
-#include <stdarg.h> /* had to change this to stdarg.h.old on one machine */
-#include <errno.h>
-#include <sys/dir.h>
-#include <fcntl.h>
-
-/* add vars to the parm hash table */
-
-void addvars(table vars)
-{
-char *s1,*s2;
-Node node;
-
- for (node = vars->first; node; node = node->next)
- {
- s1 = node->dat;
- untokenize(s1);
- node = node->next;
- s2 = node->dat;
- dovarsubs(&s2);
- if (errflag)
- break;
- untokenize(s2);
- setparm(s1,s2,0,0);
- }
- free(vars);
-}
-
-/* set a parameter to an integer value */
-
-void setiparm(char *s,long v,int isint)
-{
-struct pmnode *pmn,*pmo;
-
- if (!strcmp(s,"RANDOM"))
- {
- srand((unsigned long) v);
- return;
- }
- if (!strcmp(s,"SECONDS"))
- {
- shtimer = v+time(NULL);
- return;
- }
- if (pmo = gethnode(s,parmhtab))
- {
- char buf[12];
-
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = pmo->isint | isint)
- pmn->u.val = v;
- else
- {
- sprintf(buf,"%ld",v);
- pmn->u.str = strdup(buf);
- }
- addhnode(s,pmn,parmhtab,freepm);
- }
- else if (getenv(s) || (opts[ALLEXPORT] == OPT_SET))
- {
- char buf[12];
-
- sprintf(buf,"%ld",v);
- putenv(tricat(s,"=",buf));
- }
- else
- {
- char buf[12];
-
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = isint)
- pmn->u.val = v;
- else
- {
- sprintf(buf,"%ld",v);
- pmn->u.str = strdup(buf);
- }
- addhnode(s,pmn,parmhtab,freepm);
- addlocal(s);
- }
- if (!strcmp(s,"PERIOD"))
- {
- period = v*60;
- lastperiod = time(NULL)+period;
- }
- if (!strcmp(s,"HISTSIZE"))
- {
- tevs = v;
- if (tevs <= 2)
- tevs = 2;
- }
-}
-
-/* set a parameter to a string value */
-
-void setparm(char *s,char *t,int ex,int isint)
-{
-struct pmnode *pmn,*pmo;
-
- if (!strcmp(s,"RANDOM"))
- {
- srand((unsigned long) atol(t));
- return;
- }
- if (!strcmp(s,"SECONDS"))
- {
- shtimer = atol(t)+time(NULL);
- return;
- }
- if (ex && gethnode(s,parmhtab))
- freepm(remhnode(s,parmhtab));
- if (pmo = gethnode(s,parmhtab))
- {
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = pmo->isint | isint)
- {
- pmn->u.val = matheval(t);
- free(t);
- t = NULL;
- }
- else
- pmn->u.str = t;
- addhnode(s,pmn,parmhtab,freepm);
- }
- else if (ex || getenv(s) || (opts[ALLEXPORT] == OPT_SET))
- putenv(tricat(s,"=",t));
- else
- {
- pmn = alloc(sizeof *pmn);
- if (pmn->isint = isint)
- {
- pmn->u.val = matheval(t);
- free(t);
- t = NULL;
- }
- else
- pmn->u.str = t;
- addhnode(s,pmn,parmhtab,freepm);
-#if 0
- addlocal(s);
-#endif
- }
- if (!t)
- return;
- if (!strcmp(s,"PATH"))
- parsepath();
- if (!strcmp(s,"CDPATH"))
- parsecdpath();
- if (!strcmp(s,"IFS"))
- {
- free(ifs);
- ifs = strdup(t);
- }
- if (!strcmp(s,"PERIOD"))
- {
- period = atoi(t)*60;
- lastperiod = time(NULL)+period;
- }
- if (!strcmp(s,"HISTSIZE"))
- {
- tevs = atoi(t);
- if (tevs <= 2)
- tevs = 2;
- }
- if (!strcmp(s,"HOME"))
- {
- free(home);
- home = xsymlink(t);
- }
- if (!strcmp(s,"MAIL") || !strcmp(s,"MAILCHECK") || !strcmp(s,"MAILPATH"))
- lastmailcheck = 0;
-}
-
-void unsetparm(char *s)
-{
-char **pp;
-
- if (!strcmp(s,"HOME"))
- return;
- if (!strcmp(s,"PERIOD"))
- period = 0;
- if (!strcmp(s,"HISTSIZE"))
- tevs = 1;
- if (gethnode(s,parmhtab))
- {
- freepm(remhnode(s,parmhtab));
- return;
- }
- for (pp = environ; *pp; pp++)
- if (!strncmp(*pp,s,strlen(s)) && (*pp)[strlen(s)] == '=')
- {
- while (pp[0] = pp[1])
- pp++;
- return;
- }
-}
-
-/* get the integer value of a parameter */
-
-long getiparm(char *s)
-{
-struct pmnode *pmn;
-char *t;
-
- if (!isalpha(*s) && !s[1])
- {
- t = getsparmval(s,1);
- return (t) ? atoi(t) : 0;
- }
- if (s[0] == 'T' && s[1] == 'C' && !s[4]) /* TCxx */
- return tgetnum(s+2);
- if (!strcmp(s,"RANDOM"))
- return rand() & 0x7fff;
- if (!strcmp(s,"LINENO"))
- return lineno;
- if (!strcmp(s,"SECONDS"))
- return time(NULL)-shtimer;
- if (pmn = gethnode(s,parmhtab))
- {
- if (pmn->isint)
- return pmn->u.val;
- return atol(pmn->u.str);
- }
- return atol(getenv(s));
-}
-
-/* get the string value of a parameter */
-
-char *getparm(char *s)
-{
-struct pmnode *pmn;
-
- if (!isalpha(*s) && !s[1])
- return getsparmval(s,1);
- if (s[0] == 'T' && s[1] == 'C' && !s[4]) /* TCxx */
- {
- static char buf[1024];
- char *ss = buf;
- int t0;
-
- if (tgetstr(s+2,&ss))
- return buf;
- if ((t0 = tgetnum(s+2)) != -1)
- {
- sprintf(buf,"%d",t0);
- return buf;
- }
- return NULL;
- }
- if (!strcmp(s,"LINENO"))
- {
- static char buf[8];
-
- sprintf(buf,"%d",lineno);
- return buf;
- }
- if (!strcmp(s,"RANDOM"))
- {
- static char buf[8];
-
- sprintf(buf,"%d",rand() & 0x7fff);
- return buf;
- }
- if (!strcmp(s,"SECONDS"))
- {
- static char buf[12];
-
- sprintf(buf,"%ld",time(NULL)-shtimer);
- return buf;
- }
- if (pmn = gethnode(s,parmhtab))
- {
- static char buf[12];
-
- if (pmn->isint)
- {
- sprintf(buf,"%ld",pmn->u.val);
- return buf;
- }
- return pmn->u.str;
- }
- return getenv(s);
-}
-
-/* parse the PATH parameter into directory names in a array of
- strings and create the command hash table */
-
-void parsepath(void)
-{
-char *pptr = getparm("PATH"),*ptr;
-
- if (path)
- {
- while(pathct)
- free(path[--pathct]);
- free(path);
- }
- for (pathct = 1, ptr = pptr; *ptr; ptr++)
- if (*ptr == ':')
- pathct++;
- path = (char **) zalloc(pathct*sizeof(char *));
- pathct = 0;
- ptr = pptr;
- while(pptr)
- {
- ptr = strchr(pptr,':');
- if (ptr)
- *ptr = '\0';
- path[pathct] = strdup(pptr);
- if (ptr)
- {
- *ptr = ':';
- pptr = ptr+1;
- }
- else
- pptr = NULL;
- if (!*path[pathct])
- {
- free(path[pathct]);
- path[pathct] = strdup(".");
- }
- pathsub(&path[pathct]);
- if (*path[pathct] != '/' && strcmp(path[pathct],"."))
- {
-#ifdef PATH_WARNINGS
- zerr("PATH component not absolute pathname: %s",path[pathct]);
-#endif
- free(path[pathct--]);
- }
- pathct++;
- }
- createchtab();
-}
-
-void parsecdpath(void)
-{
-char *pptr = getparm("CDPATH"),*ptr;
-
- if (cdpath)
- {
- while(cdpathct)
- free(cdpath[--cdpathct]);
- free(cdpath);
- }
- if (pptr == NULL)
- {
- cdpath = (char **) zalloc(sizeof(char *));
- cdpath[0] = strdup(".");
- cdpathct = 1;
- return;
- }
- for (cdpathct = 2, ptr = pptr; *ptr; ptr++)
- if (*ptr == ':')
- cdpathct++;
- cdpath = (char **) zalloc(cdpathct*sizeof(char *));
- cdpath[0] = strdup(".");
- cdpathct = 1;
- ptr = pptr;
- while (pptr)
- {
- ptr = strchr(pptr,':');
- if (ptr)
- *ptr = '\0';
- cdpath[cdpathct] = strdup(pptr);
- if (ptr)
- {
- *ptr = ':';
- pptr = ptr+1;
- }
- else
- pptr = NULL;
- pathsub(&cdpath[cdpathct]);
- if (*cdpath[cdpathct] != '/')
- {
-#ifdef PATH_WARNINGS
- zerr("CDPATH component not absolute pathname: %s",cdpath[cdpathct]);
-#endif
- free(cdpath[cdpathct--]);
- }
- cdpathct++;
- }
-}
-
-/* source a file */
-
-int source(char *s)
-{
-int fd,cj = curjob,iact = opts[INTERACTIVE];
-FILE *obshin = bshin;
-
- fd = SHIN;
- opts[INTERACTIVE] = OPT_UNSET;
- if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
- {
- SHIN = fd;
- curjob = cj;
- opts[INTERACTIVE] = iact;
- return 1;
- }
- bshin = fdopen(SHIN,"r");
- loop();
- fclose(bshin);
- opts[INTERACTIVE] = iact;
- bshin = obshin;
- SHIN = fd;
- peek = EMPTY;
- curjob = cj;
- errflag = 0;
- retflag = 0;
- return 0;
-}
-
-/* try to source a file in our home directory */
-
-void sourcehome(char *s)
-{
-char buf[MAXPATHLEN];
-
- sprintf(buf,"%s/%s",getparm("HOME"),s);
- (void) source(buf);
-}
-
-/* print an error */
-
-void zerrnam(char *cmd, char *fmt, ...)
-{
-va_list ap;
-char *str;
-int num;
-
- va_start(ap,fmt);
- fputs(cmd,stderr);
- putc(':',stderr);
- putc(' ',stderr);
- while (*fmt)
- if (*fmt == '%')
- {
- fmt++;
- switch(*fmt++)
- {
- case 's': /* string */
- str = va_arg(ap,char *);
- while (*str)
- niceputc(*str++,stderr);
- break;
- case 'l': /* string with a length */
- num = va_arg(ap,int);
- str = va_arg(ap,char *);
- while (num--)
- niceputc(*str++,stderr);
- break;
- case 'd': /* number */
- num = va_arg(ap,int);
- fprintf(stderr,"%d",num);
- break;
- case '%':
- putc('%',stderr);
- break;
- case 'c': /* char */
- num = va_arg(ap,int);
- niceputc(num,stderr);
- break;
- case 'e': /* system error */
- num = va_arg(ap,int);
- if (num == EINTR)
- {
- fputs("interrupt\n",stderr);
- errflag = 1;
- return;
- }
- fputc(tolower(sys_errlist[num][0]),stderr);
- fputs(sys_errlist[num]+1,stderr);
- break;
- }
- }
- else
- putc(*fmt++,stderr);
- putc('\n',stderr);
- va_end(ap);
-}
-
-void zerr(char *fmt,...)
-{
-va_list ap;
-char *str;
-int num;
-
- va_start(ap,fmt);
- fputs("zsh: ",stderr);
- while (*fmt)
- if (*fmt == '%')
- {
- fmt++;
- switch(*fmt++)
- {
- case 's':
- str = va_arg(ap,char *);
- while (*str)
- niceputc(*str++,stderr);
- break;
- case 'l':
- num = va_arg(ap,int);
- str = va_arg(ap,char *);
- while (num--)
- niceputc(*str++,stderr);
- break;
- case 'd':
- num = va_arg(ap,int);
- fprintf(stderr,"%d",num);
- break;
- case '%':
- putc('%',stderr);
- break;
- case 'c':
- num = va_arg(ap,int);
- niceputc(num,stderr);
- break;
- case 'e':
- num = va_arg(ap,int);
- if (num == EINTR)
- {
- fputs("interrupt\n",stderr);
- errflag = 1;
- return;
- }
- fputc(tolower(sys_errlist[num][0]),stderr);
- fputs(sys_errlist[num]+1,stderr);
- break;
- }
- }
- else
- putc(*fmt++,stderr);
- putc('\n',stderr);
- va_end(ap);
-}
-
-void niceputc(int c,FILE *f)
-{
- if (istok(c))
- {
- if (c >= Pound && c <= Qtick)
- putc(tokens[c-Pound],f);
- return;
- }
- c &= 0x7f;
- if (c >= ' ' && c < '\x7f')
- putc(c,f);
- else if (c == '\n')
- {
- putc('\\',f);
- putc('n',f);
- }
- else
- {
- putc('^',f);
- putc(c|'A',f);
- }
-}
-
-/* enable ^C interrupts */
-
-void intr(void)
-{
-struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
-
- if (interact)
- sigvec(SIGINT,&vec,NULL);
- sigsetmask(0);
-}
-
-void noholdintr(void)
-{
- intr();
-}
-
-void holdintr(void)
-{
-struct sigvec vec = { handler,sigmask(SIGINT),0 };
-
- if (interact)
- {
- sigvec(SIGINT,&vec,NULL);
- sigsetmask(0);
- }
-}
-
-char *fgetline(char *buf,int len,FILE *in)
-{
- if (!fgets(buf,len,in))
- return NULL;
- buf[len] = '\0';
- buf[strlen(buf)-1] = '\0';
- return buf;
-}
-
-/* get a symlink-free pathname for s relative to PWD */
-
-char *findcwd(char *s)
-{
-char *t;
-
- if (*s == '/')
- return xsymlink(s);
- s = tricat((cwd[1]) ? cwd : "","/",s);
- t = xsymlink(s);
- free(s);
- return t;
-}
-
-static char xbuf[MAXPATHLEN];
-
-/* expand symlinks in s, and remove other weird things */
-
-char *xsymlink(char *s)
-{
- if (*s != '/')
- return NULL;
- strcpy(xbuf,"");
- if (xsymlinks(s+1))
- return strdup(s);
- if (!*xbuf)
- return strdup("/");
- return strdup(xbuf);
-}
-
-char **slashsplit(char *s)
-{
-char *t,**r,**q;
-int t0;
-
- if (!*s)
- return (char **) calloc(sizeof(char **),1);
- for (t = s, t0 = 0; *t; t++)
- if (*t == '/')
- t0++;
- q = r = (char **) zalloc(sizeof(char **)*(t0+2));
- while (t = strchr(s,'/'))
- {
- *t = '\0';
- *q++ = strdup(s);
- *t = '/';
- while (*t == '/')
- t++;
- if (!*t)
- {
- *q = NULL;
- return r;
- }
- s = t;
- }
- *q++ = strdup(s);
- *q = NULL;
- return r;
-}
-
-int islink(char *s)
-{
-char xbuf[MAXPATHLEN];
-
- if (readlink(s,xbuf,1) == -1 && errno == EINVAL)
- return 0;
- return 1;
-}
-
-int xsymlinks(char *s)
-{
-char **pp,**opp;
-char xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
-int t0;
-
- opp = pp = slashsplit(s);
- for (; *pp; pp++)
- {
- if (!strcmp(*pp,"."))
- {
- free(*pp);
- continue;
- }
- if (!strcmp(*pp,".."))
- {
- char *p;
-
- free(*pp);
- if (!strcmp(xbuf,"/"))
- continue;
- p = xbuf+strlen(xbuf);
- while (*--p != '/');
- *p = '\0';
- continue;
- }
- sprintf(xbuf2,"%s/%s",xbuf,*pp);
- t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
- if (t0 == -1)
- {
- if (errno != EINVAL)
- {
- while (*pp)
- free(*pp++);
- free(opp);
- return 1;
- }
- strcat(xbuf,"/");
- strcat(xbuf,*pp);
- free(*pp);
- }
- else
- {
- xbuf3[t0] = '\0'; /* STUPID */
- if (*xbuf3 == '/')
- {
- strcpy(xbuf,"");
- if (xsymlinks(xbuf3+1))
- return 1;
- }
- else
- if (xsymlinks(xbuf3))
- return 1;
- free(*pp);
- }
- }
- free(opp);
- return 0;
-}
-
-void printdir(char *s)
-{
-int t0;
-
- if (!strncmp(s,home,t0 = strlen(home)))
- {
- putchar('~');
- fputs(s+t0,stdout);
- }
- else
- fputs(s,stdout);
-}
-
-
-int ddifftime(time_t t1,time_t t2)
-{
- return ((long) t2-(long) t1);
-}
-
-/* see if jobs need printing */
-
-void scanjobs(void)
-{
-int t0;
-
- for (t0 = 1; t0 != MAXJOB; t0++)
- if (jobtab[t0].stat & STAT_CHANGED)
- printjob(jobtab+t0,0);
-}
-
-/* do pre-prompt stuff */
-
-void preprompt(void)
-{
-int diff;
-list list;
-char *mc = getparm("MAILCHECK"),*wc = getparm("LOGCHECK");
-struct schnode *sch,*schl;
-
- if (unset(NOTIFY))
- scanjobs();
- if (errflag)
- return;
- if (list = gethnode("precmd",shfunchtab))
- newrunlist(list);
- if (errflag)
- return;
- if (period && (time(NULL) > lastperiod+period) &&
- (list = gethnode("periodic",shfunchtab)))
- {
- newrunlist(list);
- lastperiod = time(NULL);
- }
- if (errflag)
- return;
- if (getparm("WATCH"))
- {
- diff = (int) ddifftime(lastwatch,time(NULL));
- if (diff > ((wc) ? atoi(wc)*60 : 300))
- {
- lastwatch = time(NULL);
- watch();
- }
- }
- if (errflag)
- return;
- diff = (int) ddifftime(lastmailcheck,time(NULL));
- if (diff > ((mc) ? atoi(mc) : 60))
- {
- lastmailcheck = time(NULL);
- if (getparm("MAILPATH"))
- checkmailpath();
- else
- checkmail();
- }
- for (schl = (struct schnode *) &scheds, sch = scheds; sch;
- sch = (schl = sch)->next)
- {
- if (sch->time < time(NULL))
- {
- execstring(sch->cmd);
- schl->next = sch->next;
- free(sch);
- }
- if (errflag)
- return;
- }
-}
-
-void checkmail(void)
-{
-struct stat st;
-char *s;
-
- if (!(s = getparm("MAIL")))
- return;
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- lastmailval = 0;
- lastmailsize = 0;
- return;
- }
- else
- if (lastmailval != -1 && lastmailval < st.st_mtime &&
- lastmailsize < st.st_size)
- zerr("you have new mail.");
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
-}
-
-void checkfirstmail(void)
-{
-struct stat st;
-char *s;
-
- if (!(s = getparm("MAIL")))
- return;
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- lastmailval = 0;
- lastmailsize = 0;
- return;
- }
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
- zerr("you have mail.");
-}
-
-void checkmailpath(void)
-{
-struct stat st;
-char *s = getparm("MAILPATH"),*v,*u,c,d;
-
- for (;;)
- {
- for (v = s; *v && *v != '?' && *v != ':'; v++);
- c = *v;
- *v = '\0';
- if (c != '?')
- u = NULL;
- else
- {
- for (u = v+1; *u && *u != ':'; u++);
- d = *u;
- *u = '\0';
- }
- if (stat(s,&st) == -1)
- {
- if (errno != ENOENT)
- zerr("%e: %s",errno,getparm("MAIL"));
- }
- else
- if (lastmailval != -1 && lastmailval < st.st_mtime &&
- lastmailsize < st.st_size)
- if (!u)
- fprintf(stderr,"You have new mail.\n");
- else
- {
- char *z = u;
-
- while (*z)
- if (*z == '$' && z[1] == '_')
- {
- fprintf(stderr,"%s",s);
- z += 2;
- }
- else
- fputc(*z++,stderr);
- fputc('\n',stderr);
- }
- lastmailval = st.st_mtime;
- lastmailsize = st.st_size;
- *v = c;
- if (u)
- *u = d;
- if (!c || (u && !d))
- break;
- v = (u) ? u+1 : v+1;
- }
-}
-
-/* create command hash table */
-
-void createchtab(void)
-{
-int t0,dot = 0;
-struct direct *de;
-DIR *dir;
-struct chnode *cc;
-
- holdintr();
- if (chtab)
- freehtab(chtab,freechnode);
- chtab = newhtable(101);
- for (t0 = 0; t0 != pathct; t0++)
- if (!strcmp(".",path[t0]))
- {
- dot = 1;
- break;
- }
- for (t0 = pathct-1; t0 >= 0; t0--)
- if (!strcmp(".",path[t0]))
- dot = 0;
- else
- {
- dir = opendir(path[t0]);
- if (!dir)
- {
- zerr("%e: %s",errno,path[t0]);
- continue;
- }
- readdir(dir); readdir(dir);
- while (de = readdir(dir))
- {
- cc = alloc(sizeof(struct chnode));
- cc->type = (dot) ? EXCMD_POSTDOT : EXCMD_PREDOT;
- cc->globstat = GLOB;
- cc->u.nam = tricat(path[t0],"/",de->d_name);
- addhnode(strdup(de->d_name),cc,chtab,freechnode);
- }
- closedir(dir);
- }
- addintern(chtab);
- noholdintr();
-}
-
-void freechnode(void *a)
-{
-struct chnode *c = (struct chnode *) a;
-
- if (c->type != BUILTIN)
- free(c->u.nam);
- free(c);
-}
-
-void freestr(void *a)
-{
- free(a);
-}
-
-void freeanode(void *a)
-{
-struct anode *c = (struct anode *) a;
-
- free(c->text);
- free(c);
-}
-
-void freeredir(void *a)
-{
-struct fnode *f = (struct fnode *) a;
-
- if (f)
- {
- if (f->type == HEREDOC)
- close(f->u.fd2);
- else
- free(f->u.name);
- free(f);
- }
-}
-
-void freeshfunc(void *a)
-{
- freelist((list) a);
-}
-
-void freepm(void *a)
-{
-struct pmnode *pm = a;
-
- if (!pm->isint)
- free(pm->u.str);
- free(pm);
-}
-
-void restoretty(void)
-{
- settyinfo(&shttyinfo);
-}
-
-void gettyinfo(struct ttyinfo *ti)
-{
- if (jobbing)
- {
-#ifndef BUGGY_GCC
-#ifdef TERMIOS
- ioctl(SHTTY,TCGETS,&ti->termios);
-#else
- ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
- ioctl(SHTTY,TIOCGETC,&ti->tchars);
- ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
-#endif
- ioctl(SHTTY,TIOCGWINSZ,&ti->winsize);
-#else
-#ifdef TERMIOS
- ioctl(SHTTY, ( 0x40000000 |((sizeof( struct termios)&0xff )<<16)|('T'<<8)| 8) ,&ti->termios);
-#else
- ioctl(SHTTY,(0x40000000|((sizeof(struct sgttyb)&0x1fff)<<16)|
- ('t'<<8)|8),&ti->sgttyb);
- ioctl(SHTTY,(0x40000000|((sizeof(struct tchars)&0x1fff)<<16)|
- ('t'<<8)|18),&ti->tchars);
- ioctl(SHTTY,(0x40000000|((sizeof(struct ltchars)&0x1fff)<<16)|
- ('t'<<8)|116),&ti->ltchars);
-#endif
- ioctl(SHTTY,( 0x40000000 |((sizeof( struct winsize)&0xff )<<16)|('t'<<8)| 104) ,&ti->winsize);
-#endif
- }
-}
-
-void settyinfo(struct ttyinfo *ti)
-{
- if (jobbing)
- {
-#ifndef BUGGY_GCC
-#ifdef TERMIOS
- ioctl(SHTTY,TCSETS,&ti->termios);
-#else
- ioctl(SHTTY,TIOCSETP,&ti->sgttyb);
- ioctl(SHTTY,TIOCSETC,&ti->tchars);
- ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
-#endif
- ioctl(SHTTY,TIOCSWINSZ,&ti->winsize);
-#else
-#ifdef TERMIOS
- ioctl(SHTTY, ( 0x80000000 |((sizeof( struct termios)&0xff )<<16)|('T'<<8)| 9) ,&ti->termios);
-#else
- ioctl(SHTTY,(0x80000000|((sizeof( struct sgttyb)&0x1fff)<<16)|
- ('t'<<8)|9),&ti->sgttyb);
- ioctl(SHTTY,(0x80000000|((sizeof(struct tchars)&0x1fff)<<16)|
- ('t'<<8)|17),&ti->tchars);
- ioctl(SHTTY,(0x80000000|((sizeof(struct ltchars)&0x1fff)<<16)|
- ('t'<<8)|117),&ti->ltchars);
-#endif
- ioctl(SHTTY,( 0x80000000 |((sizeof( struct winsize)&0xff )<<16)|('t'<<8)| 103) ,&ti->winsize);
-#endif
- }
-}
-
-int zyztem(char *s,char *t)
-{
-#ifdef WAITPID
-int pid,statusp;
-
- if (!(pid = fork()))
- {
- s = tricat(s," ",t);
- execl("/bin/sh","sh","-c",s,(char *) 0);
- _exit(1);
- }
- waitpid(pid,&statusp,WUNTRACED);
- if (WIFEXITED(SP(statusp)))
- return WEXITSTATUS(SP(statusp));
- return 1;
-#else
- if (!waitfork())
- {
- s = tricat(s," ",t);
- execl("/bin/sh","sh","-c",s,(char *) 0);
- _exit(1);
- }
- return 0;
-#endif
-}
-
-#ifndef WAITPID
-
-/* fork a process and wait for it to complete without confusing
- the SIGCHLD handler */
-
-int waitfork(void)
-{
-int pipes[2];
-char x;
-
- pipe(pipes);
- if (!fork())
- {
- close(pipes[0]);
- signal(SIGCHLD,SIG_DFL);
- if (!fork())
- return 0;
- wait(NULL);
- _exit(0);
- }
- close(pipes[1]);
- read(pipes[0],&x,1);
- close(pipes[0]);
- return 1;
-}
-
-#endif
-
-/* move a fd to a place >= 10 */
-
-int movefd(int fd)
-{
-int fe;
-
- if (fd == -1)
- return fd;
- if ((fe = dup(fd)) < 10)
- fe = movefd(fe);
- close(fd);
- return fe;
-}
-
-/* move fd x to y */
-
-void redup(int x,int y)
-{
- if (x != y)
- {
- dup2(x,y);
- close(x);
- }
-}
-
-void settrap(char *s,int empty)
-{
-int t0;
-
- if (strncmp(s,"TRAP",4))
- return;
- for (t0 = 0; t0 != SIGCOUNT+2; t0++)
- if (!strcmp(s+4,sigs[t0]))
- {
- if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
- || t0 == SIGPIPE))
- {
- zerr("can't trap SIG%s in interactive shells",s);
- return;
- }
- if (empty)
- {
- sigtrapped[t0] = 2;
- if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
- {
- signal(t0,SIG_IGN);
- sigtrapped[t0] = 2;
- }
- }
- else
- {
- if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
- signal(t0,handler);
- sigtrapped[t0] = 1;
- }
- return;
---cut here---cut here---cut here---pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
- }
- zerr("warning: undefined signal name: SIG%s",s+4);
-}
-
-void unsettrap(char *s)
-{
-int t0;
-
- if (strncmp(s,"TRAP",4))
- return;
- for (t0 = 0; t0 != SIGCOUNT+2; t0++)
- if (!strcmp(s+4,sigs[t0]))
- {
- if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
- || t0 == SIGPIPE))
- {
- zerr("can't trap SIG%s in interactive shells",s);
- return;
- }
- sigtrapped[t0] = 0;
- if (t0 == SIGINT)
- intr();
- else if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
- signal(t0,SIG_DFL);
- return;
- }
- zerr("warning: undefined signal name: SIG%s",s+4);
-}
-
-void dotrap(int sig)
-{
-char buf[16];
-list l;
-int sav;
-
- sav = sigtrapped[sig];
- if (sav == 2)
- return;
- sigtrapped[sig] = 2;
- sprintf(buf,"TRAP%s",sigs[sig]);
- if (l = gethnode(buf,shfunchtab))
- newrunlist(l);
- sigtrapped[sig] = sav;
-}
-
-/* get the text corresponding to a command */
-
-char *gettext(comm comm)
-{
-char *s,*t;
-
- switch(comm->type)
- {
- case SIMPLE:
- return getsimptext(comm);
- case SUBSH:
- t = getltext(comm->left);
- s = tricat("(",t,")");
- free(t);
- return s;
- case CURSH:
- case SHFUNC:
- t = getltext(comm->left);
- s = tricat("{",t,"}");
- free(t);
- return s;
- case CFOR:
- return getfortext((struct fornode *) comm->info,comm);
- case CWHILE:
- return getwhiletext((struct whilenode *) comm->info);
- case CREPEAT:
- return getrepeattext((struct repeatnode *) comm->info);
- case CIF:
- return getiftext((struct ifnode *) comm->info);
- case CCASE:
- return getcasetext((struct casenode *) comm->info,comm->args);
- case CSELECT:
- return getfortext((struct fornode *) comm->info,comm);
- default:
- return strdup("(...)");
- }
- return NULL;
-}
-
-char *getltext(list l)
-{
-char *s,*t,*u;
-
- s = getl2text(l->left);
- if (l->type == ASYNC)
- {
- t = dyncat(s," &");
- free(s);
- s = t;
- }
- if (!l->right)
- return s;
- t = getltext(l->right);
- u = tricat(s,(l->type == SYNC) ? "\n" : "",t);
- free(s);
- free(t);
- return u;
-}
-
-char *getl2text(list2 l)
-{
-char *s,*t,*u;
-
- s = getptext(l->left);
- if (!l->right)
- return s;
- t = getl2text(l->right);
- u = tricat(s,(l->type == ORNEXT) ? " || " : " && ",t);
- free(s);
- free(t);
- return u;
-}
-
-char *getptext(pline p)
-{
-char *s,*t,*u;
-
- s = gettext(p->left);
- if (!p->right)
- return s;
- t = getptext(p->right);
- u = tricat(s," | ",t);
- free(s);
- free(t);
- return u;
-}
-
-char *getsimptext(comm comm)
-{
-int len = 0;
-Node n;
-char *fstr[] = {
- ">",">!",">>",">>!","<","<<","<&",">&",">&-"
- };
-struct fnode *f;
-char *s,*t,u = '=';
-
- for (n = comm->args->first; n; n = n->next)
- len += strlen(n->dat)+1;
- if (comm->vars)
- for (n = comm->vars->first; n; n = n->next)
- len += strlen(n->dat)+1;
- for (n = comm->redir->first; n; n = n->next)
- {
- f = n->dat;
- switch(f->type)
- {
- case WRITE: case WRITENOW: case APP: case APPNOW: case READ:
- len += strlen(fstr[f->type])+strlen(f->u.name)+8;
- break;
- case HEREDOC: case MERGE: case MERGEOUT:
- len += strlen(fstr[f->type])+10;
- break;
- case CLOSE:
- len += 10;
- break;
- case INPIPE:
- case OUTPIPE:
- len += strlen(f->u.name)+10;
- break;
- }
- }
- len += strlen(comm->cmd);
- s = t = zalloc(len+5);
- if (comm->vars)
- for (n = comm->vars->first; n; n = n->next)
- {
- strucpy(&t,n->dat);
- *t++ = u;
- u = ('='+' ')-u;
- }
- strucpy(&t,comm->cmd);
- *t++ = ' ';
- for (n = comm->args->first; n; n = n->next)
- {
- strucpy(&t,n->dat);
- *t++ = ' ';
- }
- for (n = comm->redir->first; n; n = n->next)
- {
- f = n->dat;
- switch(f->type)
- {
- case WRITE: case WRITENOW: case APP: case APPNOW: case READ:
- if (f->fd1 != ((f->type == READ) ? 0 : 1))
- *t++ = '0'+f->fd1;
- strucpy(&t,fstr[f->type]);
- *t++ = ' ';
- strucpy(&t,f->u.name);
- *t++ = ' ';
- break;
- case HEREDOC: case MERGE: case MERGEOUT:
- if (f->fd1 != ((f->type == MERGEOUT) ? 1 : 0))
- *t++ = '0'+f->fd1;
- strucpy(&t,fstr[f->type]);
- *t++ = ' ';
- sprintf(t,"%d ",f->u.fd2);
- t += strlen(t);
- break;
- case CLOSE:
- *t++ = '0'+f->fd1;
- strucpy(&t,">&- ");
- break;
- case INPIPE:
- case OUTPIPE:
- if (f->fd1 != ((f->type == INPIPE) ? 0 : 1))
- *t++ = '0'+f->fd1;
- strucpy(&t,(f->type == INPIPE) ? "< " : "> ");
- strucpy(&t,f->u.name);
- strucpy(&t," ");
- len += strlen(f->u.name)+6;
- break;
- }
- }
- t[-1] = '\0';
- return s;
-}
-
-char *getfortext(struct fornode *n,comm comm)
-{
-char *s,*t,*u,*v;
-
- s = getltext(n->list);
- u = dyncat((comm->type == CFOR) ? "for " : "select ",n->name);
- if (comm->args)
- {
- t = makehlist(comm->args,0);
- v = tricat(u," in ",t);
- free(u);
- free(t);
- u = v;
- }
- v = dyncat(u,"\n do ");
- free(u);
- u = tricat(v,s,"\n done");
- free(v);
- free(s);
- return u;
-}
-
-char *getwhiletext(struct whilenode *n)
-{
-char *s,*t,*u,*v;
-
- t = getltext(n->cont);
- v = getltext(n->loop);
- s = tricat((!n->cond) ? "while " : "until ",t,"\n do ");
- u = tricat(s,v,"\n done");
- free(s);
- free(t);
- free(v);
- return u;
-}
-
-char *getrepeattext(struct repeatnode *n)
-{
-char buf[100];
-char *s,*t,*u;
-
- s = getltext(n->list);
- sprintf(buf,"%d",n->count);
- t = tricat("repeat ",buf," do ");
- u = tricat(t,s,"\n done");
- free(s);
- free(t);
- return u;
-}
-
-char *getiftext(struct ifnode *n)
-{
-int fst = 1;
-char *v = strdup("");
-char *s,*t,*u,*w;
-
- while (n && n->ifl)
- {
- s = getltext(n->ifl);
- t = getltext(n->thenl);
- u = tricat((fst) ? "if " : "elif ",s,"\n then ");
- w = tricat(u,t,"\n ");
- free(s);
- free(t);
- free(u);
- s = dyncat(v,w);
- free(v);
- free(w);
- v = s;
- fst = 0;
- n = n->next;
- }
- if (n)
- {
- s = getltext(n->thenl);
- t = tricat(v,"else ",s);
- u = dyncat(t,"\n fi");
- free(s);
- free(t);
- free(v);
- return u;
- }
- u = dyncat(v,"\n fi");
- free(v);
- return u;
-}
-
-char *getcasetext(struct casenode *n,table l)
-{
-char *s,*t,*u,*v;
-
- s = tricat("case ",l->first->dat," in ");
- while (n)
- {
- u = getltext(n->list);
- t = tricat(n->pat,") ",u);
- v = tricat(s,t," ;;\n");
- free(s);
- free(t);
- free(u);
- s = v;
- n = n->next;
- }
- t = dyncat(s,"esac\n");
- free(s);
- return t;
-}
-
-/* copy t into *s and update s */
-
-void strucpy(char **s,char *t)
-{
-char *u = *s;
-
- while (*u++ = *t++);
- *s = u-1;
-}
-
-void checkrmall(void)
-{
- fflush(stdin);
- fprintf(stderr,"zsh: are you sure you want to delete "
- "all the files? ");
- fflush(stderr);
- ding();
- errflag |= !getquery();
-}
-
-int getquery(void)
-{
-char c;
-int yes = 0;
-
- setcbreak();
- if (read(SHTTY,&c,1) == 1 && (c == 'y' || c == 'Y'))
- yes = 1;
- unsetcbreak();
- if (c != '\n')
- write(2,"\n",1);
- return yes;
-}
-
-static int d;
-static char *guess,*best;
-
-void spscan(char *s,char *junk)
-{
-int nd;
-
- nd = spdist(s,guess);
- if (nd <= d && nd != 3)
- {
- best = s;
- d = nd;
- }
-}
-
-/* spellcheck a command */
-
-void spckcmd(char **s)
-{
-char *t;
-
- if (gethnode(*s,chtab) || gethnode(*s,shfunchtab))
- return;
- for (t = *s; *t; t++)
- if (*t == '/')
- return;
- if (access(*s,F_OK) == 0)
- return;
- best = NULL;
- guess = *s;
- d = 3;
- listhtable(chtab,spscan);
- listhtable(shfunchtab,spscan);
- if (best)
- {
- fprintf(stderr,"zsh: correct to `%s' (y/n)? ",best);
- fflush(stderr);
- ding();
- if (getquery())
- {
- free(*s);
- *s = strdup(best);
- }
- }
-}
-
-void addlocal(char *s)
-{
- if (locallist)
- addnode(locallist,strdup(s));
-}
-
-/* perform pathname substitution on a PATH or CDPATH component */
-
-void pathsub(char **s)
-{
- if (**s == '=')
- **s = Equals;
- if (**s == '~')
- **s = Tilde;
- filesub((void **) s);
-}
-
-#ifndef STRFTIME
-int strftime(char *buf,int bufsize,char *fmt,struct tm *tm)
-{
-char *astr[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *estr[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
- "Aug","Sep","Oct","Nov","Dec"};
-char *lstr[] = {"12"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10","11"};
-
- while (*fmt)
- if (*fmt == '%')
- {
- fmt++;
- switch(*fmt++)
- {
- case 'a':
- strucpy(&buf,astr[tm->tm_wday]);
- break;
- case 'b':
- strucpy(&buf,estr[tm->tm_mon]);
- break;
- case 'd':
- *buf++ = '0'+tm->tm_mday/10;
- *buf++ = '0'+tm->tm_mday%10;
- break;
- case 'e':
- *buf++ = (tm->tm_mday > 9) ? '0'+tm->tm_mday/10 : ' ';
- *buf++ = '0'+tm->tm_mday%10;
- break;
- case 'k':
- *buf++ = (tm->tm_hour > 9) ? '0'+tm->tm_hour/10 : ' ';
- *buf++ = '0'+tm->tm_hour%10;
- break;
- case 'l':
- strucpy(&buf,lstr[tm->tm_hour%12]);
- break;
- case 'm':
- *buf++ = '0'+tm->tm_mon/10;
- *buf++ = '0'+tm->tm_mon%10;
- break;
- case 'M':
- *buf++ = '0'+tm->tm_min/10;
- *buf++ = '0'+tm->tm_min%10;
- break;
- case 'p':
- *buf++ = (tm->tm_hour > 11) ? 'P' : 'A';
- *buf++ = 'M';
- break;
- case 'S':
- *buf++ = '0'+tm->tm_sec/10;
- *buf++ = '0'+tm->tm_sec%10;
- break;
- case 'y':
- *buf++ = '0'+tm->tm_year/10;
- *buf++ = '0'+tm->tm_year%10;
- break;
- default:
- exit(20);
- }
- }
- else
- *buf++ = *fmt++;
- *buf = '\0';
- return 0;
-}
-#endif
-
-#ifndef PUTENV
-int putenv(char *a)
-{
-char *b = a;
-
- while (*a++ != '=');
- a[-1] = '\0';
- setenv(strdup(b),strdup(a));
- free(b);
- return 0;
-}
-#endif
-
-int ppcount(void)
-{
-Node n;
-int val = -1;
-
- for (n = pparms->first; n; n = n->next,val++);
- return val;
-}
-
End of utils.c
echo utils.pro 1>&2
sed 's/^-//' >utils.pro <<'End of utils.pro'
-void addvars(table vars);
-void setiparm(char *s,long v,int isint);
-void setparm(char *s,char *t,int ex,int isint);
-void unsetparm(char *s);
-long getiparm(char *s);
-char *getparm(char *s);
-void parsepath(void);
-void parsecdpath(void);
-int source(char *s);
-void sourcehome(char *s);
-void zerrnam(char *cmd, char *fmt, ...);
-void zerr(char *fmt,...);
-void niceputc(int c,FILE *f);
-void intr(void);
-void noholdintr(void);
-void holdintr(void);
-char *fgetline(char *buf,int len,FILE *in);
-char *findcwd(char *s);
-char *xsymlink(char *s);
-char **slashsplit(char *s);
-int islink(char *s);
-int xsymlinks(char *s);
-void printdir(char *s);
-int ddifftime(time_t t1,time_t t2);
-void scanjobs(void);
-void preprompt(void);
-void checkmail(void);
-void checkfirstmail(void);
-void checkmailpath(void);
-void createchtab(void);
-void freechnode(void *a);
-void freestr(void *a);
-void freeanode(void *a);
-void freeredir(void *a);
-void freeshfunc(void *a);
-void freepm(void *a);
-void restoretty(void);
-void gettyinfo(struct ttyinfo *ti);
-void settyinfo(struct ttyinfo *ti);
-int zyztem(char *s,char *t);
-int waitfork(void);
-int movefd(int fd);
-void redup(int x,int y);
-void settrap(char *s,int empty);
-void unsettrap(char *s);
-void dotrap(int sig);
-char *gettext(comm comm);
-char *getltext(list l);
-char *getl2text(list2 l);
-char *getptext(pline p);
-char *getsimptext(comm comm);
-char *getfortext(struct fornode *n,comm comm);
-char *getwhiletext(struct whilenode *n);
-char *getrepeattext(struct repeatnode *n);
-char *getiftext(struct ifnode *n);
-char *getcasetext(struct casenode *n,table l);
-void strucpy(char **s,char *t);
-void checkrmall(void);
-int getquery(void);
-void spscan(char *s,char *junk);
-void spckcmd(char **s);
-void addlocal(char *s);
-void pathsub(char **s);
-int strftime(char *buf,int bufsize,char *fmt,struct tm *tm);
End of utils.pro
echo vars.c 1>&2
sed 's/^-//' >vars.c <<'End of vars.c'
-/*
-
- vars.c - variable declarations
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-
-/* buffered shell input for non-interactive shells */
-
-FILE *bshin;
-
-/* null-terminated array of pointers to strings containing elements
- of PATH and CDPATH */
-
-char **path,**cdpath;
-
-/* number of elements in aforementioned array */
-
-int pathct,cdpathct;
-
-/* error/break flag */
-
-int errflag = 0;
-
-/* current history event number */
-
-int cev = 0;
-
-/* if != 0, this is the first line of the command */
-
-int firstln;
-
-/* if != 0, this is the first char of the command (not including
- white space */
-
-int firstch;
-
-/* first event number in the history table */
-
-int tfev = 1;
-
-/* capacity of history table */
-
-int tevs = 20;
-
-/* if = 1, we have performed history substitution on the current line
- if = 2, we have used the 'p' modifier */
-
-int hflag;
-
-/* default event (usually cev-1, that is, "!!") */
-
-int dev = 0;
-
-/* != 0 if we are in the middle of parsing a command (== 0 if we
- have not yet parsed the command word */
-
-int incmd = 0;
-
-/* the list of history events */
-
-table histlist;
-
-/* the current history event (can be NULL) */
-
-table curtab;
-
-/* the directory stack */
-
-table dirstack;
-
-/* a string containing all the ungot characters (hungetch()) */
-
-char *ungots;
-
-/* the pointer to the next character to read from ungots */
-
-char *ungotptr;
-
-/* the contents of the IFS parameter */
-
-char *ifs;
-
-/* != 0 if this is a subshell */
-
-int subsh;
-
-/* # of break levels (break builtin) */
-
-int breaks;
-
-/* != 0 if we have a return pending (return builtin) */
-
-int retflag;
-
-/* # of nested loops we are in */
-
-int loops;
-
-/* # of continue levels */
-
-int contflag;
-
-/* the job currently being created/waited for (not current job in the sense
- of '+' and '-', that's topjob */
-
-int curjob;
-
-/* the current job (+) */
-
-int topjob = -1;
-
-/* the previous job (-) */
-
-int prevjob = -1;
-
-/* hash table containing the aliases and reserved words */
-
-htable alhtab;
-
-/* hash table containing the parameters */
-
-htable parmhtab;
-
-/* hash table containing the builtins/hashed commands */
-
-htable chtab;
-
-/* hash table containing the shell functions */
-
-htable shfunchtab;
-
-/* the job table */
-
-struct jobnode jobtab[MAXJOB];
-
-/* the list of sched jobs pending */
-
-struct schnode *scheds = NULL;
-
-/* the last l for s/l/r/ history substitution */
-
-char *last;
-
-/* the last r for s/l/r/ history substitution */
-
-char *rast;
-
-/* if peek == STRING or ENVSTRING, the next token */
-
-char *tstr;
-
-/* who am i */
-
-char *username;
-
-/* the return code of the last command */
-
-int lastval;
-
-/* != 0 if this is a login shell */
-
-int islogin;
-
-/* the next token (enum xtok) */
-
-int peek;
-
-/* the file descriptor associated with the next token, if it
- is something like '<' or '>>', etc. */
-
-int peekfd;
-
-/* input fd from the coprocess */
-
-int spin = -1;
-
-/* output fd from the coprocess */
-
-int spout = -1;
-
-/* the last time we checked mail */
-
-time_t lastmailcheck;
-
-/* the last modified date on the mail file last time we checked */
-
-time_t lastmailval;
-
-/* the last time we checked the people in the WATCH variable */
-
-time_t lastwatch;
-
-/* the last time we did the periodic() shell function */
-
-time_t lastperiod;
-
-/* $SECONDS = time(NULL) - shtimer */
-
-time_t shtimer;
-
-/* the size of the mail file last time we checked */
-
-off_t lastmailsize;
-
-/* $$ */
-
-long procnum;
-
-/* $! (the pid of the last background command invoked */
-
-long proclast;
-
-/* the process group of the shell */
-
-long shpgrp;
-
-/* the current working directory */
-
-char *cwd;
-
-/* the hostname, truncated after the '.' */
-
-char *hostM;
-
-/* the hostname */
-
-char *hostm;
-
-/* the home directory */
-
-char *home;
-
-/* the positional parameters */
-
-table pparms;
-
-/* the list of local variables we have to destroy */
-
-table locallist;
-
-/* the shell input fd */
-
-int SHIN;
-
-/* the shell tty fd */
-
-int SHTTY;
-
-/* the stack of aliases we are expanding */
-
-struct anode *alstack[MAXAL];
-
-/* the alias stack pointer; also, the number of aliases currently
- being expanded */
-
-int alix = 0;
-
-/* != 0 means we are reading input from a string */
-
-int strin = 0;
-
-/* == 1 means we are doing TAB expansion
- == 2 means expansion has occurred during TAB expansion */
-
-int magic = 0;
-
-/* period between periodic() commands, in seconds */
-
-int period = 0;
-
-/* != 0 means history is turned off (through !" or setopt nobanghist) */
-
-int stophist = 0;
-
-/* != 0 means we have removed the current event from the history list */
-
-int histremmed = 0;
-
-/* the options; e.g. if opts['a'] is nonzero, -a is turned on */
-
-int opts[128];
-
-/* LINENO */
-
-int lineno;
-
-/* != 0 means we have called execlist() and then intend to exit(),
- so don't fork if not necessary */
-
-int exiting = 0;
-
-/* the limits for child processes */
-
-struct rlimit limits[RLIM_NLIMITS];
-
-/* the tokens */
-
-char *tokens = "#$^*()$=|{}[]`<>?~`,";
-
-/* the current word in the history list */
-
-char *hlastw;
-
-/* the pointer to the current character in the current word
- in the history list */
-
-char *hlastp;
-
-/* the size of the current word in the history list */
-
-int hlastsz;
-
-/* the alias expansion status - if == ALSTAT_MORE, we just finished
- expanding an alias ending with a space */
-
-int alstat;
-
-/* we have printed a 'you have stopped (running) jobs.' message */
-
-int stopmsg;
-
-/* the default tty state */
-
-struct ttyinfo shttyinfo;
-
-/* signal names */
-
-char *sigs[] = { "EXIT",
- "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "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"
-};
-
-/* signals that are trapped = 1, signals ignored =2 */
-
-int sigtrapped[SIGCOUNT+2];
-
End of vars.c
echo vars.pro 1>&2
sed 's/^-//' >vars.pro <<'End of vars.pro'
End of vars.pro
echo zhistory.c 1>&2
sed 's/^-//' >zhistory.c <<'End of zhistory.c'
-/*
-
- zhistory.c - interface between readline an zsh's ideas of history
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "zsh.h"
-#include "funcs.h"
-#include "readline/history.h"
-
-/* bindings to make zsh and readline get along */
-
-static int histline;
-
-void using_history(void)
-{
- histline = cev;
-}
-
-int where_history(void)
-{
- return histline;
-}
-
-int history_set_pos(int pos)
-{
- histline = pos;
- return 0;
-}
-
-HIST_ENTRY *current_history(void)
-{
-table tab;
-char *str;
-HIST_ENTRY *he;
-
- tab = quietgetevent(histline);
- if (!tab)
- return NULL;
- str = makehlist(tab,0);
- he = (HIST_ENTRY *) malloc(sizeof *he);
- he->line = str;
- he->data = NULL;
- return he;
-}
-
-HIST_ENTRY *previous_history(void)
-{
- if (histline == tfev)
- return NULL;
- histline--;
- return current_history();
-}
-
-HIST_ENTRY *next_history(void)
-{
- if (histline == cev)
- return NULL;
- histline++;
- return current_history();
-}
-
-char *extracthistarg(int num)
-{
-Node n;
-
- if (histlist->last == (Node) histlist ||
- histlist->last->last == (Node) histlist)
- return NULL;
- n = ((table) (histlist->last->last))->first;
- for (; n && num; num--,n = n->next);
- if (!n)
- return NULL;
- return strdup(n->dat);
-}
-
End of zhistory.c
echo readline/chardefs.h 1>&2
sed 's/^-//' >readline/chardefs.h <<'End of readline/chardefs.h'
-/* chardefs.h -- Character definitions for readline. */
-#ifndef _CHARDEFS_
-
-#ifndef savestring
-#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
-#endif
-
-#ifndef whitespace
-#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
-#endif
-
-#ifdef CTRL
-#undef CTRL
-#endif
-
-/* Some character stuff. */
-#define control_character_threshold 0x020 /* smaller than this is control */
-#define meta_character_threshold 0x07f /* larger than this is Meta. */
-#define control_character_bit 0x40 /* 0x000000, must be off. */
-#define meta_character_bit 0x080 /* x0000000, must be on. */
-
-#define CTRL(c) ((c) & (~control_character_bit))
-#define META(c) ((c) | meta_character_bit)
-
-#define UNMETA(c) ((c) & (~meta_character_bit))
-#define UNCTRL(c) to_upper(((c)|control_character_bit))
-
-#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
-#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
-
-#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
-
-#ifndef to_upper
-#define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
-#define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
-#endif
-
-#define CTRL_P(c) ((c) < control_character_threshold)
-#define META_P(c) ((c) > meta_character_threshold)
-
-#define NEWLINE '\n'
-#define RETURN CTRL('M')
-#define RUBOUT 0x07f
-#define TAB '\t'
-#define ABORT_CHAR CTRL('G')
-#define PAGE CTRL('L')
-#define SPACE 0x020
-#define ESC CTRL('[')
-
-#endif /* _CHARDEFS_ */
End of readline/chardefs.h
echo readline/emacs_keymap.c 1>&2
sed 's/^-//' >readline/emacs_keymap.c <<'End of readline/emacs_keymap.c'
-/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef FILE
-#include <stdio.h>
-#endif /* FILE */
-
-#include "readline.h"
-
-/* An array of function pointers, one for each possible key.
- If the type byte is ISKMAP, then the pointer is the address of
- a keymap. */
-
-KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
-
- /* Control keys. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, rl_beg_of_line }, /* Control-a */
- { ISFUNC, rl_backward }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, rl_delete }, /* Control-d */
- { ISFUNC, rl_end_of_line }, /* Control-e */
- { ISFUNC, rl_forward }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, rl_rubout }, /* Control-h */ /* pjf */
- { ISFUNC, rl_complete }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, rl_clear_screen }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_get_next_history }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, rl_get_previous_history }, /* Control-p */
- { ISFUNC, rl_quoted_insert }, /* Control-q */
- { ISFUNC, (Function *)0x0 }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
- { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_undo_command }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_insert }, /* SPACE */
- { ISFUNC, rl_insert }, /* ! */
- { ISFUNC, rl_insert }, /* " */
- { ISFUNC, rl_insert }, /* # */
- { ISFUNC, rl_insert }, /* $ */
- { ISFUNC, rl_insert }, /* % */
- { ISFUNC, rl_insert }, /* & */
- { ISFUNC, rl_insert }, /* ' */
- { ISFUNC, rl_insert }, /* ( */
- { ISFUNC, rl_insert }, /* ) */
- { ISFUNC, rl_insert }, /* * */
- { ISFUNC, rl_insert }, /* + */
- { ISFUNC, rl_insert }, /* , */
- { ISFUNC, rl_insert }, /* - */
- { ISFUNC, rl_insert }, /* . */
- { ISFUNC, rl_insert }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_insert }, /* 0 */
- { ISFUNC, rl_insert }, /* 1 */
- { ISFUNC, rl_insert }, /* 2 */
- { ISFUNC, rl_insert }, /* 3 */
- { ISFUNC, rl_insert }, /* 4 */
- { ISFUNC, rl_insert }, /* 5 */
- { ISFUNC, rl_insert }, /* 6 */
- { ISFUNC, rl_insert }, /* 7 */
- { ISFUNC, rl_insert }, /* 8 */
- { ISFUNC, rl_insert }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, rl_insert }, /* : */
- { ISFUNC, rl_insert }, /* ; */
- { ISFUNC, rl_insert }, /* < */
- { ISFUNC, rl_insert }, /* = */
- { ISFUNC, rl_insert }, /* > */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_insert }, /* A */
- { ISFUNC, rl_insert }, /* B */
- { ISFUNC, rl_insert }, /* C */
- { ISFUNC, rl_insert }, /* D */
- { ISFUNC, rl_insert }, /* E */
- { ISFUNC, rl_insert }, /* F */
- { ISFUNC, rl_insert }, /* G */
- { ISFUNC, rl_insert }, /* H */
- { ISFUNC, rl_insert }, /* I */
- { ISFUNC, rl_insert }, /* J */
- { ISFUNC, rl_insert }, /* K */
- { ISFUNC, rl_insert }, /* L */
- { ISFUNC, rl_insert }, /* M */
- { ISFUNC, rl_insert }, /* N */
- { ISFUNC, rl_insert }, /* O */
- { ISFUNC, rl_insert }, /* P */
- { ISFUNC, rl_insert }, /* Q */
- { ISFUNC, rl_insert }, /* R */
- { ISFUNC, rl_insert }, /* S */
- { ISFUNC, rl_insert }, /* T */
- { ISFUNC, rl_insert }, /* U */
- { ISFUNC, rl_insert }, /* V */
- { ISFUNC, rl_insert }, /* W */
- { ISFUNC, rl_insert }, /* X */
- { ISFUNC, rl_insert }, /* Y */
- { ISFUNC, rl_insert }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_insert }, /* [ */
- { ISFUNC, rl_insert }, /* \ */
- { ISFUNC, rl_insert }, /* ] */
- { ISFUNC, rl_insert }, /* ^ */
- { ISFUNC, rl_insert }, /* _ */
- { ISFUNC, rl_insert }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_insert }, /* a */
- { ISFUNC, rl_insert }, /* b */
- { ISFUNC, rl_insert }, /* c */
- { ISFUNC, rl_insert }, /* d */
- { ISFUNC, rl_insert }, /* e */
- { ISFUNC, rl_insert }, /* f */
- { ISFUNC, rl_insert }, /* g */
- { ISFUNC, rl_insert }, /* h */
- { ISFUNC, rl_insert }, /* i */
- { ISFUNC, rl_insert }, /* j */
- { ISFUNC, rl_insert }, /* k */
- { ISFUNC, rl_insert }, /* l */
- { ISFUNC, rl_insert }, /* m */
- { ISFUNC, rl_insert }, /* n */
- { ISFUNC, rl_insert }, /* o */
- { ISFUNC, rl_insert }, /* p */
- { ISFUNC, rl_insert }, /* q */
- { ISFUNC, rl_insert }, /* r */
- { ISFUNC, rl_insert }, /* s */
- { ISFUNC, rl_insert }, /* t */
- { ISFUNC, rl_insert }, /* u */
- { ISFUNC, rl_insert }, /* v */
- { ISFUNC, rl_insert }, /* w */
- { ISFUNC, rl_insert }, /* x */
- { ISFUNC, rl_insert }, /* y */
- { ISFUNC, rl_insert }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, rl_insert }, /* { */
- { ISFUNC, rl_insert }, /* | */
- { ISFUNC, rl_insert }, /* } */
- { ISFUNC, rl_insert }, /* ~ */
- { ISFUNC, rl_rubout } /* RUBOUT */
-};
-
-KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
-
- /* Meta keys. Just like above, but the high bit is set. */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
- { ISFUNC, rl_abort }, /* Meta-Control-g */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-h */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-i */
- { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
- { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */
- { ISFUNC, rl_revert_line }, /* Meta-Control-r */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */
- { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */
-
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-] */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */
- { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, (Function *)rl_magic_space }, /* Meta-SPACE */
- { ISFUNC, (Function *)0x0 }, /* Meta-! */
- { ISFUNC, (Function *)0x0 }, /* Meta-" */
- { ISFUNC, (Function *)0x0 }, /* Meta-# */
- { ISFUNC, rl_check_spelling }, /* Meta-$ */
- { ISFUNC, (Function *)0x0 }, /* Meta-% */
- { ISFUNC, (Function *)0x0 }, /* Meta-& */
- { ISFUNC, (Function *)0x0 }, /* Meta-' */
- { ISFUNC, (Function *)0x0 }, /* Meta-( */
- { ISFUNC, (Function *)0x0 }, /* Meta-) */
- { ISFUNC, (Function *)0x0 }, /* Meta-* */
- { ISFUNC, (Function *)0x0 }, /* Meta-+ */
- { ISFUNC, (Function *)0x0 }, /* Meta-, */
- { ISFUNC, rl_digit_argument }, /* Meta-- */
- { ISFUNC, (Function *)0x0 }, /* Meta-. */
- { ISFUNC, (Function *)0x0 }, /* Meta-/ */
-
- /* Regular digits. */
- { ISFUNC, rl_digit_argument }, /* Meta-0 */
- { ISFUNC, rl_digit_argument }, /* Meta-1 */
- { ISFUNC, rl_digit_argument }, /* Meta-2 */
- { ISFUNC, rl_digit_argument }, /* Meta-3 */
- { ISFUNC, rl_digit_argument }, /* Meta-4 */
- { ISFUNC, rl_digit_argument }, /* Meta-5 */
- { ISFUNC, rl_digit_argument }, /* Meta-6 */
- { ISFUNC, rl_digit_argument }, /* Meta-7 */
- { ISFUNC, rl_digit_argument }, /* Meta-8 */
- { ISFUNC, rl_digit_argument }, /* Meta-9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* Meta-: */
- { ISFUNC, (Function *)0x0 }, /* Meta-; */
- { ISFUNC, rl_beginning_of_history }, /* Meta-< */
- { ISFUNC, (Function *)0x0 }, /* Meta-= */
- { ISFUNC, rl_end_of_history }, /* Meta-> */
- { ISFUNC, rl_possible_completions }, /* Meta-? */
- { ISFUNC, (Function *)0x0 }, /* Meta-@ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-A */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-B */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-C */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-D */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-E */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-F */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-G */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-H */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-I */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-J */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-K */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-L */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-M */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-N */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-O */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-P */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-R */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-S */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-T */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-U */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-V */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-W */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-X */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
- { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_function_key }, /* Meta-[ */
- { ISFUNC, (Function *)0x0 }, /* Meta-\ */
- { ISFUNC, (Function *)0x0 }, /* Meta-] */
- { ISFUNC, (Function *)0x0 }, /* Meta-^ */
- { ISFUNC, (Function *)0x0 }, /* Meta-_ */
- { ISFUNC, (Function *)0x0 }, /* Meta-` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* Meta-a */
- { ISFUNC, rl_backward_word }, /* Meta-b */
- { ISFUNC, rl_capitalize_word }, /* Meta-c */
- { ISFUNC, rl_kill_word }, /* Meta-d */
- { ISFUNC, (Function *)0x0 }, /* Meta-e */
- { ISFUNC, rl_forward_word }, /* Meta-f */
- { ISFUNC, (Function *)0x0 }, /* Meta-g */
- { ISFUNC, (Function *)0x0 }, /* Meta-h */
- { ISFUNC, (Function *)0x0 }, /* Meta-i */
- { ISFUNC, (Function *)0x0 }, /* Meta-j */
- { ISFUNC, (Function *)0x0 }, /* Meta-k */
- { ISFUNC, rl_downcase_word }, /* Meta-l */
- { ISFUNC, (Function *)0x0 }, /* Meta-m */
- { ISFUNC, (Function *)0x0 }, /* Meta-n */
- { ISFUNC, (Function *)0x0 }, /* Meta-o */
- { ISFUNC, (Function *)0x0 }, /* Meta-p */
- { ISFUNC, (Function *)0x0 }, /* Meta-q */
- { ISFUNC, rl_revert_line }, /* Meta-r */
- { ISFUNC, (Function *)0x0 }, /* Meta-s */
- { ISFUNC, rl_transpose_words }, /* Meta-t */
- { ISFUNC, rl_upcase_word }, /* Meta-u */
- { ISFUNC, (Function *)0x0 }, /* Meta-v */
- { ISFUNC, (Function *)0x0 }, /* Meta-w */
- { ISFUNC, (Function *)0x0 }, /* Meta-x */
- { ISFUNC, rl_yank_pop }, /* Meta-y */
- { ISFUNC, (Function *)0x0 }, /* Meta-z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* Meta-{ */
- { ISFUNC, (Function *)0x0 }, /* Meta-| */
- { ISFUNC, (Function *)0x0 }, /* Meta-} */
- { ISFUNC, (Function *)0x0 }, /* Meta-~ */
- { ISFUNC, rl_backward_kill_word } /* Meta-rubout */
-};
-
-KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
-
- /* Control keys. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, (Function *)0x0 }, /* Control-d */
- { ISFUNC, (Function *)0x0 }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, (Function *)0x0 }, /* Control-h */
- { ISFUNC, (Function *)0x0 }, /* Control-i */
- { ISFUNC, (Function *)0x0 }, /* Control-j */
- { ISFUNC, (Function *)0x0 }, /* Control-k */
- { ISFUNC, (Function *)0x0 }, /* Control-l */
- { ISFUNC, (Function *)0x0 }, /* Control-m */
- { ISFUNC, (Function *)0x0 }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, (Function *)0x0 }, /* Control-p */
- { ISFUNC, (Function *)0x0 }, /* Control-q */
- { ISFUNC, rl_re_read_init_file }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, (Function *)0x0 }, /* Control-t */
- { ISFUNC, rl_undo_command }, /* Control-u */
- { ISFUNC, (Function *)0x0 }, /* Control-v */
- { ISFUNC, (Function *)0x0 }, /* Control-w */
- { ISFUNC, (Function *)0x0 }, /* Control-x */
- { ISFUNC, (Function *)0x0 }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
- { ISFUNC, (Function *)0x0 }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, (Function *)0x0 }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, (Function *)0x0 }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, (Function *)0x0 }, /* # */
- { ISFUNC, (Function *)0x0 }, /* $ */
- { ISFUNC, (Function *)0x0 }, /* % */
- { ISFUNC, (Function *)0x0 }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, rl_start_kbd_macro }, /* ( */
- { ISFUNC, rl_end_kbd_macro }, /* ) */
- { ISFUNC, (Function *)0x0 }, /* * */
- { ISFUNC, (Function *)0x0 }, /* + */
- { ISFUNC, (Function *)0x0 }, /* , */
- { ISFUNC, (Function *)0x0 }, /* - */
- { ISFUNC, (Function *)0x0 }, /* . */
- { ISFUNC, (Function *)0x0 }, /* / */
-
- /* Regular digits. */
- { ISFUNC, (Function *)0x0 }, /* 0 */
- { ISFUNC, (Function *)0x0 }, /* 1 */
- { ISFUNC, (Function *)0x0 }, /* 2 */
- { ISFUNC, (Function *)0x0 }, /* 3 */
- { ISFUNC, (Function *)0x0 }, /* 4 */
- { ISFUNC, (Function *)0x0 }, /* 5 */
- { ISFUNC, (Function *)0x0 }, /* 6 */
- { ISFUNC, (Function *)0x0 }, /* 7 */
- { ISFUNC, (Function *)0x0 }, /* 8 */
- { ISFUNC, (Function *)0x0 }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, (Function *)0x0 }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, (Function *)0x0 }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, (Function *)0x0 }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* A */
- { ISFUNC, rl_do_lowercase_version }, /* B */
- { ISFUNC, rl_do_lowercase_version }, /* C */
- { ISFUNC, rl_do_lowercase_version }, /* D */
- { ISFUNC, rl_do_lowercase_version }, /* E */
- { ISFUNC, rl_do_lowercase_version }, /* F */
- { ISFUNC, rl_do_lowercase_version }, /* G */
- { ISFUNC, rl_do_lowercase_version }, /* H */
- { ISFUNC, rl_do_lowercase_version }, /* I */
- { ISFUNC, rl_do_lowercase_version }, /* J */
- { ISFUNC, rl_do_lowercase_version }, /* K */
- { ISFUNC, rl_do_lowercase_version }, /* L */
- { ISFUNC, rl_do_lowercase_version }, /* M */
- { ISFUNC, rl_do_lowercase_version }, /* N */
- { ISFUNC, rl_do_lowercase_version }, /* O */
- { ISFUNC, rl_do_lowercase_version }, /* P */
- { ISFUNC, rl_do_lowercase_version }, /* Q */
- { ISFUNC, rl_do_lowercase_version }, /* R */
- { ISFUNC, rl_do_lowercase_version }, /* S */
- { ISFUNC, rl_do_lowercase_version }, /* T */
- { ISFUNC, rl_do_lowercase_version }, /* U */
- { ISFUNC, rl_do_lowercase_version }, /* V */
- { ISFUNC, rl_do_lowercase_version }, /* W */
- { ISFUNC, rl_do_lowercase_version }, /* X */
- { ISFUNC, rl_do_lowercase_version }, /* Y */
- { ISFUNC, rl_do_lowercase_version }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* [ */
- { ISFUNC, (Function *)0x0 }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, (Function *)0x0 }, /* ^ */
- { ISFUNC, (Function *)0x0 }, /* _ */
- { ISFUNC, (Function *)0x0 }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* a */
- { ISFUNC, (Function *)0x0 }, /* b */
- { ISFUNC, (Function *)0x0 }, /* c */
- { ISFUNC, (Function *)0x0 }, /* d */
- { ISFUNC, rl_call_last_kbd_macro }, /* e */
- { ISFUNC, (Function *)0x0 }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, (Function *)0x0 }, /* h */
- { ISFUNC, (Function *)0x0 }, /* i */
- { ISFUNC, (Function *)0x0 }, /* j */
- { ISFUNC, (Function *)0x0 }, /* k */
- { ISFUNC, (Function *)0x0 }, /* l */
- { ISFUNC, (Function *)0x0 }, /* m */
- { ISFUNC, (Function *)0x0 }, /* n */
- { ISFUNC, (Function *)0x0 }, /* o */
- { ISFUNC, (Function *)0x0 }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, (Function *)0x0 }, /* r */
- { ISFUNC, (Function *)0x0 }, /* s */
- { ISFUNC, (Function *)0x0 }, /* t */
- { ISFUNC, (Function *)0x0 }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, (Function *)0x0 }, /* w */
- { ISFUNC, (Function *)0x0 }, /* x */
- { ISFUNC, (Function *)0x0 }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, (Function *)0x0 }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, (Function *)0x0 }, /* ~ */
- { ISFUNC, rl_backward_kill_line } /* RUBOUT */
-};
End of readline/emacs_keymap.c
echo readline/funmap.c 1>&2
sed 's/^-//' >readline/funmap.c <<'End of readline/funmap.c'
-/* funmap.c -- attach names to functions. */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#define STATIC_MALLOC
-#ifndef STATIC_MALLOC
-extern char *xmalloc (), *xrealloc ();
-#else
-static char *xmalloc (), *xrealloc ();
-#endif
-
-#ifndef FILE
-#include <stdio.h>
-#endif /* FILE */
-
-#include "readline.h"
-
-FUNMAP **funmap = (FUNMAP **)NULL;
-static int funmap_size = 0;
-static int funmap_entry = 0;
-
-static FUNMAP default_funmap[] = {
- { "beginning-of-line", rl_beg_of_line },
- { "backward-char", rl_backward },
- { "delete-char", rl_delete },
- { "end-of-line", rl_end_of_line },
- { "forward-char", rl_forward },
- { "accept-line", rl_newline },
- { "kill-line", rl_kill_line },
- { "clear-screen", rl_clear_screen },
- { "next-history", rl_get_next_history },
- { "previous-history", rl_get_previous_history },
- { "quoted-insert", rl_quoted_insert },
- { "transpose-chars", rl_transpose_chars },
- { "unix-line-discard", rl_unix_line_discard },
- { "unix-word-rubout", rl_unix_word_rubout },
- { "yank", rl_yank },
- { "yank-pop", rl_yank_pop },
- { "yank-nth-arg", rl_yank_nth_arg },
- { "backward-delete-char", rl_rubout },
- { "backward-word", rl_backward_word },
- { "kill-word", rl_kill_word },
- { "forward-word", rl_forward_word },
- { "tab-insert", rl_tab_insert },
- { "backward-kill-word", rl_backward_kill_word },
- { "backward-kill-line", rl_backward_kill_line },
- { "transpose-words", rl_transpose_words },
- { "digit-argument", rl_digit_argument },
- { "complete", rl_complete },
- { "possible-completions", rl_possible_completions },
- { "do-lowercase-version", rl_do_lowercase_version },
- { "digit-argument", rl_digit_argument },
- { "universal-argument", rl_universal_argument },
- { "abort", rl_abort },
- { "undo", rl_undo_command },
- { "upcase-word", rl_upcase_word },
- { "downcase-word", rl_downcase_word },
- { "capitalize-word", rl_capitalize_word },
- { "revert-line", rl_revert_line },
- { "beginning-of-history", rl_beginning_of_history },
- { "end-of-history", rl_end_of_history },
- { "self-insert", rl_insert },
- { "start-kbd-macro", rl_start_kbd_macro },
- { "end-kbd-macro", rl_end_kbd_macro },
- { "re-read-init-file", rl_re_read_init_file },
- { "history-expand", rl_magic_space },
- { "check-spelling", rl_check_spelling },
-#ifdef VI_MODE
- { "vi-movement-mode", rl_vi_movement_mode },
- { "vi-insertion-mode", rl_vi_insertion_mode },
- { "vi-arg-digit", rl_vi_arg_digit },
- { "vi-prev-word", rl_vi_prev_word },
- { "vi-next-word", rl_vi_next_word },
- { "vi-char-search", rl_vi_char_search },
- { "vi-editing-mode", rl_vi_editing_mode },
- { "vi-eof-maybe", rl_vi_eof_maybe },
- { "vi-append-mode", rl_vi_append_mode },
- { "vi-put", rl_vi_put },
- { "vi-append-eol", rl_vi_append_eol },
- { "vi-insert-beg", rl_vi_insert_beg },
- { "vi-delete", rl_vi_delete },
- { "vi-comment", rl_vi_comment },
- { "vi-first-print", rl_vi_first_print },
- { "vi-fword", rl_vi_fword },
- { "vi-fWord", rl_vi_fWord },
- { "vi-bword", rl_vi_bword },
- { "vi-bWord", rl_vi_bWord },
- { "vi-eword", rl_vi_eword },
- { "vi-eWord", rl_vi_eWord },
- { "vi-end-word", rl_vi_end_word },
- { "vi-change-case", rl_vi_change_case },
- { "vi-match", rl_vi_match },
- { "vi-bracktype", rl_vi_bracktype },
- { "vi-change-char", rl_vi_change_char },
- { "vi-yank-arg", rl_vi_yank_arg },
- { "vi-search", rl_vi_search },
- { "vi-search-again", rl_vi_search_again },
- { "vi-dosearch", rl_vi_dosearch },
- { "vi-subst", rl_vi_subst },
- { "vi-overstrike", rl_vi_overstrike },
- { "vi-overstrike-delete", rl_vi_overstrike_delete },
- { "vi-replace, ", rl_vi_replace },
- { "vi-column", rl_vi_column },
- { "vi-delete-to", rl_vi_delete_to },
- { "vi-change-to", rl_vi_change_to },
- { "vi-yank-to", rl_vi_yank_to },
- { "vi-complete", rl_vi_complete },
-#endif /* VI_MODE */
-
- {(char *)NULL, (Function *)NULL }
-};
-
-rl_add_funmap_entry (name, function)
- char *name;
- Function *function;
-{
- if (funmap_entry + 2 >= funmap_size)
- if (!funmap)
- funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *));
- else
- funmap =
- (FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *));
-
- funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
- funmap[funmap_entry]->name = name;
- funmap[funmap_entry]->function = function;
-
- funmap[++funmap_entry] = (FUNMAP *)NULL;
-}
-
-static int funmap_initialized = 0;
-
-/* Make the funmap contain all of the default entries. */
-rl_initialize_funmap ()
-{
- register int i;
-
- if (funmap_initialized)
- return;
-
- for (i = 0; default_funmap[i].name; i++)
- rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
-
- funmap_initialized = 1;
-}
-
-/* Things that mean `Control'. */
-char *possible_control_prefixes[] = {
- "Control-", "C-", "CTRL-", (char *)NULL
-};
-
-char *possible_meta_prefixes[] = {
- "Meta", "M-", (char *)NULL
-};
-
-#ifdef STATIC_MALLOC
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static void memory_error_and_abort ();
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static void
-memory_error_and_abort ()
-{
- fprintf (stderr, "history: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
End of readline/funmap.c
echo readline/history.h 1>&2
sed 's/^-//' >readline/history.h <<'End of readline/history.h'
-/* History.h -- the names of functions that you can call in history. */
-/* modified by pjf */
-
-typedef struct _hist_entry {
- char *line;
- char *data;
-} HIST_ENTRY;
-
-/* For convenience only. You set this when interpreting history commands.
- It is the logical offset of the first history element. */
-extern int tfev;
-#define history_base tfev
-
-/* Begin a session in which the history functions might be used. This
- just initializes the interactive variables. */
-extern void using_history ();
-
-/* Place STRING at the end of the history list.
- The associated data field (if any) is set to NULL. */
-/* extern void add_history (); */
-
-/* Returns the number which says what history element we are now
- looking at. */
-extern int where_history ();
-
-/* Set the position in the history list to POS. */
-int history_set_pos ();
-
-/* Search for STRING in the history list, starting at POS, an
- absolute index into the list. DIR, if negative, says to search
- backwards from POS, else forwards.
- Returns the absolute index of the history element where STRING
- was found, or -1 otherwise. */
-extern int history_search_pos ();
-
-/* A reasonably useless function, only here for completeness. WHICH
- is the magic number that tells us which element to delete. The
- elements are numbered from 0. */
-/* inline HIST_ENTRY *remove_history () {return NULL;} */
-
-/* Stifle the history list, remembering only MAX number of entries. */
-/* extern void stifle_history (); */
-
-/* Stop stifling the history. This returns the previous amount the
- history was stifled by. The value is positive if the history was
- stifled, negative if it wasn't. */
-/* extern int unstifle_history (); */
-
-/* Add the contents of FILENAME to the history list, a line at a time.
- If FILENAME is NULL, then read from ~/.history. Returns 0 if
- successful, or errno if not. */
-/* extern int read_history (); */
-
-/* Append the current history to FILENAME. If FILENAME is NULL,
- then append the history list to ~/.history. Values returned
- are as in read_history (). */
-/* extern int write_history (); */
-
-
-/* Make the history entry at WHICH have LINE and DATA. This returns
- the old entry so you can dispose of the data. In the case of an
- invalid WHICH, a NULL pointer is returned. */
-/* extern HIST_ENTRY *replace_history_entry (); */
-
-/* Return the history entry at the current position, as determined by
- history_offset. If there is no entry there, return a NULL pointer. */
-HIST_ENTRY *current_history ();
-
-/* Back up history_offset to the previous history entry, and return
- a pointer to that entry. If there is no previous entry, return
- a NULL pointer. */
-extern HIST_ENTRY *previous_history ();
-
-/* Move history_offset forward to the next item in the input_history,
- and return the a pointer to that entry. If there is no next entry,
- return a NULL pointer. */
-extern HIST_ENTRY *next_history ();
-
-/* Return a NULL terminated array of HIST_ENTRY which is the current input
- history. Element 0 of this list is the beginning of time. If there
- is no history, return NULL. */
-/*extern HIST_ENTRY **history_list ();*/
-
-/* Search the history for STRING, starting at history_offset.
- If DIRECTION < 0, then the search is through previous entries,
- else through subsequent. If the string is found, then
- current_history () is the history entry, and the value of this function
- is the offset in the line of that history entry that the string was
- found in. Otherwise, nothing is changed, and a -1 is returned. */
-/* extern int history_search (); */
-
-/* Expand the string STRING, placing the result into OUTPUT, a pointer
- to a string. Returns:
-
- 0) If no expansions took place (or, if the only change in
- the text was the de-slashifying of the history expansion
- character)
- 1) If expansions did take place
- -1) If there was an error in expansion.
-
- If an error ocurred in expansion, then OUTPUT contains a descriptive
- error message. */
-/*extern int history_expand ();*/
-
-/* Extract a string segment consisting of the FIRST through LAST
- arguments present in STRING. Arguments are broken up as in
- the shell. pjf: only 1-segment strings are supported. */
-extern char *history_arg_extract ();
-
-
End of readline/history.h
echo readline/keymaps.c 1>&2
sed 's/^-//' >readline/keymaps.c <<'End of readline/keymaps.c'
-/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "keymaps.h"
-#include "emacs_keymap.c"
-
-#ifdef VI_MODE
-#include "vi_keymap.c"
-#endif
-
-/* Remove these declarations when we have a complete libgnu.a. */
-#define STATIC_MALLOC
-#ifndef STATIC_MALLOC
-extern char *xmalloc (), *xrealloc ();
-#else
-static char *xmalloc (), *xrealloc ();
-#endif
-
-/* **************************************************************** */
-/* */
-/* Functions for manipulating Keymaps. */
-/* */
-/* **************************************************************** */
-
-
-/* Return a new, empty keymap.
- Free it with free() when you are done. */
-Keymap
-rl_make_bare_keymap ()
-{
- register int i;
- Keymap keymap = (Keymap)xmalloc (128 * sizeof (KEYMAP_ENTRY));
-
- for (i = 0; i < 128; i++)
- {
- keymap[i].type = ISFUNC;
- keymap[i].function = (Function *)NULL;
- }
-
- for (i = 'A'; i < ('Z' + 1); i++)
- {
- keymap[i].type = ISFUNC;
- keymap[i].function = rl_do_lowercase_version;
- }
-
- return (keymap);
-}
-
-/* Return a new keymap which is a copy of MAP. */
-Keymap
-rl_copy_keymap (map)
- Keymap map;
-{
- register int i;
- Keymap temp = rl_make_bare_keymap ();
-
- for (i = 0; i < 128; i++)
- {
- temp[i].type = map[i].type;
- temp[i].function = map[i].function;
- }
- return (temp);
-}
-
-/* Return a new keymap with the printing characters bound to rl_insert,
- the uppercase Meta characters bound to run their lowercase equivalents,
- and the Meta digits bound to produce numeric arguments. */
-Keymap
-rl_make_keymap ()
-{
- extern rl_insert (), rl_rubout (), rl_do_lowercase_version ();
- extern rl_digit_argument ();
- register int i;
- Keymap newmap;
-
- newmap = rl_make_bare_keymap ();
-
- /* All printing characters are self-inserting. */
- for (i = ' '; i < 126; i++)
- newmap[i].function = rl_insert;
-
- newmap[TAB].function = rl_insert;
- newmap[RUBOUT].function = rl_rubout;
-
- return (newmap);
-}
-
-/* Free the storage associated with MAP. */
-rl_discard_keymap (map)
- Keymap (map);
-{
- int i;
-
- if (!map)
- return;
-
- for (i = 0; i < 128; i++)
- {
- switch (map[i].type)
- {
- case ISFUNC:
- break;
-
- case ISKMAP:
- rl_discard_keymap ((Keymap)map[i].function);
- break;
-
- case ISMACR:
- free ((char *)map[i].function);
- break;
- }
- }
-}
-
-#ifdef STATIC_MALLOC
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static void memory_error_and_abort ();
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static void
-memory_error_and_abort ()
-{
- fprintf (stderr, "readline: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
End of readline/keymaps.c
echo readline/keymaps.h 1>&2
sed 's/^-//' >readline/keymaps.h <<'End of readline/keymaps.h'
-/* keymaps.h -- Manipulation of readline keymaps. */
-
-#ifndef _KEYMAPS_H_
-#define _KEYMAPS_H_
-
-#include <readline/chardefs.h>
-
-#ifndef __FUNCTION_DEF
-typedef int Function ();
-#define __FUNCTION_DEF
-#endif
-
-/* A keymap contains one entry for each key in the ASCII set.
- Each entry consists of a type and a pointer.
- POINTER is the address of a function to run, or the
- address of a keymap to indirect through.
- TYPE says which kind of thing POINTER is. */
-typedef struct _keymap_entry {
- char type;
- Function *function;
-} KEYMAP_ENTRY;
-
-/* I wanted to make the above structure contain a union of:
- union { Function *function; struct _keymap_entry *keymap; } value;
- but this made it impossible for me to create a static array.
- Maybe I need C lessons. */
-
-typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[128];
-typedef KEYMAP_ENTRY *Keymap;
-
-/* The values that TYPE can have in a keymap entry. */
-#define ISFUNC 0
-#define ISKMAP 1
-#define ISMACR 2
-
-extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
-extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
-
-/* Return a new, empty keymap.
- Free it with free() when you are done. */
-Keymap rl_make_bare_keymap ();
-
-/* Return a new keymap which is a copy of MAP. */
-Keymap rl_copy_keymap ();
-
-/* Return a new keymap with the printing characters bound to rl_insert,
- the lowercase Meta characters bound to run their equivalents, and
- the Meta digits bound to produce numeric arguments. */
-Keymap rl_make_keymap ();
-
-#endif /* _KEYMAPS_H_ */
-
-
End of readline/keymaps.h
echo readline/readline.c 1>&2
sed 's/^-//' >readline/readline.c <<'End of readline/readline.c'
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
-
- This file contains the Readline Library (the Library), a set of
- routines for providing Emacs style line input to programs that ask
- for it.
-
- The Library is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- The Library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- The GNU General Public License is often shipped with GNU software, and
- is generally kept in a file called COPYING or LICENSE. If you do not
- have a copy of the license, write to the Free Software Foundation,
- 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Remove these declarations when we have a complete libgnu.a. */
-#define STATIC_MALLOC
-#ifndef STATIC_MALLOC
-extern char *xmalloc (), *xrealloc ();
-#else
-static char *xmalloc (), *xrealloc ();
-#endif
-
-char *docompsubs();
-extern int errno,errflag;
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/param.h>
-#include <signal.h>
-
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else
-#if defined (sparc) && defined (sun)
-#include <alloca.h>
-#endif
-#endif
-
-#define NEW_TTY_DRIVER
-#if defined (SYSV) || defined (hpux)
-#undef NEW_TTY_DRIVER
-#include <termio.h>
-#else
-#include <sgtty.h>
-#endif
-
-#include <errno.h>
-extern int errno;
-
-#include <setjmp.h>
-
-/* These next are for filename completion. Perhaps this belongs
- in a different place. */
-#include <sys/stat.h>
-
-#include <pwd.h>
-#ifdef SYSV
-struct passwd *getpwuid (), *getpwent ();
-#endif
-
-#define HACK_TERMCAP_MOTION
-
-#ifndef SYSV
-#include <sys/dir.h>
-#else /* SYSV */
-#if defined (xenix)
-#include <sys/ndir.h>
-#else
-#ifdef hpux
-#include <ndir.h>
-#else
-#include <dirent.h>
-#define direct dirent
-#define d_namlen d_reclen
-#endif /* hpux */
-#endif /* xenix */
-#endif /* SYSV */
-
-#ifndef O_CBREAK
-#define O_CBREAK CBREAK
-#define O_ECHO ECHO
-#define O_RAW RAW
-#endif
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#ifndef digit
-#define digit(c) ((c) >= '0' && (c) <= '9')
-#endif
-
-#ifndef isletter
-#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
-#endif
-
-#ifndef digit_value
-#define digit_value(c) ((c) - '0')
-#endif
-
-#ifndef member
-char *index ();
-#define member(c, s) ((c) ? index ((s), (c)) : 0)
-#endif
-
-#ifndef isident
-#define isident(c) ((isletter(c) || digit(c) || c == '_'))
-#endif
-
-#ifndef exchange
-#define exchange(x, y) {int temp = x; x = y; y = temp;}
-#endif
-
-static update_line ();
-static void output_character_function ();
-static delete_chars ();
-static delete_chars ();
-static insert_some_chars ();
-
-void rl_safe_insert_text();
-
-#ifdef VOID_SIGHANDLER
-#define sighandler void
-#else
-#define sighandler int
-#endif
-
-/* This typedef is equivalant to the one for Function; it allows us
- to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
-typedef sighandler SigHandler ();
-
-#ifdef SIGWINCH
-static sighandler rl_handle_sigwinch ();
-static SigHandler *old_sigwinch = (SigHandler *)NULL;
-#endif
-
-/* If on, then readline handles signals in a way that doesn't screw. */
-#define HANDLE_SIGNALS
-
-#if defined (SYSV)
-#ifdef HANDLE_SIGNALS
-#undef HANDLE_SIGNALS
-#endif
-#endif
-
-
-/* **************************************************************** */
-/* */
-/* Line editing input utility */
-/* */
-/* **************************************************************** */
-
-/* A pointer to the keymap that is currently in use.
- By default, it is the standard emacs keymap. */
-Keymap keymap = emacs_standard_keymap;
-
-#define vi_mode 0
-#define emacs_mode 1
-
-/* The current style of editing. */
-int rl_editing_mode = emacs_mode;
-
-/* Non-zero if the previous command was a kill command. */
-static int last_command_was_kill = 0;
-
-/* The current value of the numeric argument specified by the user. */
-int rl_numeric_arg = 1;
-
-/* Non-zero if an argument was typed. */
-int rl_explicit_arg = 0;
-
-/* Temporary value used while generating the argument. */
-static int arg_sign = 1;
-
-/* Non-zero means we have been called at least once before. */
-static int rl_initialized = 0;
-
-/* If non-zero, this program is running in an EMACS buffer. */
-static char *running_in_emacs = (char *)NULL;
-
-/* The current offset in the current input line. */
-int rl_point;
-
-/* Mark in the current input line. */
-int rl_mark;
-
-/* Length of the current input line. */
-int rl_end;
-
-/* Make this non-zero to return the current input_line. */
-int rl_done;
-
-/* The last function executed by readline. */
-Function *rl_last_func = (Function *)NULL;
-
-/* Top level environment for readline_internal (). */
-static jmp_buf readline_top_level;
-
-/* The streams we interact with. */
-static FILE *in_stream, *out_stream;
-
-/* The names of the streams that we do input and output to. */
-FILE *rl_instream = stdin, *rl_outstream = stdout;
-
-/* Non-zero means echo characters as they are read. */
-int readline_echoing_p = 1;
-
-/* Current prompt. */
-char *rl_prompt;
-
-/* The number of characters read in order to type this complete command. */
-int rl_key_sequence_length = 0;
-
-/* 1 means the line editor is active. */
-int rl_active = 0;
-
-/* 1 means we are waiting for a character. */
-int rl_waiting = 0;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal () prints the first prompt. */
-Function *rl_startup_hook = (Function *)NULL;
-
-/* What we use internally. You should always refer to RL_LINE_BUFFER. */
-static char *the_line;
-
-/* The character that can generate an EOF. Really read from
- the terminal driver... just defaulted here. */
-static int eof_char = CTRL ('D');
-
-/* Non-zero makes this the next keystroke to read. */
-int rl_pending_input = 0;
-
-/* Pointer to a useful terminal name. */
-char *rl_terminal_name = (char *)NULL;
-
-/* Line buffer and maintenence. */
-char *rl_line_buffer = (char *)NULL;
-static int rl_line_buffer_len = 0;
-#define DEFAULT_BUFFER_SIZE 256
-
-
-/* **************************************************************** */
-/* */
-/* `Forward' declarations */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means do not parse any lines other than comments and
- parser directives. */
-static unsigned char parsing_conditionalized_out = 0;
-
-/* Caseless strcmp (). */
-static int stricmp (), strnicmp ();
-
-/* Non-zero means to save keys that we dispatch on in a kbd macro. */
-static int defining_kbd_macro = 0;
-
-
-/* **************************************************************** */
-/* */
-/* Top Level Functions */
-/* */
-/* **************************************************************** */
-
-/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means
- none. A return value of NULL means that EOF was encountered. */
-char *
-readline (prompt)
-char *prompt;
-{
- int rl_prep_terminal (), rl_deprep_terminal ();
- char *readline_internal ();
- char *value;
-
- rl_prompt = prompt;
-
- /* If we are at EOF return a NULL string. */
- if (rl_pending_input == EOF)
- {
- rl_pending_input = 0;
- return ((char *)NULL);
- }
-
- rl_initialize ();
- rl_prep_terminal ();
-
-#ifdef SIGWINCH
- old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch);
-#endif
-
-#ifdef HANDLE_SIGNALS
- rl_set_signals ();
-#endif
-
- rl_active = 1;
- rl_waiting = 0;
- value = readline_internal ();
- rl_active = 0;
- rl_deprep_terminal ();
-
-#ifdef SIGWINCH
- signal (SIGWINCH, old_sigwinch);
-#endif
-
-#ifdef HANDLE_SIGNALS
- rl_clear_signals ();
-#endif
-
- return (value);
-}
-
-/* Read a line of input from the global rl_instream, doing output on
- the global rl_outstream.
- If rl_prompt is non-null, then that is our prompt. */
-char *
-readline_internal ()
-{
- int lastc, c, eof_found;
-
- in_stream = rl_instream;
- out_stream = rl_outstream;
- lastc = eof_found = 0;
-
- if (rl_startup_hook)
- (*rl_startup_hook) ();
-
- if (!readline_echoing_p)
- {
- if (rl_prompt)
- {
- fprintf (out_stream, "%s", rl_prompt);
- fflush (out_stream);
- }
- }
- else
- {
- rl_on_new_line ();
- rl_redisplay ();
-#ifdef VI_MODE
- if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode ();
-#endif /* VI_MODE */
- }
-
- while (!rl_done)
- {
- int lk = last_command_was_kill;
- int code = setjmp (readline_top_level);
-
- if (code)
- rl_redisplay ();
-
- if (!rl_pending_input)
- {
- /* Then initialize the argument and number of keys read. */
- rl_init_argument ();
- rl_key_sequence_length = 0;
- }
-
- c = rl_read_key ();
- if (c == EOF)
- {
- eof_found = 1;
- putc('\n',stderr);
- break;
- }
-
- /* EOF typed to a non-blank line is a <NL>. */
- if (c == EOF && rl_end)
- c = NEWLINE;
-
- if (errflag)
- {
- eof_found = 1;
- break;
- }
-
- /* The character eof_char typed to blank line, and not as the
- previous character is interpreted as EOF. */
- if (((c == eof_char && lastc != c) || c == EOF) && !rl_end)
- {
- eof_found = 1;
- break;
- }
-
- lastc = c;
- rl_dispatch (c, keymap);
-
- /* If there was no change in last_command_was_kill, then no kill
- has taken place. Note that if input is pending we are reading
- a prefix command, so nothing has changed yet. */
- if (!rl_pending_input)
- {
- if (lk == last_command_was_kill)
- last_command_was_kill = 0;
- }
-
-#ifdef VI_MODE
- /* In vi mode, when you exit insert mode, the cursor moves back
- over the previous character. We explicitly check for that here. */
- if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
- rl_vi_check ();
-#endif
- if (!rl_done)
- rl_redisplay ();
- }
-
- /* Restore the original of this history line, iff the line that we
- are editing was originally in the history, AND the line has changed. */
- {
- HIST_ENTRY *entry = current_history ();
-
- if (entry && rl_undo_list)
- {
- char *temp = savestring (the_line);
- rl_revert_line ();
- free_history_entry (entry);
-
- strcpy (the_line, temp);
- free (temp);
- }
- }
-
- /* At any rate, it is highly likely that this line has an undo list. Get
- rid of it now. */
- if (rl_undo_list)
- free_undo_list ();
-
- if (eof_found)
- return (char *)NULL;
- else
- return (savestring (the_line));
-}
-
-
-/* **************************************************************** */
-/* */
-/* Signal Handling */
-/* */
-/* **************************************************************** */
-
-#ifdef SIGWINCH
-static sighandler
-rl_handle_sigwinch (sig, code, scp)
-int sig, code;
-struct sigcontext *scp;
-{
- char *term = rl_terminal_name, *getenv ();
-
- if (readline_echoing_p)
- {
- if (!term)
- term = getenv ("TERM");
- if (!term)
- term = "dumb";
- rl_reset_terminal (term);
-#ifdef NEVER
- crlf ();
- rl_forced_update_display ();
-#endif
- }
-
- if (old_sigwinch &&
- old_sigwinch != (SigHandler *)SIG_IGN &&
- old_sigwinch != (SigHandler *)SIG_DFL)
- (*old_sigwinch)(sig, code, scp);
-}
-#endif /* SIGWINCH */
-
-#ifdef HANDLE_SIGNALS
-/* Interrupt handling. */
-static SigHandler *old_int = (SigHandler *)NULL,
-*old_tstp = (SigHandler *)NULL,
-*old_ttou = (SigHandler *)NULL,
-*old_ttin = (SigHandler *)NULL,
-*old_cont = (SigHandler *)NULL;
-
-/* Handle an interrupt character. */
-static sighandler
-rl_signal_handler (sig, code, scp)
-int sig, code;
-struct sigcontext *scp;
-{
- rl_prep_terminal (), rl_deprep_terminal ();
-
- switch (sig)
- {
- case SIGINT:
- free_undo_list ();
- rl_clear_message ();
- rl_init_argument ();
-#ifdef SIGWINCH
- signal (SIGWINCH, old_sigwinch);
-#endif
-
-#ifdef SIGTSTP
- case SIGTSTP:
- case SIGTTOU:
- case SIGTTIN:
-#endif
-
- rl_clean_up_for_exit ();
- rl_deprep_terminal ();
- rl_clear_signals ();
- rl_pending_input = 0;
-
- kill (getpid (), sig);
- sigsetmask (0);
-
- rl_prep_terminal ();
- rl_set_signals ();
- }
-}
-
-rl_set_signals ()
-{
- old_int = (SigHandler *)signal (SIGINT, rl_signal_handler);
- if (old_int == (SigHandler *)SIG_IGN)
- signal (SIGINT, SIG_IGN);
-
-#ifdef SIGTSTP
- old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler);
- if (old_tstp == (SigHandler *)SIG_IGN)
- signal (SIGTSTP, SIG_IGN);
-#endif
-#ifdef SIGTTOU
- old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler);
- old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler);
-
- if (old_tstp == (SigHandler *)SIG_IGN)
- {
- signal (SIGTTOU, SIG_IGN);
- signal (SIGTTIN, SIG_IGN);
- }
-#endif
-}
-
-rl_clear_signals ()
-{
- signal (SIGINT, old_int);
-
-#ifdef SIGTSTP
- signal (SIGTSTP, old_tstp);
-#endif
-#ifdef SIGTTOU
- signal (SIGTTOU, old_ttou);
- signal (SIGTTIN, old_ttin);
-#endif
-}
-#endif /* HANDLE_SIGNALS */
-
-
-/* **************************************************************** */
-/* */
-/* Character Input Buffering */
-/* */
-/* **************************************************************** */
-
-/* If the terminal was in xoff state when we got to it, then xon_char
- contains the character that is supposed to start it again. */
-static int xon_char, xoff_state;
-static int pop_index = 0, push_index = 0, ibuffer_len = 511;
-static unsigned char ibuffer[512];
-
-/* Non-null means it is a pointer to a function to run while waiting for
- character input. */
-Function *rl_event_hook = (Function *)NULL;
-
-#define any_typein (push_index != pop_index)
-
-/* Add KEY to the buffer of characters to be read. */
-rl_stuff_char (key)
-int key;
-{
- if (key == EOF)
- {
- key = NEWLINE;
- rl_pending_input = EOF;
- }
- ibuffer[push_index++] = key;
- if (push_index >= ibuffer_len)
- push_index = 0;
-}
-
-/* Return the amount of space available in the
- buffer for stuffing characters. */
-int
-ibuffer_space ()
-{
- if (pop_index > push_index)
- return (pop_index - push_index);
- else
- return (ibuffer_len - (push_index - pop_index));
-}
-
-/* Get a key from the buffer of characters to be read.
- Return the key in KEY.
- Result is KEY if there was a key, or 0 if there wasn't. */
-int
-rl_get_char (key)
-int *key;
-{
- if (push_index == pop_index)
- return (0);
-
- *key = ibuffer[pop_index++];
-
- if (pop_index >= ibuffer_len)
- pop_index = 0;
-
- return (1);
-}
-
-/* Stuff KEY into the *front* of the input buffer.
- Returns non-zero if successful, zero if there is
- no space left in the buffer. */
-int
-rl_unget_char (key)
-int key;
-{
- if (ibuffer_space ())
- {
- pop_index--;
- if (pop_index < 0)
- pop_index = ibuffer_len - 1;
- ibuffer[pop_index] = key;
- return (1);
- }
- return (0);
-}
-
-/* If a character is available to be read, then read it
- and stuff it into IBUFFER. Otherwise, just return. */
-rl_gather_tyi ()
-{
- int tty = fileno (in_stream);
- register int tem, result = -1;
- long chars_avail;
- char input;
-
-#ifdef FIONREAD
- result = ioctl (tty, FIONREAD, &chars_avail);
-#endif
-
- if (result == -1)
- {
- fcntl (tty, F_SETFL, O_NDELAY);
- chars_avail = read (tty, &input, 1);
- fcntl (tty, F_SETFL, 0);
- if (chars_avail == -1 && errno == EAGAIN)
- return;
- }
-
- tem = ibuffer_space ();
-
- if (chars_avail > tem)
- chars_avail = tem;
-
- /* One cannot read all of the available input. I can only read a single
- character at a time, or else programs which require input can be
- thwarted. If the buffer is larger than one character, I lose.
- Damn! */
- if (tem < ibuffer_len)
- chars_avail = 0;
-
- if (result != -1)
- {
- while (chars_avail--)
- rl_stuff_char (rl_getc (in_stream));
- }
- else
- {
- if (chars_avail)
- rl_stuff_char (input);
- }
-}
-
-/* Read a key, including pending input. */
-int
-rl_read_key ()
-{
- int c;
-
- rl_key_sequence_length++;
-
- if (rl_pending_input)
- {
- c = rl_pending_input;
- rl_pending_input = 0;
- }
- else
- {
- static int next_macro_key ();
-
- /* If input is coming from a macro, then use that. */
- if (c = next_macro_key ())
- return (c);
-
- /* If the user has an event function, then call it periodically. */
- if (rl_event_hook)
- {
- while (rl_event_hook && !rl_get_char (&c))
- {
- (*rl_event_hook) ();
- rl_gather_tyi ();
- }
- }
- else
- {
- if (!rl_get_char (&c))
- c = rl_getc (in_stream);
- }
- }
-
-#ifdef NEVER /* This breaks supdup to 4.0.3c machines. */
-#ifdef TIOCSTART
- /* Ugh. But I can't think of a better way. */
- if (xoff_state && c == xon_char)
- {
- ioctl (fileno (in_stream), TIOCSTART, 0);
- xoff_state = 0;
- return (rl_read_key ());
- }
-#endif /* TIOCSTART */
-#endif
-
- return (c);
-}
-
-/* I'm beginning to hate the declaration rules for various compilers. */
-static void add_macro_char ();
-
-/* Do the command associated with KEY in MAP.
- If the associated command is really a keymap, then read
- another key, and dispatch into that map. */
-rl_dispatch (key, map)
-register int key;
-Keymap map;
-{
-
- if (defining_kbd_macro)
- add_macro_char (key);
-
- if (key > 127 && key < 256)
- {
- if (map[ESC].type == ISKMAP)
- {
- map = (Keymap)map[ESC].function;
- key -= 128;
- rl_dispatch (key, map);
- }
- else
- ding ();
- return;
- }
-
- switch (map[key].type)
- {
- case ISFUNC:
- {
- Function *func = map[key].function;
-
- if (func != (Function *)NULL)
- {
- /* Special case rl_do_lowercase_version (). */
- if (func == rl_do_lowercase_version)
- {
- rl_dispatch (to_lower (key), map);
- return;
- }
-
- (*map[key].function)(rl_numeric_arg * arg_sign, key);
- }
- else
- {
- ding ();
- return;
- }
- }
- break;
-
- case ISKMAP:
- if (map[key].function != (Function *)NULL)
- {
- int newkey;
-
- rl_key_sequence_length++;
- newkey = rl_read_key ();
- rl_dispatch (newkey, (Keymap)map[key].function);
- }
- else
- {
- ding ();
- return;
- }
- break;
-
- case ISMACR:
- if (map[key].function != (Function *)NULL)
- {
- static with_macro_input ();
- char *macro = savestring ((char *)map[key].function);
-
- with_macro_input (macro);
- return;
- }
- break;
- }
-
- /* If we have input pending, then the last command was a prefix
- command. Don't change the state of rl_last_func. */
- if (!rl_pending_input)
- rl_last_func = map[key].function;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Hacking Keyboard Macros */
-/* */
-/* **************************************************************** */
-
-/* The currently executing macro string. If this is non-zero,
- then it is a malloc ()'ed string where input is coming from. */
-static char *executing_macro = (char *)NULL;
-
-/* The offset in the above string to the next character to be read. */
-static int executing_macro_index = 0;
-
-/* The current macro string being built. Characters get stuffed
- in here by add_macro_char (). */
-static char *current_macro = (char *)NULL;
-
-/* The size of the buffer allocated to current_macro. */
-static int current_macro_size = 0;
-
-/* The index at which characters are being added to current_macro. */
-static int current_macro_index = 0;
-
-/* A structure used to save nested macro strings.
- It is a linked list of string/index for each saved macro. */
-struct saved_macro {
- struct saved_macro *next;
- char *string;
- int index;
-};
-
-/* The list of saved macros. */
-struct saved_macro *macro_list = (struct saved_macro *)NULL;
-
-/* Forward declarations of static functions. Thank you C. */
-static void push_executing_macro (), pop_executing_macro ();
-
-/* This one has to be declared earlier in the file. */
-/* static void add_macro_char (); */
-
-/* Set up to read subsequent input from STRING.
- STRING is free ()'ed when we are done with it. */
-static
-with_macro_input (string)
-char *string;
-{
- push_executing_macro ();
- executing_macro = string;
- executing_macro_index = 0;
-}
-
-/* Return the next character available from a macro, or 0 if
- there are no macro characters. */
-static int
-next_macro_key ()
-{
- if (!executing_macro)
- return (0);
-
- if (!executing_macro[executing_macro_index])
- {
- pop_executing_macro ();
- return (next_macro_key ());
- }
-
- return (executing_macro[executing_macro_index++]);
-}
-
-/* Save the currently executing macro on a stack of saved macros. */
-static void
-push_executing_macro ()
-{
- struct saved_macro *saver;
-
- saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
- saver->next = macro_list;
- saver->index = executing_macro_index;
- saver->string = executing_macro;
-
- macro_list = saver;
-}
-
-/* Discard the current macro, replacing it with the one
- on the top of the stack of saved macros. */
-static void
-pop_executing_macro ()
-{
- if (executing_macro)
- free (executing_macro);
-
- executing_macro = (char *)NULL;
- executing_macro_index = 0;
-
- if (macro_list)
- {
- struct saved_macro *disposer = macro_list;
- executing_macro = macro_list->string;
- executing_macro_index = macro_list->index;
- macro_list = macro_list->next;
- free (disposer);
- }
-}
-
-/* Add a character to the macro being built. */
-static void
-add_macro_char (c)
-int c;
-{
- if (current_macro_index + 1 >= current_macro_size)
- {
- if (!current_macro)
- current_macro = (char *)xmalloc (current_macro_size = 25);
- else
- current_macro =
- (char *)xrealloc (current_macro, current_macro_size += 25);
- }
-
- current_macro[current_macro_index++] = c;
- current_macro[current_macro_index] = '\0';
-}
-
-/* Begin defining a keyboard macro.
- Keystrokes are recorded as they are executed.
- End the definition with rl_end_kbd_macro ().
- If a numeric argument was explicitly typed, then append this
- definition to the end of the existing macro, and start by
- re-executing the existing macro. */
-rl_start_kbd_macro (ignore1, ignore2)
-int ignore1, ignore2;
-{
- if (defining_kbd_macro)
- rl_abort ();
-
- if (rl_explicit_arg)
- {
- if (current_macro)
- with_macro_input (savestring (current_macro));
- }
- else
- current_macro_index = 0;
-
- defining_kbd_macro = 1;
-}
-
-/* Stop defining a keyboard macro.
- A numeric argument says to execute the macro right now,
- that many times, counting the definition as the first time. */
-rl_end_kbd_macro (count, ignore)
-int count, ignore;
-{
- if (!defining_kbd_macro)
- rl_abort ();
-
- current_macro_index -= (rl_key_sequence_length - 1);
- current_macro[current_macro_index] = '\0';
-
- defining_kbd_macro = 0;
-
- rl_call_last_kbd_macro (--count, 0);
-}
-
-/* Execute the most recently defined keyboard macro.
- COUNT says how many times to execute it. */
-rl_call_last_kbd_macro (count, ignore)
-int count, ignore;
-{
- if (!current_macro)
- rl_abort ();
-
- while (count--)
- with_macro_input (savestring (current_macro));
-}
-
-
-/* **************************************************************** */
-/* */
-/* Initializations */
-/* */
-/* **************************************************************** */
-
-/* Initliaze readline (and terminal if not already). */
-rl_initialize ()
-{
- extern char *rl_display_prompt;
-
- /* If we have never been called before, initialize the
- terminal and data structures. */
- if (!rl_initialized)
- {
- readline_initialize_everything ();
- rl_initialized++;
- }
-
- /* Initalize the current line information. */
- rl_point = rl_end = 0;
- the_line = rl_line_buffer;
- the_line[0] = 0;
-
- /* We aren't done yet. We haven't even gotten started yet! */
- rl_done = 0;
-
- /* Tell the history routines what is going on. */
- start_using_history ();
-
- /* Make the display buffer match the state of the line. */
- {
- extern char *rl_display_prompt;
- extern int forced_display;
-
- rl_on_new_line ();
-
- rl_display_prompt = rl_prompt ? rl_prompt : "";
- forced_display = 1;
- }
-
- /* No such function typed yet. */
- rl_last_func = (Function *)NULL;
-
- /* Parsing of key-bindings begins in an enabled state. */
- parsing_conditionalized_out = 0;
-}
-
-/* Initialize the entire state of the world. */
-readline_initialize_everything ()
-{
- /* Find out if we are running in Emacs. */
- running_in_emacs = (char *)getenv ("EMACS");
-
- /* Allocate data structures. */
- if (!rl_line_buffer)
- rl_line_buffer =
- (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
-
- /* Initialize the terminal interface. */
- init_terminal_io ((char *)NULL);
-
- /* Bind tty characters to readline functions. */
- readline_default_bindings ();
-
- /* Initialize the function names. */
- rl_initialize_funmap ();
-
- /* Read in the init file. */
- rl_read_init_file ((char *)NULL);
-
- /* If the completion parser's default word break characters haven't
- been set yet, then do so now. */
- {
- extern char *rl_completer_word_break_characters;
- extern char *rl_basic_word_break_characters;
-
- if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = rl_basic_word_break_characters;
- }
-}
-
-/* If this system allows us to look at the values of the regular
- input editing characters, then bind them to their readline
- equivalents. */
-readline_default_bindings ()
-{
-
-#ifdef NEW_TTY_DRIVER
- struct sgttyb ttybuff;
- int tty = fileno (rl_instream);
-
- if (ioctl (tty, TIOCGETP, &ttybuff) != -1)
- {
- int erase = ttybuff.sg_erase, kill = ttybuff.sg_kill;
-
- if (erase != -1 && keymap[erase].type == ISFUNC)
- keymap[erase].function = rl_rubout;
-
- if (kill != -1 && keymap[kill].type == ISFUNC)
- keymap[kill].function = rl_unix_line_discard;
- }
-
-#ifdef TIOCGLTC
- {
- struct ltchars lt;
-
- if (ioctl (tty, TIOCGLTC, <) != -1)
- {
- int erase = lt.t_werasc, nextc = lt.t_lnextc;
-
- if (erase != -1 && keymap[erase].type == ISFUNC)
- keymap[erase].function = rl_unix_word_rubout;
-
- if (nextc != -1 && keymap[nextc].type == ISFUNC)
- keymap[nextc].function = rl_quoted_insert;
- }
- }
-#endif /* TIOCGLTC */
-#else /* not NEW_TTY_DRIVER */
- struct termio ttybuff;
- int tty = fileno (rl_instream);
-
- if (ioctl (tty, TCGETA, &ttybuff) != -1)
- {
- int erase = ttybuff.c_cc[VERASE];
- int kill = ttybuff.c_cc[VKILL]l
-
- if (erase != -1 && keymap[(unsigned char)erase].type == ISFUNC)
- keymap[(unsigned char)erase].function = rl_rubout;
-
- if (kill != -1 && keymap[(unsigned char)kill].type == ISFUNC)
- keymap[(unsigned char)kill].function = rl_unix_line_discard;
- }
-#endif /* NEW_TTY_DRIVER */
-}
-
-
-/* **************************************************************** */
-/* */
-/* Numeric Arguments */
-/* */
-/* **************************************************************** */
-
-/* Handle C-u style numeric args, as well as M--, and M-digits. */
-
-/* Add the current digit to the argument in progress. */
-rl_digit_argument (ignore, key)
-int ignore, key;
-{
- rl_pending_input = key;
- rl_digit_loop ();
-}
-
-/* What to do when you abort reading an argument. */
-rl_discard_argument ()
-{
- ding ();
- rl_clear_message ();
- rl_init_argument ();
-}
-
-/* Create a default argument. */
-rl_init_argument ()
-{
- rl_numeric_arg = arg_sign = 1;
- rl_explicit_arg = 0;
-}
-
-/* C-u, universal argument. Multiply the current argument by 4.
- Read a key. If the key has nothing to do with arguments, then
- dispatch on it. If the key is the abort character then abort. */
-rl_universal_argument ()
-{
- rl_numeric_arg *= 4;
- rl_digit_loop ();
-}
-
-rl_digit_loop ()
-{
- int key, c;
- while (1)
- {
- rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg);
- key = c = rl_read_key ();
-
- if (keymap[c].type == ISFUNC &&
- keymap[c].function == rl_universal_argument)
- {
- rl_numeric_arg *= 4;
- continue;
- }
- c = UNMETA (c);
- if (numeric (c))
- {
- if (rl_explicit_arg)
- rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
- else
- rl_numeric_arg = (c - '0');
- rl_explicit_arg = 1;
- }
- else
- {
- if (c == '-' && !rl_explicit_arg)
- {
- rl_numeric_arg = 1;
- arg_sign = -1;
- }
- else
- {
- rl_clear_message ();
- rl_dispatch (key, keymap);
- return;
- }
- }
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* Display stuff */
-/* */
-/* **************************************************************** */
-
-/* This is the stuff that is hard for me. I never seem to write good
- display routines in C. Let's see how I do this time. */
-
-/* (PWP) Well... Good for a simple line updater, but totally ignores
- the problems of input lines longer than the screen width.
-
- update_line and the code that calls it makes a multiple line,
- automatically wrapping line update. Carefull attention needs
- to be paid to the vertical position variables.
-
- handling of terminals with autowrap on (incl. DEC braindamage)
- could be improved a bit. Right now I just cheat and decrement
- screenwidth by one. */
-
-/* Keep two buffers; one which reflects the current contents of the
- screen, and the other to draw what we think the new contents should
- be. Then compare the buffers, and make whatever changes to the
- screen itself that we should. Finally, make the buffer that we
- just drew into be the one which reflects the current contents of the
- screen, and place the cursor where it belongs.
-
- Commands that want to can fix the display themselves, and then let
- this function know that the display has been fixed by setting the
- RL_DISPLAY_FIXED variable. This is good for efficiency. */
-
-/* Termcap variables: */
-extern char *term_up, *term_dc, *term_cr;
-extern int screenheight, screenwidth, terminal_can_insert;
-
---cut here---cut here---cut here---pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
-/* What YOU turn on when you have handled all redisplay yourself. */
-int rl_display_fixed = 0;
-
-/* The visible cursor position. If you print some text, adjust this. */
-int last_c_pos = 0;
-int last_v_pos = 0;
-
-/* The last left edge of text that was displayed. This is used when
- doing horizontal scrolling. It shifts in thirds of a screenwidth. */
-static int last_lmargin = 0;
-
-/* The line display buffers. One is the line currently displayed on
- the screen. The other is the line about to be displayed. */
-static char *visible_line = (char *)NULL;
-static char *invisible_line = (char *)NULL;
-
-/* Number of lines currently on screen minus 1. */
-int vis_botlin = 0;
-
-/* A buffer for `modeline' messages. */
-char msg_buf[128];
-
-/* Non-zero forces the redisplay even if we thought it was unnecessary. */
-int forced_display = 0;
-
-/* The stuff that gets printed out before the actual text of the line.
- This is usually pointing to rl_prompt. */
-char *rl_display_prompt = (char *)NULL;
-
-/* Default and initial buffer size. Can grow. */
-static int line_size = 1024;
-
-/* Non-zero means to always use horizontal scrolling in line display. */
-int horizontal_scroll_mode = 0;
-
-/* I really disagree with this, but my boss (among others) insists that we
- support compilers that don't work. I don't think we are gaining by doing
- so; what is the advantage in producing better code if we can't use it? */
-/* The following two declarations belong inside the
- function block, not here. */
-static void move_cursor_relative ();
-static void output_some_chars ();
-static void output_character_function ();
-static int compare_strings ();
-
-/* Basic redisplay algorithm. */
-rl_redisplay ()
-{
- register int in, out, c, linenum;
- register char *line = invisible_line;
- int c_pos = 0;
- int inv_botlin = 0; /* Number of lines in newly drawn buffer. */
-
- extern int readline_echoing_p;
-
- if (!readline_echoing_p)
- return;
-
- if (!rl_display_prompt)
- rl_display_prompt = "";
-
- if (!invisible_line)
- {
- visible_line = (char *)xmalloc (line_size);
- invisible_line = (char *)xmalloc (line_size);
- line = invisible_line;
- for (in = 0; in < line_size; in++)
- {
- visible_line[in] = 0;
- invisible_line[in] = 1;
- }
- rl_on_new_line ();
- }
-
- /* Draw the line into the buffer. */
- c_pos = -1;
-
- /* Mark the line as modified or not. We only do this for history
- lines. No we don't. -pjf */
- out = 0;
- /*if (current_history () && rl_undo_list)
- {
- line[out++] = '*';
- line[out] = '\0';
- }*/
-
- /* If someone thought that the redisplay was handled, but the currently
- visible line has a different modification state than the one about
- to become visible, then correct the callers misconception. */
- if (visible_line[0] != invisible_line[0])
- rl_display_fixed = 0;
-
- strncpy (line + out, rl_display_prompt, strlen (rl_display_prompt));
- out += strlen (rl_display_prompt);
- line[out] = '\0';
-
- for (in = 0; in < rl_end; in++)
- {
- c = the_line[in];
-
- if (out + 1 >= line_size)
- {
- line_size *= 2;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
-
- if (in == rl_point)
- c_pos = out;
-
- if (c > 127)
- {
- line[out++] = 'M';
- line[out++] = '-';
- line[out++] = c - 128;
- }
-#define DISPLAY_TABS
-#ifdef DISPLAY_TABS
- else if (c == '\t')
- {
- register int newout = (out | (int)7) + 1;
- while (out < newout)
- line[out++] = ' ';
- }
-#endif
- else if (c == '\n')
- {
- line[out++] = '\\';
- line[out++] = 'n';
- }
- else if (c < 32)
- {
- line[out++] = '^';
- line[out++] = c + 64;
- }
- else
- line[out++] = c;
- }
- line[out] = '\0';
- if (c_pos < 0)
- c_pos = out;
-
- /* PWP: now is when things get a bit hairy. The visible and invisible
- line buffers are really multiple lines, which would wrap every
- (screenwidth - 1) characters. Go through each in turn, finding
- the changed region and updating it. The line order is top to bottom. */
-
- /* If we can move the cursor up and down, then use multiple lines,
- otherwise, let long lines display in a single terminal line, and
- horizontally scroll it. */
-
- if (!horizontal_scroll_mode && term_up && *term_up)
- {
- int total_screen_chars = (screenwidth * screenheight);
-
- if (!rl_display_fixed || forced_display)
- {
- forced_display = 0;
-
- /* If we have more than a screenful of material to display, then
- only display a screenful. We should display the last screen,
- not the first. I'll fix this in a minute. */
- if (out >= total_screen_chars)
- out = total_screen_chars - 1;
-
- /* Number of screen lines to display. */
- inv_botlin = out / screenwidth;
-
- /* For each line in the buffer, do the updating display. */
- for (linenum = 0; linenum <= inv_botlin; linenum++)
- update_line (linenum > vis_botlin ? ""
- : &visible_line[linenum * screenwidth],
- &invisible_line[linenum * screenwidth],
- linenum);
-
- /* We may have deleted some lines. If so, clear the left over
- blank ones at the bottom out. */
- if (vis_botlin > inv_botlin)
- {
- char *tt;
- for (; linenum <= vis_botlin; linenum++)
- {
- tt = &visible_line[linenum * screenwidth];
- move_vert (linenum);
- move_cursor_relative (0, tt);
- clear_to_eol ((linenum == vis_botlin)?
- strlen (tt) : screenwidth);
- }
- }
- vis_botlin = inv_botlin;
-
- /* Move the cursor where it should be. */
- move_vert (c_pos / screenwidth);
- move_cursor_relative (c_pos % screenwidth,
- &invisible_line[(c_pos / screenwidth) * screenwidth]);
- }
- }
- else /* Do horizontal scrolling. */
- {
- int lmargin;
-
- /* Always at top line. */
- last_v_pos = 0;
-
- /* If the display position of the cursor would be off the edge
- of the screen, start the display of this line at an offset that
- leaves the cursor on the screen. */
- if (c_pos - last_lmargin > screenwidth - 2)
- lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
- else if (c_pos - last_lmargin < 1)
- lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
- else
- lmargin = last_lmargin;
-
- /* If the first character on the screen isn't the first character
- in the display line, indicate this with a special character. */
- if (lmargin > 0)
- line[lmargin] = '<';
-
- if (lmargin + screenwidth < out)
- line[lmargin + screenwidth - 1] = '>';
-
- if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
- {
- forced_display = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin], 0);
-
- move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
- last_lmargin = lmargin;
- }
- }
- fflush (out_stream);
-
- /* Swap visible and non-visible lines. */
- {
- char *temp = visible_line;
- visible_line = invisible_line;
- invisible_line = temp;
- rl_display_fixed = 0;
- }
-}
-
-/* PWP: update_line() is based on finding the middle difference of each
- line on the screen; vis:
-
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
-old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
-
- All are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handeled.
-
- Could be made even smarter, but this works well enough */
-static
-update_line (old, new, current_line)
-register char *old, *new;
-int current_line;
-{
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
- int lendiff, wsatend;
-
- /* Find first difference. */
- for (ofd = old, nfd = new;
- (ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
- ;
-
- /* Move to the end of the screen line. */
- for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
- for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
-
- /* If no difference, continue to next line. */
- if (ofd == oe && nfd == ne)
- return;
-
- wsatend = 1; /* flag for trailing whitespace */
- ols = oe - 1; /* find last same */
- nls = ne - 1;
- while ((*ols == *nls) && (ols > ofd) && (nls > nfd))
- {
- if (*ols != ' ')
- wsatend = 0;
- ols--;
- nls--;
- }
-
- if (wsatend)
- {
- ols = oe;
- nls = ne;
- }
- else if (*ols != *nls)
- {
- if (*ols) /* don't step past the NUL */
- ols++;
- if (*nls)
- nls++;
- }
-
- move_vert (current_line);
- move_cursor_relative (ofd - old, old);
-
- /* if (len (new) > len (old)) */
- lendiff = (nls - nfd) - (ols - ofd);
-
- /* Insert (diff(len(old),len(new)) ch */
- if (lendiff > 0)
- {
- if (terminal_can_insert)
- {
- extern char *term_IC;
-
- /* Sometimes it is cheaper to print the characters rather than
- use the terminal's capabilities. */
- if ((2 * (ne - nfd)) < lendiff && !term_IC)
- {
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- }
- else
- {
- if (*ols)
- {
- insert_some_chars (nfd, lendiff);
- last_c_pos += lendiff;
- }
- else
- {
- /* At the end of a line the characters do not have to
- be "inserted". They can just be placed on the screen. */
- output_some_chars (nfd, lendiff);
- last_c_pos += lendiff;
- }
- /* Copy (new) chars to screen from first diff to last match. */
- if (((nls - nfd) - lendiff) > 0)
- {
- output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
- last_c_pos += ((nls - nfd) - lendiff);
- }
- }
- }
- else
- { /* cannot insert chars, write to EOL */
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- }
- }
- else /* Delete characters from line. */
- {
- /* If possible and inexpensive to use terminal deletion, then do so. */
- if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
- {
- if (lendiff)
- delete_chars (-lendiff); /* delete (diff) characters */
-
- /* Copy (new) chars to screen from first diff to last match */
- if ((nls - nfd) > 0)
- {
- output_some_chars (nfd, (nls - nfd));
- last_c_pos += (nls - nfd);
- }
- }
- /* Otherwise, print over the existing material. */
- else
- {
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- clear_to_eol ((oe - old) - (ne - new));
- }
- }
-}
-
-/* (PWP) tell the update routines that we have moved onto a
- new (empty) line. */
-rl_on_new_line ()
-{
- if (visible_line)
- visible_line[0] = '\0';
-
- last_c_pos = last_v_pos = 0;
- vis_botlin = last_lmargin = 0;
-}
-
-/* Actually update the display, period. */
-rl_forced_update_display ()
-{
- if (visible_line)
- {
- register char *temp = visible_line;
-
- while (*temp) *temp++ = '\0';
- }
- rl_on_new_line ();
- forced_display++;
- rl_redisplay ();
-}
-
-/* Move the cursor from last_c_pos to NEW, which are buffer indices.
- DATA is the contents of the screen line of interest; i.e., where
- the movement is being done. */
-static void
-move_cursor_relative (new, data)
-int new;
-char *data;
-{
- register int i;
-
- /* It may be faster to output a CR, and then move forwards instead
- of moving backwards. */
- if (new + 1 < last_c_pos - new)
- {
- tputs (term_cr, 1, output_character_function);
- last_c_pos = 0;
- }
-
- if (last_c_pos == new) return;
-
- if (last_c_pos < new)
- {
- /* Move the cursor forward. We do it by printing the command
- to move the cursor forward if there is one, else print that
- portion of the output buffer again. Which is cheaper? */
-
- /* The above comment is left here for posterity. It is faster
- to print one character (non-control) than to print a control
- sequence telling the terminal to move forward one character.
- That kind of control is for people who don't know what the
- data is underneath the cursor. */
-#ifdef HACK_TERMCAP_MOTION
- extern char *term_forward_char;
-
- if (term_forward_char)
- for (i = last_c_pos; i < new; i++)
- tputs (term_forward_char, 1, output_character_function);
- else
- for (i = last_c_pos; i < new; i++)
- putc (data[i], out_stream);
-#else
- for (i = last_c_pos; i < new; i++)
- putc (data[i], out_stream);
-#endif /* HACK_TERMCAP_MOTION */
- }
- else
- backspace (last_c_pos - new);
- last_c_pos = new;
-}
-
-/* PWP: move the cursor up or down. */
-move_vert (to)
-int to;
-{
- void output_character_function ();
- register int delta, i;
-
- if (last_v_pos == to) return;
-
- if (to > screenheight)
- return;
-
- if ((delta = to - last_v_pos) > 0)
- {
- for (i = 0; i < delta; i++)
- putc ('\n', out_stream);
- tputs (term_cr, 1, output_character_function);
- last_c_pos = 0; /* because crlf() will do \r\n */
- }
- else
- { /* delta < 0 */
- if (term_up && *term_up)
- for (i = 0; i < -delta; i++)
- tputs (term_up, 1, output_character_function);
- }
- last_v_pos = to; /* now to is here */
-}
-
-/* Physically print C on out_stream. This is for functions which know
- how to optimize the display. */
-rl_show_char (c)
-int c;
-{
- if (c > 127)
- {
- fprintf (out_stream, "M-");
- c -= 128;
- }
-
-#ifdef DISPLAY_TABS
- if (c < 32 && c != '\t')
-#else
- if (c < 32)
-#endif
- {
-
- c += 64;
- }
-
- putc (c, out_stream);
- fflush (out_stream);
-}
-
-#ifdef DISPLAY_TABS
-int
-rl_character_len (c, pos)
-register int c, pos;
-{
- if (c < ' ' || c > 126)
- {
- if (c == '\t')
- return (((pos | (int)7) + 1) - pos);
- else
- return (3);
- }
- else
- return (1);
-}
-#else
-int
-rl_character_len (c)
-int c;
-{
- if (c < ' ' || c > 126)
- return (3);
- else
- return (1);
-}
-#endif /* DISPLAY_TAB */
-
-/* How to print things in the "echo-area". The prompt is treated as a
- mini-modeline. */
-rl_message (string, arg1, arg2)
-char *string;
-{
- sprintf (msg_buf, string, arg1, arg2);
- rl_display_prompt = msg_buf;
- rl_redisplay ();
-}
-
-/* How to clear things from the "echo-area". */
-rl_clear_message ()
-{
- rl_display_prompt = rl_prompt;
- rl_redisplay ();
-}
-
-/* **************************************************************** */
-/* */
-/* Terminal and Termcap */
-/* */
-/* **************************************************************** */
-
-static char *term_buffer = (char *)NULL;
-static char *term_string_buffer = (char *)NULL;
-
-/* Non-zero means this terminal can't really do anything. */
-int dumb_term = 0;
-
-char PC;
-char *BC, *UP;
-
-/* Some strings to control terminal actions. These are output by tputs (). */
-char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
-
-int screenwidth, screenheight;
-
-/* Non-zero if we determine that the terminal can do character insertion. */
-int terminal_can_insert = 0;
-
-/* How to insert characters. */
-char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
-
-/* How to delete characters. */
-char *term_dc, *term_DC;
-
-#ifdef HACK_TERMCAP_MOTION
-char *term_forward_char;
-#endif /* HACK_TERMCAP_MOTION */
-
-/* How to go up a line. */
-char *term_up;
-
-/* Re-initialize the terminal considering that the TERM/TERMCAP variable
- has changed. */
-rl_reset_terminal (terminal_name)
-char *terminal_name;
-{
- init_terminal_io (terminal_name);
-}
-
-init_terminal_io (terminal_name)
-char *terminal_name;
-{
- char *term = (terminal_name? terminal_name : (char *)getenv ("TERM"));
- char *tgetstr (), *buffer;
-
-
- if (!term_string_buffer)
- term_string_buffer = (char *)xmalloc (2048);
-
- if (!term_buffer)
- term_buffer = (char *)xmalloc (2048);
-
- buffer = term_string_buffer;
-
- term_clrpag = term_cr = term_clreol = (char *)NULL;
-
- if (!term)
- term = "dumb";
-
- if (tgetent (term_buffer, term) < 0)
- {
- dumb_term = 1;
- return;
- }
-
- BC = tgetstr ("pc", &buffer);
- PC = buffer ? *buffer : 0;
-
- term_backspace = tgetstr ("le", &buffer);
-
- term_cr = tgetstr ("cr", &buffer);
- term_clreol = tgetstr ("ce", &buffer);
- term_clrpag = tgetstr ("cl", &buffer);
-
- if (!term_cr)
- term_cr = "\r";
-
-#ifdef HACK_TERMCAP_MOTION
- term_forward_char = tgetstr ("nd", &buffer);
-#endif /* HACK_TERMCAP_MOTION */
-
- screenwidth = tgetnum ("co");
- if (screenwidth <= 0)
- screenwidth = 80;
- screenwidth--; /* PWP: avoid autowrap bugs */
-
- screenheight = tgetnum ("li");
- if (screenheight <= 0)
- screenheight = 24;
-
- term_im = tgetstr ("im", &buffer);
- term_ei = tgetstr ("ei", &buffer);
- term_IC = tgetstr ("IC", &buffer);
- term_ic = tgetstr ("ic", &buffer);
-
- /* "An application program can assume that the terminal can do
- character insertion if *any one of* the capabilities `IC',
- `im', `ic' or `ip' is provided." But we can't do anything if
- only `ip' is provided, so... */
- terminal_can_insert = (term_IC || term_im || term_ic);
-
- term_up = tgetstr ("up", &buffer);
- term_dc = tgetstr ("dc", &buffer);
- term_DC = tgetstr ("DC", &buffer);
-}
-
-/* A function for the use of tputs () */
-static void
-output_character_function (c)
-int c;
-{
- putc (c, out_stream);
-}
-
-/* Write COUNT characters from STRING to the output stream. */
-static void
-output_some_chars (string, count)
-char *string;
-int count;
-{
- fwrite (string, 1, count, out_stream);
-}
-
-
-/* Delete COUNT characters from the display line. */
-static
-delete_chars (count)
-int count;
-{
- if (count > screenwidth)
- return;
-
- if (term_DC && *term_DC)
- {
- char *tgoto (), *buffer;
- buffer = tgoto (term_DC, 0, count);
- tputs (buffer, 1, output_character_function);
- }
- else
- {
- if (term_dc && *term_dc)
- while (count--)
- tputs (term_dc, 1, output_character_function);
- }
-}
-
-/* Insert COUNT character from STRING to the output stream. */
-static
-insert_some_chars (string, count)
-char *string;
-int count;
-{
- /* If IC is defined, then we do not have to "enter" insert mode. */
- if (term_IC)
- {
- char *tgoto (), *buffer;
- buffer = tgoto (term_IC, 0, count);
- tputs (buffer, 1, output_character_function);
- output_some_chars (string, count);
- }
- else
- {
- register int i;
-
- /* If we have to turn on insert-mode, then do so. */
- if (term_im && *term_im)
- tputs (term_im, 1, output_character_function);
-
- /* If there is a special command for inserting characters, then
- use that first to open up the space. */
- if (term_ic && *term_ic)
- {
- for (i = count; i--; )
- tputs (term_ic, 1, output_character_function);
- }
-
- /* Print the text. */
- output_some_chars (string, count);
-
- /* If there is a string to turn off insert mode, we had best use
- it now. */
- if (term_ei && *term_ei)
- tputs (term_ei, 1, output_character_function);
- }
-}
-
-/* Move the cursor back. */
-backspace (count)
-int count;
-{
- register int i;
-
- if (term_backspace)
- for (i = 0; i < count; i++)
- tputs (term_backspace, 1, output_character_function);
- else
- for (i = 0; i < count; i++)
- putc ('\b', out_stream);
-}
-
-/* Move to the start of the next line. */
-crlf ()
-{
- tputs (term_cr, 1, output_character_function);
- putc ('\n', out_stream);
-}
-
-/* Clear to the end of the line. COUNT is the minimum
- number of character spaces to clear, */
-clear_to_eol (count)
-int count;
-{
- if (term_clreol)
- {
- tputs (term_clreol, 1, output_character_function);
- }
- else
- {
- register int i;
-
- /* Do one more character space. */
- count++;
-
- for (i = 0; i < count; i++)
- putc (' ', out_stream);
-
- backspace (count);
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* Saving and Restoring the TTY */
-/* */
-/* **************************************************************** */
-
-#ifdef NEW_TTY_DRIVER
-
-/* We use this to get and set the tty_flags. */
-static struct sgttyb the_ttybuff;
-
-/* Put the terminal in CBREAK mode so that we can detect key presses. */
-rl_prep_terminal ()
-{
-int original_tty_flags,local_mode_flags;
-
- static int firsttime = 1;
- int tty = fileno (rl_instream);
-
- /* We always get the latest tty values. Maybe stty changed them. */
- ioctl (tty, TIOCGETP, &the_ttybuff);
- original_tty_flags = ((the_ttybuff.sg_flags)&~(O_CBREAK|O_RAW))|O_ECHO;
-
- readline_echoing_p = (original_tty_flags & ECHO);
-
- /* If this terminal doesn't care how the 8th bit is used,
- then we can use it for the meta-key.
- We check by seeing if BOTH odd and even parity are allowed. */
- if ((the_ttybuff.sg_flags & ODDP) && (the_ttybuff.sg_flags & EVENP))
- {
-#ifdef PASS8
- the_ttybuff.sg_flags |= PASS8;
-#endif
- }
-
- /* Hack on local mode flags if we can. */
-#if defined (TIOCLGET) && defined (LPASS8)
- {
- int flags;
-
- ioctl (tty, TIOCLGET, &local_mode_flags);
- flags = local_mode_flags | LPASS8;
- ioctl (tty, TIOCLSET, &flags);
- }
-#endif
-
-#ifdef TIOCGETC
- {
- struct tchars temp;
-
- ioctl (tty, TIOCGETC, &temp);
-
- /* Get rid of C-s and C-q.
- We remember the value of startc (C-q) so that if the terminal is in
- xoff state, the user can xon it by pressing that character. */
- xon_char = temp.t_startc;
- temp.t_stopc = -1;
- temp.t_startc = -1;
-
- /* If there is an XON character, bind it to restart the output. */
- if (xon_char != -1)
- rl_bind_key (xon_char, rl_restart_output);
-
- /* If there is an EOF char, bind eof_char to it. */
- if (temp.t_eofc != -1)
- eof_char = temp.t_eofc;
-
-#ifdef NEVER
- /* Get rid of C-\ and C-c. */
- temp.t_intrc = temp.t_quitc = -1;
-#endif
-
- ioctl (tty, TIOCSETC, &temp);
- }
-#endif /* TIOCGETC */
-
-#ifdef TIOCGLTC
- {
- struct ltchars temp;
-
- ioctl (tty, TIOCGLTC, &temp);
-
- /* Make the interrupt keys go away. Just enough to make people happy. */
- temp.t_dsuspc = -1; /* C-y */
- temp.t_lnextc = -1; /* C-v */
-
- ioctl (tty, TIOCSLTC, &temp);
- }
-#endif /* TIOCGLTC */
-
- the_ttybuff.sg_flags &= ~ECHO;
- the_ttybuff.sg_flags |= CBREAK;
- ioctl (tty, TIOCSETN, &the_ttybuff);
-}
-
-
-#else /* !defined (NEW_TTY_DRIVER) */
-
-#if !defined (VMIN)
-#define VMIN VEOF
-#endif
-
-#if !defined (VTIME)
-#define VTIME VEOL
-#endif
-
-static struct termio otio;
-
-rl_prep_terminal ()
-{
- int tty = fileno (rl_instream);
- struct termio tio;
-
- ioctl (tty, TCGETA, &tio);
- ioctl (tty, TCGETA, &otio);
-
- readline_echoing_p = (tio.c_lflag & ECHO);
-
- tio.c_lflag &= ~(ICANON|ECHO);
- tio.c_iflag &= ~(IXON|IXOFF|IXANY|ISTRIP|INPCK);
-
-#if !defined (HANDLE_SIGNALS)
- tio.c_lflag &= ~ISIG;
-#endif
-
- tio.c_cc[VMIN] = 1;
- tio.c_cc[VTIME] = 0;
- ioctl (tty, TCSETAW, &tio);
- ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
-}
-
-#endif /* NEW_TTY_DRIVER */
-
-/* Restore the terminal to its original state. */
-rl_deprep_terminal ()
-{
- rl_active = 0;
- restoretty();
-}
-
-
-/* **************************************************************** */
-/* */
-/* Utility Functions */
-/* */
-/* **************************************************************** */
-
-/* Return 0 if C is not a member of the class of characters that belong
- in words, or 1 if it is. */
-
-int allow_pathname_alphabetic_chars = 0;
-char *pathname_alphabetic_chars = "/-_=~.#$";
-
-int
-alphabetic (c)
-int c;
-{
- char *rindex ();
- if (pure_alphabetic (c) || (numeric (c)))
- return (1);
-
- if (allow_pathname_alphabetic_chars)
- return ((int)rindex (pathname_alphabetic_chars, c));
- else
- return (0);
-}
-
-/* Return non-zero if C is a numeric character. */
-int
-numeric (c)
-int c;
-{
- return (c >= '0' && c <= '9');
-}
-
-/* Ring the terminal bell. */
-int
-ding ()
-{
-extern int opts[128];
-
- if (readline_echoing_p && opts['B'] == 0)
- {
- fprintf (stderr, "\007");
- fflush (stderr);
- }
- return (-1);
-}
-
-/* How to abort things. */
-rl_abort ()
-{
- ding ();
- rl_clear_message ();
- rl_init_argument ();
- rl_pending_input = 0;
-
- defining_kbd_macro = 0;
- while (executing_macro)
- pop_executing_macro ();
-
- longjmp (readline_top_level, 1);
-}
-
-/* Return a copy of the string between FROM and TO.
- FROM is inclusive, TO is not. */
-static char *
-rl_copy (from, to)
-int from, to;
-{
- register int length;
- char *copy;
-
- /* Fix it if the caller is confused. */
- if (from > to) {
- int t = from;
- from = to;
- to = t;
- }
-
- length = to - from;
- copy = (char *)xmalloc (1 + length);
- strncpy (copy, the_line + from, length);
- copy[length] = '\0';
- return (copy);
-}
-
-
-/* **************************************************************** */
-/* */
-/* Insert and Delete */
-/* */
-/* **************************************************************** */
-
-
-/* Insert a string of text into the line at point. This is the only
- way that you should do insertion. rl_insert () calls this
- function. */
-rl_insert_text (string)
-char *string;
-{
- extern int doing_an_undo;
- register int i, l = strlen (string);
- while (rl_end + l >= rl_line_buffer_len)
- {
- rl_line_buffer =
- (char *)xrealloc (rl_line_buffer,
- rl_line_buffer_len += DEFAULT_BUFFER_SIZE);
- the_line = rl_line_buffer;
- }
-
- for (i = rl_end; i >= rl_point; i--)
- the_line[i + l] = the_line[i];
- strncpy (the_line + rl_point, string, l);
-
- /* Remember how to undo this if we aren't undoing something. */
- if (!doing_an_undo)
- {
- /* If possible and desirable, concatenate the undos. */
- if ((strlen (string) == 1) &&
- rl_undo_list &&
- (rl_undo_list->what == UNDO_INSERT) &&
- (rl_undo_list->end == rl_point) &&
- (rl_undo_list->end - rl_undo_list->start < 20))
- rl_undo_list->end++;
- else
- rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
- }
- rl_point += l;
- rl_end += l;
- the_line[rl_end] = '\0';
-}
-
-/* Delete the string between FROM and TO. FROM is
- inclusive, TO is not. */
-rl_delete_text (from, to)
-int from, to;
-{
- extern int doing_an_undo;
- register char *text;
-
- /* Fix it if the caller is confused. */
- if (from > to) {
- int t = from;
- from = to;
- to = t;
- }
- text = rl_copy (from, to);
- strncpy (the_line + from, the_line + to, rl_end - to);
-
- /* Remember how to undo this delete. */
- if (!doing_an_undo)
- rl_add_undo (UNDO_DELETE, from, to, text);
- else
- free (text);
-
- rl_end -= (to - from);
- the_line[rl_end] = '\0';
-}
-
-
-/* **************************************************************** */
-/* */
-/* Readline character functions */
-/* */
-/* **************************************************************** */
-
-/* This is not a gap editor, just a stupid line input routine. No hair
- is involved in writing any of the functions, and none should be. */
-
-/* Note that:
-
- rl_end is the place in the string that we would place '\0';
- i.e., it is always safe to place '\0' there.
-
- rl_point is the place in the string where the cursor is. Sometimes
- this is the same as rl_end.
-
- Any command that is called interactively receives two arguments.
- The first is a count: the numeric arg pased to this command.
- The second is the key which invoked this command.
-*/
-
-
-/* **************************************************************** */
-/* */
-/* Movement Commands */
-/* */
-/* **************************************************************** */
-
-/* Note that if you `optimize' the display for these functions, you cannot
- use said functions in other functions which do not do optimizing display.
- I.e., you will have to update the data base for rl_redisplay, and you
- might as well let rl_redisplay do that job. */
-
-/* Move forward COUNT characters. */
-rl_forward (count)
-int count;
-{
- if (count < 0)
- rl_backward (-count);
- else
- while (count)
- {
-#ifdef VI_MODE
- if (rl_point == (rl_end - (rl_editing_mode == vi_mode)))
-#else
- if (rl_point == rl_end)
-#endif
- {
- ding ();
- return;
- }
- else
- rl_point++;
- --count;
- }
-}
-
-/* Move backward COUNT characters. */
-rl_backward (count)
-int count;
-{
- if (count < 0)
- rl_forward (-count);
- else
- while (count)
- {
- if (!rl_point)
- {
- ding ();
- return;
- }
- else
- --rl_point;
- --count;
- }
-}
-
-/* Move to the beginning of the line. */
-rl_beg_of_line ()
-{
- rl_point = 0;
-}
-
-/* Move to the end of the line. */
-rl_end_of_line ()
-{
- rl_point = rl_end;
-}
-
-/* Move forward a word. We do what Emacs does. */
-rl_forward_word (count)
-int count;
-{
- int c;
-
- if (count < 0)
- {
- rl_backward_word (-count);
- return;
- }
-
- while (count)
- {
- if (rl_point == rl_end)
- return;
-
- /* If we are not in a word, move forward until we are in one.
- Then, move forward until we hit a non-alphabetic character. */
- c = the_line[rl_point];
- if (!alphabetic (c))
- {
- while (++rl_point < rl_end)
- {
- c = the_line[rl_point];
- if (alphabetic (c)) break;
- }
- }
- if (rl_point == rl_end) return;
- while (++rl_point < rl_end)
- {
- c = the_line[rl_point];
- if (!alphabetic (c)) break;
- }
- --count;
- }
-}
-
-/* Move backward a word. We do what Emacs does. */
-rl_backward_word (count)
-int count;
-{
- int c;
-
- if (count < 0)
- {
- rl_forward_word (-count);
- return;
- }
-
- while (count)
- {
- if (!rl_point)
- return;
-
- /* Like rl_forward_word (), except that we look at the characters
- just before point. */
-
- c = the_line[rl_point - 1];
- if (!alphabetic (c))
- {
- while (--rl_point)
- {
- c = the_line[rl_point - 1];
- if (alphabetic (c)) break;
- }
- }
-
- while (rl_point)
- {
- c = the_line[rl_point - 1];
- if (!alphabetic (c))
- break;
- else --rl_point;
- }
- --count;
- }
-}
-
-/* Clear the current line. Numeric argument to C-l does this. */
-rl_refresh_line ()
-{
- int curr_line = last_c_pos / screenwidth;
- extern char *term_clreol;
-
- move_vert(curr_line);
- move_cursor_relative (0, the_line); /* XXX is this right */
-
- if (term_clreol)
- tputs (term_clreol, 1, output_character_function);
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-}
-
-/* C-l typed to a line without quoting clears the screen, and then reprints
- the prompt and the current input line. Given a numeric arg, redraw only
- the current line. */
-rl_clear_screen ()
-{
- extern char *term_clrpag;
-
- if (rl_explicit_arg)
- {
- rl_refresh_line ();
- return;
- }
-
- if (term_clrpag)
- tputs (term_clrpag, 1, output_character_function);
- else
- crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Text commands */
-/* */
-/* **************************************************************** */
-
-/* Insert the character C at the current location, moving point forward. */
-rl_insert (count, c)
-int count, c;
-{
- register int i;
- char *string;
-
- if (count <= 0)
- return;
-
- /* If we can optimize, then do it. But don't let people crash
- readline because of extra large arguments. */
- if (count > 1 && count < 1024)
- {
- string = (char *)alloca (1 + count);
-
- for (i = 0; i < count; i++)
- string[i] = c;
-
- string[i] = '\0';
- rl_insert_text (string);
- return;
- }
-
- if (count > 1024)
- {
- int decreaser;
-
- string = (char *)alloca (1024 + 1);
-
- for (i = 0; i < 1024; i++)
- string[i] = c;
-
- while (count)
- {
- decreaser = (count > 1024 ? 1024 : count);
- string[decreaser] = '\0';
- rl_insert_text (string);
- count -= decreaser;
- }
- return;
- }
-
- /* We are inserting a single character.
- If there is pending input, then make a string of all of the
- pending characters that are bound to rl_insert, and insert
- them all. */
- if (any_typein)
- {
- int key = 0, t;
-
- i = 0;
- string = (char *)alloca (ibuffer_len + 1);
- string[i++] = c;
-
- while ((t = rl_get_char (&key)) &&
- (keymap[key].type == ISFUNC &&
- keymap[key].function == rl_insert))
- string[i++] = key;
-
- if (t)
- rl_unget_char (key);
-
- string[i] = '\0';
- rl_insert_text (string);
- return;
- }
- else
- {
- /* Inserting a single character. */
- string = (char *)alloca (2);
-
- string[1] = '\0';
- string[0] = c;
- rl_insert_text (string);
- }
-}
-
-/* Insert the next typed character verbatim. */
-rl_quoted_insert (count)
-int count;
-{
- int c = rl_read_key ();
- rl_insert (count, c);
-}
-
-/* Insert a tab character. */
-rl_tab_insert (count)
-int count;
-{
- rl_insert (count, '\t');
-}
-
-/* What to do when a NEWLINE is pressed. We accept the whole line.
- KEY is the key that invoked this command. I guess it could have
- meaning in the future. */
-rl_newline (count, key)
-int count, key;
-{
-
- rl_done = 1;
-#ifdef VI_MODE
- {
- extern int vi_doing_insert;
- if (vi_doing_insert)
- {
- rl_end_undo_group ();
- vi_doing_insert = 0;
- }
- }
-#endif /* VI_MODE */
-
- if (readline_echoing_p)
- {
- move_vert (vis_botlin);
- vis_botlin = 0;
- crlf ();
- fflush (out_stream);
- rl_display_fixed++;
- }
- rl_end_of_line();
- rl_insert(1,'\n'); /* added by pjf */
-}
-
-rl_clean_up_for_exit ()
-{
- if (readline_echoing_p)
- {
- move_vert (vis_botlin);
- vis_botlin = 0;
- fflush (out_stream);
- rl_restart_output ();
- }
-}
-
-/* What to do for some uppercase characters, like meta characters,
- and some characters appearing in emacs_ctlx_keymap. This function
- is just a stub, you bind keys to it and the code in rl_dispatch ()
- is special cased. */
-rl_do_lowercase_version (ignore1, ignore2)
-int ignore1, ignore2;
-{
-}
-
-/* Rubout the character behind point. */
-rl_rubout (count)
-int count;
-{
- if (count < 0)
- {
- rl_delete (-count);
- return;
- }
-
- if (!rl_point)
- {
- ding ();
- return;
- }
-
- if (count > 1)
- {
- int orig_point = rl_point;
- rl_backward (count);
- rl_kill_text (orig_point, rl_point);
- }
- else
- {
- int c = the_line[--rl_point];
- rl_delete_text (rl_point, rl_point + 1);
-
- if (rl_point == rl_end && alphabetic (c) && last_c_pos)
- {
- backspace (1);
- putc (' ', out_stream);
- backspace (1);
- last_c_pos--;
- rl_display_fixed++;
- }
- }
-}
-
-/* Delete the character under the cursor. Given a numeric argument,
- kill that many characters instead. */
-rl_delete (count, invoking_key)
-int count, invoking_key;
-{
- if (count < 0)
- {
- rl_rubout (-count);
- return;
- }
-
- if (rl_point == rl_end)
- {
- ding ();
- return;
- }
-
- if (count > 1)
- {
- int orig_point = rl_point;
- rl_forward (count);
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- }
- else
- rl_delete_text (rl_point, rl_point + 1);
-}
-
-
-/* **************************************************************** */
-/* */
-/* Kill commands */
-/* */
-/* **************************************************************** */
-
-/* The next two functions mimic unix line editing behaviour, except they
- save the deleted text on the kill ring. This is safer than not saving
- it, and since we have a ring, nobody should get screwed. */
-
-/* This does what C-w does in Unix. We can't prevent people from
- using behaviour that they expect. */
-rl_unix_word_rubout ()
-{
- if (!rl_point) ding ();
- else {
- int orig_point = rl_point;
- while (rl_point && whitespace (the_line[rl_point - 1]))
- rl_point--;
- while (rl_point && !whitespace (the_line[rl_point - 1]))
- rl_point--;
- rl_kill_text (rl_point, orig_point);
- }
-}
-
-/* Here is C-u doing what Unix does. You don't *have* to use these
- key-bindings. We have a choice of killing the entire line, or
- killing from where we are to the start of the line. We choose the
- latter, because if you are a Unix weenie, then you haven't backspaced
- into the line at all, and if you aren't, then you know what you are
- doing. (pjf: I disagree*/
-rl_unix_line_discard ()
-{
- rl_end_of_line();
- if (!rl_point) ding ();
- else {
- rl_kill_text (rl_point, 0);
- rl_point = 0;
- }
-}
-
-
-
-/* **************************************************************** */
-/* */
-/* Commands For Typos */
-/* */
-/* **************************************************************** */
-
-/* Random and interesting things in here. */
-
-
-/* **************************************************************** */
-/* */
-/* Changing Case */
-/* */
-/* **************************************************************** */
-
-/* The three kinds of things that we know how to do. */
-#define UpCase 1
-#define DownCase 2
-#define CapCase 3
-
-/* Uppercase the word at point. */
-rl_upcase_word (count)
-int count;
-{
- rl_change_case (count, UpCase);
-}
-
-/* Lowercase the word at point. */
-rl_downcase_word (count)
-int count;
-{
- rl_change_case (count, DownCase);
-}
-
-/* Upcase the first letter, downcase the rest. */
-rl_capitalize_word (count)
-int count;
-{
- rl_change_case (count, CapCase);
-}
-
-/* The meaty function.
- Change the case of COUNT words, performing OP on them.
- OP is one of UpCase, DownCase, or CapCase.
- If a negative argument is given, leave point where it started,
- otherwise, leave it where it moves to. */
-rl_change_case (count, op)
-int count, op;
-{
- register int start = rl_point, end;
- int state = 0;
-
- rl_forward_word (count);
- end = rl_point;
-
- if (count < 0)
- {
- int temp = start;
- start = end;
- end = temp;
- }
-
- /* We are going to modify some text, so let's prepare to undo it. */
- rl_modifying (start, end);
-
- for (; start < end; start++)
- {
- switch (op)
- {
- case UpCase:
- the_line[start] = to_upper (the_line[start]);
- break;
-
- case DownCase:
- the_line[start] = to_lower (the_line[start]);
- break;
-
- case CapCase:
- if (state == 0)
- {
- the_line[start] = to_upper (the_line[start]);
- state = 1;
- }
- else
- {
- the_line[start] = to_lower (the_line[start]);
- }
- if (!pure_alphabetic (the_line[start]))
- state = 0;
- break;
-
- default:
- abort ();
- }
- }
- rl_point = end;
-}
-
-/* **************************************************************** */
-/* */
-/* Transposition */
-/* */
-/* **************************************************************** */
-
-/* Transpose the words at point. */
-rl_transpose_words (count)
-int count;
-{
- char *word1, *word2;
- int w1_beg, w1_end, w2_beg, w2_end;
- int orig_point = rl_point;
-
- if (!count) return;
-
- /* Find the two words. */
- rl_forward_word (count);
- w2_end = rl_point;
- rl_backward_word (1);
- w2_beg = rl_point;
- rl_backward_word (count);
- w1_beg = rl_point;
- rl_forward_word (1);
- w1_end = rl_point;
-
- /* Do some check to make sure that there really are two words. */
- if ((w1_beg == w2_beg) || (w2_beg < w1_end))
- {
- ding ();
- rl_point = orig_point;
- return;
- }
-
- /* Get the text of the words. */
- word1 = rl_copy (w1_beg, w1_end);
- word2 = rl_copy (w2_beg, w2_end);
-
- /* We are about to do many insertions and deletions. Remember them
- as one operation. */
- rl_begin_undo_group ();
-
- /* Do the stuff at word2 first, so that we don't have to worry
- about word1 moving. */
- rl_point = w2_beg;
- rl_delete_text (w2_beg, w2_end);
- rl_insert_text (word1);
-
- rl_point = w1_beg;
- rl_delete_text (w1_beg, w1_end);
- rl_insert_text (word2);
-
- /* This is exactly correct since the text before this point has not
- changed in length. */
- rl_point = w2_end;
-
- /* I think that does it. */
- rl_end_undo_group ();
- free (word1);
- free (word2);
-}
-
-/* Transpose the characters at point. If point is at the end of the line,
- then transpose the characters before point. */
-rl_transpose_chars (count)
-int count;
-{
- if (!count)
- return;
-
- if (!rl_point || rl_end < 2) {
- ding ();
- return;
- }
-
- while (count) {
- if (rl_point == rl_end) {
- int t = the_line[rl_point - 1];
- the_line[rl_point - 1] = the_line[rl_point - 2];
- the_line[rl_point - 2] = t;
- } else {
- int t = the_line[rl_point];
- the_line[rl_point] = the_line[rl_point - 1];
- the_line[rl_point - 1] = t;
- if (count < 0 && rl_point)
- rl_point--;
- else
- rl_point++;
- }
- if (count < 0)
- count++;
- else
- count--;
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* Bogus Flow Control */
-/* */
-/* **************************************************************** */
-
-rl_restart_output (count, key)
-int count, key;
-{
- int fildes = fileno (stdin);
-#ifdef TIOCSTART
- ioctl (fildes, TIOCSTART, 0);
-#endif /* TIOCSTART */
-}
-
-/* **************************************************************** */
-/* */
-/* Completion matching, from readline's point of view. */
-/* */
-/* **************************************************************** */
-
-/* Pointer to the generator function for completion_matches ().
- NULL means to use filename_entry_function (), the default filename
- completer. */
-Function *rl_completion_entry_function = (Function *)NULL;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-Function *rl_attempted_completion_function = (Function *)NULL;
-
-/* Complete the word at or before point. You have supplied the function
- that does the initial simple matching selection algorithm (see
- completion_matches ()). The default is to do filename completion. */
-rl_complete (ignore, invoking_key)
-int ignore, invoking_key;
-{
- rl_complete_internal (TAB);
-}
-
-/* List the possible completions. See description of rl_complete (). */
-rl_possible_completions ()
-{
- rl_complete_internal ('?');
-}
-
-/* The user must press "y" or "n". Non-zero return means "y" pressed. */
-get_y_or_n ()
-{
- int c;
-loop:
- c = rl_read_key ();
- if (c == 'y' || c == 'Y') return (1);
- if (c == 'n' || c == 'N') return (0);
- if (c == ABORT_CHAR) rl_abort ();
- ding ();
- goto loop;
-}
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if
- she is sure she wants to see them all. */
-int rl_completion_query_items = 100;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The contents of this variable is what breaks words
- in the shell, i.e. " \t\n\"\\'`@><" */
-char *rl_basic_word_break_characters = " \t\n@><;(";
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-char *rl_completer_word_break_characters = (char *)NULL;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-char *rl_special_prefixes = (char *)NULL;
-
-/* If non-zero, then disallow duplicates in the matches. */
-int rl_ignore_completion_duplicates = 1;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-int rl_filename_completion_desired = 0;
-
-/* Complete the word at or before point.
- WHAT_TO_DO says what to do with the completion.
- `?' means list the possible completions.
- TAB means do standard completion.
- `*' means insert all of the possible completions. */
-rl_complete_internal (what_to_do)
-int what_to_do;
-{
- char *filename_completion_function ();
- char **completion_matches (), **matches;
- Function *our_func;
- int start, end,did = 0;
- char *text;
-
- if (rl_completion_entry_function)
- our_func = rl_completion_entry_function;
- else
- our_func = (int (*)())filename_completion_function;
-
- /* Only the completion entry function can change this. */
- rl_filename_completion_desired = 0;
-
- /* We now look backwards for the start of a filename/variable word. */
- end = rl_point;
- if (rl_point)
- {
- for(;;) {
- while (--rl_point >= 0 &&
- !rindex (rl_completer_word_break_characters, the_line[rl_point]))
- if (the_line[rl_point] == '`')
- while(rl_point-- && the_line[rl_point] != '`');
- else if (the_line[rl_point] == '\'')
- while(rl_point-- && the_line[rl_point] != '\'');
- else if (the_line[rl_point] == '\"')
- while(rl_point-- && the_line[rl_point] != '\"');
-
- if (rl_point < 0)
- {
- rl_point = end;
- ding();
- return 0;
- }
- if (rl_point == 0 || the_line[rl_point-1] != '\\')
- break;
- rl_point--;
- }
- /* If we are at a word break, then advance past it. */
- if (rindex (rl_completer_word_break_characters, (the_line[rl_point])))
- rl_point++;
- }
-
- start = rl_point;
- rl_point = end;
- text = rl_copy (start, end);
- text = docompsubs(text,&did);
- rl_prep_terminal();
- if (!text)
- return 0;
- if (did)
- {
- rl_delete_text (start, rl_point);
- rl_point = start;
- if (what_to_do == '?')
- puts(text);
- else if (did == 2)
- rl_insert_text(text);
- else
- rl_safe_insert_text (text);
- free(text);
- return 0;
- }
- /* If the user wants to TRY to complete, but then wants to give
- up and use the default completion function, they set the
- variable rl_attempted_completion_function. */
- if (rl_attempted_completion_function)
- {
- matches =
- (char **)(*rl_attempted_completion_function) (text, start, end);
-
- if (matches)
- goto after_usual_completion;
- }
-
- matches = completion_matches (text, our_func, start, end);
-
-after_usual_completion:
- free (text);
-
- if (!matches)
- ding ();
- else
- {
- register int i;
-
-some_matches:
-
- /* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
- insert being identical to the other completions. */
- if (rl_ignore_completion_duplicates)
- {
- char *lowest_common;
- int j, newlen = 0;
-
- /* Sort the items. */
- /* It is safe to sort this array, because the lowest common
- denominator found in matches[0] will remain in place. */
- for (i = 0; matches[i]; i++);
- qsort (matches, i, sizeof (char *), compare_strings);
-
- /* Remember the lowest common denimator for it may be unique. */
- lowest_common = savestring (matches[0]);
-
- for (i = 0; matches[i + 1]; i++)
- {
- if (strcmp (matches[i], matches[i + 1]) == 0)
- {
- free (matches[i]);
- matches[i] = (char *)-1;
- }
- else
- newlen++;
- }
-
- /* We have marked all the dead slots with (char *)-1.
- Copy all the non-dead entries into a new array. */
- {
- char **temp_array =
- (char **)malloc ((3 + newlen) * sizeof (char *));
-
- for (i = 1, j = 1; matches[i]; i++)
- if (matches[i] != (char *)-1)
- temp_array[j++] = matches[i];
- temp_array[j] = (char *)NULL;
-
- if (matches[0] != (char *)-1)
- free (matches[0]);
- free (matches);
-
- matches = temp_array;
- }
-
- /* Place the lowest common denominator back in [0]. */
- matches[0] = lowest_common;
-
- /* If there is one string left, and it is identical to the
- lowest common denominator, then the LCD is the string to
- insert. */
- if (j == 2 && strcmp (matches[0], matches[1]) == 0)
- {
- free (matches[1]);
- matches[1] = (char *)NULL;
- }
- }
-
- switch (what_to_do)
- {
- case TAB:
- if (matches[0])
- {
- rl_delete_text (start, rl_point);
- rl_point = start;
- rl_safe_insert_text (matches[0]);
- }
-
- /* If there are more matches, ring the bell to indicate.
- If this was the only match, and we are hacking files,
- check the file to see if it was a directory. If so,
- add a '/' to the name. If not, and we are at the end
- of the line, then add a space. */
- if (matches[1])
- {
- extern int opts[128];
-
- ding (); /* There are other matches remaining. */
- if (opts['9'] == 2)
- goto autolist;
- }
- else
- {
- char temp_string[2];
-
- temp_string[0] = ' ';
- temp_string[1] = '\0';
-
- if (rl_filename_completion_desired)
- {
- struct stat finfo;
- char *tilde_expand ();
- char *filename = tilde_expand (matches[0]);
-
- if ((stat (filename, &finfo) == 0) &&
- ((finfo.st_mode & S_IFMT) == S_IFDIR))
- {
- if (the_line[rl_point] != '/')
- rl_insert_text ("/");
- }
- else
- {
- if (rl_point == rl_end)
- rl_insert_text (temp_string);
- }
- free (filename);
- }
- else
- {
- if (rl_point == rl_end)
- rl_insert_text (temp_string);
- }
- }
- break;
-
- case '*':
- {
- int i = 1;
-
- rl_delete_text (start, rl_point);
- rl_point = start;
- rl_begin_undo_group ();
- if (matches[1])
- {
- while (matches[i])
- {
- rl_safe_insert_text (matches[i++]);
- rl_insert_text (" ");
- }
- }
- else
- {
- rl_safe_insert_text (matches[0]);
- rl_insert_text (" ");
- }
- rl_end_undo_group ();
- }
- break;
-
-
- case '?':
- {
- int len, count, limit, max = 0;
- int j, k, l;
-
-autolist:
- /* Handle simple case first. What if there is only one answer? */
- if (!matches[1])
- {
- char *rindex (), *temp;
-
- if (rl_filename_completion_desired)
- temp = rindex (matches[0], '/');
- else
- temp = (char *)NULL;
-
- if (!temp)
- temp = matches[0];
- else
- temp++;
-
- crlf ();
- fprintf (out_stream, "%s", temp);
- crlf ();
- goto restart;
- }
-
- /* There is more than one answer. Find out how many there are,
- and find out what the maximum printed length of a single entry
- is. */
- for (i = 1; matches[i]; i++)
- {
- char *rindex (), *temp = (char *)NULL;
-
- /* If we are hacking filenames, then only count the characters
- after the last slash in the pathname. */
- if (rl_filename_completion_desired)
- temp = rindex (matches[i], '/');
- else
- temp = (char *)NULL;
-
- if (!temp)
- temp = matches[i];
- else
- temp++;
-
- if (strlen (temp) > max)
- max = strlen (temp);
- }
-
- len = i;
-
- /* If there are many items, then ask the user if she
- really wants to see them all. */
- if (len >= rl_completion_query_items)
- {
- crlf ();
- fprintf (out_stream,
- "There are %d possibilities. Do you really", len);
- crlf ();
- fprintf (out_stream, "wish to see them all? (y or n)");
- fflush (out_stream);
- if (!get_y_or_n ())
- {
- crlf ();
- goto restart;
- }
- }
- /* How many items of MAX length can we fit in the screen window? */
- max += 2;
- limit = screenwidth / max;
- if (limit != 1 && (limit * max == screenwidth))
- limit--;
-
- /* How many iterations of the printing loop? */
- count = (len + (limit - 1)) / limit;
-
- /* Watch out for special case. If LEN is less than LIMIT, then
- just do the inner printing loop. */
- if (len < limit) count = 1;
-
- /* Sort the items if they are not already sorted. */
- if (!rl_ignore_completion_duplicates)
- qsort (matches, len, sizeof (char *), compare_strings);
-
- /* Print the sorted items, up-and-down alphabetically, like
- ls might. */
- crlf ();
-
- for (i = 1; i < count + 1; i++)
- {
- for (j = 0, l = i; j < limit; j++)
- {
- if (l > len || !matches[l])
- {
- break;
- }
- else
- {
- char *rindex (), *temp = (char *)NULL;
-
- if (rl_filename_completion_desired)
- temp = rindex (matches[l], '/');
- else
- temp = (char *)NULL;
-
- if (!temp)
- temp = matches[l];
- else
- temp++;
-
- fprintf (out_stream, "%s", temp);
- for (k = 0; k < max - strlen (temp); k++)
- putc (' ', out_stream);
- }
- l += count;
- }
- crlf ();
- }
-restart:
-
- rl_on_new_line ();
- }
- break;
-
- default:
- abort ();
- }
-
- for (i = 0; matches[i]; i++)
- free (matches[i]);
- free (matches);
- }
-}
-
-/* Stupid comparison routine for qsort () ing strings. */
-static int
-compare_strings (s1, s2)
-char **s1, **s2;
-{
- return (strcmp (*s1, *s2));
-}
-
-/* If non-null, this contains the address of a function to call if the
- standard meaning for expanding a tilde fails. The function is called
- with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if there is no expansion. */
-Function *rl_tilde_expander = (Function *)NULL;
-
-/* Expand FILENAME if it begins with a tilde. This always returns
- a new string. */
-char *
-tilde_expand (filename)
-char *filename;
-{
- char *dirname = filename ? savestring (filename) : (char *)NULL;
-
- if (dirname && *dirname == '~')
- {
- char *temp_name;
- if (!dirname[1] || dirname[1] == '/')
- {
- /* Prepend $HOME to the rest of the string. */
- char *temp_home = (char *)getenv ("HOME");
-
- temp_name = (char *)alloca (1 + strlen (&dirname[1])
- + (temp_home? strlen (temp_home) : 0));
- temp_name[0] = '\0';
- if (temp_home)
- strcpy (temp_name, temp_home);
- strcat (temp_name, &dirname[1]);
- free (dirname);
- dirname = savestring (temp_name);
- }
- else
- {
- struct passwd *getpwnam (), *user_entry;
- char *username = (char *)alloca (257);
- int i, c;
-
- for (i = 1; c = dirname[i]; i++)
- {
- if (c == '/') break;
- else username[i - 1] = c;
- }
- username[i - 1] = '\0';
-
- if (!(user_entry = getpwnam (username)))
- {
- /* If the calling program has a special syntax for
- expanding tildes, and we couldn't find a standard
- expansion, then let them try. */
- if (rl_tilde_expander)
- {
- char *expansion;
-
- expansion = (char *)(*rl_tilde_expander) (username);
-
- if (expansion)
- {
- temp_name = (char *)alloca (1 + strlen (expansion)
- + strlen (&dirname[i]));
- strcpy (temp_name, expansion);
- strcat (temp_name, &dirname[i]);
- free (expansion);
- goto return_name;
- }
- }
- /*
- * We shouldn't report errors.
- */
- }
- else
- {
- temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir)
- + strlen (&dirname[i]));
- strcpy (temp_name, user_entry->pw_dir);
- strcat (temp_name, &dirname[i]);
-return_name:
- free (dirname);
- dirname = savestring (temp_name);
- }
- }
- }
- return (dirname);
-}
-
-
-/* **************************************************************** */
-/* */
-/* Undo, and Undoing */
-/* */
-/* **************************************************************** */
-
-/* Non-zero tells rl_delete_text and rl_insert_text to not add to
- the undo list. */
-int doing_an_undo = 0;
-
-/* The current undo list for THE_LINE. */
-UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
-
-/* Remember how to undo something. Concatenate some undos if that
- seems right. */
-rl_add_undo (what, start, end, text)
-enum undo_code what;
-int start, end;
-char *text;
-{
- UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
- temp->what = what;
- temp->start = start;
- temp->end = end;
- temp->text = text;
- temp->next = rl_undo_list;
- rl_undo_list = temp;
-}
-
-/* Free the existing undo list. */
-free_undo_list ()
-{
- while (rl_undo_list) {
- UNDO_LIST *release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
-
- if (release->what == UNDO_DELETE)
- free (release->text);
-
- free (release);
- }
-}
-
-/* Undo the next thing in the list. Return 0 if there
- is nothing to undo, or non-zero if there was. */
-int
-rl_do_undo ()
-{
- UNDO_LIST *release;
- int waiting_for_begin = 0;
-
-undo_thing:
- if (!rl_undo_list)
- return (0);
-
- doing_an_undo = 1;
-
- switch (rl_undo_list->what) {
-
- /* Undoing deletes means inserting some text. */
- case UNDO_DELETE:
- rl_point = rl_undo_list->start;
- rl_insert_text (rl_undo_list->text);
- free (rl_undo_list->text);
- break;
-
- /* Undoing inserts means deleting some text. */
- case UNDO_INSERT:
- rl_delete_text (rl_undo_list->start, rl_undo_list->end);
- rl_point = rl_undo_list->start;
- break;
-
- /* Undoing an END means undoing everything 'til we get to
- a BEGIN. */
- case UNDO_END:
- waiting_for_begin++;
- break;
-
- /* Undoing a BEGIN means that we are done with this group. */
- case UNDO_BEGIN:
- if (waiting_for_begin)
- waiting_for_begin--;
- else
- abort ();
- break;
- }
-
- doing_an_undo = 0;
-
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
- free (release);
-
- if (waiting_for_begin)
- goto undo_thing;
-
- return (1);
-}
-
-/* Begin a group. Subsequent undos are undone as an atomic operation. */
-rl_begin_undo_group ()
-{
- rl_add_undo (UNDO_BEGIN, 0, 0, 0);
-}
-
-/* End an undo group started with rl_begin_undo_group (). */
-rl_end_undo_group ()
-{
- rl_add_undo (UNDO_END, 0, 0, 0);
-}
-
-/* Save an undo entry for the text from START to END. */
-rl_modifying (start, end)
-int start, end;
-{
- if (start > end)
- {
- int t = start;
- start = end;
- end = t;
- }
-
- if (start != end)
- {
- char *temp = rl_copy (start, end);
- rl_begin_undo_group ();
- rl_add_undo (UNDO_DELETE, start, end, temp);
- rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
- rl_end_undo_group ();
- }
-}
-
-/* Revert the current line to its previous state. */
-rl_revert_line ()
-{
- if (!rl_undo_list) ding ();
- else {
- while (rl_undo_list)
- rl_do_undo ();
- }
-}
-
-/* Do some undoing of things that were done. */
-rl_undo_command (count)
-{
- if (count < 0) return; /* Nothing to do. */
-
- while (count)
- {
- if (rl_do_undo ())
- {
- count--;
- }
- else
- {
- ding ();
- break;
- }
- }
-}
-
-/* **************************************************************** */
-/* */
-/* History Utilities */
-/* */
-/* **************************************************************** */
-
-/* We already have a history library, and that is what we use to control
- the history features of readline. However, this is our local interface
- to the history mechanism. */
-
-/* While we are editing the history, this is the saved
- version of the original line. */
-HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
-
-/* Set the history pointer back to the last entry in the history. */
-start_using_history ()
-{
- using_history ();
- if (saved_line_for_history)
- free_history_entry (saved_line_for_history);
-
- saved_line_for_history = (HIST_ENTRY *)NULL;
-}
-
-/* Free the contents (and containing structure) of a HIST_ENTRY. */
-free_history_entry (entry)
-HIST_ENTRY *entry;
-{
- if (!entry) return;
- if (entry->line)
- free (entry->line);
- free (entry);
-}
-
-/* Perhaps put back the current line if it has changed. */
-maybe_replace_line ()
-{
- HIST_ENTRY *temp = current_history ();
-
- /* If the current line has changed, save the changes. */
- if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) {
- free (temp->line);
- free (temp);
- }
-}
-
-/* Put back the saved_line_for_history if there is one. */
-maybe_unsave_line ()
-{
- if (saved_line_for_history) {
- strcpy (the_line, saved_line_for_history->line);
- rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
- free_history_entry (saved_line_for_history);
- saved_line_for_history = (HIST_ENTRY *)NULL;
- rl_end = rl_point = strlen (the_line);
- } else {
- ding ();
- }
-}
-
-/* Save the current line in saved_line_for_history. */
-maybe_save_line ()
-{
- if (!saved_line_for_history) {
- saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- saved_line_for_history->line = savestring (the_line);
- saved_line_for_history->data = (char *)rl_undo_list;
- }
-}
-
-
-
-/* **************************************************************** */
-/* */
-/* History Commands */
-/* */
-/* **************************************************************** */
-
-/* Meta-< goes to the start of the history. */
-rl_beginning_of_history ()
-{
- rl_get_previous_history (1 + where_history ());
-}
-
-/* Meta-> goes to the end of the history. (The current line). */
-rl_end_of_history ()
-{
- maybe_replace_line ();
- using_history ();
- maybe_unsave_line ();
-}
-
-/* Move down to the next history line. */
-rl_get_next_history (count)
-int count;
-{
- HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
-
- if (count < 0)
- {
- rl_get_previous_history (-count);
- return;
- }
-
- if (!count)
- return;
-
- maybe_replace_line ();
-
- while (count)
- {
- temp = next_history ();
- if (!temp)
- break;
- if (--count)
- free(temp);
- }
-
- if (!temp)
- maybe_unsave_line ();
- else
- {
- free(temp);
- strcpy (the_line, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = rl_point = strlen (the_line);
- }
-}
-
-/* Get the previous item out of our interactive history, making it the current
- line. If there is no previous history, just ding. */
-rl_get_previous_history (count)
-int count;
-{
- HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
- HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
-
- if (count < 0)
- {
- rl_get_next_history (-count);
- return;
- }
-
- if (!count)
- return;
-
- /* If we don't have a line saved, then save this one. */
- maybe_save_line ();
-
- /* If the current line has changed, save the changes. */
- maybe_replace_line ();
-
- while (count)
- {
- temp = previous_history ();
- if (!temp)
- break;
- else
- old_temp = temp;
- if (--count)
- free(temp);
- }
-
- /* If there was a large argument, and we moved back to the start of the
- history, that is not an error. So use the last value found. */
- if (!temp && old_temp)
- temp = old_temp;
-
- if (!temp)
- ding ();
- else
- {
- strcpy (the_line, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = rl_point = strlen (the_line);
-#ifdef VI_MODE
- if (rl_editing_mode == vi_mode)
- rl_point = 0;
-#endif /* VI_MODE */
- }
-}
-
-/* There is a command in ksh which yanks into this line, the last word
- of the previous line. Here it is. We left it on M-. */
-rl_yank_previous_last_arg (ignore)
-int ignore;
-{
-}
-
-/* Make C be the next command to be executed. */
-rl_execute_next (c)
-int c;
-{
- rl_pending_input = c;
-}
-
-/* **************************************************************** */
-/* */
-/* Killing Mechanism */
-/* */
-/* **************************************************************** */
-
-/* What we assume for a max number of kills. */
-#define DEFAULT_MAX_KILLS 10
-
-/* The real variable to look at to find out when to flush kills. */
-int rl_max_kills = DEFAULT_MAX_KILLS;
-
-/* Where to store killed text. */
-char **rl_kill_ring = (char **)NULL;
-
-/* Where we are in the kill ring. */
-int rl_kill_index = 0;
-
-/* How many slots we have in the kill ring. */
-int rl_kill_ring_length = 0;
-
-/* How to say that you only want to save a certain amount
- of kill material. */
-rl_set_retained_kills (num)
-int num;
-{
-}
-
-/* The way to kill something. This appends or prepends to the last
- kill, if the last command was a kill command. if FROM is less
- than TO, then the text is appended, otherwise prepended. If the
- last command was not a kill command, then a new slot is made for
- this kill. */
-rl_kill_text (from, to)
-int from, to;
-{
- int slot;
- char *text = rl_copy (from, to);
-
- /* Is there anything to kill? */
- if (from == to) {
- free (text);
- last_command_was_kill++;
- return;
- }
-
- /* Delete the copied text from the line. */
- rl_delete_text (from, to);
-
- /* First, find the slot to work with. */
- if (!last_command_was_kill) {
-
- /* Get a new slot. */
- if (!rl_kill_ring) {
-
- /* If we don't have any defined, then make one. */
- rl_kill_ring =
- (char **)xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
- slot = 1;
-
- } else {
-
- /* We have to add a new slot on the end, unless we have exceeded
- the max limit for remembering kills. */
- slot = rl_kill_ring_length;
- if (slot == rl_max_kills) {
- register int i;
- free (rl_kill_ring[0]);
- for (i = 0; i < slot; i++)
- rl_kill_ring[i] = rl_kill_ring[i + 1];
- } else {
- rl_kill_ring =
- (char **)xrealloc (rl_kill_ring,
- ((slot = (rl_kill_ring_length += 1)) + 1)
- * sizeof (char *));
- }
- }
- slot--;
- } else {
- slot = rl_kill_ring_length - 1;
- }
-
- /* If the last command was a kill, prepend or append. */
- if (last_command_was_kill) {
- char *old = rl_kill_ring[slot];
- char *new = (char *)xmalloc (1 + strlen (old) + strlen (text));
-
- if (from < to) {
- strcpy (new, old);
- strcat (new, text);
- } else {
- strcpy (new, text);
- strcat (new, old);
- }
- free (old);
- free (text);
- rl_kill_ring[slot] = new;
- } else {
- rl_kill_ring[slot] = text;
- }
- rl_kill_index = slot;
- last_command_was_kill++;
-}
-
-/* Now REMEMBER! In order to do prepending or appending correctly, kill
- commands always make rl_point's original position be the FROM argument,
- and rl_point's extent be the TO argument. */
-
-
-/* **************************************************************** */
-/* */
-/* Killing Commands */
-/* */
-/* **************************************************************** */
-
-/* Delete the word at point, saving the text in the kill ring. */
-rl_kill_word (count)
-int count;
-{
- int orig_point = rl_point;
-
- if (count < 0)
- rl_backward_kill_word (-count);
- else
- {
- rl_forward_word (count);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
-
- rl_point = orig_point;
- }
-}
-
-/* Rubout the word before point, placing it on the kill ring. */
-rl_backward_kill_word (count)
-int count;
-{
- int orig_point = rl_point;
-
- if (count < 0)
- rl_kill_word (-count);
- else
- {
- rl_backward_word (count);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
- }
-}
-
-/* Kill from here to the end of the line. If DIRECTION is negative, kill
- back to the line start instead. */
-rl_kill_line (direction)
-int direction;
-{
- int orig_point = rl_point;
-
- if (direction < 0)
- rl_backward_kill_line (1);
- else
- {
- rl_end_of_line ();
- if (orig_point != rl_point)
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- }
-}
-
-/* Kill backwards to the start of the line. If DIRECTION is negative, kill
- forwards to the line end instead. */
-rl_backward_kill_line (direction)
-int direction;
-{
- int orig_point = rl_point;
-
- if (direction < 0)
- rl_kill_line (1);
- else
- {
- if (!rl_point)
- ding ();
- else
- {
- rl_beg_of_line ();
- rl_kill_text (orig_point, rl_point);
- }
- }
-}
-
-/* Yank back the last killed text. This ignores arguments. */
-rl_yank ()
-{
- if (!rl_kill_ring) rl_abort ();
- rl_insert_text (rl_kill_ring[rl_kill_index]);
-}
-
-/* If the last command was yank, or yank_pop, and the text just
- before point is identical to the current kill item, then
- delete that text from the line, rotate the index down, and
- yank back some other text. */
-rl_yank_pop ()
-{
- int l;
-
- if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
- !rl_kill_ring)
- {
- rl_abort ();
- }
-
- l = strlen (rl_kill_ring[rl_kill_index]);
- if (((rl_point - l) >= 0) &&
- (strncmp (the_line + (rl_point - l),
- rl_kill_ring[rl_kill_index], l) == 0))
- {
- rl_delete_text ((rl_point - l), rl_point);
- rl_point -= l;
- rl_kill_index--;
- if (rl_kill_index < 0)
- rl_kill_index = rl_kill_ring_length - 1;
- rl_yank ();
- }
- else
- rl_abort ();
-
-}
-
-extern char *extracthistarg();
-
-/* Yank the COUNTth argument from the previous history line. */
-rl_yank_nth_arg (count, ignore)
-int count;
-{
-char *arg;
-
- arg = extracthistarg(count);
- if (!arg || !*arg)
- {
- ding ();
- return;
- }
-
- rl_begin_undo_group ();
- if (rl_point && the_line[rl_point - 1] != ' ')
- rl_insert_text (" ");
- rl_insert_text (arg);
- free (arg);
- rl_end_undo_group ();
-}
-
-/* Vi Mode. */
-#ifdef VI_MODE
-#include "vi_mode.c"
-#endif /* VI_MODE */
-
-/* How to toggle back and forth between editing modes. */
-rl_vi_editing_mode ()
-{
-#ifdef VI_MODE
- rl_editing_mode = vi_mode;
- rl_vi_insertion_mode ();
-#endif /* VI_MODE */
-}
-
-rl_emacs_editing_mode ()
-{
- rl_editing_mode = emacs_mode;
- keymap = emacs_standard_keymap;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Completion */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means that case is not significant in completion. */
-int completion_case_fold = 0;
-
-/* Return an array of (char *) which is a list of completions for TEXT.
- If there are no completions, return a NULL pointer.
- The first entry in the returned array is the substitution for TEXT.
- The remaining entries are the possible completions.
- The array is terminated with a NULL pointer.
-
- ENTRY_FUNCTION is a function of two args, and returns a (char *).
- The first argument is TEXT.
- The second is a state argument; it should be zero on the first call, and
- non-zero on subsequent calls. It returns a NULL pointer to the caller
- when there are no more matches.
- */
-char **
-completion_matches (text, entry_function)
-char *text;
-char *(*entry_function) ();
-{
- /* Number of slots in match_list. */
- int match_list_size;
-
- /* The list of matches. */
- char **match_list =
- (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *));
-
- /* Number of matches actually found. */
- int matches = 0;
-
- /* Temporary string binder. */
- char *string;
-
- match_list[1] = (char *)NULL;
-
- while (string = (*entry_function) (text, matches))
- {
- if (matches + 1 == match_list_size)
- match_list =
- (char **)xrealloc (match_list,
- ((match_list_size += 10) + 1) * sizeof (char *));
-
- match_list[++matches] = string;
- match_list[matches + 1] = (char *)NULL;
- }
-
- /* If there were any matches, then look through them finding out the
- lowest common denominator. That then becomes match_list[0]. */
- if (matches)
- {
- register int i = 1;
- int low = 100000; /* Count of max-matched characters. */
-
- /* If only one match, just use that. */
- if (matches == 1)
- {
- match_list[0] = match_list[1];
- match_list[1] = (char *)NULL;
- }
- else
- {
- /* Otherwise, compare each member of the list with
- the next, finding out where they stop matching. */
-
- while (i < matches)
- {
- register int c1, c2, si;
-
- if (completion_case_fold)
- {
- for (si = 0;
- (c1 = to_lower(match_list[i][si])) &&
- (c2 = to_lower(match_list[i + 1][si]));
- si++)
- if (c1 != c2) break;
- }
- else
- {
- for (si = 0;
- (c1 = match_list[i][si]) &&
- (c2 = match_list[i + 1][si]);
- si++)
- if (c1 != c2) break;
- }
-
- if (low > si) low = si;
- i++;
- }
- match_list[0] = (char *)xmalloc (low + 1);
- strncpy (match_list[0], match_list[1], low);
- match_list[0][low] = '\0';
- }
- }
- else /* There were no matches. */
- {
- free (match_list);
- match_list = (char **)NULL;
- }
- return (match_list);
-}
-
-/* Okay, now we write the entry_function for filename completion. In the
- general case. Note that completion in the shell is a little different
- because of all the pathnames that must be followed when looking up the
- completion for a command. */
-char *
-filename_completion_function (text, state)
-int state;
-char *text;
-{
- static DIR *directory;
- static char *filename = (char *)NULL;
- static char *dirname = (char *)NULL;
- static char *users_dirname = (char *)NULL;
- static int filename_len;
-
- struct direct *entry = (struct direct *)NULL;
-
- /* If we don't have any state, then do some initialization. */
- if (!state)
- {
- char *rindex (), *temp;
-
- if (dirname) free (dirname);
- if (filename) free (filename);
- if (users_dirname) free (users_dirname);
-
- filename = savestring (text);
- if (!*text) text = ".";
- dirname = savestring (text);
-
- temp = rindex (dirname, '/');
-
- if (temp)
- {
- strcpy (filename, ++temp);
- *temp = '\0';
- }
- else
- strcpy (dirname, ".");
-
- /* We aren't done yet. We also support the "~user" syntax. */
-
- /* Save the version of the directory that the user typed. */
- users_dirname = savestring (dirname);
- directory = opendir (dirname);
- filename_len = strlen (filename);
-
- rl_filename_completion_desired = 1;
- }
-
- /* At this point we should entertain the possibility of hacking wildcarded
- filenames, like /usr/man*\/te<TAB>. If the directory name contains
- globbing characters, then build an array of directories to glob on, and
- glob on the first one. */
-
- /* Now that we have some state, we can read the directory. */
-
- while (directory && (entry = readdir (directory)))
- {
- /* Special case for no filename.
- All entries except "." and ".." match. */
- if (!filename_len)
- {
- if ((strcmp (entry->d_name, ".") != 0) &&
- (strcmp (entry->d_name, "..") != 0))
- break;
- }
- else
- {
- /* Otherwise, if these match upto the length of filename, then
- it is a match. */
-#ifdef TMB_SYSV
- if ((strlen (entry->d_name) >= filename_len) &&
- (strncmp (filename, entry->d_name, filename_len) == 0))
-#else
- if ((entry->d_namlen >= filename_len) &&
- (strncmp (filename, entry->d_name, filename_len) == 0))
-#endif /* TMB_SYSV */
- {
- break;
- }
- }
- }
-
- if (!entry)
- {
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- return (char *)NULL;
- }
- else
- {
- char *temp;
-
- if (dirname && (strcmp (dirname, ".") != 0))
- {
-#ifdef TMB_SYSV
- temp = (char *)xmalloc (1 + strlen (users_dirname)
- + strlen (entry->d_name));
-#else
- temp = (char *)xmalloc (1 + strlen (users_dirname)
- + entry->d_namlen);
-#endif /* TMB_SYSV */
- strcpy (temp, users_dirname);
- strcat (temp, entry->d_name);
- }
- else
- {
- temp = (savestring (entry->d_name));
- }
- return (temp);
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* Binding keys */
-/* */
-/* **************************************************************** */
-
-/* rl_add_defun (char *name, Function *function, int key)
- Add NAME to the list of named functions. Make FUNCTION
- be the function that gets called.
- If KEY is not -1, then bind it. */
-rl_add_defun (name, function, key)
-char *name;
-Function *function;
-int key;
-{
- if (key != -1)
- rl_bind_key (key, function);
- rl_add_funmap_entry (name, function);
-}
-
-/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
-int
-rl_bind_key (key, function)
-int key;
-Function *function;
-{
- if (key < 0)
- return (key);
-
- if (key > 127 && key < 256)
- {
- if (keymap[ESC].type == ISKMAP)
- {
- Keymap escmap = (Keymap)keymap[ESC].function;
-
- key -= 128;
- escmap[key].type = ISFUNC;
- escmap[key].function = function;
- return (0);
- }
- return (key);
- }
-
- keymap[key].type = ISFUNC;
- keymap[key].function = function;
- return (0);
-}
-
-/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid
- KEY. */
-int
-rl_bind_key_in_map (key, function, map)
-int key;
-Function *function;
-Keymap map;
-{
- int result;
- Keymap oldmap = keymap;
-
- keymap = map;
- result = rl_bind_key (key, function);
- keymap = oldmap;
- return (result);
-}
-
-/* Make KEY do nothing in the currently selected keymap.
- Returns non-zero in case of error. */
-int
-rl_unbind_key (key)
-int key;
-{
- return (rl_bind_key (key, (Function *)NULL));
-}
-
-/* Make KEY do nothing in MAP.
- Returns non-zero in case of error. */
-int
-rl_unbind_key_in_map (key, map)
-int key;
-Keymap map;
-{
- return (rl_bind_key_in_map (key, (Function *)NULL, map));
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- FUNCTION. This makes new keymaps as necessary. The initial
- place to do bindings is in MAP. */
-rl_set_key (keyseq, function, map)
-char *keyseq;
-Function *function;
-Keymap map;
-{
- rl_generic_bind (ISFUNC, keyseq, function, map);
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- the string of characters MACRO. This makes new keymaps as
- necessary. The initial place to do bindings is in MAP. */
-rl_macro_bind (keyseq, macro, map)
-char *keyseq, *macro;
-Keymap map;
-{
- char *macro_keys = (char *)xmalloc (2 * (strlen (macro)));
- int macro_keys_len;
-
- if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len))
- {
- free (macro_keys);
- return;
- }
- rl_generic_bind (ISMACR, keyseq, macro_keys, map);
-}
-
-/* Bind the key sequence represented by the string KEYSEQ to
- the arbitrary pointer DATA. TYPE says what kind of data is
- pointed to by DATA, right now this can be a function (ISFUNC),
- a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps
- as necessary. The initial place to do bindings is in MAP. */
-rl_generic_bind (type, keyseq, data, map)
-int type;
-char *keyseq, *data;
-Keymap map;
-{
- char *keys;
- int keys_len;
- register int i;
-
- /* If no keys to bind to, exit right away. */
- if (!keyseq || !*keyseq)
- {
- if (type == ISMACR)
- free (data);
- return;
- }
-
- keys = (char *)alloca (1 + (2 * strlen (keyseq)));
-
- /* Translate the ASCII representation of KEYSEQ into an array
- of characters. Stuff the characters into ARRAY, and the
- length of ARRAY into LENGTH. */
- if (rl_translate_keyseq (keyseq, keys, &keys_len))
- return;
-
- /* Bind keys, making new keymaps as necessary. */
- for (i = 0; i < keys_len; i++)
- {
- if (i + 1 < keys_len)
- {
- if (map[keys[i]].type != ISKMAP)
- {
- if (map[i].type == ISMACR)
- free ((char *)map[i].function);
-
- map[keys[i]].type = ISKMAP;
- map[keys[i]].function = (Function *)rl_make_bare_keymap ();
- }
- map = (Keymap)map[keys[i]].function;
- }
- else
- {
- if (map[keys[i]].type == ISMACR)
- free ((char *)map[keys[i]].function);
-
- map[keys[i]].function = (Function *)data;
- map[keys[i]].type = type;
- }
- }
-}
-
-/* Translate the ASCII representation of SEQ, stuffing the
- values into ARRAY, an array of characters. LEN gets the
- final length of ARRAY. Return non-zero if there was an
- error parsing SEQ. */
-rl_translate_keyseq (seq, array, len)
-char *seq, *array;
-int *len;
-{
- register int i, c, l = 0;
-
- for (i = 0; c = seq[i]; i++)
- {
- if (c == '\\')
- {
- c = seq[++i];
-
- if (!c)
- break;
-
- if (((c == 'C' || c == 'M') && seq[i + 1] == '-') ||
- (c == 'e'))
- {
- /* Handle special case of backwards define. */
- if (strncmp (&seq[i], "C-\\M-", 5) == 0)
- {
- array[l++] = ESC;
- i += 5;
- array[l++] = CTRL (to_upper (seq[i]));
- if (!seq[i])
- i--;
- continue;
- }
-
- switch (c)
- {
- case 'M':
- i++;
- array[l++] = ESC;
- break;
-
- case 'C':
- i += 2;
- array[l++] = CTRL (to_upper (seq[i]));
- break;
-
- case 'e':
- array[l++] = ESC;
- }
-
- continue;
- }
- }
- array[l++] = c;
- }
-
- *len = l;
- array[l] = '\0';
- return (0);
-}
-
-/* Return a pointer to the function that STRING represents.
- If STRING doesn't have a matching function, then a NULL pointer
- is returned. */
-Function *
-rl_named_function (string)
-char *string;
-{
- register int i;
-
- for (i = 0; funmap[i]; i++)
- if (stricmp (funmap[i]->name, string) == 0)
- return (funmap[i]->function);
- return ((Function *)NULL);
-}
-
---cut here---cut here---cut here---pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (12/15/90)
---cut here---cut here---cut here---
-/* The last key bindings file read. */
-static char *last_readline_init_file = "~/.inputrc";
-
-/* Re-read the current keybindings file. */
-rl_re_read_init_file (count, ignore)
-int count, ignore;
-{
- rl_read_init_file (last_readline_init_file);
-}
-
-/* Do key bindings from a file. If FILENAME is NULL it defaults
- to `~/.inputrc'. If the file existed and could be opened and
- read, 0 is returned, otherwise errno is returned. */
-int
-rl_read_init_file (filename)
-char *filename;
-{
- extern int errno;
- int line_size, line_index;
- char *line = (char *)xmalloc (line_size = 100);
- char *openname;
- FILE *file;
-
- int c;
-
- /* Default the filename. */
- if (!filename)
- filename = "~/.inputrc";
-
- openname = tilde_expand (filename);
-
- /* Open the file. */
- file = fopen (openname, "r");
- free (openname);
-
- if (!file)
- return (errno);
-
- last_readline_init_file = filename;
-
- /* Loop reading lines from the file. Lines that start with `#' are
- comments, all other lines are commands for readline initialization. */
- while ((c = rl_getc (file)) != EOF)
- {
- /* If comment, flush to EOL. */
- if (c == '#')
- {
- while ((c = rl_getc (file)) != EOF && c != '\n');
- if (c == EOF)
- goto function_exit;
- continue;
- }
-
- /* Otherwise, this is the start of a line. Read the
- line from the file. */
- line_index = 0;
- while (c != EOF && c != '\n')
- {
- line[line_index++] = c;
- if (line_index == line_size)
- line = (char *)xrealloc (line, line_size += 100);
- c = rl_getc (file);
- }
- line[line_index] = '\0';
-
- /* Parse the line. */
- rl_parse_and_bind (line);
- }
-
-function_exit:
-
- free (line);
- /* Close up the file and exit. */
- fclose (file);
- return (0);
-}
-
-
-/* **************************************************************** */
-/* */
-/* Parser Directives */
-/* */
-/* **************************************************************** */
-
-/* Conditionals. */
-
-/* Calling programs set this to have their argv[0]. */
-char *rl_readline_name = "other";
-
-/* Stack of previous values of parsing_conditionalized_out. */
-static unsigned char *if_stack = (unsigned char *)NULL;
-static int if_stack_depth = 0;
-static int if_stack_size = 0;
-
-/* Push parsing_conditionalized_out, and set parser state based on ARGS. */
-parser_if (args)
-char *args;
-{
- register int i;
-
- /* Push parser state. */
- if (if_stack_depth + 1 >= if_stack_size)
- {
- if (!if_stack)
- if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
- else
- if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
- }
- if_stack[if_stack_depth++] = parsing_conditionalized_out;
-
- /* We only check to see if the first word in ARGS is the same as the
- value stored in rl_readline_name. */
-
- /* Isolate first argument. */
- for (i = 0; args[i] && !whitespace (args[i]); i++);
-
- if (args[i])
- args[i++] = '\0';
-
- if (stricmp (args, rl_readline_name) == 0)
- parsing_conditionalized_out = 0;
- else
- parsing_conditionalized_out = 1;
-}
-
-/* Invert the current parser state if there is anything on the stack. */
-parser_else (args)
-char *args;
-{
- if (if_stack_depth)
- parsing_conditionalized_out = !parsing_conditionalized_out;
- else
- {
- /* *** What, no error message? *** */
- }
-}
-
-/* Terminate a conditional, popping the value of
- parsing_conditionalized_out from the stack. */
-parser_endif (args)
-char *args;
-{
- if (if_stack_depth)
- parsing_conditionalized_out = if_stack[--if_stack_depth];
- else
- {
- /* *** What, no error message? *** */
- }
-}
-
-/* Associate textual names with actual functions. */
-static struct {
- char *name;
- Function *function;
-} parser_directives [] = {
- { "if", parser_if },
- { "endif", parser_endif },
- { "else", parser_else },
- { (char *)0x0, (Function *)0x0 }
-};
-
-
-/* Handle a parser directive. STATEMENT is the line of the directive
- without any leading `$'. */
-static int
-handle_parser_directive (statement)
-char *statement;
-{
- register int i;
- char *directive, *args;
-
- /* Isolate the actual directive. */
-
- /* Skip whitespace. */
- for (i = 0; whitespace (statement[i]); i++);
-
- directive = &statement[i];
-
- for (; statement[i] && !whitespace (statement[i]); i++);
-
- if (statement[i])
- statement[i++] = '\0';
-
- for (; statement[i] && whitespace (statement[i]); i++);
-
- args = &statement[i];
-
- /* Lookup the command, and act on it. */
- for (i = 0; parser_directives[i].name; i++)
- if (stricmp (directive, parser_directives[i].name) == 0)
- {
- (*parser_directives[i].function) (args);
- return (0);
- }
-
- /* *** Should an error message be output? */
- return (1);
-}
-
-/* Read the binding command from STRING and perform it.
- A key binding command looks like: Keyname: function-name\0,
- a variable binding command looks like: set variable value.
- A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
-rl_parse_and_bind (string)
-char *string;
-{
- extern char *possible_control_prefixes[], *possible_meta_prefixes[];
- char *rindex (), *funname, *kname;
- static int substring_member_of_array ();
- register int c;
- int key, i;
-
- if (!string || !*string || *string == '#')
- return;
-
- /* If this is a parser directive, act on it. */
- if (*string == '$')
- {
- handle_parser_directive (&string[1]);
- return;
- }
-
- /* If we are supposed to be skipping parsing right now, then do it. */
- if (parsing_conditionalized_out)
- return;
-
- i = 0;
- /* If this keyname is a complex key expression surrounded by quotes,
- advance to after the matching close quote. */
- if (*string == '"')
- {
- for (i = 1; c = string[i]; i++)
- {
- if (c == '"' && string[i - 1] != '\\')
- break;
- }
- }
-
- /* Advance to the colon (:) or whitespace which separates the two objects. */
- for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
-
- /* Mark the end of the command (or keyname). */
- if (string[i])
- string[i++] = '\0';
-
- /* If this is a command to set a variable, then do that. */
- if (stricmp (string, "set") == 0)
- {
- char *var = string + i;
- char *value;
-
- /* Make VAR point to start of variable name. */
- while (*var && whitespace (*var)) var++;
-
- /* Make value point to start of value string. */
- value = var;
- while (*value && !whitespace (*value)) value++;
- if (*value)
- *value++ = '\0';
- while (*value && whitespace (*value)) value++;
-
- rl_variable_bind (var, value);
- return;
- }
-
- /* Skip any whitespace between keyname and funname. */
- for (; string[i] && whitespace (string[i]); i++);
- funname = &string[i];
-
- /* Now isolate funname.
- For straight function names just look for whitespace, since
- that will signify the end of the string. But this could be a
- macro definition. In that case, the string is quoted, so skip
- to the matching delimiter. */
- if (*funname == '\'' || *funname == '"')
- {
- int delimiter = string[i++];
-
- for (; c = string[i]; i++)
- {
- if (c == delimiter && string[i - 1] != '\\')
- break;
- }
- if (c)
- i++;
- }
-
- /* Advance to the end of the string. */
- for (; string[i] && !whitespace (string[i]); i++);
-
- /* No extra whitespace at the end of the string. */
- string[i] = '\0';
-
- /* If this is a new-style key-binding, then do the binding with
- rl_set_key (). Otherwise, let the older code deal with it. */
- if (*string == '"')
- {
- char *seq = (char *)alloca (1 + strlen (string));
- register int j, k = 0;
-
- for (j = 1; string[j]; j++)
- {
- if (string[j] == '"' && string[j - 1] != '\\')
- break;
-
- seq[k++] = string[j];
- }
- seq[k] = '\0';
-
- /* Binding macro? */
- if (*funname == '\'' || *funname == '"')
- {
- j = strlen (funname);
-
- if (j && funname[j - 1] == *funname)
- funname[j - 1] = '\0';
-
- rl_macro_bind (seq, &funname[1], keymap);
- }
- else
- rl_set_key (seq, rl_named_function (funname), keymap);
-
- return;
- }
-
- /* Get the actual character we want to deal with. */
- kname = rindex (string, '-');
- if (!kname)
- kname = string;
- else
- kname++;
-
- key = glean_key_from_name (kname);
-
- /* Add in control and meta bits. */
- if (substring_member_of_array (string, possible_control_prefixes))
- key = CTRL (to_upper (key));
-
- if (substring_member_of_array (string, possible_meta_prefixes))
- key = META (key);
-
- /* Temporary. Handle old-style keyname with macro-binding. */
- if (*funname == '\'' || *funname == '"')
- {
- char seq[2];
- int fl = strlen (funname);
-
- seq[0] = key;
- seq[1] = '\0';
- if (fl && funname[fl - 1] == *funname)
- funname[fl - 1] = '\0';
-
- rl_macro_bind (seq, &funname[1], keymap);
- }
- else
- rl_bind_key (key, rl_named_function (funname));
-}
-
-rl_variable_bind (name, value)
-char *name, *value;
-{
- if (stricmp (name, "editing-mode") == 0)
- {
- if (strnicmp (value, "vi", 2) == 0)
- {
-#ifdef VI_MODE
- keymap = vi_insertion_keymap;
- rl_editing_mode = vi_mode;
-#endif /* VI_MODE */
- }
- else if (strnicmp (value, "emacs", 5) == 0)
- {
- keymap = emacs_standard_keymap;
- rl_editing_mode = emacs_mode;
- }
- }
- else if (stricmp (name, "horizontal-scroll-mode") == 0)
- {
- if (!*value || stricmp (value, "On") == 0)
- horizontal_scroll_mode = 1;
- else
- horizontal_scroll_mode = 0;
- }
-}
-
-/* Return the character which matches NAME.
- For example, `Space' returns ' '. */
-
-typedef struct {
- char *name;
- int value;
-} assoc_list;
-
-assoc_list name_key_alist[] = {
- { "Space", ' ' },
- { "SPC", ' ' },
- { "Rubout", 0x7f },
- { "DEL", 0x7f },
- { "Tab", 0x09 },
- { "Newline", '\n' },
- { "Return", '\r' },
- { "RET", '\r' },
- { "LFD", '\n' },
- { "Escape", '\033' },
- { "ESC", '\033' },
- { (char *)0x0, 0 }
-};
-
-
-int
-glean_key_from_name (name)
-char *name;
-{
- register int i;
-
- for (i = 0; name_key_alist[i].name; i++)
- if (stricmp (name, name_key_alist[i].name) == 0)
- return (name_key_alist[i].value);
-
- return (*name);
-}
-
-
-/* **************************************************************** */
-/* */
-/* String Utility Functions */
-/* */
-/* **************************************************************** */
-
-/* Return non-zero if any members of ARRAY are a substring in STRING. */
-static int
-substring_member_of_array (string, array)
-char *string, **array;
-{
- static char *strindex ();
-
- while (*array)
- {
- if (strindex (string, *array))
- return (1);
- array++;
- }
- return (0);
-}
-
-/* Whoops, Unix doesn't have strnicmp. */
-
-/* Compare at most COUNT characters from string1 to string2. Case
- doesn't matter. */
-static int
-strnicmp (string1, string2, count)
-char *string1, *string2;
-{
- register char ch1, ch2;
-
- while (count)
- {
- ch1 = *string1++;
- ch2 = *string2++;
- if (to_upper(ch1) == to_upper(ch2))
- count--;
- else break;
- }
- return (count);
-}
-
-/* strcmp (), but caseless. */
-static int
-stricmp (string1, string2)
-char *string1, *string2;
-{
- register char ch1, ch2;
-
- while (*string1 && *string2)
- {
- ch1 = *string1++;
- ch2 = *string2++;
- if (to_upper(ch1) != to_upper(ch2))
- return (1);
- }
- return (*string1 | *string2);
-}
-
-/* Determine if s2 occurs in s1. If so, return a pointer to the
- match in s1. The compare is case insensitive. */
-static char *
-strindex (s1, s2)
-register char *s1, *s2;
-{
- register int i, l = strlen (s2);
- register int len = strlen (s1);
-
- for (i = 0; (len - i) >= l; i++)
- if (strnicmp (&s1[i], s2, l) == 0)
- return (s1 + i);
- return ((char *)NULL);
-}
-
-
-/* **************************************************************** */
-/* */
-/* SYSV Support */
-/* */
-/* **************************************************************** */
-
-/* Since system V reads input differently than we do, I have to
- make a special version of getc for that. */
-
-#include <sys/errno.h>
-
-int
-rl_getc (stream)
-FILE *stream;
-{
- int result;
- unsigned char c;
-
- rl_waiting = 1;
- result = read (fileno (stream), &c, sizeof (char));
- rl_waiting = 0;
- if (result == sizeof (char))
- return (c);
-
- if (errno != EINTR)
- return EOF;
- rl_done = rl_end = errflag = 1;
- return EOF;
-}
-
-#ifdef STATIC_MALLOC
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static void memory_error_and_abort ();
-
-static char *
-xmalloc (bytes)
-int bytes;
-{
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
-char *pointer;
-int bytes;
-{
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static void
-memory_error_and_abort ()
-{
- fprintf (stderr, "readline: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
-/*
- * Local variables:
- * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
- * end:
- */
-
-rl_function_key(count) /* pjf */
-{
- switch(rl_getc(rl_instream))
- {
- case 'A':
- rl_get_previous_history(count);
- break;
- case 'B':
- rl_get_next_history(count);
- break;
- case 'C':
- rl_forward(count);
- break;
- case 'D':
- rl_backward(count);
- break;
- default:
- ding();
- break;
- }
-}
-
-static char *spname();
-
-rl_check_spelling()
-{
- char *match;
- int start, end, delimiter = 0;
- char *text;
-
- /* We now look backwards for the start of a filename/variable word. */
- end = rl_point;
- if (rl_point)
- {
- while (--rl_point &&
- !rindex (rl_completer_word_break_characters, the_line[rl_point]));
-
- /* If we are at a word break, then advance past it. */
- if (rindex (rl_completer_word_break_characters, (the_line[rl_point])))
- {
- /* If the character that caused the word break was a quoting
- character, then remember it as the delimiter. */
- if (rindex ("\"'", the_line[rl_point]) && (end - rl_point) > 1)
- delimiter = the_line[rl_point];
-
- /* If the character isn't needed to determine something special
- about what kind of completion to perform, then advance past it. */
-
- if (!rl_special_prefixes ||
- !rindex (rl_special_prefixes, the_line[rl_point]))
- rl_point++;
- }
- }
-
- start = rl_point;
- rl_point = end;
- text = rl_copy (start, end);
-
- match = spname(text);
-
- free (text);
-
- if (!match)
- ding ();
- else
- {
- rl_delete_text (start, rl_point);
- rl_point = start;
- rl_insert_text (match);
- }
-}
-
-/* next 3 functions stolen from Kernighan & Pike */
-/* "The UNIX Programming Environment" (w/o permission) */
-
-static char *spname (oldname) char *oldname;
-{
- char *p,guess[MAXPATHLEN+1],best[MAXPATHLEN+1];
- char newname[MAXPATHLEN+1];
- char *new = newname, *old = oldname;
-
- for (;;)
- {
- while (*old == '/')
- *new++ = *old++;
- *new = '\0';
- if (*old == '\0')
- return newname;
- p = guess;
- for (; *old != '/' && *old != '\0'; old++)
- if (p < guess+MAXPATHLEN)
- *p++ = *old;
- *p = '\0';
- if (mindist(newname,guess,best) >= 3)
- return oldname;
- for (p = best; *new = *p++; )
- new++;
- }
-}
-
-mindist(dir,guess,best) char *dir,*guess,*best;
-{
- int d,nd;
- DIR *dd;
- struct direct *de;
-
- if (dir[0] == '\0')
- dir = ".";
- d = 3;
- if (!(dd = opendir(dir)))
- return d;
- while (de = readdir(dd))
- {
- nd = spdist(de->d_name,guess);
- if (nd <= d && nd != 3) {
- strcpy(best,de->d_name);
- d = nd;
- if (d == 0)
- break;
- }
- }
- closedir(dd);
- return d;
-}
-
-#define EQ(s,t) (strcmp(s,t) == 0)
-
-spdist(s,t) char *s, *t;
-{
- while (*s++ == *t)
- if (*t++ == '\0')
- return 0;
- if (*--s)
- {
- if (*t)
- {
- if (s[1] && t[1] && *s == t[1] && *t == s[1] &&
- EQ(s+2,t+2))
- return 1;
- if (EQ(s+1,t+1))
- return 2;
- }
- if (EQ(s+1,t))
- return 2;
- }
- if (*t && EQ(s,t+1))
- return 2;
- return 3;
-}
-
-char *strpbrk(s,t) char *s,*t;
-{
- char *u = t;
-
- while (*s)
- {
- for (t = u; *t; t++)
- if (*s == *t)
- return s;
- s++;
- }
- return NULL;
-}
-
-void rl_safe_insert_text(s) char *s;
-{
- char *bad = " \\!#$^*()|=[]{}`\'\";?><";
- char *t;
-
- for(;;)
- if (t = strpbrk(s,bad))
- {
- char a = *t;
-
- *t = '\0';
- rl_insert_text(s);
- rl_insert_text("\\");
- *t = a;
- a = t[1];
- t[1] = '\0';
- rl_insert_text(t);
- t[1] = a;
- s = t+1;
- }
- else
- {
- rl_insert_text(s);
- return;
- }
-}
-
-#define HERR -125
-
-extern int magic;
-char *strdup();
-int hgetc();
-
-rl_magic_space ()
-{
- int c,pt = 0;
- char *str;
-
- the_line[rl_end] = '\0'; /* necessary? */
- str = strdup(the_line);
- strinbeg();
- magic = 1;
- hungets(strdup("\n"));
- hungets(strdup(the_line));
- while ((c = hgetc()) != EOF)
- {
- if (c == HERR)
- {
- strcpy(the_line,str);
- free(str);
- hflush();
- magic = 0;
- strinend();
- rl_on_new_line();
- rl_redisplay();
- return 0;
- }
- if (c == '!')
- the_line[pt++] = '\\';
- the_line[pt++] = c;
- }
- if (!pt)
- fprintf(stderr,"Whoops.\n");
- the_line[rl_end = rl_point = pt-1] = '\0';
- magic = 0;
- strinend();
- free(str);
-}
End of readline/readline.c
echo readline/readline.h 1>&2
sed 's/^-//' >readline/readline.h <<'End of readline/readline.h'
-/* Readline.h -- the names of functions callable from within readline. */
-
-#ifndef _READLINE_H_
-#define _READLINE_H_
-
-#include <readline/keymaps.h>
-
-#ifndef __FUNCTION_DEF
-typedef int Function ();
-#define __FUNCTION_DEF
-#endif
-
-/* The functions for manipulating the text of the line within readline.
-Most of these functions are bound to keys by default. */
-extern int
-rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
-rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
-rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
-rl_quoted_insert (), rl_transpose_chars
-(), rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout
-(), rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
-rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
-rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words
-(), rl_complete (), rl_possible_completions (), rl_do_lowercase_version
-(), rl_digit_argument (), rl_universal_argument (), rl_abort (),
-rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
-rl_end_of_history (), rl_insert (),
-rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
-rl_restart_output (), rl_re_read_init_file ();
-
-extern int rl_function_key(); /* pjf */
-extern int rl_check_spelling(),rl_magic_space();
-extern int rl_break_c();
-
-/* These are *both* defined even when VI_MODE is not. */
-extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
-
-#ifdef VI_MODE
-/* Things for vi mode. */
-extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
-rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
-rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
-rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
-rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
-rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
-rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), rl_vi_change_char (),
-rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
-rl_vi_dosearch (), rl_vi_subst (), rl_vi_overstrike (),
-rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
-rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), rl_vi_complete ();
-#endif /* VI_MODE */
-
-/* Keyboard macro commands. */
-extern int
-rl_start_kbd_macro (), rl_end_kbd_macro (), rl_call_last_kbd_macro ();
-
-/* Maintaining the state of undo. We remember individual deletes and inserts
- on a chain of things to do. */
-
-/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
- to insert some text, and UNDO_INSERT means to delete some text. I.e.,
- the code tells undo what to undo, not how to undo it. */
-enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
-
-/* What an element of THE_UNDO_LIST looks like. */
-typedef struct undo_list {
- struct undo_list *next;
- int start, end; /* Where the change took place. */
- char *text; /* The text to insert, if undoing a delete. */
- enum undo_code what; /* Delete, Insert, Begin, End. */
-} UNDO_LIST;
-
-/* The current undo list for RL_LINE_BUFFER. */
-extern UNDO_LIST *rl_undo_list;
-
-/* The data structure for mapping textual names to code addresses. */
-typedef struct {
- char *name;
- Function *function;
-} FUNMAP;
-
-extern FUNMAP **funmap;
-
-/* **************************************************************** */
-/* */
-/* Well Published Variables */
-/* */
-/* **************************************************************** */
-
-/* The name of the calling program. You should initialize this to
- whatever was in argv[0]. It is used when parsing conditionals. */
-extern char *rl_readline_name;
-
-/* The line buffer that is in use. */
-extern char *rl_line_buffer;
-
-/* The location of point, and end. */
-extern int rl_point, rl_end;
-
-/* The name of the terminal to use. */
-extern char *rl_terminal_name;
-
-/* The input and output streams. */
-extern FILE *rl_instream, *rl_outstream;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The contents of this variable is what breaks words
- in the shell, i.e. "n\"\\'`@$>". */
-extern char *rl_basic_word_break_characters;
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-extern char *rl_completer_word_break_characters;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-extern char *rl_special_prefixes;
-
-/* Pointer to the generator function for completion_matches ().
- NULL means to use filename_entry_function (), the default filename
- completer. */
-extern Function *rl_completion_entry_function;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-extern Function *rl_attempted_completion_function;
-
-/* If non-null, this contains the address of a function to call if the
- standard meaning for expanding a tilde fails. The function is called
- with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
- which is the expansion, or a NULL pointer if there is no expansion. */
-extern Function *rl_tilde_expander;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal () prints the first prompt. */
-extern Function *rl_startup_hook;
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
-extern Function *rl_symbolic_link_hook;
-
-/* Non-zero means that modified history lines are preceded
- with an asterisk. */
-extern int rl_show_star;
-
-/* **************************************************************** */
-/* */
-/* Well Published Functions */
-/* */
-/* **************************************************************** */
-
-/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
-extern char *readline ();
-
-/* Return an array of strings which are the result of repeatadly calling
- FUNC with TEXT. */
-extern char **completion_matches ();
-
-/* rl_add_defun (char *name, Function *function, int key)
- Add NAME to the list of named functions. Make FUNCTION
- be the function that gets called.
- If KEY is not -1, then bind it. */
-extern int rl_add_defun ();
-
-
-#endif /* _READLINE_H_ */
-
End of readline/readline.h
echo readline/vi_keymap.c 1>&2
sed 's/^-//' >readline/vi_keymap.c <<'End of readline/vi_keymap.c'
-/* vi_keymap.c -- the keymap for vi_mode in readline (). */
-
-/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Readline, a library for reading lines
- of text with interactive input and history editing.
-
- Readline is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- Readline is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef FILE
-#include <stdio.h>
-#endif /* FILE */
-
-#include "readline.h"
-
-extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
-
-/* The keymap arrays for handling vi mode. */
-KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
-
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
- { ISFUNC, rl_emacs_editing_mode }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, rl_abort }, /* Control-g */
- { ISFUNC, rl_rubout }, /* Control-h */ /* pjf */
- { ISFUNC, (Function *)0x0 }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, rl_clear_screen }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_get_next_history }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, rl_get_previous_history }, /* Control-p */
- { ISFUNC, rl_quoted_insert }, /* Control-q */
- { ISFUNC, (Function *)0x0 }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISFUNC, (Function *)0x0 }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
-
- { ISKMAP, (Function *)vi_escape_keymap }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_undo_command }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_forward }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, rl_vi_comment }, /* # */
- { ISFUNC, rl_end_of_line }, /* $ */
- { ISFUNC, rl_vi_match }, /* % */
- { ISFUNC, (Function *)0x0 }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, (Function *)0x0 }, /* ( */
- { ISFUNC, (Function *)0x0 }, /* ) */
- { ISFUNC, rl_vi_complete }, /* * */
- { ISFUNC, rl_get_next_history}, /* + */
- { ISFUNC, rl_vi_char_search }, /* , */
- { ISFUNC, rl_get_previous_history }, /* - */
- { ISFUNC, (Function *)0x0 }, /* . */
- { ISFUNC, rl_vi_search }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_vi_arg_digit }, /* 0 */
- { ISFUNC, rl_vi_arg_digit }, /* 1 */
- { ISFUNC, rl_vi_arg_digit }, /* 2 */
- { ISFUNC, rl_vi_arg_digit }, /* 3 */
- { ISFUNC, rl_vi_arg_digit }, /* 4 */
- { ISFUNC, rl_vi_arg_digit }, /* 5 */
- { ISFUNC, rl_vi_arg_digit }, /* 6 */
- { ISFUNC, rl_vi_arg_digit }, /* 7 */
- { ISFUNC, rl_vi_arg_digit }, /* 8 */
- { ISFUNC, rl_vi_arg_digit }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, rl_vi_char_search }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, (Function *)0x0 }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, rl_vi_search }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_vi_append_eol }, /* A */
- { ISFUNC, rl_vi_prev_word}, /* B */
- { ISFUNC, rl_vi_change_to }, /* C */
- { ISFUNC, rl_vi_delete_to }, /* D */
- { ISFUNC, rl_vi_end_word }, /* E */
- { ISFUNC, rl_vi_char_search }, /* F */
- { ISFUNC, (Function *)0x0 }, /* G */
- { ISFUNC, (Function *)0x0 }, /* H */
- { ISFUNC, rl_vi_insert_beg }, /* I */
- { ISFUNC, (Function *)0x0 }, /* J */
- { ISFUNC, (Function *)0x0 }, /* K */
- { ISFUNC, (Function *)0x0 }, /* L */
- { ISFUNC, (Function *)0x0 }, /* M */
- { ISFUNC, rl_vi_search_again }, /* N */
- { ISFUNC, (Function *)0x0 }, /* O */
- { ISFUNC, rl_vi_put }, /* P */
- { ISFUNC, (Function *)0x0 }, /* Q */
- { ISFUNC, rl_vi_replace }, /* R */
- { ISFUNC, rl_vi_subst }, /* S */
- { ISFUNC, rl_vi_char_search }, /* T */
- { ISFUNC, rl_revert_line }, /* U */
- { ISFUNC, (Function *)0x0 }, /* V */
- { ISFUNC, rl_vi_next_word }, /* W */
- { ISFUNC, rl_rubout }, /* X */
- { ISFUNC, rl_vi_yank_to }, /* Y */
- { ISFUNC, (Function *)0x0 }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* [ */
- { ISFUNC, (Function *)0x0 }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, rl_vi_first_print }, /* ^ */
- { ISFUNC, rl_vi_yank_arg }, /* _ */
- { ISFUNC, (Function *)0x0 }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_vi_append_mode }, /* a */
- { ISFUNC, rl_vi_prev_word }, /* b */
- { ISFUNC, rl_vi_change_to }, /* c */
- { ISFUNC, rl_vi_delete_to }, /* d */
- { ISFUNC, rl_vi_end_word }, /* e */
- { ISFUNC, rl_vi_char_search }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, rl_backward }, /* h */
- { ISFUNC, rl_vi_insertion_mode }, /* i */
- { ISFUNC, rl_get_next_history }, /* j */
- { ISFUNC, rl_get_previous_history }, /* k */
- { ISFUNC, rl_forward }, /* l */
- { ISFUNC, (Function *)0x0 }, /* m */
- { ISFUNC, rl_vi_search_again }, /* n */
- { ISFUNC, (Function *)0x0 }, /* o */
- { ISFUNC, rl_vi_put }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, rl_vi_change_char }, /* r */
- { ISFUNC, rl_vi_subst }, /* s */
- { ISFUNC, rl_vi_char_search }, /* t */
- { ISFUNC, rl_undo_command }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, rl_vi_next_word }, /* w */
- { ISFUNC, rl_vi_delete }, /* x */
- { ISFUNC, rl_vi_yank_to }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, rl_vi_column }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, rl_vi_change_case }, /* ~ */
- { ISFUNC, rl_backward } /* RUBOUT */
-};
-
-
-KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
-
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, rl_insert }, /* Control-a */
- { ISFUNC, rl_insert }, /* Control-b */
- { ISFUNC, rl_insert }, /* Control-c */
- { ISFUNC, rl_vi_eof_maybe }, /* Control-d */
- { ISFUNC, rl_insert }, /* Control-e */
- { ISFUNC, rl_insert }, /* Control-f */
- { ISFUNC, rl_insert }, /* Control-g */
- { ISFUNC, rl_rubout }, /* Control-h */
- { ISFUNC, rl_complete }, /* Control-i */
- { ISFUNC, rl_newline }, /* Control-j */
- { ISFUNC, rl_insert }, /* Control-k */
- { ISFUNC, rl_insert }, /* Control-l */
- { ISFUNC, rl_newline }, /* Control-m */
- { ISFUNC, rl_insert }, /* Control-n */
- { ISFUNC, rl_insert }, /* Control-o */
- { ISFUNC, rl_insert }, /* Control-p */
- { ISFUNC, rl_insert }, /* Control-q */
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, (Function *)0x0 },
- { ISFUNC, rl_transpose_chars }, /* Control-t */
- { ISFUNC, rl_unix_line_discard }, /* Control-u */
- { ISFUNC, rl_quoted_insert }, /* Control-v */
- { ISFUNC, rl_unix_word_rubout }, /* Control-w */
- { ISFUNC, rl_insert }, /* Control-x */
- { ISFUNC, rl_yank }, /* Control-y */
- { ISFUNC, rl_insert }, /* Control-z */
-
- { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
- { ISFUNC, rl_insert }, /* Control-\ */
- { ISFUNC, rl_insert }, /* Control-] */
- { ISFUNC, rl_insert }, /* Control-^ */
- { ISFUNC, rl_undo_command }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, rl_insert }, /* SPACE */
- { ISFUNC, rl_insert }, /* ! */
- { ISFUNC, rl_insert }, /* " */
- { ISFUNC, rl_insert }, /* # */
- { ISFUNC, rl_insert }, /* $ */
- { ISFUNC, rl_insert }, /* % */
- { ISFUNC, rl_insert }, /* & */
- { ISFUNC, rl_insert }, /* ' */
- { ISFUNC, rl_insert }, /* ( */
- { ISFUNC, rl_insert }, /* ) */
- { ISFUNC, rl_insert }, /* * */
- { ISFUNC, rl_insert }, /* + */
- { ISFUNC, rl_insert }, /* , */
- { ISFUNC, rl_insert }, /* - */
- { ISFUNC, rl_insert }, /* . */
- { ISFUNC, rl_insert }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_insert }, /* 0 */
- { ISFUNC, rl_insert }, /* 1 */
- { ISFUNC, rl_insert }, /* 2 */
- { ISFUNC, rl_insert }, /* 3 */
- { ISFUNC, rl_insert }, /* 4 */
- { ISFUNC, rl_insert }, /* 5 */
- { ISFUNC, rl_insert }, /* 6 */
- { ISFUNC, rl_insert }, /* 7 */
- { ISFUNC, rl_insert }, /* 8 */
- { ISFUNC, rl_insert }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, rl_insert }, /* : */
- { ISFUNC, rl_insert }, /* ; */
- { ISFUNC, rl_insert }, /* < */
- { ISFUNC, rl_insert }, /* = */
- { ISFUNC, rl_insert }, /* > */
- { ISFUNC, rl_insert }, /* ? */
- { ISFUNC, rl_insert }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_insert }, /* A */
- { ISFUNC, rl_insert }, /* B */
- { ISFUNC, rl_insert }, /* C */
- { ISFUNC, rl_insert }, /* D */
- { ISFUNC, rl_insert }, /* E */
- { ISFUNC, rl_insert }, /* F */
- { ISFUNC, rl_insert }, /* G */
- { ISFUNC, rl_insert }, /* H */
- { ISFUNC, rl_insert }, /* I */
- { ISFUNC, rl_insert }, /* J */
- { ISFUNC, rl_insert }, /* K */
- { ISFUNC, rl_insert }, /* L */
- { ISFUNC, rl_insert }, /* M */
- { ISFUNC, rl_insert }, /* N */
- { ISFUNC, rl_insert }, /* O */
- { ISFUNC, rl_insert }, /* P */
- { ISFUNC, rl_insert }, /* Q */
- { ISFUNC, rl_insert }, /* R */
- { ISFUNC, rl_insert }, /* S */
- { ISFUNC, rl_insert }, /* T */
- { ISFUNC, rl_insert }, /* U */
- { ISFUNC, rl_insert }, /* V */
- { ISFUNC, rl_insert }, /* W */
- { ISFUNC, rl_insert }, /* X */
- { ISFUNC, rl_insert }, /* Y */
- { ISFUNC, rl_insert }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, rl_insert }, /* [ */
- { ISFUNC, rl_insert }, /* \ */
- { ISFUNC, rl_insert }, /* ] */
- { ISFUNC, rl_insert }, /* ^ */
- { ISFUNC, rl_insert }, /* _ */
- { ISFUNC, rl_insert }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, rl_insert }, /* a */
- { ISFUNC, rl_insert }, /* b */
- { ISFUNC, rl_insert }, /* c */
- { ISFUNC, rl_insert }, /* d */
- { ISFUNC, rl_insert }, /* e */
- { ISFUNC, rl_insert }, /* f */
- { ISFUNC, rl_insert }, /* g */
- { ISFUNC, rl_insert }, /* h */
- { ISFUNC, rl_insert }, /* i */
- { ISFUNC, rl_insert }, /* j */
- { ISFUNC, rl_insert }, /* k */
- { ISFUNC, rl_insert }, /* l */
- { ISFUNC, rl_insert }, /* m */
- { ISFUNC, rl_insert }, /* n */
- { ISFUNC, rl_insert }, /* o */
- { ISFUNC, rl_insert }, /* p */
- { ISFUNC, rl_insert }, /* q */
- { ISFUNC, rl_insert }, /* r */
- { ISFUNC, rl_insert }, /* s */
- { ISFUNC, rl_insert }, /* t */
- { ISFUNC, rl_insert }, /* u */
- { ISFUNC, rl_insert }, /* v */
- { ISFUNC, rl_insert }, /* w */
- { ISFUNC, rl_insert }, /* x */
- { ISFUNC, rl_insert }, /* y */
- { ISFUNC, rl_insert }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, rl_insert }, /* { */
- { ISFUNC, rl_insert }, /* | */
- { ISFUNC, rl_insert }, /* } */
- { ISFUNC, rl_insert }, /* ~ */
- { ISFUNC, rl_rubout } /* RUBOUT */
-};
-
-KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
-
- /* The regular control keys come first. */
- { ISFUNC, (Function *)0x0 }, /* Control-@ */
- { ISFUNC, (Function *)0x0 }, /* Control-a */
- { ISFUNC, (Function *)0x0 }, /* Control-b */
- { ISFUNC, (Function *)0x0 }, /* Control-c */
- { ISFUNC, (Function *)0x0 }, /* Control-d */
- { ISFUNC, (Function *)0x0 }, /* Control-e */
- { ISFUNC, (Function *)0x0 }, /* Control-f */
- { ISFUNC, (Function *)0x0 }, /* Control-g */
- { ISFUNC, (Function *)0x0 }, /* Control-h */
- { ISFUNC, rl_tab_insert}, /* Control-i */
- { ISFUNC, rl_emacs_editing_mode}, /* Control-j */
- { ISFUNC, rl_kill_line }, /* Control-k */
- { ISFUNC, (Function *)0x0 }, /* Control-l */
- { ISFUNC, rl_emacs_editing_mode}, /* Control-m */
- { ISFUNC, (Function *)0x0 }, /* Control-n */
- { ISFUNC, (Function *)0x0 }, /* Control-o */
- { ISFUNC, (Function *)0x0 }, /* Control-p */
- { ISFUNC, (Function *)0x0 }, /* Control-q */
- { ISFUNC, (Function *)0x0 }, /* Control-r */
- { ISFUNC, (Function *)0x0 }, /* Control-s */
- { ISFUNC, (Function *)0x0 }, /* Control-t */
- { ISFUNC, (Function *)0x0 }, /* Control-u */
- { ISFUNC, (Function *)0x0 }, /* Control-v */
- { ISFUNC, (Function *)0x0 }, /* Control-w */
- { ISFUNC, (Function *)0x0 }, /* Control-x */
- { ISFUNC, (Function *)0x0 }, /* Control-y */
- { ISFUNC, (Function *)0x0 }, /* Control-z */
-
- { ISFUNC, rl_vi_movement_mode }, /* Control-[ */
- { ISFUNC, (Function *)0x0 }, /* Control-\ */
- { ISFUNC, (Function *)0x0 }, /* Control-] */
- { ISFUNC, (Function *)0x0 }, /* Control-^ */
- { ISFUNC, rl_undo_command }, /* Control-_ */
-
- /* The start of printing characters. */
- { ISFUNC, (Function *)0x0 }, /* SPACE */
- { ISFUNC, (Function *)0x0 }, /* ! */
- { ISFUNC, (Function *)0x0 }, /* " */
- { ISFUNC, (Function *)0x0 }, /* # */
- { ISFUNC, (Function *)0x0 }, /* $ */
- { ISFUNC, (Function *)0x0 }, /* % */
- { ISFUNC, (Function *)0x0 }, /* & */
- { ISFUNC, (Function *)0x0 }, /* ' */
- { ISFUNC, (Function *)0x0 }, /* ( */
- { ISFUNC, (Function *)0x0 }, /* ) */
- { ISFUNC, (Function *)0x0 }, /* * */
- { ISFUNC, (Function *)0x0 }, /* + */
- { ISFUNC, (Function *)0x0 }, /* , */
- { ISFUNC, (Function *)0x0 }, /* - */
- { ISFUNC, (Function *)0x0 }, /* . */
- { ISFUNC, (Function *)0x0 }, /* / */
-
- /* Regular digits. */
- { ISFUNC, rl_vi_arg_digit }, /* 0 */
- { ISFUNC, rl_vi_arg_digit }, /* 1 */
- { ISFUNC, rl_vi_arg_digit }, /* 2 */
- { ISFUNC, rl_vi_arg_digit }, /* 3 */
- { ISFUNC, rl_vi_arg_digit }, /* 4 */
- { ISFUNC, rl_vi_arg_digit }, /* 5 */
- { ISFUNC, rl_vi_arg_digit }, /* 6 */
- { ISFUNC, rl_vi_arg_digit }, /* 7 */
- { ISFUNC, rl_vi_arg_digit }, /* 8 */
- { ISFUNC, rl_vi_arg_digit }, /* 9 */
-
- /* A little more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* : */
- { ISFUNC, (Function *)0x0 }, /* ; */
- { ISFUNC, (Function *)0x0 }, /* < */
- { ISFUNC, (Function *)0x0 }, /* = */
- { ISFUNC, (Function *)0x0 }, /* > */
- { ISFUNC, (Function *)0x0 }, /* ? */
- { ISFUNC, (Function *)0x0 }, /* @ */
-
- /* Uppercase alphabet. */
- { ISFUNC, rl_do_lowercase_version }, /* A */
- { ISFUNC, rl_do_lowercase_version }, /* B */
- { ISFUNC, rl_do_lowercase_version }, /* C */
- { ISFUNC, rl_do_lowercase_version }, /* D */
- { ISFUNC, rl_do_lowercase_version }, /* E */
- { ISFUNC, rl_do_lowercase_version }, /* F */
- { ISFUNC, rl_do_lowercase_version }, /* G */
- { ISFUNC, rl_do_lowercase_version }, /* H */
- { ISFUNC, rl_do_lowercase_version }, /* I */
- { ISFUNC, rl_do_lowercase_version }, /* J */
- { ISFUNC, rl_do_lowercase_version }, /* K */
- { ISFUNC, rl_do_lowercase_version }, /* L */
- { ISFUNC, rl_do_lowercase_version }, /* M */
- { ISFUNC, rl_do_lowercase_version }, /* N */
- { ISFUNC, rl_do_lowercase_version }, /* O */
- { ISFUNC, rl_do_lowercase_version }, /* P */
- { ISFUNC, rl_do_lowercase_version }, /* Q */
- { ISFUNC, rl_do_lowercase_version }, /* R */
- { ISFUNC, rl_do_lowercase_version }, /* S */
- { ISFUNC, rl_do_lowercase_version }, /* T */
- { ISFUNC, rl_do_lowercase_version }, /* U */
- { ISFUNC, rl_do_lowercase_version }, /* V */
- { ISFUNC, rl_do_lowercase_version }, /* W */
- { ISFUNC, rl_do_lowercase_version }, /* X */
- { ISFUNC, rl_do_lowercase_version }, /* Y */
- { ISFUNC, rl_do_lowercase_version }, /* Z */
-
- /* Some more punctuation. */
- { ISFUNC, (Function *)0x0 }, /* [ */
- { ISFUNC, (Function *)0x0 }, /* \ */
- { ISFUNC, (Function *)0x0 }, /* ] */
- { ISFUNC, (Function *)0x0 }, /* ^ */
- { ISFUNC, (Function *)0x0 }, /* _ */
- { ISFUNC, (Function *)0x0 }, /* ` */
-
- /* Lowercase alphabet. */
- { ISFUNC, (Function *)0x0 }, /* a */
- { ISFUNC, (Function *)0x0 }, /* b */
- { ISFUNC, (Function *)0x0 }, /* c */
- { ISFUNC, (Function *)0x0 }, /* d */
- { ISFUNC, (Function *)0x0 }, /* e */
- { ISFUNC, (Function *)0x0 }, /* f */
- { ISFUNC, (Function *)0x0 }, /* g */
- { ISFUNC, (Function *)0x0 }, /* h */
- { ISFUNC, (Function *)0x0 }, /* i */
- { ISFUNC, (Function *)0x0 }, /* j */
- { ISFUNC, (Function *)0x0 }, /* k */
- { ISFUNC, (Function *)0x0 }, /* l */
- { ISFUNC, (Function *)0x0 }, /* m */
- { ISFUNC, (Function *)0x0 }, /* n */
- { ISFUNC, (Function *)0x0 }, /* o */
- { ISFUNC, (Function *)0x0 }, /* p */
- { ISFUNC, (Function *)0x0 }, /* q */
- { ISFUNC, (Function *)0x0 }, /* r */
- { ISFUNC, (Function *)0x0 }, /* s */
- { ISFUNC, (Function *)0x0 }, /* t */
- { ISFUNC, (Function *)0x0 }, /* u */
- { ISFUNC, (Function *)0x0 }, /* v */
- { ISFUNC, (Function *)0x0 }, /* w */
- { ISFUNC, (Function *)0x0 }, /* x */
- { ISFUNC, (Function *)0x0 }, /* y */
- { ISFUNC, (Function *)0x0 }, /* z */
-
- /* Final punctuation. */
- { ISFUNC, (Function *)0x0 }, /* { */
- { ISFUNC, (Function *)0x0 }, /* | */
- { ISFUNC, (Function *)0x0 }, /* } */
- { ISFUNC, (Function *)0x0 }, /* ~ */
- { ISFUNC, rl_backward_kill_word } /* RUBOUT */
-};
End of readline/vi_keymap.c
echo readline/vi_mode.c 1>&2
sed 's/^-//' >readline/vi_mode.c <<'End of readline/vi_mode.c'
-/* vi_mode.c -- A vi emulation mode for Bash.
-
- Derived from code written by Jeff Sparkes (jeff1@????).
- */
-
-
-/* **************************************************************** */
-/* */
-/* VI Emulation Mode */
-/* */
-/* **************************************************************** */
-
-/* Last string searched for from `/' or `?'. */
-static char *vi_last_search = (char *)NULL;
-static int vi_histpos;
-
-/* Non-zero means enter insertion mode. */
-int vi_doing_insert = 0;
-
-/* *** UNCLEAN *** */
-/* Command keys which do movement for xxx_to commands. */
-static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
-
-/* Keymap used for vi replace characters. Created dynamically since
- rarely used. */
-static Keymap vi_replace_map = (Keymap)NULL;
-
-/* The number of characters inserted in the last replace operation. */
-static vi_replace_count = 0;
-
-/* Yank the nth arg from the previous line into this line at point. */
-rl_vi_yank_arg (count)
- int count;
-{
- rl_yank_nth_arg (count, 0);
-}
-
-/* Search again for the last thing searched for. */
-rl_vi_search_again (ignore, key)
- int ignore, key;
-{
- switch (key)
- {
- case 'n':
- rl_vi_dosearch (vi_last_search, -1);
- break;
-
- case 'N':
- rl_vi_dosearch (vi_last_search, 1);
- break;
- }
-}
-
-/* Do a vi style search. */
-rl_vi_search (count, key)
- int count, key;
-{
- int dir, c, save_pos;
- char *p;
-
- switch (key)
- {
- case '?':
- dir = 1;
- break;
-
- case '/':
- dir = -1;
- break;
-
- default:
- ding ();
- return;
- }
-
- vi_histpos = where_history ();
- maybe_save_line ();
- save_pos = rl_point;
-
- /* Reuse the line input buffer to read the search string. */
- the_line[0] = 0;
- rl_end = rl_point = 0;
- p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
-
- sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
-
- rl_message (p, 0, 0);
-
- while (c = rl_read_key ())
- {
- switch (c)
- {
- case CTRL('H'):
- case RUBOUT:
- if (rl_point == 0)
- {
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = save_pos;
- return;
- }
-
- case CTRL('W'):
- case CTRL('U'):
- rl_dispatch (c, keymap);
- break;
-
- case ESC:
- case RETURN:
- case NEWLINE:
- goto dosearch;
- break;
-
- case CTRL('C'):
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = 0;
- ding ();
- return;
-
- default:
- rl_insert (1, c);
- break;
- }
- rl_redisplay ();
- }
- dosearch:
- if (vi_last_search)
- free (vi_last_search);
-
- vi_last_search = savestring (the_line);
- rl_vi_dosearch (the_line, dir);
-}
-
-rl_vi_dosearch (string, dir)
- char *string;
- int dir;
-{
-#ifdef 0
- int old, save = vi_histpos;
- HIST_ENTRY *h;
-
- if (string == 0 || *string == 0 || vi_histpos < 0)
- {
- ding ();
- return;
- }
-
- if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
- {
- maybe_unsave_line ();
- rl_clear_message ();
- rl_point = 0;
- ding ();
- return;
- }
-
- vi_histpos = save;
-
- old = where_history ();
- history_set_pos (vi_histpos);
- h = current_history ();
- history_set_pos (old);
-
- strcpy (the_line, h->line);
- rl_undo_list = (UNDO_LIST *)h->data;
- rl_end = strlen (the_line);
- rl_point = 0;
- rl_clear_message ();
-#endif
-}
-
-/* Completion, from vi's point of view. */
-rl_vi_complete (ignore, key)
- int ignore, key;
-{
- if (!whitespace (the_line[rl_point]))
- {
- if (!whitespace (the_line[rl_point + 1]))
- rl_vi_end_word (1, 'E');
- rl_point++;
- }
-
- if (key == '*')
- rl_complete_internal ('*');
- else
- rl_complete (0, key);
-
- rl_vi_insertion_mode ();
-}
-
-/* Previous word in vi mode. */
-rl_vi_prev_word (count, key)
- int count, key;
-{
- if (count < 0)
- {
- rl_vi_next_word (-count, key);
- return;
- }
-
- if (uppercase_p (key))
- rl_vi_bWord (count);
- else
- rl_vi_bword (count);
-}
-
-/* Next word in vi mode. */
-rl_vi_next_word (count, key)
- int count;
-{
- if (count < 0)
- {
- rl_vi_prev_word (-count, key);
- return;
- }
-
- if (uppercase_p (key))
- rl_vi_fWord (count);
- else
- rl_vi_fword (count);
-}
-
-/* Move to the end of the ?next? word. */
-rl_vi_end_word (count, key)
- int count, key;
-{
- if (count < 0)
- {
- ding ();
- return;
- }
-
- if (uppercase_p (key))
- rl_vi_eWord (count);
- else
- rl_vi_eword (count);
-}
-
-/* Move forward a word the way that 'W' does. */
-rl_vi_fWord (count)
- int count;
-{
- while (count-- && rl_point < (rl_end - 1))
- {
- /* Skip until whitespace. */
- while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
- rl_point++;
-
- /* Now skip whitespace. */
- while (whitespace (the_line[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
-}
-
-rl_vi_bWord (count)
- int count;
-{
- while (count-- && rl_point > 0)
- {
- while (rl_point-- >= 0 && whitespace (the_line[rl_point]));
- while (rl_point >= 0 && !whitespace (the_line[rl_point]))
- rl_point--;
- rl_point++;
- }
-}
-
-rl_vi_eWord (count)
- int count;
-{
- while (count -- && rl_point < (rl_end - 1))
- {
- while (rl_point++ < rl_end && whitespace (the_line[rl_point]));
- while (rl_point++ < rl_end && !whitespace (the_line[rl_point]));
- rl_point--;
- }
-}
-
-rl_vi_fword (count)
- int count;
-{
- while (count -- && rl_point < (rl_end - 1))
- {
- if (isident (the_line[rl_point]))
- {
- while (isident (the_line[rl_point]) && rl_point < rl_end)
- rl_point += 1;
- }
- else if (!whitespace (the_line[rl_point]))
- {
- while (!isident (the_line[rl_point]) &&
- !whitespace (the_line[rl_point]) && rl_point < rl_end)
- rl_point += 1;
- }
-
- while (whitespace (the_line[rl_point]) && rl_point < rl_end)
- rl_point++;
- }
-}
-
-rl_vi_bword (count)
- int count;
-{
- while (count -- && rl_point > 0)
- {
- while (--rl_point > 0 && whitespace (the_line[rl_point]));
- if (rl_point > 0)
- {
- if (isident (the_line[rl_point]))
- while (--rl_point >= 0 && isident (the_line[rl_point]));
- else
- while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
- !whitespace (the_line[rl_point]));
- rl_point++;
- }
- }
-}
-
-rl_vi_eword (count)
- int count;
-{
- while (count -- && rl_point < rl_end - 1)
- {
- while (++rl_point < rl_end && whitespace (the_line[rl_point]));
-
- if (rl_point < rl_end)
- {
- if (isident (the_line[rl_point]))
- while (++rl_point < rl_end && isident (the_line[rl_point]));
- else
- while (++rl_point < rl_end && !isident (the_line[rl_point])
- && !whitespace (the_line[rl_point]));
- rl_point--;
- }
- }
-}
-
-rl_vi_insert_beg ()
-{
- rl_beg_of_line ();
- rl_vi_insertion_mode ();
- return 0;
-}
-
-rl_vi_append_mode ()
-{
- if (rl_point < rl_end)
- rl_point += 1;
- rl_vi_insertion_mode ();
- return 0;
-}
-
-rl_vi_append_eol ()
-{
- rl_end_of_line ();
- rl_vi_append_mode ();
- return 0;
-}
-
-/* What to do in the case of C-d. */
-rl_vi_eof_maybe (count, c)
- int count, c;
-{
- rl_newline (1, '\n');
-}
-
-/* Insertion mode stuff. */
-
-/* Switching from one mode to the other really just involves
- switching keymaps. */
-rl_vi_insertion_mode ()
-{
- keymap = vi_insertion_keymap;
-}
-
-rl_vi_movement_mode ()
-{
- if (rl_point > 0)
- rl_backward (1);
-
- keymap = vi_movement_keymap;
- vi_done_inserting ();
-}
-
-vi_done_inserting ()
-{
- if (vi_doing_insert)
- {
- rl_end_undo_group ();
- vi_doing_insert = 0;
- }
-}
-
-rl_vi_arg_digit (count, c)
- int count, c;
-{
- if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
- rl_beg_of_line ();
- else
- rl_digit_argument (count, c);
-}
-
-/* Doesn't take an arg count in vi */
-rl_vi_change_case (ignore1, ignore2)
- int ignore1, ignore2;
-{
- char c = 0;
-
- if (uppercase_p (the_line[rl_point]))
- c = to_lower (the_line[rl_point]);
- else if (lowercase_p (the_line[rl_point]))
- c = to_upper (the_line[rl_point]);
-
- /* Vi is kind of strange here. */
- if (c)
- {
- rl_begin_undo_group ();
- rl_delete (1, c);
- rl_insert (1, c);
- rl_end_undo_group ();
- rl_vi_check ();
- }
- else
- rl_forward (1);
-}
-
-rl_vi_put (count, key)
- int count, key;
-{
- if (!uppercase_p (key))
- rl_forward (1);
-
- rl_yank ();
- rl_backward (1);
-}
-
-rl_vi_check ()
-{
- if (rl_point && rl_point == rl_end)
- rl_point--;
-}
-
-rl_vi_column (count)
-{
- if (count > rl_end)
- rl_end_of_line ();
- else
- rl_point = count - 1;
-}
-
-int
-rl_vi_domove (key, nextkey)
- int key, *nextkey;
-{
- int c, save;
-
- rl_mark = rl_point;
- c = rl_read_key ();
- *nextkey = c;
-
- if (!member (c, vi_motion))
- {
- if (digit (c))
- {
- save = rl_numeric_arg;
- rl_digit_loop1 ();
- rl_numeric_arg *= save;
- }
- else if ((key == 'd' && c == 'd') ||
- (key == 'c' && c == 'c'))
- {
- rl_mark = rl_end;
- rl_beg_of_line ();
- return (0);
- }
- else
- return (-1);
- }
-
- rl_dispatch (c, keymap);
-
- /* No change in position means the command failed. */
- if (rl_mark == rl_point)
- return (-1);
-
- if ((c == 'w' || c == 'W') && rl_point < rl_end)
- rl_point--;
-
- if (rl_mark < rl_point)
- exchange (rl_point, rl_mark);
-
- return (0);
-}
-
-/* A simplified loop for vi. Don't dispatch key at end.
- Don't recognize minus sign? */
-rl_digit_loop1 ()
-{
- int key, c;
-
- while (1)
- {
- rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
- key = c = rl_read_key ();
-
- if (keymap[c].type == ISFUNC &&
- keymap[c].function == rl_universal_argument)
- {
- rl_numeric_arg *= 4;
- continue;
- }
- c = UNMETA (c);
- if (numeric (c))
- {
- if (rl_explicit_arg)
- rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
- else
- rl_numeric_arg = (c - '0');
- rl_explicit_arg = 1;
- }
- else
- {
- rl_clear_message ();
- rl_stuff_char (key);
- }
- }
-}
-
-rl_vi_delete_to (count, key)
- int count, key;
-{
- int c;
-
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return;
- }
-
- if ((c != '|') && (c != 'h') && rl_mark < rl_end)
- rl_mark++;
-
- rl_kill_text (rl_point, rl_mark);
-}
-
-rl_vi_change_to (count, key)
- int count, key;
-{
- int c;
-
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return;
- }
-
- if ((c != '|') && (c != 'h') && rl_mark < rl_end)
- rl_mark++;
-
- rl_begin_undo_group ();
- vi_doing_insert = 1;
- rl_kill_text (rl_point, rl_mark);
- rl_vi_insertion_mode ();
-}
-
-rl_vi_yank_to (count, key)
- int count, key;
-{
- int c, save = rl_point;
-
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove (key, &c))
- {
- ding ();
- return;
- }
-
- rl_begin_undo_group ();
- rl_kill_text (rl_point, rl_mark);
- rl_end_undo_group ();
- rl_do_undo ();
- rl_point = save;
-}
-
-rl_vi_delete (count)
-{
- if (rl_point >= rl_end - 1)
- {
- rl_delete (count, 0);
- if (rl_point > 0)
- rl_backward (1);
- }
- else
- rl_delete (count, 0);
-}
-
-/* Turn the current line into a comment in shell history. A ksh function */
-rl_vi_comment ()
-{
- rl_beg_of_line ();
- rl_insert_text (": "); /* # doesn't work in interactive mode */
- rl_redisplay ();
- rl_newline (1, '\010');
-}
-
-rl_vi_first_print ()
-{
- rl_back_to_indent ();
-}
-
-rl_back_to_indent (ignore1, ignore2)
- int ignore1, ignore2;
-{
- rl_beg_of_line ();
- while (rl_point < rl_end && whitespace (the_line[rl_point]))
- rl_point++;
-}
-
-/* NOTE: it is necessary that opposite directions are inverses */
-#define FTO 1 /* forward to */
-#define BTO -1 /* backward to */
-#define FFIND 2 /* forward find */
-#define BFIND -2 /* backward find */
-
-rl_vi_char_search (count, key)
- int count, key;
-{
- static char target;
- static int orig_dir, dir;
- int pos;
-
- if (key == ';' || key == ',')
- dir = (key == ';' ? orig_dir : -orig_dir);
- else
- {
- target = rl_getc (in_stream);
-
- switch (key)
- {
- case 't':
- orig_dir = dir = FTO;
- break;
-
- case 'T':
- orig_dir = dir = BTO;
- break;
-
- case 'f':
- orig_dir = dir = FFIND;
- break;
-
- case 'F':
- orig_dir = dir = BFIND;
- break;
- }
- }
-
- pos = rl_point;
-
- if (dir < 0)
- {
- pos--;
- do
- {
- if (the_line[pos] == target)
- {
- if (dir == BTO)
- rl_point = pos + 1;
- else
- rl_point = pos;
- return;
- }
- }
- while (pos--);
-
- if (pos < 0)
- {
- ding ();
- return;
- }
- }
- else
- { /* dir > 0 */
- pos++;
- do
- {
- if (the_line[pos] == target)
- {
- if (dir == FTO)
- rl_point = pos - 1;
- else
- rl_point = pos;
- return;
- }
- }
- while (++pos < rl_end);
-
- if (pos >= (rl_end - 1))
- ding ();
- }
-}
-
-/* Match brackets */
-rl_vi_match ()
-{
- int count = 1, brack, pos;
-
- pos = rl_point;
- if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
- {
- while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
- rl_point < rl_end - 1)
- rl_forward (1);
-
- if (brack <= 0)
- {
- rl_point = pos;
- ding ();
- return;
- }
- }
-
- pos = rl_point;
-
- if (brack < 0)
- {
- while (count)
- {
- if (--pos >= 0)
- {
- int b = rl_vi_bracktype (the_line[pos]);
- if (b == -brack)
- count--;
- else if (b == brack)
- count++;
- }
- else
- {
- ding ();
- return;
- }
- }
- }
- else
- { /* brack > 0 */
- while (count)
- {
- if (++pos < rl_end)
- {
- int b = rl_vi_bracktype (the_line[pos]);
- if (b == -brack)
- count--;
- else if (b == brack)
- count++;
- }
- else
- {
- ding ();
- return;
- }
- }
- }
- rl_point = pos;
-}
-
-int
-rl_vi_bracktype (c)
- int c;
-{
- switch (c)
- {
- case '(': return 1;
- case ')': return -1;
- case '[': return 2;
- case ']': return -2;
- case '{': return 3;
- case '}': return -3;
- default: return 0;
- }
-}
-
-rl_vi_change_char ()
-{
- int c;
-
- c = rl_getc (in_stream);
-
- switch (c)
- {
- case '\033':
- case CTRL('C'):
- return;
-
- default:
- rl_begin_undo_group ();
- rl_delete (1, c);
- rl_insert (1, c);
- rl_end_undo_group ();
- break;
- }
-}
-
-rl_vi_subst (count, key)
- int count, key;
-{
- rl_begin_undo_group ();
- vi_doing_insert = 1;
-
- if (uppercase_p (key))
- {
- rl_beg_of_line ();
- rl_kill_line (1);
- }
- else
- rl_delete (1, key);
-
- rl_vi_insertion_mode ();
-}
-
-rl_vi_overstrike (count, key)
- int count, key;
-{
- int i;
-
- if (vi_doing_insert == 0)
- {
- vi_doing_insert = 1;
- rl_begin_undo_group ();
- }
-
- for (i = 0; i < count; i++)
- {
- vi_replace_count++;
- rl_begin_undo_group ();
-
- if (rl_point < rl_end)
- {
- rl_delete (1, key);
- rl_insert (1, key);
- }
- else
- rl_insert (1, key);
-
- rl_end_undo_group ();
- }
-}
-
-rl_vi_overstrike_delete (count)
- int count;
-{
- int i, s;
-
- for (i = 0; i < count; i++)
- {
- if (vi_replace_count == 0)
- {
- ding ();
- break;
- }
- s = rl_point;
-
- if (rl_do_undo ())
- vi_replace_count--;
-
- if (rl_point == s)
- rl_backward (1);
- }
-
- if (vi_replace_count == 0 && vi_doing_insert)
- {
- rl_end_undo_group ();
- rl_do_undo ();
- vi_doing_insert = 0;
- }
-}
-
-rl_vi_replace ()
-{
- int i;
-
- vi_replace_count = 0;
-
- vi_replace_map = rl_make_bare_keymap ();
-
- for (i = ' '; i < 127; i++)
- vi_replace_map[i].function = rl_vi_overstrike;
-
- vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
- vi_replace_map[ESC].function = rl_vi_movement_mode;
- vi_replace_map[RETURN].function = rl_newline;
- vi_replace_map[NEWLINE].function = rl_newline;
- keymap = vi_replace_map;
-}
-
-/*
- * Try to complete the word we are standing on or the word that ends with
- * the previous character. A space matches everything.
- * Word delimiters are space and ;.
- */
-rl_vi_possible_completions()
-{
- int save_pos = rl_point;
-
- if (!index (" ;", the_line[rl_point]))
- {
- while (!index(" ;", the_line[++rl_point]))
- ;
- }
- else if (the_line[rl_point-1] == ';')
- {
- ding ();
- return (0);
- }
-
- rl_possible_completions ();
- rl_point = save_pos;
-
- return (0);
-}
End of readline/vi_mode.c
echo readline/Makefile 1>&2
sed 's/^-//' >readline/Makefile <<'End of readline/Makefile'
-## -*- text -*- ####################################################
-# #
-# Makefile for readline and history libraries. #
-# #
-####################################################################
-
-# Here is a rule for making .o files from .c files that doesn't force
-# the type of the machine (like -sun3) into the flags.
-.c.o:
- $(CC) -c $(CFLAGS) $(LOCAL_INCLUDES) $(CPPFLAGS) $*.c
-
-# Destination installation directory. The libraries are copied to DESTDIR
-# when you do a `make install', and the header files to INCDIR/readline/*.h.
-DESTDIR = /usr/gnu/lib
-INCDIR = /usr/gnu/include
-
-# Define TYPES as -DVOID_SIGHANDLER if your operating system uses
-# a return type of "void" for signal handlers.
-TYPES = -DVOID_SIGHANDLER
-
-# Define SYSV as -DSYSV if you are using a System V operating system.
-#SYSV = -DSYSV
-
-# HP-UX compilation requires the BSD library.
-#LOCAL_LIBS = -lBSD
-
-# Xenix compilation requires -ldir -lx
-#LOCAL_LIBS = -ldir -lx
-
-# Comment this out if you don't think that anyone will ever desire
-# the vi line editing mode and features.
-READLINE_DEFINES = -DVI_MODE
-
-DEBUG_FLAGS =
-LDFLAGS = $(DEBUG_FLAGS)
-CFLAGS = $(DEBUG_FLAGS) $(TYPE) $(SYSV) -I.
-
-# A good alternative is gcc -traditional.
-CC = gcc -traditional
-RANLIB = /usr/bin/ranlib
-AR = ar
-RM = rm
-CP = cp
-
-LOCAL_INCLUDES = -I../
-
-CSOURCES = readline.c history.c funmap.c keymaps.c vi_mode.c \
- emacs_keymap.c vi_keymap.c keymaps.c
-
-HSOURCES = readline.h chardefs.h history.h keymaps.h
-SOURCES = $(CSOURCES) $(HSOURCES)
-
-DOCUMENTATION = readline.texinfo inc-readline.texinfo \
- history.texinfo inc-history.texinfo
-
-SUPPORT = COPYING Makefile $(DOCUMENTATION) ChangeLog
-
-THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
-
-##########################################################################
-
-all: readline.o funmap.o keymaps.o
-# all: libreadline.a
-
-libreadline.a: readline.o history.o funmap.o keymaps.o
- $(RM) -f libreadline.a
- $(AR) clq libreadline.a readline.o history.o funmap.o keymaps.o
- -if [ -f $(RANLIB) ]; then $(RANLIB) libreadline.a; fi
-
-readline.o: readline.h chardefs.h keymaps.h history.h readline.c vi_mode.c
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-history.o: history.c history.h
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-funmap.o: readline.h
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-keymaps.o: emacs_keymap.c vi_keymap.c keymaps.h chardefs.h keymaps.c
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-libtest: libreadline.a libtest.c
- $(CC) -o libtest $(CFLAGS) $(CPPFLAGS) -L. libtest.c -lreadline -ltermcap
-
-readline: readline.c history.o keymaps.o funmap.o readline.h chardefs.h
- $(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) -DTEST -o readline readline.c funmap.o \
- keymaps.o history.o -L. -ltermcap
-
-readline.tar: $(THINGS_TO_TAR)
- tar -cf readline.tar $(THINGS_TO_TAR)
-
-readline.tar.Z: readline.tar
- compress -f readline.tar
-
-install: $(DESTDIR)/libreadline.a includes
-
-includes:
- if [ ! -r $(INCDIR)/readline ]; then\
- mkdir $(INCDIR)/readline;\
- chmod a+r $(INCDIR)/readline;\
- fi
- $(CP) readline.h keymaps.h chardefs.h $(INCDIR)/readline/
-clean:
- rm -f *.o *.a *.log *.cp *.tp *.vr *.fn *.aux *.pg *.toc
-
-$(DESTDIR)/libreadline.a: libreadline.a
- -mv $(DESTDIR)/libreadline.a $(DESTDIR)/libreadline.old
- cp libreadline.a $(DESTDIR)/libreadline.a
- $(RANLIB) -t $(DESTDIR)/libreadline.a
End of readline/Makefile
echo zsh.h 1>&2
sed 's/^-//' >zsh.h <<'End of zsh.h'
-/*
-
- zsh.h - the header file, basically
-
- This file is part of zsh, the Z shell.
-
- zsh is free software; no one can prevent you from reading the source
- code, or giving it to someone else.
- This file is copyrighted under the GNU General Public License, which
- can be found in the file called COPYING.
-
- Copyright (C) 1990 Paul Falstad
-
- zsh is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts
- responsibility to anyone for the consequences of using it or for
- whether it serves any particular purpose or works at all, unless he
- says so in writing. Refer to the GNU General Public License
- for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- zsh, but only under the conditions described in the GNU General Public
- License. A copy of this license is supposed to have been given to you
- along with zsh so you can know your rights and responsibilities.
- It should be in a file named COPYING.
-
- Among other things, the copyright notice and this notice must be
- preserved on all copies.
-
-*/
-
-#include "config.h"
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/file.h>
-#include <signal.h>
-#ifdef TERMIOS
-#include <sys/termios.h>
-#else
-#include <sgtty.h>
-#endif
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#define VERSIONSTR "zsh v1.0"
-
-#define FOREVER for(;;)
-
-/* size of job table */
-
-#define MAXJOB 16
-
-void *realloc(void *,int),*malloc(int),*calloc(int,int);
-
-char *getenv(char *);
-
-/* the tokens */
-
-enum xfubar {
- HQUOT = -127, /* quote char used for history */
- ALPOP, /* marker, causes parser to pop alias stack */
- HERR, /* history error indicator */
- Pound, /* # */
- String, /* $ */
- Hat, /* ^ */
- Star, /* * */
- Inpar, /* ( */
- Outpar, /* ) */
- Qstring, /* $, in quotes */
- Equals, /* = (initial) */
- Bar, /* |, except when used as a pipe char */
- Inbrace, /* {, except when used for current shells */
- Outbrace, /* }, except when used for current shells */
- Inbrack, /* [ */
- Outbrack, /* ] */
- Tick, /* ` */
- Inang, /* <, except when used for redirection */
- Outang, /* >, except when used for redirection */
- Quest, /* ? */
- Tilde, /* ~ (initial) */
- Qtick, /* `, in quotes */
- Comma, /* , */
- Nularg /* marker, keeps explicit null arguments around,
- does some other stuff */
- };
-
-/* HQUOT separately defined in readline.c */
-
-/* returns true if X is a token */
-
-#define istok(X) (((char) (X)) <= Nularg)
-
-/* HQUOT in the form of a string */
-
-#define HQUOTS "\x81"
-
-/* ALPOP in the form of a string */
-
-#define ALPOPS " \x82"
-
-extern char **environ;
-
-/* list of tokens */
-
-extern char *tokens;
-
-/* tokens used in peek variable with gettok/matchit */
-/* do not confuse with above tokens; above tokens appear in strings,
- following tokens possible values of 'peek' variable */
-
-enum xpeek {
- EMPTY, /* nothing gotten yet */
- SEMI, /* ; */
- DSEMI, /* ;; */
- AMPER, /* & */
- DAMPER, /* && */
- NEWLIN, /* \n */
- INPAR, /* ( */
- INBRACE, /* { */
- OUTPAR, /* ) */
- OUTBRACE, /* } */
- OUTANG, /* > */
- OUTANGBANG, /* >! */
- DOUTANG, /* >> */
- DOUTANGBANG, /* >>! */
- INANG, /* < */
- DINANG, /* << */
- INANGAMP, /* <& */
- OUTANGAMP, /* >& */
- OUTANGAMPBANG, /* >&! */
- DOUTANGAMP, /* >>& */
- DOUTANGAMPBANG, /* >>&! */
- BAR, /* | */
- DBAR, /* || */
- BARAMP, /* |& */
- BANG, /* ! */
- STRING, /* string of chars and tokens */
- ENVSTRING, /* string of chars and tokens with a = in it */
- /* the below are all reserved words */
- DO,
- DONE,
- ESAC,
- THEN,
- ELIF,
- ELSE,
- FI,
- FOR,
- CASE,
- IF,
- WHILE,
- FUNC,
- REPEAT,
- TIME,
- UNTIL,
- EXEC,
- COMMAND,
- SELECT,
- COPROC
- };
-
-/* linked list data type */
-
-typedef struct xlist *table;
-typedef struct xnode *Node;
-
-struct xnode {
- Node next,last;
- void *dat;
- };
-struct xlist {
- Node first,last;
- };
-
-
-typedef struct pnode *pline;
-typedef struct lnode *list;
-typedef struct l2node *list2;
-typedef struct cnode *comm;
-typedef struct jobnode *job;
-
-/* tree element for lists */
-
-struct lnode {
- struct l2node *left;
- struct lnode *right;
- int type;
- };
-
-enum ltype {
- SYNC, /* ; */
- ASYNC /* & */
- };
-
-/* tree element for sublists */
-
-struct l2node {
- struct pnode *left;
- struct l2node *right;
- int type;
- int flags; /* one of PFLAGS below; applies to pnode *left */
- };
-
-enum l2type {
- ORNEXT = 10, /* || */
- ANDNEXT /* && */
- };
-
-#define PFLAG_TIMED 4 /* time ... */
-#define PFLAG_NOT 1 /* ! ... */
-#define PFLAG_COPROC 32 /* coproc ... */
-
-/* tree element for pipes */
-
-struct pnode {
- struct cnode *left;
- struct pnode *right;
- int type;
- };
-
-enum ptype {
- END, /* pnode *right is null */
- PIPE /* pnode *right is the rest of the pipeline */
- };
-
-/* tree element for commands */
-
-struct cnode {
- struct lnode *left; /* for SUBSH/CURSH/SHFUNC */
- char *cmd; /* command name */
- table args; /* argmument list (char *'s) */
- table redir; /* i/o redirections (struct fnode *'s) */
- table vars; /* parameter list (char *'s), can be null;
- two entries in table for each parameter
- assignment; "name" and "value" */
- int type;
- int flags;
- void *info; /* pointer to appropriate control structure,
- if this is a CFOR, CWHILE, etc. */
- };
-
-enum ctype {
- SIMPLE, /* simple command */
- SUBSH, /* ( left ) */
- CURSH, /* { left } */
- SHFUNC, /* converted to { left } in execcomm */
- CFOR,
- CWHILE,
- CREPEAT,
- CIF,
- CCASE,
- CSELECT
- };
-#define CFLAG_EXEC 1 /* exec ... */
-#define CFLAG_COMMAND 2 /* command ... */
-
-struct fnode {
- union {
- char *name; /* source/dest filename */
- int fd2; /* source/dest file descriptor */
- } u;
- int type;
- int fd1; /* affected file descriptor */
- };
-
-enum ftype {
- WRITE, /* #> name */
- WRITENOW, /* #>! name */
- APP, /* #>> name */
- APPNOW, /* #>>! name */
- READ, /* #< name */
- HEREDOC, /* #<< fd2 */
- MERGE, /* #<& fd2 */
- MERGEOUT, /* #>& fd2 */
- CLOSE, /* #>&-, #<&- */
- INPIPE, /* #< name, where name is <(...) */
- OUTPIPE, /* #> name, where name is >(...) */
- NONE
- };
-
-struct fornode { /* for/select */
- char *name; /* parameter to assign values to */
- list list; /* list of names to loop through */
- int inflag; /* != 0 if 'in ...' was specified */
- };
-struct casenode { /* arg list of cnode struct contains word to test */
- struct casenode *next; /* next pattern */
- char *pat;
- list list; /* list to execute */
- };
-struct ifnode {
- struct ifnode *next;
- list ifl; /* if/elif test list (can be null in case of else) */
- list thenl; /* then list */
- };
-struct whilenode {
- list cont; /* condition */
- list loop; /* list to execute until condition met */
- int cond; /* 0 for while, 1 for until */
- };
-struct repeatnode {
- int count; /* # of iterations */
- list list;
- };
-
-
-/* structure used for multiple i/o redirection */
-/* one for each fd open */
-
-struct mnode {
- 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];
- };
-
-/* node used in command hash table */
-
-struct chnode
-{
- int type;
- int globstat; /* status of filename gen for this command */
- union {
- char *nam; /* full pathname if type != BUILTIN */
- int (*func)(); /* func to exec if type == BUILTIN */
- } u;
- };
-
-enum chtype {
- EXCMD_PREDOT, /* external command in PATH before . */
- EXCMD_POSTDOT, /* external command in PATH after . */
- BUILTIN
- };
-
-/* value for globstat field in chnode
-
- sample command: foo -xyz -pdq bar ble boz */
-
-enum globx {
- GLOB, /* all args globbed */
- MOSTGLOB, /* ble, boz globbed */
- NOGLOB /* no args globbed */
- };
-
-/* node used in parameter hash table */
-
-struct pmnode {
- union {
- char *str; /* value */
- long val; /* value if declared integer */
- } u;
- int isint; /* != 0 if declared integer */
- };
-
-/* tty state structure */
-
-struct ttyinfo {
-#ifdef TERMIOS
- struct termios termios;
-#else
- struct sgttyb sgttyb;
- struct tchars tchars;
- struct ltchars ltchars;
-#endif
- struct winsize winsize;
- };
-
-extern struct ttyinfo shttyinfo;
-
-/* entry in job table */
-
-struct jobnode {
- long gleader; /* process group leader of this job */
- int stat;
- char *cwd; /* current working dir of shell when
- this job was spawned */
- struct procnode *procs; /* list of processes */
- table filelist; /* list of files to delete when done */
- struct ttyinfo ttyinfo; /* saved tty state */
- };
-
-#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 */
-
-/* node in job process lists */
-
-struct procnode {
- struct procnode *next;
- long pid;
- char *text; /* text to print when 'jobs' is run */
- int statusp; /* return code from wait3() */
- int lastfg; /* set if this procnode represents a
- fragment of a pipeline run in a subshell
- for commands like:
-
- foo | bar | ble
-
- where foo is a current shell function
- or control structure. The command
- actually executed is:
-
- foo | (bar | ble)
-
- That's two procnodes in the parent
- shell, the latter having this flag set. */
- struct timeval ru_utime;
- struct timeval ru_stime;
- time_t bgtime; /* time job was spawned */
- time_t endtime; /* time job exited */
- };
-
-/* node in alias hash table */
-
-struct anode {
- char *text; /* expansion of alias */
- int cmd; /* one for regular aliases,
- zero for -a aliases,
- negative for reserved words */
- int inuse; /* alias is being expanded */
- };
-
-/* node in sched list */
-
-struct schnode {
- struct schnode *next;
- char *cmd; /* command to run */
- time_t time; /* when to run it */
- };
-
-#define MAXAL 20 /* maximum number of aliases expanded at once */
-
-typedef struct xhtab *htable;
-
-/* node in hash table */
-
-struct hnode {
- struct hnode *hchain;
- char *nam;
- void *dat;
- };
-
-/* hash table structure */
-
-struct xhtab {
- int hsize,ct;
- struct hnode **nodes; /* array of size hsize */
- };
-
-typedef struct xpath *qath; /* used in globbing - see glob.c */
-typedef struct xcomp *comp; /* "" */
-
-extern char *sys_errlist[];
-extern int errno;
-
-#define pushnode(X,Y) insnode(X,(Node) X,Y)
-
-#define OPT_INVALID 1 /* opt is invalid, like -$ */
-#define OPT_UNSET 0
-#define OPT_SET 2
-
-#define CLOBBER '1'
-#define NOBADPATTERN '2'
-#define NONOMATCH '3'
-#define GLOBDOTS '4'
-#define NOTIFY '5'
-#define ALLEXPORT 'a'
-#define ERREXIT 'e'
-#define BGNICE '6'
-#define IGNOREEOF '7'
-#define KEYWORD 'k'
-#define MARKDIRS '8'
-#define MONITOR 'm'
-#define NOEXEC 'n'
-#define NOGLOBOPT 'F'
-#define NORCS 'f'
-#define SHINSTDIN 's'
-#define NOUNSET 'u'
-#define VERBOSE 'v'
-#define XTRACE 'x'
-#define INTERACTIVE 'i'
-#define AUTOLIST '9'
-#define CORRECT '0'
-#define DEXTRACT 'A'
-#define NOBEEP 'B'
-#define PRINTEXITVALUE 'C'
-#define PUSHDTOHOME 'D'
-#define PUSHDSILENT 'E'
-#define NULLGLOB 'G'
-#define RMSTARSILENT 'H'
-#define IGNOREBRACES 'I'
-#define CDABLEVARS 'J'
-#define NOBANGHIST 'K'
-
-#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 SIGCOUNT (SIGUSR2+1)
-#define SIGERR (SIGUSR2+1)
-#define SIGDEBUG (SIGUSR2+2)
-#define SIGEXIT 0
-
-#define SP(x) (*((union wait *) &(x)))
-
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(x) (((union wait*)&(x))->w_retcode)
-#define WTERMSIG(x) (((union wait*)&(x))->w_termsig)
-#define WSTOPSIG(x) (((union wait*)&(x))->w_stopsig)
-#endif
-
-#ifndef S_ISBLK
-#define _IFMT 0170000
-#define _IFDIR 0040000
-#define _IFCHR 0020000
-#define _IFBLK 0060000
-#define _IFREG 0100000
-#define _IFLNK 0120000
-#define _IFSOCK 0140000
-#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)
-#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
-#define S_ISSOCK(m) (((m)&_IFMT) == _IFSOCK)
-#endif
-
-/* buffered shell input for non-interactive shells */
-
-extern FILE *bshin;
-
-/* null-terminated array of pointers to strings containing elements
- of PATH and CDPATH */
-
-extern char **path,**cdpath;
-
-/* number of elements in aforementioned array */
-
-extern int pathct,cdpathct;
-
-/* error/break flag */
-
-extern int errflag;
-
-/* current history event number */
-
-extern int cev;
-
-/* if != 0, this is the first line of the command */
-
-extern int firstln;
-
-/* if != 0, this is the first char of the command (not including
- white space */
-
-extern int firstch;
-
-/* first event number in the history table */
-
-extern int tfev;
-
-/* capacity of history table */
-
-extern int tevs;
-
-/* if = 1, we have performed history substitution on the current line
- if = 2, we have used the 'p' modifier */
-
-extern int hflag;
-
-/* default event (usually cev-1, that is, "!!") */
-
-extern int dev;
-
-/* != 0 if we are in the middle of parsing a command (== 0 if we
- have not yet parsed the command word */
-
-extern int incmd;
-
-/* the list of history events */
-
-extern table histlist;
-
-/* the current history event (can be NULL) */
-
-extern table curtab;
-
-/* the directory stack */
-
-extern table dirstack;
-
-/* a string containing all the ungot characters (hungetch()) */
-
-extern char *ungots;
-
-/* the pointer to the next character to read from ungots */
-
-extern char *ungotptr;
-
-/* the contents of the IFS parameter */
-
-extern char *ifs;
-
-/* != 0 if this is a subshell */
-
-extern int subsh;
-
-/* # of break levels (break builtin) */
-
-extern int breaks;
-
-/* != 0 if we have a return pending (return builtin) */
-
-extern int retflag;
-
-/* # of nested loops we are in */
-
-extern int loops;
-
-/* # of continue levels */
-
-extern int contflag;
-
-/* the job currently being created/waited for (not current job in the sense
- of '+' and '-', that's topjob */
-
-extern int curjob;
-
-/* the current job (+) */
-
-extern int topjob;
-
-/* the previous job (-) */
-
-extern int prevjob;
-
-/* hash table containing the aliases and reserved words */
-
-extern htable alhtab;
-
-/* hash table containing the parameters */
-
-extern htable parmhtab;
-
-/* hash table containing the builtins/hashed commands */
-
-extern htable chtab;
-
-/* hash table containing the shell functions */
-
-extern htable shfunchtab;
-
-/* the job table */
-
-extern struct jobnode jobtab[MAXJOB];
-
-/* the list of sched jobs pending */
-
-extern struct schnode *scheds;
-
-/* the last l for s/l/r/ history substitution */
-
-extern char *last;
-
-/* the last r for s/l/r/ history substitution */
-
-extern char *rast;
-
-/* if peek == STRING or ENVSTRING, the next token */
-
-extern char *tstr;
-
-/* who am i */
-
-extern char *username;
-
-/* the return code of the last command */
-
-extern int lastval;
-
-/* != 0 if this is a login shell */
-
-extern int islogin;
-
-/* the next token (enum xtok) */
-
-extern int peek;
-
-/* the file descriptor associated with the next token, if it
- is something like '<' or '>>', etc. */
-
-extern int peekfd;
-
-/* input fd from the coprocess */
-
-extern int spin;
-
-/* output fd from the coprocess */
-
-extern int spout;
-
-/* the last time we checked mail */
-
-extern time_t lastmailcheck;
-
-/* the last modified date on the mail file last time we checked */
-
-extern time_t lastmailval;
-
-/* 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;
-
-/* the size of the mail file last time we checked */
-
-extern off_t lastmailsize;
-
-/* $$ */
-
-extern long procnum;
-
-/* $! (the pid of the last background command invoked */
-
-extern long proclast;
-
-/* the process group of the shell */
-
-extern long shpgrp;
-
-/* the current working directory */
-
-extern char *cwd;
-
-/* the hostname, truncated after the '.' */
-
-extern char *hostM;
-
-/* the hostname */
-
-extern char *hostm;
-
-/* the home directory */
-
-extern char *home;
-
-/* the positional parameters */
-
-extern table pparms;
-
-/* the list of local variables we have to destroy */
-
-extern table locallist;
-
-/* the shell input fd */
-
-extern int SHIN;
-
-/* the shell tty fd */
-
-extern int SHTTY;
-
-/* the stack of aliases we are expanding */
-
-extern struct anode *alstack[MAXAL];
-
-/* the alias stack pointer; also, the number of aliases currently
- being expanded */
-
-extern int alix;
-
-/* != 0 means we are reading input from a string */
-
-extern int strin;
-
-/* == 1 means we are doing TAB expansion
- == 2 means expansion has occurred during TAB expansion */
-
-extern int magic;
-
-/* period between periodic() commands, in seconds */
-
-extern int period;
-
-/* != 0 means history is turned off (through !" or setopt nobanghist) */
-
-extern int stophist;
-
-/* != 0 means we have removed the current event from the history list */
-
-extern int histremmed;
-
-/* the options; e.g. if opts['a'] is nonzero, -a is turned on */
-
-extern int opts[128];
-
-/* LINENO */
-
-extern int lineno;
-
-/* != 0 means we have called execlist() and then intend to exit(),
- so don't fork if not necessary */
-
-extern int exiting;
-
-/* the limits for child processes */
-
-extern struct rlimit limits[RLIM_NLIMITS];
-
-/* the tokens */
-
-extern char *tokens;
-
-/* the current word in the history list */
-
-extern char *hlastw;
-
-/* the pointer to the current character in the current word
- in the history list */
-
-extern char *hlastp;
-
-/* the size of the current word in the history list */
-
-extern int hlastsz;
-
-/* the alias expansion status - if == ALSTAT_MORE, we just finished
-extern 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;
-
-/* signal names */
-
-extern char *sigs[];
-
-/* signals that are trapped = 1, signals ignored =2 */
-
-extern int sigtrapped[];
-
End of zsh.h
echo proto 1>&2
sed 's/^-//' >proto <<'End of proto'
-#! /bin/sh
-#
-# proto - prototype generating script
-#
-# This file is part of zsh, the Z shell.
-#
-# zsh is free software etc etc.
-#
-for i
-do
- rm $i.pro
- grep -v '[{};:#]' $i.c | grep '^[A-Za-z]' |
- grep -v '^[ ]' |
- grep -v static | sed 's/$/;/' >$i.pro
-done
-
End of proto
---cut here---cut here---cut here---